diff --git a/.gitignore b/.gitignore index f20c730c..6115e13d 100644 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,4 @@ _ReSharper*/ *.o BIN/ ipch/ +*.map diff --git a/0readme_30.txt b/0readme_30.txt deleted file mode 100644 index e1a623cf..00000000 --- a/0readme_30.txt +++ /dev/null @@ -1,166 +0,0 @@ -Notes For V3.0-2 - -RESTRICTION: The FP15 and XVM features of the PDP-15 are only partially -debugged. Do NOT enable these features for normal operations. - -1. New Features in 3.0-2 - -1.1 PDP-1 - -- The LOAD command takes an optional argument specifying the memory field - to be loaded. -- The PTR BOOT command takes its starting memory field from the TA (address - switch) register. - -2. Bugs Fixed in 3.0-2 - -2.1 SCP and libraries - -- Fixed end of file problem in dep, idep. -- Fixed handling of trailing spaces in dep, idep. - -2.2 PDP-1 - -- Fixed system hang if continue after PTR error. -- Fixed PTR to start/stop on successive rpa instructions. - -2.3 PDP 18b family - -- Fixed priorities in PDP-15 API (differs from PDP-9). -- Fixed sign handling in PDP-15 EAE unsigned mul/div (differs from PDP-9). -- Fixed bug in CAF, clears API subsystem. - -2.4 1401 - -- Fixed tape read end-of-record handling based on real 1401. -- Added diagnostic read (space forward). - -2.5 1620 - -- Fixed bug in immediate index add (found by Michael Short). - -3. New Features in 3.0 vs prior releases - -3.1 SCP and Libraries - -- Added ASSIGN/DEASSIGN (logical name) commands. -- Changed RESTORE to unconditionally detach files. -- Added E11 and TPC format support to magtape library. -- Fixed bug in SHOW CONNECTIONS. -- Added USE_ADDR64 support - -3.2 All magtapes - -- Magtapes support SIMH format, E11 format, and TPC format (read only). -- SET FORMAT=format sets the specified tape unit's format. -- SHOW FORMAT displays the specified tape unit's format. -- Tape format can also be set as part of the ATTACH command, using - the -F switch. - -3.3 VAX - -- VAX can be compiled without USE_INT64. -- If compiled with USE_INT64 and USE_ADDR64, RQ and TQ controllers support - files > 2GB. -- VAX ROM has speed control (SET ROM DELAY/NODELAY). - -3.4 PDP-1 - -- Added block loader format support to LOAD. -- Changed BOOT PTR to allow loading of all of the first bank of memory. - -3.5 PDP-18b Family - -- Added PDP-4 EAE support. -- Added PDP-15 FP15 support. -- Added PDP-15 XVM support. -- Added PDP-15 "re-entrancy ECO". -- Added PDP-7, PDP-9, PDP-15 hardware RIM loader support in BOOT PTR. - -4. Bugs Fixed in 3.0 vs prior releases - -4.1 VAX - -- Fixed CVTfi bug: integer overflow not set if exponent out of range -- Fixed EMODx bugs: - o First and second operands reversed - o Separated fraction received wrong exponent - o Overflow calculation on separated integer incorrect - o Fraction not set to zero if exponent out of range -- Fixed interval timer and ROM access to pass power-up self-test even on very - fast host processors (fixes from Mark Pizzolato). -- Fixed bug in user disk size (found by Chaskiel M Grundman). - -4.2 1401 - -- Fixed mnemonic, instruction lengths, and reverse scan length check bug for MCS. -- Fixed MCE bug, BS off by 1 if zero suppress. -- Fixed chaining bug, D lost if return to SCP. -- Fixed H branch, branch occurs after continue. -- Added check for invalid 8 character MCW, LCA. -- Fixed magtape load-mode end of record response. -- Revised fetch to model hardware more closely. - -4.3 Nova - -- Fixed DSK variable size interaction with restore. -- Fixed bug in DSK set size routine. - -4.4 PDP-1 - -- Fixed DT variable size interaction with restore. -- Updated CPU, line printer, standard devices to detect indefinite I/O wait. -- Fixed incorrect logical, missing activate, break in drum simulator. -- Fixed bugs in instruction decoding, overprinting for line printer. - -4.5 PDP-11 - -- Fixed DT variable size interaction with restore. -- Fixed bug in MMR1 update (found by Tim Stark). -- Added XQ features and fixed bugs: - o Corrected XQ interrupts on IE state transition (code by Tom Evans). - o Added XQ interrupt clear on soft reset. - o Removed XQ interrupt when setting XL or RL (multiple people). - o Added SET/SHOW XQ STATS. - o Added SHOW XQ FILTERS. - o Added ability to split received packet into multiple buffers. - o Added explicit runt and giant packet processing. -- Fixed bug in user disk size (found by Chaskiel M Grundman). - -4.6 PDP-18B - -- Fixed DT, RF variable size interaction with restore. -- Fixed MT bug in MTTR. -- Fixed bug in PDP-4 line printer overprinting. -- Fixed bug in PDP-15 memory protect/skip interaction. -- Fixed bug in RF set size routine. -- Increased PTP TIME for PDP-15 operating systems. - -4.7 PDP-8 - -- Fixed DT, DF, RF, RX variable size interaction with restore. -- Fixed MT bug in SKTR. -- Fixed bug in DF, RF set size routine. - -4.8 HP2100 - -- Fixed bug in DP (13210A controller only), DQ read status. -- Fixed bug in DP, DQ seek complete. -- Fixed DR drum sizes. -- Fixed DR variable capacity interaction with SAVE/RESTORE. - -4.9 GRI - -- Fixed bug in SC queue pointer management. - -4.10 PDP-10 - -- Fixed bug in RP read header. - -4.11 Ibm1130 - -- Fixed bugs found by APL 1130. - -4.12 Altairz80 - -- Fixed bug in real-time clock on Windows host. diff --git a/0readme_ethernet.txt b/0readme_ethernet.txt deleted file mode 100644 index 938fcf71..00000000 --- a/0readme_ethernet.txt +++ /dev/null @@ -1,162 +0,0 @@ -This file contains information about the XQ/SIM_ETHER package. - -------------------------------------------------------------------------------- - -The XQ emulator is a host-independant software emulation of Digital's -DELQA (M7516) and DEQNA (M7504) Q-bus ethernet cards for the SIMH emulator. - -The XQ emulator uses the Sim_Ether module to execute host-specific ethernet -packet reads and writes, since all operating systems talk to real ethernet -cards/controllers differently. The host-dependant Sim_Ether module currently -supports Windows, Linux, NetBSD, and OpenBSD. - -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. 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 direct or hub(repeater) segment. - -------------------------------------------------------------------------------- - -Windows notes: - 1. The Windows-specific code uses the WinPCAP 3.0 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* the WinPCAP runtime package. - 3. 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. 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. - 4. WinPCAP loops packet writes back into the read queue. This causes problems - since the XQ controller is not expecting to read it's own packet. A fix - to the packet read filter was added to reject packets from the current MAC, - but this defeats DECNET's duplicate node number detection scheme. A more - correct fix for WinPCAP will be explored as time allows. - -Building on Windows: - 1. Install WinPCAP 3.0. - 2. Put the required .h files (bittypes,devioctl,ip6_misc,packet32,pcap, - pcap-stdinc).h from the WinPCAP 3.0 developer's kit in the compiler's path - 3. Put the required .lib files (packet,wpcap).lib from the WinPCAP 3.0 - developer's kit in the linker's path - 4. If you're using Borland C++, use COFF2OMF to convert the .lib files into - a format that can be used by the compiler. - 5. Define USE_NETWORK if you want the network functionality. - 6. Build it! - -------------------------------------------------------------------------------- - -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. Alternative methods for avoiding the - 'run as root' requirement will be welcomed. - -Building on Linux, NetBSD, and OpenBSD: - 1. Get/install the libpcap package for your unix version. http://rpmfind.net - might be a useful site for finding the linux variants. - 2. Use Make USE_NETWORK=1 if you want the network functionality. - 3. Build it! - -------------------------------------------------------------------------------- - -VAX simulator support: - -An OpenVMS VAX v7.2 system with DECNET Phase IV, MultiNet 4.4a, and LAT 5.3 has -been successfully run. Other testers have reported success booting NetBSD also. - - -PDP11 simulator support: - -An RT-11 v5.3 system with a freeware TCP/IP stack has been successfully run. -Other testers have reported that RSX with DECNET and the NetBSD operating -systems also work. RSTS/E v10.1 has preliminary support - RSTS/E boots and -enables the XH (XQ) device - DECNET and LAT software have not been tested. - -------------------------------------------------------------------------------- - -Things planned for future releases: - 1. PDP-11 bootstrap/bootrom - 2. Full MOP implementation - 3. DESQA support (if someone can get me the user manuals) - 4. DETQA support [DELQA-Turbo] (I have the manual) - 5. DEUNA/DELUA support - -------------------------------------------------------------------------------- - -Things which I need help with: - 1. Porting Sim_Ether packet driver to other host platforms, especially VMS. - 2. Information about Remote MOP processing - 3. VAX/PDP-11 hardware diagnotics image files and docs, to test XQ thoroughly. - 4. Feedback on operation with other VAX/PDP-11 OS's. - -------------------------------------------------------------------------------- - -Please send all patches, questions, feedback, clarifications, and help to: - dhittner AT northropgrumman DOT com - -Thanks, and Enjoy!! -Dave - - -=============================================================================== - Change Log -=============================================================================== - -05-Jun-03 Release: - 1. Added SET/SHOW XQ STATS - 2. Added SHOW XQ FILTERS - 3. Added ability to split received packet into multiple buffers - 4. Added explicit runt & giant packet processing - -------------------------------------------------------------------------------- - -30-May-03 Release: - 1. Corrected bug in xq_setmac introduced in v3.0 (multiple people) - 2. Made XQ receive buffer allocation dynamic to reduce scp executable size - 3. Optimized some structs, removed legacy variables (Mark Pizzolato) - 4. Changed #ifdef WIN32 to _WIN32 for consistancy - -------------------------------------------------------------------------------- - -06-May-03 Release: - 1. Added second XQ controller - 2. Added SIMH v3.0 compatibility - 3. Removed SET ADDRESS functionality - -------------------------------------------------------------------------------- - -10-Apr-03 Release: - 1. Added preliminary support for RSTS/E - 2. Added PDP-11 bootrom load via CSR flags - 3. Support for SPARC linux (thanks to Mark Pizzolato) - -------------------------------------------------------------------------------- - -11-Mar-03 Release: - 1. Added support for RT-11 TCP/IP - 2. Corrected interrupts (thanks to Tom Evans and Bob Supnik) - 3. Moved change log to the bottom of the readme file, cleaned up document - -------------------------------------------------------------------------------- - -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 - -------------------------------------------------------------------------------- - -08-Nov-02 Release: - 1. Added USE_NETWORK conditional to Sim_Ether - 2. Fixed behaviour of SHOW XQ ETH if no devices exist - 3. Added OpenBSD support to Sim_Ether (courtesy of Federico Schwindt) - 4. Added ethX detection simplification (from Megan Gentry) - -=============================================================================== diff --git a/ALTAIR/altair.txt b/ALTAIR/altair.txt deleted file mode 100644 index 13f0c361..00000000 --- a/ALTAIR/altair.txt +++ /dev/null @@ -1,211 +0,0 @@ -Altair 8800 Simulator -===================== - -1. Background. - - The MITS (Micro Instrumentation and Telemetry Systems) Altair 8800 -was announced on the January 1975 cover of Popular Electronics, which -boasted you could buy and build this powerful computer kit for only $397. -The kit consisted at that time of only the parts to build a case, power -supply, card cage (18 slots), CPU card, and memory card with 256 *bytes* of -memory. Still, thousands were ordered within the first few months after the -announcement, starting the personal computer revolution as we know it today. - - Many laugh at the small size of the that first kit, noting there -were no peripherals and the 256 byte memory size. But the computer was an -open system, and by 1977 MITS and many other small startups had added many -expansion cards to make the Altair quite a respectable little computer. The -"Altair Bus" that made this possible was soon called the S-100 Bus, later -adopted as an industry standard, and eventually became the IEE-696 Bus. - -2. Hardware - - We are simulating a fairly "loaded" Altair 8800 from about 1977, -with the following configuration: - - device simulates - name(s) - - CPU Altair 8800 with Intel 8080 CPU board, 62KB - of RAM, 2K of EPROM with start boot ROM. - 2SIO MITS 88-2SIO Dual Serial Interface Board. Port 1 - is assumed to be connected to a serial "glass - TTY" that is your terminal running the Simulator. - PTR Paper Tape Reader attached to port 2 of the - 2SIO board. - PTP Paper Tape Punch attached to port 2 of the - 2SIO board. This also doubles as a printer - port. - DSK MITS 88-DISK Floppy Disk controller with up - to eight drives. - -2.1 CPU - - We have 2 CPU options that were not present on the original -machine but are useful in the simulator. We also allow you to select -memory sizes, but be aware that some sample software requires the full -64K (i.e. CP/M) and the MITS Disk Basic and Altair DOS require about -a minimum of 24K. - - SET CPU 8080 Simulates the 8080 CPU (normal) - SET CPU Z80 Simulates the later Z80 CPU [At the present time - this is not fully implemented and is not to be - trusted with real Z80 software] - SET CPU ITRAP Causes the simulator to halt if an invalid 8080 - Opcode is detected. - SET CPU NOITRAP Does not stop on an invalid Opcode. This is - how the real 8080 works. - SET CPU 4K - SET CPU 8K - SET CPU 12K - SET CPU 16K - ...... - SET CPU 64K All these set various CPU memory configurations. - The 2K EPROM at the high end of memory is always - present and will always boot. - -The BOOT EPROM card starts at address 177400. Jumping to this address -will always boot drive 0 of the floppy controller. If no valid bootable -software is present there the machine crashes. This is historically -accurate behavior. - -The real 8080, on receiving a HLT (Halt) instruction, freezes the processor -and only an interrupt or CPU hardware reset will restore it. The simulator -is alot nicer, it will halt but send you back to the simulator command line. - -CPU Registers include the following: - - name size comments - - PC 16 The Program Counter - A 8 The accumulator - BC 16 The BC register pair. Register B is the high - 8 bits, C is the lower 8 bits - DE 16 The DE register pair. D is the top 8 bits, E is - the bottom. - HL 16 The HL register pair. H is top, L is bottom. - C 1 Carry flag. - Z 1 Zero Flag. - AC 1 Auxillary Carry flag. - P 1 Parity flag. - S 1 Sign flag. - SR 16 The front panel switches. - BREAK 16 Breakpoint address (377777 to disable). - WRU 8 The interrupt character. This starts as 005 - (ctrl-E) but some Altair software uses this - keystroke so best to change this to something - exotic such as 035 (which is Ctl-]). - - -2.2 The Serial I/O Card (2SIO) - - This simple programmed I/O device provides 2 serial ports to the -outside world, which could be hardware jumpered to support RS-232 plugs or a -TTY current loop interface. The standard I/O addresses assigned by MITS -was 20-21 (octal) for the first port, and 22-23 (octal) for the second. -We follow this standard in the Simulator. - - The simulator directs I/O to/from the first port to the screen. The -second port reads from an attachable "tape reader" file on input, and writes -to an attachable "punch file" on output. These files are considered a -simple stream of 8-bit bytes. - -2.3 The 88-DISK controller. - - The MITS 88-DISK is a simple programmed I/O interface to the MITS -8-inch floppy drive, which was basically a Pertec FD-400 with a power -supply and buffer board builtin. The controller supports neither interrupts -nor DMA, so floppy access required the sustained attention of the CPU. -The standard I/O addresses were 10, 11, and 12 (octal), and we follow the -standard. Details on controlling this hardware are in the altair_dsk.c -source file. - - -3. Sample Software - - Running an Altair in 1977 you would be running either MITS Disk -Extended BASIC, or the brand new and sexy CP/M Operating System from Digital -Research. Or possibly, you ordered Altair DOS back when it was promised in -1975, and are still waiting for it to be delivered in early 1977. - - We have samples of all three for you to check out. We can't go into -the details of how they work, but we'll give you a few hints. - - -3.1 CP/M Version 2.2 - - This version is my own port of the standard CP/M to the Altair. -There were some "official" versions but I don't have them. None were -endorsed or sold by MITS to my knowledge, however. - To boot CP/M: - - sim> attach dsk0 altcpm.dsk - sim> go 177400 - 62K CP/M VERSION 2.2 (ALTAIR 8800) - A>DIR - - CP/M feels like DOS, sort of. DIR will work. I have included all -the standard CP/M utilities, plus a few common public-domain ones. I also -include the sources to the customized BIOS and some other small programs. -TYPE will print an ASCII file. DUMP will dump a binary one. LS is a better -DIR than DIR. ASM will assemble .ASM files to Hex, LOAD will "load" them to -binary format (.COM). ED is a simple editor, #A command will bring the -source file to the buffer, T command will "type" lines, L will move lines, -E exits the editor. 20L20T will move down 20 lines, and type 20. Very -DECish. DDT is the debugger, SUBMIT is a batch-type command processor. -A sample batch file that will assemble and write out the bootable CP/M -image (on drive A) is "SYSGEN.SUB". To run it, type "SUBMIT SYSGEN". - - -3.2 MITS Disk Extended BASIC Version 4.1 - - This was the commonly used software for serious users of the Altair -computer. It is a powerful (but slow) BASIC with some extended commands to -allow it to access and manage the disk. There was no operating system it -ran under. To boot: - - sim> attach dsk0 mbasic.dsk - sim> go 177400 - - MEMORY SIZE? [return] - LINEPRINTER? C [return] - HIGHEST DISK NUMBER? 0 [return] (3 here = 4 drive system) - NUMBER OF FILES? 3 [return] - NUMBER OF RANDOM FILES? 2 [return] - - 44297 BYTES FREE - ALTAIR BASIC REV. 4.1 - [DISK EXTENDED VERSION] - COPYRIGHT 1977 BY MITS INC. - OK - mount 0 - OK - files - - -3.3 Altair DOS Version 1.0 - - This was long promised but not delivered until it was almost -irrelevant. A short attempted tour will reveal it to be a dog, far inferior -to CP/M. To boot: - - sim> attach dsk0 altdos.dsk - sim> go 177400 - - MEMORY SIZE? 64 [return] - INTERRUPTS? N [return] - HIGHEST DISK NUMBER? 0 [return] (3 here = 4 drive system) - HOW MANY DISK FILES? 3 [return] - HOW MANY RANDOM FILES? 2 [return] - - 056769 BYTES AVAILABLE - DOS MONITOR VER 1.0 - COPYRIGHT 1977 BY MITS INC - .mnt 0 - - .dir 0 - - - - - diff --git a/ALTAIR/altair_cpu.c b/ALTAIR/altair_cpu.c deleted file mode 100644 index 1977d0e2..00000000 --- a/ALTAIR/altair_cpu.c +++ /dev/null @@ -1,1189 +0,0 @@ -/* altair_cpu.c: MITS Altair Intel 8080 CPU simulator - - Copyright (c) 1997-2003, Charles E. Owen - - 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 Charles E. Owen shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Charles E. Owen. - - cpu 8080 CPU - - 08-Oct-02 RMS Tied off spurious compiler warnings - - The register state for the 8080 CPU is: - - A<0:7> Accumulator - BC<0:15> BC Register Pair - DE<0:15> DE Register Pair - HL<0:15> HL Register Pair - C carry flag - Z zero flag - S Sign bit - AC Aux carry - P Parity bit - PC<0:15> program counter - SP<0:15> Stack Pointer - - The 8080 is an 8-bit CPU, which uses 16-bit registers to address - up to 64KB of memory. - - The 78 basic instructions come in 1, 2, and 3-byte flavors. -*/ - -/* This routine is the instruction decode routine for the 8080. - 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 - I/O error in I/O simulator - Invalid OP code (if ITRAP is set on CPU) - - 2. Interrupts. - There are 8 possible levels of interrupt, and in effect they - do a hardware CALL instruction to one of 8 possible low - memory addresses. - - 3. Non-existent memory. On the 8080, reads to non-existent memory - return 0377, 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: - - altair_cpu.c add I/O service routines to dev_table - altair_sys.c add pointer to data structures in sim_devices -*/ - - -#include - -#include "altair_defs.h" - -#define UNIT_V_OPSTOP (UNIT_V_UF) /* Stop on Invalid OP? */ -#define UNIT_OPSTOP (1 << UNIT_V_OPSTOP) -#define UNIT_V_CHIP (UNIT_V_UF+1) /* 8080 or Z80 */ -#define UNIT_CHIP (1 << UNIT_V_CHIP) -#define UNIT_V_MSIZE (UNIT_V_UF+2) /* Memory Size */ -#define UNIT_MSIZE (1 << UNIT_V_MSIZE) - -unsigned char M[MAXMEMSIZE]; /* memory */ -int32 A = 0; /* accumulator */ -int32 BC = 0; /* BC register pair */ -int32 DE = 0; /* DE register pair */ -int32 HL = 0; /* HL register pair */ -int32 SP = 0; /* Stack pointer */ -int32 C = 0; /* carry flag */ -int32 Z = 0; /* Zero flag */ -int32 AC = 0; /* Aux carry */ -int32 S = 0; /* sign flag */ -int32 P = 0; /* parity flag */ -int32 saved_PC = 0; /* program counter */ -int32 SR = 0; /* switch register */ -int32 INTE = 0; /* Interrupt Enable */ -int32 int_req = 0; /* Interrupt request */ -int32 chip = 0; /* 0 = 8080 chip, 1 = z80 chip */ - -int32 PCX; /* External view of PC */ - -extern int32 sim_int_char; -extern int32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */ - -/* function prototypes */ - -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); -void setarith(int32 reg); -void setlogical(int32 reg); -void setinc(int32 reg); -int32 getreg(int32 reg); -void putreg(int32 reg, int32 val); -int32 getpair(int32 reg); -int32 getpush(int32 reg); -void putpush(int32 reg, int32 data); -void putpair(int32 reg, int32 val); -void parity(int32 reg); -int32 cond(int32 con); - -extern int32 sio0s(int32 io, int32 data); -extern int32 sio0d(int32 io, int32 data); -extern int32 sio1s(int32 io, int32 data); -extern int32 sio1d(int32 io, int32 data); -extern int32 dsk10(int32 io, int32 data); -extern int32 dsk11(int32 io, int32 data); -extern int32 dsk12(int32 io, int32 data); -int32 nulldev(int32 io, int32 data); - -/* This is the I/O configuration table. There are 255 possible -device addresses, if a device is plugged to a port it's routine -address is here, 'nulldev' means no device is available -*/ -struct idev { - int32 (*routine)(); -}; -struct idev dev_table[256] = { -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 000 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 004 */ -{&dsk10}, {&dsk11}, {&dsk12}, {&nulldev}, /* 010 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 014 */ -{&sio0s}, {&sio0d}, {&sio1s}, {&sio1d}, /* 020 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 024 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 030 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 034 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 040 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 044 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 050 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 054 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 060 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 064 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 070 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 074 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 100 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 104 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 110 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 114 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 120 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 124 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 130 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 134 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 140 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 144 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 150 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 154 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 160 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 164 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 170 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 174 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 200 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 204 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 210 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 214 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 220 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 224 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 230 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 234 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 240 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 244 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 250 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 254 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 260 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 264 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 270 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 274 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 300 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 304 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 310 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 314 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 320 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 324 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 330 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 334 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 340 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 344 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 350 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 354 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 360 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 364 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 370 */ -{&nulldev}, {&nulldev}, {&nulldev}, {&nulldev} }; /* 374 */ - -/* Altair MITS standard BOOT EPROM, fits in upper 256K of memory */ - -int32 bootrom[256] = { - 0041, 0000, 0114, 0021, 0030, 0377, 0016, 0346, - 0032, 0167, 0023, 0043, 0015, 0302, 0010, 0377, - 0303, 0000, 0114, 0000, 0000, 0000, 0000, 0000, - 0363, 0061, 0142, 0115, 0257, 0323, 0010, 0076, /* 46000 */ - 0004, 0323, 0011, 0303, 0031, 0114, 0333, 0010, /* 46010 */ - 0346, 0002, 0302, 0016, 0114, 0076, 0002, 0323, /* 46020 */ - 0011, 0333, 0010, 0346, 0100, 0302, 0016, 0114, - 0021, 0000, 0000, 0006, 0000, 0333, 0010, 0346, - 0004, 0302, 0045, 0114, 0076, 0020, 0365, 0325, - 0305, 0325, 0021, 0206, 0200, 0041, 0324, 0114, - 0333, 0011, 0037, 0332, 0070, 0114, 0346, 0037, - 0270, 0302, 0070, 0114, 0333, 0010, 0267, 0372, - 0104, 0114, 0333, 0012, 0167, 0043, 0035, 0312, - 0132, 0114, 0035, 0333, 0012, 0167, 0043, 0302, - 0104, 0114, 0341, 0021, 0327, 0114, 0001, 0200, - 0000, 0032, 0167, 0276, 0302, 0301, 0114, 0200, - 0107, 0023, 0043, 0015, 0302, 0141, 0114, 0032, - 0376, 0377, 0302, 0170, 0114, 0023, 0032, 0270, - 0301, 0353, 0302, 0265, 0114, 0361, 0361, 0052, - 0325, 0114, 0325, 0021, 0000, 0377, 0315, 0316, - 0114, 0321, 0332, 0276, 0114, 0315, 0316, 0114, - 0322, 0256, 0114, 0004, 0004, 0170, 0376, 0040, - 0332, 0054, 0114, 0006, 0001, 0312, 0054, 0114, - 0333, 0010, 0346, 0002, 0302, 0240, 0114, 0076, - 0001, 0323, 0011, 0303, 0043, 0114, 0076, 0200, - 0323, 0010, 0303, 0000, 0000, 0321, 0361, 0075, - 0302, 0056, 0114, 0076, 0103, 0001, 0076, 0117, - 0001, 0076, 0115, 0107, 0076, 0200, 0323, 0010, - 0170, 0323, 0001, 0303, 0311, 0114, 0172, 0274, - 0300, 0173, 0275, 0311, 0204, 0000, 0114, 0044, - 0026, 0126, 0026, 0000, 0000, 0000, 0000, 0000 -}; - -/* 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 (PC, saved_PC, 16) }, - { ORDATA (A, A, 8) }, - { ORDATA (BC, BC, 16) }, - { ORDATA (DE, DE, 16) }, - { ORDATA (HL, HL, 16) }, - { ORDATA (SP, SP, 16) }, - { FLDATA (C, C, 16) }, - { FLDATA (Z, Z, 16) }, - { FLDATA (AC, AC, 16) }, - { FLDATA (S, S, 16) }, - { FLDATA (P, P, 16) }, - { FLDATA (INTE, INTE, 16) }, - { ORDATA (SR, SR, 16) }, - { ORDATA (WRU, sim_int_char, 8) }, - { NULL } }; - -MTAB cpu_mod[] = { - { UNIT_CHIP, UNIT_CHIP, "Z80", "Z80", NULL }, - { UNIT_CHIP, 0, "8080", "8080", NULL }, - { UNIT_OPSTOP, UNIT_OPSTOP, "ITRAP", "ITRAP", NULL }, - { UNIT_OPSTOP, 0, "NOITRAP", "NOITRAP", 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, 65535, NULL, "64K", &cpu_set_size }, - { 0 } }; - -DEVICE cpu_dev = { - "CPU", &cpu_unit, cpu_reg, cpu_mod, - 1, 8, 16, 1, 8, 8, - &cpu_ex, &cpu_dep, &cpu_reset, - NULL, NULL, NULL }; - -int32 sim_instr (void) -{ - extern int32 sim_interval; - int32 PC, IR, OP, DAR, reason, hi, lo, carry, i; - - PC = saved_PC & ADDRMASK; /* load local PC */ - C = C & 0200000; - reason = 0; - - /* Main instruction fetch/decode loop */ - - while (reason == 0) { /* loop until halted */ - if (sim_interval <= 0) { /* check clock queue */ - if (reason = sim_process_event ()) break; - } - - if (int_req > 0) { /* interrupt? */ - - /* 8080 interrupts not implemented yet. None were used, - on a standard Altair 8800. All I/O is programmed. */ - - } /* end interrupt */ - - if (sim_brk_summ && - sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */ - reason = STOP_IBKPT; /* stop simulation */ - break; - } - - if (PC == 0177400) { /* BOOT PROM address */ - for (i = 0; i < 250; i++) { - M[i + 0177400] = bootrom[i] & 0xFF; - } - } - - PCX = PC; - - IR = OP = M[PC]; /* fetch instruction */ - - PC = (PC + 1) & ADDRMASK; /* increment PC */ - - sim_interval--; - - if (OP == 0166) { /* HLT Instruction*/ - reason = STOP_HALT; - PC--; - continue; - } - - /* Handle below all operations which refer to registers or - register pairs. After that, a large switch statement - takes care of all other opcodes */ - - if ((OP & 0xC0) == 0x40) { /* MOV */ - DAR = getreg(OP & 0x07); - putreg((OP >> 3) & 0x07, DAR); - continue; - } - if ((OP & 0xC7) == 0x06) { /* MVI */ - putreg((OP >> 3) & 0x07, M[PC]); - PC++; - continue; - } - if ((OP & 0xCF) == 0x01) { /* LXI */ - DAR = M[PC] & 0x00ff; - PC++; - DAR = DAR | (M[PC] <<8) & 0xFF00;; - putpair((OP >> 4) & 0x03, DAR); - PC++; - continue; - } - if ((OP & 0xEF) == 0x0A) { /* LDAX */ - DAR = getpair((OP >> 4) & 0x03); - putreg(7, M[DAR]); - continue; - } - if ((OP & 0xEF) == 0x02) { /* STAX */ - DAR = getpair((OP >> 4) & 0x03); - M[DAR] = getreg(7); - continue; - } - - if ((OP & 0xF8) == 0xB8) { /* CMP */ - DAR = A & 0xFF; - DAR -= getreg(OP & 0x07); - setarith(DAR); - continue; - } - if ((OP & 0xC7) == 0xC2) { /* JMP */ - if (cond((OP >> 3) & 0x07) == 1) { - lo = M[PC]; - PC++; - hi = M[PC]; - PC++; - PC = (hi << 8) + lo; - } else { - PC += 2; - } - continue; - } - if ((OP & 0xC7) == 0xC4) { /* CALL */ - if (cond((OP >> 3) & 0x07) == 1) { - lo = M[PC]; - PC++; - hi = M[PC]; - PC++; - SP--; - M[SP] = (PC >> 8) & 0xff; - SP--; - M[SP] = PC & 0xff; - PC = (hi << 8) + lo; - } else { - PC += 2; - } - continue; - } - if ((OP & 0xC7) == 0xC0) { /* RET */ - if (cond((OP >> 3) & 0x07) == 1) { - PC = M[SP]; - SP++; - PC |= (M[SP] << 8) & 0xff00; - SP++; - } - continue; - } - if ((OP & 0xC7) == 0xC7) { /* RST */ - SP--; - M[SP] = (PC >> 8) & 0xff; - SP--; - M[SP] = PC & 0xff; - PC = OP & 0x38; - continue; - } - - if ((OP & 0xCF) == 0xC5) { /* PUSH */ - DAR = getpush((OP >> 4) & 0x03); - SP--; - M[SP] = (DAR >> 8) & 0xff; - SP--; - M[SP] = DAR & 0xff; - continue; - } - if ((OP & 0xCF) == 0xC1) { /*POP */ - DAR = M[SP]; - SP++; - DAR |= M[SP] << 8; - SP++; - putpush((OP >> 4) & 0x03, DAR); - continue; - } - if ((OP & 0xF8) == 0x80) { /* ADD */ - A += getreg(OP & 0x07); - setarith(A); - A = A & 0xFF; - continue; - } - if ((OP & 0xF8) == 0x88) { /* ADC */ - carry = 0; - if (C) carry = 1; - A += getreg(OP & 0x07); - A += carry; - setarith(A); - A = A & 0xFF; - continue; - } - if ((OP & 0xF8) == 0x90) { /* SUB */ - A -= getreg(OP & 0x07); - setarith(A); - A = A & 0xFF; - continue; - } - if ((OP & 0xF8) == 0x98) { /* SBB */ - carry = 0; - if (C) carry = 1; - A -= (getreg(OP & 0x07)) + carry ; - setarith(A); - A = A & 0xFF; - continue; - } - if ((OP & 0xC7) == 0x04) { /* INR */ - DAR = getreg((OP >> 3) & 0x07); - DAR++; - setinc(DAR); - DAR = DAR & 0xFF; - putreg((OP >> 3) & 0x07, DAR); - continue; - } - if ((OP & 0xC7) == 0x05) { /* DCR */ - DAR = getreg((OP >> 3) & 0x07); - DAR--; - setinc(DAR); - DAR = DAR & 0xFF; - putreg((OP >> 3) & 0x07, DAR); - continue; - } - if ((OP & 0xCF) == 0x03) { /* INX */ - DAR = getpair((OP >> 4) & 0x03); - DAR++; - DAR = DAR & 0xFFFF; - putpair((OP >> 4) & 0x03, DAR); - continue; - } - if ((OP & 0xCF) == 0x0B) { /* DCX */ - DAR = getpair((OP >> 4) & 0x03); - DAR--; - DAR = DAR & 0xFFFF; - putpair((OP >> 4) & 0x03, DAR); - continue; - } - if ((OP & 0xCF) == 0x09) { /* DAD */ - HL += getpair((OP >> 4) & 0x03); - C = 0; - if (HL & 0x10000) - C = 0200000; - HL = HL & 0xFFFF; - continue; - } - if ((OP & 0xF8) == 0xA0) { /* ANA */ - A &= getreg(OP & 0x07); - C = 0; - setlogical(A); - A &= 0xFF; - continue; - } - if ((OP & 0xF8) == 0xA8) { /* XRA */ - A ^= getreg(OP & 0x07); - C = 0; - setlogical(A); - A &= 0xFF; - continue; - } - if ((OP & 0xF8) == 0xB0) { /* ORA */ - A |= getreg(OP & 0x07); - C = 0; - setlogical(A); - A &= 0xFF; - continue; - } - - - - /* The Big Instruction Decode Switch */ - - switch (IR) { - - /* Logical instructions */ - - case 0376: { /* CPI */ - DAR = A & 0xFF; - DAR -= M[PC]; - PC++; - setarith(DAR); - break; - } - case 0346: { /* ANI */ - A &= M[PC]; - PC++; - C = AC = 0; - setlogical(A); - A &= 0xFF; - break; - } - case 0356: { /* XRI */ - A ^= M[PC]; - PC++; - C = AC = 0; - setlogical(A); - A &= 0xFF; - break; - } - case 0366: { /* ORI */ - A |= M[PC]; - PC++; - C = AC = 0; - setlogical(A); - A &= 0xFF; - break; - } - - /* Jump instructions */ - - case 0303: { /* JMP */ - lo = M[PC]; - PC++; - hi = M[PC]; - PC++; - PC = (hi << 8) + lo; - break; - } - case 0351: { /* PCHL */ - PC = HL; - break; - } - case 0315: { /* CALL */ - lo = M[PC]; - PC++; - hi = M[PC]; - PC++; - SP--; - M[SP] = (PC >> 8) & 0xff; - SP--; - M[SP] = PC & 0xff; - PC = (hi << 8) + lo; - break; - } - case 0311: { /* RET */ - PC = M[SP]; - SP++; - PC |= (M[SP] << 8) & 0xff00; - SP++; - break; - } - - /* Data Transfer Group */ - - case 062: { /* STA */ - lo = M[PC]; - PC++; - hi = M[PC]; - PC++; - DAR = (hi << 8) + lo; - M[DAR] = A; - break; - } - case 072: { /* LDA */ - lo = M[PC]; - PC++; - hi = M[PC]; - PC++; - DAR = (hi << 8) + lo; - A = M[DAR]; - break; - } - case 042: { /* SHLD */ - lo = M[PC]; - PC++; - hi = M[PC]; - PC++; - DAR = (hi << 8) + lo; - M[DAR] = HL; - DAR++; - M[DAR] = (HL >>8) & 0x00ff; - break; - } - case 052: { /* LHLD */ - lo = M[PC]; - PC++; - hi = M[PC]; - PC++; - DAR = (hi << 8) + lo; - HL = M[DAR]; - DAR++; - HL = HL | (M[DAR] <<8); - break; - } - case 0353: { /* XCHG */ - DAR = HL; - HL = DE; - DE = DAR; - break; - } - - /* Arithmetic Group */ - - case 0306: { /* ADI */ - A += M[PC]; - PC++; - setarith(A); - A = A & 0xFF; - break; - } - case 0316: { /* ACI */ - carry = 0; - if (C) carry = 1; - A += M[PC]; - A += carry; - PC++; - setarith(A); - A = A & 0xFF; - break; - } - case 0326: { /* SUI */ - A -= M[PC]; - PC++; - setarith(A); - A = A & 0xFF; - break; - } - case 0336: { /* SBI */ - carry = 0; - if (C) carry = 1; - A -= (M[PC] + carry); - PC++; - setarith(A); - A = A & 0xFF; - break; - } - case 047: { /* DAA */ - DAR = A & 0x0F; - if (DAR > 9 || AC > 0) { - DAR += 6; - A &= 0xF0; - A |= DAR & 0x0F; - if (DAR & 0x10) - AC = 0200000; - else - AC = 0; - } - DAR = (A >> 4) & 0x0F; - if (DAR > 9 || AC > 0) { - DAR += 6; - if (AC) DAR++; - A &= 0x0F; - A |= (DAR << 4); - } - if ((DAR << 4) & 0x100) - C = 0200000; - else - C = 0; - if (A & 0x80) { - S = 0200000; - } else { - S = 0; - } - if ((A & 0xff) == 0) - Z = 0200000; - else - Z = 0; - parity(A); - A = A & 0xFF; - break; - } - case 07: { /* RLC */ - C = 0; - C = (A << 9) & 0200000; - A = (A << 1) & 0xFF; - if (C) - A |= 0x01; - break; - } - case 017: { /* RRC */ - C = 0; - if ((A & 0x01) == 1) - C |= 0200000; - A = (A >> 1) & 0xFF; - if (C) - A |= 0x80; - break; - } - case 027: { /* RAL */ - DAR = C; - C = 0; - C = (A << 9) & 0200000; - A = (A << 1) & 0xFF; - if (DAR) - A |= 1; - else - A &= 0xFE; - break; - } - case 037: { /* RAR */ - DAR = C; - C = 0; - if ((A & 0x01) == 1) - C |= 0200000; - A = (A >> 1) & 0xFF; - if (DAR) - A |= 0x80; - else - A &= 0x7F; - break; - } - case 057: { /* CMA */ - A = ~ A; - A &= 0xFF; - break; - } - case 077: { /* CMC */ - C = ~ C; - C &= 0200000; - break; - } - case 067: { /* STC */ - C = 0200000; - break; - } - - /* Stack, I/O & Machine Control Group */ - - case 0: { /* NOP */ - break; - } - case 0343: { /* XTHL */ - lo = M[SP]; - hi = M[SP + 1]; - M[SP] = HL & 0xFF; - M[SP + 1] = (HL >> 8) & 0xFF; - HL = (hi << 8) + lo; - break; - } - case 0371: { /* SPHL */ - SP = HL; - break; - } - case 0373: { /* EI */ - INTE = 0200000; - break; - } - case 0363: { /* DI */ - INTE = 0; - break; - } - case 0333: { /* IN */ - DAR = M[PC] & 0xFF; - PC++; - if (DAR == 0xFF) { - A = (SR >> 8) & 0xFF; - } else { - A = dev_table[DAR].routine(0, 0); - } - break; - } - case 0323: { /* OUT */ - DAR = M[PC] & 0xFF; - PC++; - dev_table[DAR].routine(1, A); - break; - } - - default: { - if (cpu_unit.flags & UNIT_OPSTOP) { - reason = STOP_OPCODE; - PC--; - } - break; - } - } -} - -/* Simulation halted */ - -saved_PC = PC; -return reason; -} - -/* Test an 8080 flag condition and return 1 if true, 0 if false */ -int32 cond(int32 con) -{ - int32 r = 0; - - switch (con) { - case 0: - if (Z == 0) return (1); - break; - case 1: - if (Z != 0) return (1); - break; - case 2: - if (C == 0) return (1); - break; - case 3: - if (C != 0) return (1); - break; - case 4: - if (P == 0) return (1); - break; - case 5: - if (P != 0) return (1); - break; - case 6: - if (S == 0) return (1); - break; - case 7: - if (S != 0) return (1); - break; - default: - break; - } - return (0); -} - -/* Set the arry, ign, ero and

arity flags following - an arithmetic operation on 'reg'. -*/ - -void setarith(int32 reg) -{ - int32 bc = 0; - - if (reg & 0x100) - C = 0200000; - else - C = 0; - if (reg & 0x80) { - bc++; - S = 0200000; - } else { - S = 0; - } - if ((reg & 0xff) == 0) - Z = 0200000; - else - Z = 0; - AC = 0; - if (cpu_unit.flags & UNIT_CHIP) { - P = 0; /* parity is zero for *all* arith ops on Z80 */ - } else { - parity(reg); - } -} - -/* Set the arry, ign, ero amd

arity flags following - a logical (bitwise) operation on 'reg'. -*/ - -void setlogical(int32 reg) -{ - C = 0; - if (reg & 0x80) { - S = 0200000; - } else { - S = 0; - } - if ((reg & 0xff) == 0) - Z = 0200000; - else - Z = 0; - AC = 0; - parity(reg); -} - -/* Set the Parity (P) flag based on parity of 'reg', i.e., number - of bits on even: P=0200000, else P=0 -*/ - -void parity(int32 reg) -{ - int32 bc = 0; - - if (reg & 0x01) bc++; - if (reg & 0x02) bc++; - if (reg & 0x04) bc++; - if (reg & 0x08) bc++; - if (reg & 0x10) bc++; - if (reg & 0x20) bc++; - if (reg & 0x40) bc++; - if (reg & 0x80) bc++; - P = ~(bc << 16); - P &= 0200000; -} - -/* Set the ign, ero amd

arity flags following - an INR/DCR operation on 'reg'. -*/ - -void setinc(int32 reg) -{ - int32 bc = 0; - - if (reg & 0x80) { - bc++; - S = 0200000; - } else { - S = 0; - } - if ((reg & 0xff) == 0) - Z = 0200000; - else - Z = 0; - if (cpu_unit.flags & UNIT_CHIP) { - P = 0; /* parity is zero for *all* arith ops on Z80 */ - } else { - parity(reg); - } -} - -/* Get an 8080 register and return it */ -int32 getreg(int32 reg) -{ - switch (reg) { - case 0: - return ((BC >>8) & 0x00ff); - case 1: - return (BC & 0x00FF); - case 2: - return ((DE >>8) & 0x00ff); - case 3: - return (DE & 0x00ff); - case 4: - return ((HL >>8) & 0x00ff); - case 5: - return (HL & 0x00ff); - case 6: - return (M[HL]); - case 7: - return (A); - default: - break; - } - return 0; -} - -/* Put a value into an 8080 register from memory */ -void putreg(int32 reg, int32 val) -{ - switch (reg) { - case 0: - BC = BC & 0x00FF; - BC = BC | (val <<8); - break; - case 1: - BC = BC & 0xFF00; - BC = BC | val; - break; - case 2: - DE = DE & 0x00FF; - DE = DE | (val <<8); - break; - case 3: - DE = DE & 0xFF00; - DE = DE | val; - break; - case 4: - HL = HL & 0x00FF; - HL = HL | (val <<8); - break; - case 5: - HL = HL & 0xFF00; - HL = HL | val; - break; - case 6: - M[HL] = val & 0xff; - break; - case 7: - A = val & 0xff; - default: - break; - } -} - -/* Return the value of a selected register pair */ -int32 getpair(int32 reg) -{ - switch (reg) { - case 0: - return (BC); - case 1: - return (DE); - case 2: - return (HL); - case 3: - return (SP); - default: - break; - } - return 0; -} - -/* Return the value of a selected register pair, in PUSH - format where 3 means A& flags, not SP */ -int32 getpush(int32 reg) -{ - int32 stat; - - switch (reg) { - case 0: - return (BC); - case 1: - return (DE); - case 2: - return (HL); - case 3: - stat = A << 8; - if (S) stat |= 0x80; - if (Z) stat |= 0x40; - if (AC) stat |= 0x10; - if (P) stat |= 0x04; - stat |= 0x02; - if (C) stat |= 0x01; - return (stat); - default: - break; - } - return 0; -} - - -/* Place data into the indicated register pair, in PUSH - format where 3 means A& flags, not SP */ -void putpush(int32 reg, int32 data) -{ - switch (reg) { - case 0: - BC = data; - break; - case 1: - DE = data; - break; - case 2: - HL = data; - break; - case 3: - A = (data >> 8) & 0xff; - S = Z = AC = P = C = 0; - if (data & 0x80) S = 0200000; - if (data & 0x40) Z = 0200000; - if (data & 0x10) AC = 0200000; - if (data & 0x04) P = 0200000; - if (data & 0x01) C = 0200000; - break; - default: - break; - } -} - - -/* Put a value into an 8080 register pair */ -void putpair(int32 reg, int32 val) -{ - switch (reg) { - case 0: - BC = val; - break; - case 1: - DE = val; - break; - case 2: - HL = val; - break; - case 3: - SP = val; - break; - default: - break; - } -} - - -/* Reset routine */ - -t_stat cpu_reset (DEVICE *dptr) -{ -C = 0; -Z = 0; -saved_PC = 0; -int_req = 0; -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] & 0377; -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 & 0377; - return SCPE_OK; -} - -t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -int32 mc = 0; -uint32 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; -} - -int32 nulldev(int32 flag, int32 data) -{ - if (flag == 0) - return (0377); - return 0; -} - diff --git a/ALTAIR/altair_defs.h b/ALTAIR/altair_defs.h deleted file mode 100644 index 5786247e..00000000 --- a/ALTAIR/altair_defs.h +++ /dev/null @@ -1,42 +0,0 @@ -/* altair_defs.h: MITS Altair simulator definitions - - Copyright (c) 1997-2003, Charles E. Owen - - 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 Charles E. Owen shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Charles E. Owen. -*/ - -#include "sim_defs.h" /* simulator defns */ - -/* Memory */ - -#define MAXMEMSIZE 65536 /* max memory size */ -#define MEMSIZE (cpu_unit.capac) /* actual memory size */ -#define ADDRMASK (MAXMEMSIZE - 1) /* address mask */ -#define MEM_ADDR_OK(x) (((uint32) (x)) < MEMSIZE) - -/* Simulator stop codes */ - -#define STOP_RSRV 1 /* must be 1 */ -#define STOP_HALT 2 /* HALT */ -#define STOP_IBKPT 3 /* breakpoint */ -#define STOP_OPCODE 4 - diff --git a/ALTAIR/altair_dsk.c b/ALTAIR/altair_dsk.c deleted file mode 100644 index 5ae54cf5..00000000 --- a/ALTAIR/altair_dsk.c +++ /dev/null @@ -1,366 +0,0 @@ -/* altair_dsk.c: MITS Altair 88-DISK Simulator - - Copyright (c) 1997-2003, Charles E. Owen - - 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 Charles E. Owen shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Charles E. Owen. - - The 88_DISK is a 8-inch floppy controller which can control up - to 16 daisy-chained Pertec FD-400 hard-sectored floppy drives. - Each diskette has physically 77 tracks of 32 137-byte sectors - each. - - The controller is interfaced to the CPU by use of 3 I/O addreses, - standardly, these are device numbers 10, 11, and 12 (octal). - - Address Mode Function - ------- ---- -------- - - 10 Out Selects and enables Controller and Drive - 10 In Indicates status of Drive and Controller - 11 Out Controls Disk Function - 11 In Indicates current sector position of disk - 12 Out Write data - 12 In Read data - - Drive Select Out (Device 10 OUT): - - +---+---+---+---+---+---+---+---+ - | C | X | X | X | Device | - +---+---+---+---+---+---+---+---+ - - C = If this bit is 1, the disk controller selected by 'device' is - cleared. If the bit is zero, 'device' is selected as the - device being controlled by subsequent I/O operations. - X = not used - Device = value zero thru 15, selects drive to be controlled. - - Drive Status In (Device 10 IN): - - +---+---+---+---+---+---+---+---+ - | R | Z | I | X | X | H | M | W | - +---+---+---+---+---+---+---+---+ - - W - When 0, write circuit ready to write another byte. - M - When 0, head movement is allowed - H - When 0, indicates head is loaded for read/write - X - not used (will be 0) - I - When 0, indicates interrupts enabled (not used this simulator) - Z - When 0, indicates head is on track 0 - R - When 0, indicates that read circuit has new byte to read - - Drive Control (Device 11 OUT): - - +---+---+---+---+---+---+---+---+ - | W | C | D | E | U | H | O | I | - +---+---+---+---+---+---+---+---+ - - I - When 1, steps head IN one track - O - When 1, steps head OUT out track - H - When 1, loads head to drive surface - U - When 1, unloads head - E - Enables interrupts (ignored this simulator) - D - Disables interrupts (ignored this simulator) - C - When 1 lowers head current (ignored this simulator) - W - When 1, starts Write Enable sequence: W bit on device 10 - (see above) will go 1 and data will be read from port 12 - until 137 bytes have been read by the controller from - that port. The W bit will go off then, and the sector data - will be written to disk. Before you do this, you must have - stepped the track to the desired number, and waited until - the right sector number is presented on device 11 IN, then - set this bit. - - Sector Position (Device 11 IN): - - As the sectors pass by the read head, they are counted and the - number of the current one is available in this register. - - +---+---+---+---+---+---+---+---+ - | X | X | Sector Number | T | - +---+---+---+---+---+---+---+---+ - - X = Not used - Sector number = binary of the sector number currently under the - head, 0-31. - T = Sector True, is a 1 when the sector is positioned to read or - write. - -*/ - -#include - -#include "altair_defs.h" - -#define UNIT_V_ENABLE (UNIT_V_UF + 0) /* Write Enable */ -#define UNIT_ENABLE (1 << UNIT_V_ENABLE) - -#define DSK_SECTSIZE 137 -#define DSK_SECT 32 -#define DSK_TRACSIZE 4384 -#define DSK_SURF 1 -#define DSK_CYL 77 -#define DSK_SIZE (DSK_SECT * DSK_SURF * DSK_CYL * DSK_SECTSIZE) - -t_stat dsk_svc (UNIT *uptr); -t_stat dsk_reset (DEVICE *dptr); -void writebuf(); - -extern int32 PCX; - -/* Global data on status */ - -int32 cur_disk = 8; /* Currently selected drive */ -int32 cur_track[9] = {0, 0, 0, 0, 0, 0, 0, 0, 377}; -int32 cur_sect[9] = {0, 0, 0, 0, 0, 0, 0, 0, 377}; -int32 cur_byte[9] = {0, 0, 0, 0, 0, 0, 0, 0, 377}; -int32 cur_flags[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0}; - -char dskbuf[137]; /* Data Buffer */ -int32 dirty = 0; /* 1 when buffer has unwritten data in it */ -UNIT *dptr; /* fileref to write dirty buffer to */ - -int32 dsk_rwait = 100; /* rotate latency */ - - -/* 88DSK Standard I/O Data Structures */ - -UNIT dsk_unit[] = { - { UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, DSK_SIZE) }, - { UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, DSK_SIZE) }, - { UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, DSK_SIZE) }, - { UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, DSK_SIZE) }, - { UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, DSK_SIZE) }, - { UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, DSK_SIZE) }, - { UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, DSK_SIZE) }, - { UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, DSK_SIZE) } - }; - -REG dsk_reg[] = { - { ORDATA (DISK, cur_disk, 4) }, - { NULL } }; - -DEVICE dsk_dev = { - "DSK", dsk_unit, dsk_reg, NULL, - 8, 10, 31, 1, 8, 8, - NULL, NULL, &dsk_reset, - NULL, NULL, NULL }; - -/* Service routines to handle simlulator functions */ - -/* service routine - actually gets char & places in buffer */ - -t_stat dsk_svc (UNIT *uptr) -{ -return SCPE_OK; -} - -/* Reset routine */ - -t_stat dsk_reset (DEVICE *dptr) -{ -cur_disk = 0; -return SCPE_OK; -} - -/* I/O instruction handlers, called from the CPU module when an - IN or OUT instruction is issued. - - Each function is passed an 'io' flag, where 0 means a read from - the port, and 1 means a write to the port. On input, the actual - input is passed as the return value, on output, 'data' is written - to the device. -*/ - -/* Disk Controller Status/Select */ - -/* IMPORTANT: The status flags read by port 8 IN instruction are - INVERTED, that is, 0 is true and 1 is false. To handle this, the - simulator keeps it's own status flags as 0=false, 1=true; and - returns the COMPLEMENT of the status flags when read. This makes - setting/testing of the flag bits more logical, yet meets the - simulation requirement that they are reversed in hardware. -*/ - -int32 dsk10(int32 io, int32 data) -{ - - if (io == 0) { /* IN: return flags */ - return ((~cur_flags[cur_disk]) & 0xFF); /* Return the COMPLEMENT! */ - } - - /* OUT: Controller set/reset/enable/disable */ - - if (dirty == 1) - writebuf(); - - /*printf("\n[%o] OUT 10: %x", PCX, data);*/ - cur_disk = data & 0x0F; - if (data & 0x80) { - cur_flags[cur_disk] = 0; /* Disable drive */ - cur_sect[cur_disk = 0377]; - cur_byte[cur_disk = 0377]; - return (0); - } - cur_flags[cur_disk] = 0x1A; /* Enable: head move true */ - cur_sect[cur_disk] = 0377; /* reset internal counters */ - cur_byte[cur_disk] = 0377; - if (cur_track[cur_disk] == 0) - cur_flags[cur_disk] |= 0x40; /* track 0 if there */ - return (0); -} - -/* Disk Drive Status/Functions */ - -int32 dsk11(int32 io, int32 data) -{ - int32 stat; - - if (io == 0) { /* Read sector position */ - /*printf("\n[%o] IN 11", PCX);*/ - if (dirty == 1) - writebuf(); - if (cur_flags[cur_disk] & 0x04) { /* head loaded? */ - cur_sect[cur_disk]++; - if (cur_sect[cur_disk] > 31) - cur_sect[cur_disk] = 0; - cur_byte[cur_disk] = 0377; - stat = cur_sect[cur_disk] << 1; - stat &= 0x3E; /* return 'sector true' bit = 0 (true) */ - stat |= 0xC0; /* set on 'unused' bits */ - return (stat); - } else { - return (0); /* head not loaded - return 0 */ - } - } - - /* Drive functions */ - - if (cur_disk > 7) - return (0); /* no drive selected - can do nothin */ - - /*printf("\n[%o] OUT 11: %x", PCX, data);*/ - if (data & 0x01) { /* Step head in */ - cur_track[cur_disk]++; - if (cur_track[cur_disk] > 76 ) - cur_track[cur_disk] = 76; - if (dirty == 1) - writebuf(); - cur_sect[cur_disk] = 0377; - cur_byte[cur_disk] = 0377; - } - - if (data & 0x02) { /* Step head out */ - cur_track[cur_disk]--; - if (cur_track[cur_disk] < 0) { - cur_track[cur_disk] = 0; - cur_flags[cur_disk] |= 0x40; /* track 0 if there */ - } - if (dirty == 1) - writebuf(); - cur_sect[cur_disk] = 0377; - cur_byte[cur_disk] = 0377; - } - - if (dirty == 1) - writebuf(); - - if (data & 0x04) { /* Head load */ - cur_flags[cur_disk] |= 0x04; /* turn on head loaded bit */ - cur_flags[cur_disk] |= 0x80; /* turn on 'read data available */ - } - - if (data & 0x08) { /* Head Unload */ - cur_flags[cur_disk] &= 0xFB; /* off on 'head loaded' */ - cur_flags[cur_disk] &= 0x7F; /* off on 'read data avail */ - cur_sect[cur_disk] = 0377; - cur_byte[cur_disk] = 0377; - } - - /* Interrupts & head current are ignored */ - - if (data & 0x80) { /* write sequence start */ - cur_byte[cur_disk] = 0; - cur_flags[cur_disk] |= 0x01; /* enter new write data on */ - } - return 0; -} - -/* Disk Data In/Out*/ - -int32 dsk12(int32 io, int32 data) -{ - static int32 rtn, i; - static long pos; - UNIT *uptr; - - uptr = dsk_dev.units + cur_disk; - if (io == 0) { - if ((i = cur_byte[cur_disk]) < 138) { /* just get from buffer */ - cur_byte[cur_disk]++; - return (dskbuf[i] & 0xFF); - } - /* physically read the sector */ - /*printf("\n[%o] IN 12 (READ) T%d S%d", PCX, cur_track[cur_disk], - cur_sect[cur_disk]);*/ - pos = DSK_TRACSIZE * cur_track[cur_disk]; - pos += DSK_SECTSIZE * cur_sect[cur_disk]; - rtn = fseek(uptr -> fileref, pos, 0); - rtn = fread(dskbuf, 137, 1, uptr -> fileref); - cur_byte[cur_disk] = 1; - return (dskbuf[0] & 0xFF); - } else { - if (cur_byte[cur_disk] > 136) { - i = cur_byte[cur_disk]; - dskbuf[i] = data & 0xFF; - writebuf(); - return (0); - } - i = cur_byte[cur_disk]; - dirty = 1; - dptr = uptr; - dskbuf[i] = data & 0xFF; - cur_byte[cur_disk]++; - return (0); - } -} - -void writebuf() -{ - long pos; - int32 rtn, i; - - i = cur_byte[cur_disk]; /* null-fill rest of sector if any */ - while (i < 138) { - dskbuf[i] = 0; - i++; - } - /*printf("\n[%o] OUT 12 (WRITE) T%d S%d", PCX, cur_track[cur_disk], - cur_sect[cur_disk]); i = getch(); */ - pos = DSK_TRACSIZE * cur_track[cur_disk]; /* calc file pos */ - pos += DSK_SECTSIZE * cur_sect[cur_disk]; - rtn = fseek(dptr -> fileref, pos, 0); - rtn = fwrite(dskbuf, 137, 1, dptr -> fileref); - cur_flags[cur_disk] &= 0xFE; /* ENWD off */ - cur_byte[cur_disk] = 0377; - dirty = 0; - return; -} diff --git a/ALTAIR/altair_sio.c b/ALTAIR/altair_sio.c deleted file mode 100644 index 9c212160..00000000 --- a/ALTAIR/altair_sio.c +++ /dev/null @@ -1,258 +0,0 @@ -/* altair_sio: MITS Altair serial I/O card - - Copyright (c) 1997-2003, Charles E. Owen - - 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 Charles E. Owen shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Charles E. Owen. - - These functions support a simulated MITS 2SIO interface card. - The card had two physical I/O ports which could be connected - to any serial I/O device that would connect to a current loop, - RS232, or TTY interface. Available baud rates were jumper - selectable for each port from 110 to 9600. - - All I/O is via programmed I/O. Each each has a status port - and a data port. A write to the status port can select - some options for the device (0x03 will reset the port). - A read of the status port gets the port status: - - +---+---+---+---+---+---+---+---+ - | X X X X X X O I | - +---+---+---+---+---+---+---+---+ - - I - A 1 in this bit position means a character has been received - on the data port and is ready to be read. - O - A 1 in this bit means the port is ready to receive a character - on the data port and transmit it out over the serial line. - - A read to the data port gets the buffered character, a write - to the data port writes the character to the device. -*/ - -#include - -#include "altair_defs.h" - -#define UNIT_V_ANSI (UNIT_V_UF + 0) /* ANSI mode */ -#define UNIT_ANSI (1 << UNIT_V_ANSI) - -t_stat sio_svc (UNIT *uptr); -t_stat sio_reset (DEVICE *dptr); -t_stat ptr_svc (UNIT *uptr); -t_stat ptr_reset (DEVICE *dptr); -t_stat ptp_svc (UNIT *uptr); -t_stat ptp_reset (DEVICE *dptr); - -int32 ptr_stopioe = 0, ptp_stopioe = 0; /* stop on error */ - -/* 2SIO Standard I/O Data Structures */ - -UNIT sio_unit = { UDATA (&sio_svc, 0, 0), - KBD_POLL_WAIT }; - -REG sio_reg[] = { - { ORDATA (DATA, sio_unit.buf, 8) }, - { ORDATA (STAT, sio_unit.u3, 8) }, - { NULL } }; - -MTAB sio_mod[] = { - { UNIT_ANSI, 0, "TTY", "TTY", NULL }, - { UNIT_ANSI, UNIT_ANSI, "ANSI", "ANSI", NULL }, - { 0 } }; - -DEVICE sio_dev = { - "2SIO", &sio_unit, sio_reg, sio_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &sio_reset, - NULL, NULL, NULL }; - -UNIT ptr_unit = { UDATA (&ptr_svc, UNIT_SEQ + UNIT_ATTABLE, 0), - KBD_POLL_WAIT }; - -REG ptr_reg[] = { - { ORDATA (DATA, ptr_unit.buf, 8) }, - { ORDATA (STAT, ptr_unit.u3, 8) }, - { ORDATA (POS, ptr_unit.pos, T_ADDR_W) }, - { NULL } }; - -DEVICE ptr_dev = { - "PTR", &ptr_unit, ptr_reg, NULL, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &ptr_reset, - NULL, NULL, NULL }; - -UNIT ptp_unit = { UDATA (&ptp_svc, UNIT_SEQ + UNIT_ATTABLE, 0), - KBD_POLL_WAIT }; - -REG ptp_reg[] = { - { ORDATA (DATA, ptp_unit.buf, 8) }, - { ORDATA (STAT, ptp_unit.u3, 8) }, - { ORDATA (POS, ptp_unit.pos, T_ADDR_W) }, - { NULL } }; - -DEVICE ptp_dev = { - "PTP", &ptp_unit, ptp_reg, NULL, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &ptp_reset, - NULL, NULL, NULL }; - -/* Service routines to handle simulator functions */ - -/* service routine - actually gets char & places in buffer */ - -int32 sio_svc (UNIT *uptr) -{ - int32 temp; - - sim_activate (&sio_unit, sio_unit.wait); /* continue poll */ - if ((temp = sim_poll_kbd ()) < SCPE_KFLAG) - return temp; /* no char or error? */ - sio_unit.buf = temp & 0377; /* Save char */ - sio_unit.u3 |= 0x01; /* Set status */ - - /* Do any special character handling here */ - - sio_unit.pos++; - return SCPE_OK; -} - - -int32 ptr_svc (UNIT *uptr) -{ - return SCPE_OK; -} - -int32 ptp_svc (UNIT *uptr) -{ - return SCPE_OK; -} - - -/* Reset routine */ - -int32 sio_reset (DEVICE *dptr) -{ - sio_unit.buf = 0; /* Data */ - sio_unit.u3 = 0x02; /* Status */ - sim_activate (&sio_unit, sio_unit.wait); /* activate unit */ - return SCPE_OK; -} - - -int32 ptr_reset (DEVICE *dptr) -{ - ptr_unit.buf = 0; - ptr_unit.u3 = 0x02; - sim_cancel (&ptr_unit); /* deactivate unit */ - return SCPE_OK; -} - -int32 ptp_reset (DEVICE *dptr) -{ - ptp_unit.buf = 0; - ptp_unit.u3 = 0x02; - sim_cancel (&ptp_unit); /* deactivate unit */ - return SCPE_OK; -} - - -/* I/O instruction handlers, called from the CPU module when an - IN or OUT instruction is issued. - - Each function is passed an 'io' flag, where 0 means a read from - the port, and 1 means a write to the port. On input, the actual - input is passed as the return value, on output, 'data' is written - to the device. -*/ - -int32 sio0s(int32 io, int32 data) -{ - if (io == 0) { - return (sio_unit.u3); - } else { - if (data == 0x03) { /* reset port! */ - sio_unit.u3 = 0x02; - sio_unit.buf = 0; - sio_unit.pos = 0; - } - return (0); - } -} - -int32 sio0d(int32 io, int32 data) -{ - if (io == 0) { - sio_unit.u3 = sio_unit.u3 & 0xFE; - return (sio_unit.buf); - } else { - sim_putchar(data); - } - return 0; -} - -/* Port 2 controls the PTR/PTP devices */ - -int32 sio1s(int32 io, int32 data) -{ - if (io == 0) { - if ((ptr_unit.flags & UNIT_ATT) == 0) /* attached? */ - return 0x02; - if (ptr_unit.u3 != 0) /* No more data? */ - return 0x02; - return (0x03); /* ready to read/write */ - } else { - if (data == 0x03) { - ptr_unit.u3 = 0; - ptr_unit.buf = 0; - ptr_unit.pos = 0; - ptp_unit.u3 = 0; - ptp_unit.buf = 0; - ptp_unit.pos = 0; - } - return (0); - } -} - -int32 sio1d(int32 io, int32 data) -{ - int32 temp; - UNIT *uptr; - - if (io == 0) { - if ((ptr_unit.flags & UNIT_ATT) == 0) /* attached? */ - return 0; - if (ptr_unit.u3 != 0) - return 0; - uptr = ptr_dev.units; - if ((temp = getc(uptr -> fileref)) == EOF) { /* end of file? */ - ptr_unit.u3 = 0x01; - return 0; - } - ptr_unit.pos++; - return (temp & 0xFF); - } else { - uptr = ptp_dev.units; - putc(data, uptr -> fileref); - ptp_unit.pos++; - } - return 0; -} - diff --git a/ALTAIR/altair_sys.c b/ALTAIR/altair_sys.c deleted file mode 100644 index cf558d41..00000000 --- a/ALTAIR/altair_sys.c +++ /dev/null @@ -1,302 +0,0 @@ -/* altair_sys.c: MITS Altair system interface - - Copyright (c) 1997-2003, Charles E. Owen - - 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 Charles E. Owen shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Charles E. Owen. -*/ - -#include -#include "altair_defs.h" - -extern DEVICE cpu_dev; -extern DEVICE dsk_dev; -extern UNIT cpu_unit; -extern REG cpu_reg[]; -extern DEVICE sio_dev; -extern DEVICE ptr_dev; -extern DEVICE ptp_dev; -extern DEVICE lpt_dev; -extern unsigned char M[]; -extern int32 saved_PC; - -/* SCP data structures - - sim_name simulator name string - sim_PC pointer to saved PC register descriptor - sim_emax number of words needed 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[] = "Altair 8800"; - -REG *sim_PC = &cpu_reg[0]; - -int32 sim_emax = 4; - -DEVICE *sim_devices[] = { &cpu_dev, &sio_dev, &ptr_dev, - &ptp_dev, &dsk_dev, NULL }; - -const char *sim_stop_messages[] = { - "Unknown error", - "Unknown I/O Instruction", - "HALT instruction", - "Breakpoint", - "Invalid Opcode" }; - -static const char *opcode[] = { -"NOP", "LXI B", "STAX B", "INX B", /* 000-003 */ -"INR B", "DCR B", "MVI B", "RLC", /* 004-007 */ -"???", "DAD B", "LDAX B", "DCX B", /* 010-013 */ -"INR C", "DCR C", "MVI C", "RRC", /* 014-017 */ -"???", "LXI D", "STAX D", "INX D", /* 020-023 */ -"INR D", "DCR D", "MVI D", "RAL", /* 024-027 */ -"???", "DAD D", "LDAX D", "DCX D", /* 030-033 */ -"INR E", "DCR E", "MVI E", "RAR", /* 034-037 */ -"???", "LXI H", "SHLD", "INX H", /* 040-043 */ -"INR H", "DCR H", "MVI H", "DAA", /* 044-047 */ -"???", "DAD H", "LHLD", "DCX H", /* 050-053 */ -"INR L", "DCR L", "MVI L", "CMA", /* 054-057 */ -"???", "LXI SP", "STA", "INX SP", /* 060-063 */ -"INR M", "DCR M", "MVI M", "STC", /* 064-067 */ -"???", "DAD SP", "LDA", "DCX SP", /* 070-073 */ -"INR A", "DCR A", "MVI A", "CMC", /* 074-077 */ -"MOV B,B", "MOV B,C", "MOV B,D", "MOV B,E", /* 100-103 */ -"MOV B,H", "MOV B,L", "MOV B,M", "MOV B,A", /* 104-107 */ -"MOV C,B", "MOV C,C", "MOV C,D", "MOV C,E", /* 110-113 */ -"MOV C,H", "MOV C,L", "MOV C,M", "MOV C,A", /* 114-117 */ -"MOV D,B", "MOV D,C", "MOV D,D", "MOV D,E", /* 120-123 */ -"MOV D,H", "MOV D,L", "MOV D,M", "MOV D,A", /* 124-127 */ -"MOV E,B", "MOV E,C", "MOV E,D", "MOV E,E", /* 130-133 */ -"MOV E,H", "MOV E,L", "MOV E,M", "MOV E,A", /* 134-137 */ -"MOV H,B", "MOV H,C", "MOV H,D", "MOV H,E", /* 140-143 */ -"MOV H,H", "MOV H,L", "MOV H,M", "MOV H,A", /* 144-147 */ -"MOV L,B", "MOV L,C", "MOV L,D", "MOV L,E", /* 150-153 */ -"MOV L,H", "MOV L,L", "MOV L,M", "MOV L,A", /* 154-157 */ -"MOV M,B", "MOV M,C", "MOV M,D", "MOV M,E", /* 160-163 */ -"MOV M,H", "MOV M,L", "HLT", "MOV M,A", /* 164-167 */ -"MOV A,B", "MOV A,C", "MOV A,D", "MOV A,E", /* 170-173 */ -"MOV A,H", "MOV A,L", "MOV A,M", "MOV A,A", /* 174-177 */ -"ADD B", "ADD C", "ADD D", "ADD E", /* 200-203 */ -"ADD H", "ADD L", "ADD M", "ADD A", /* 204-207 */ -"ADC B", "ADC C", "ADC D", "ADC E", /* 210-213 */ -"ADC H", "ADC L", "ADC M", "ADC A", /* 214-217 */ -"SUB B", "SUB C", "SUB D", "SUB E", /* 220-223 */ -"SUB H", "SUB L", "SUB M", "SUB A", /* 224-227 */ -"SBB B", "SBB C", "SBB D", "SBB E", /* 230-233 */ -"SBB H", "SBB L", "SBB M", "SBB A", /* 234-237 */ -"ANA B", "ANA C", "ANA D", "ANA E", /* 240-243 */ -"ANA H", "ANA L", "ANA M", "ANA A", /* 244-247 */ -"XRA B", "XRA C", "XRA D", "XRA E", /* 250-253 */ -"XRA H", "XRA L", "XRA M", "XRA A", /* 254-257 */ -"ORA B", "ORA C", "ORA D", "ORA E", /* 260-263 */ -"ORA H", "ORA L", "ORA M", "ORA A", /* 264-267 */ -"CMP B", "CMP C", "CMP D", "CMP E", /* 270-273 */ -"CMP H", "CMP L", "CMP M", "CMP A", /* 274-277 */ -"RNZ", "POP B", "JNZ", "JMP", /* 300-303 */ -"CNZ", "PUSH B", "ADI", "RST 0", /* 304-307 */ -"RZ", "RET", "JZ", "???", /* 310-313 */ -"CZ", "CALL", "ACI", "RST 1", /* 314-317 */ -"RNC", "POP D", "JNC", "OUT", /* 320-323 */ -"CNC", "PUSH D", "SUI", "RST 2", /* 324-327 */ -"RC", "???", "JC", "IN", /* 330-333 */ -"CC", "???", "SBI", "RST 3", /* 334-337 */ -"RPO", "POP H", "JPO", "XTHL", /* 340-343 */ -"CPO", "PUSH H", "ANI", "RST 4", /* 344-347 */ -"RPE", "PCHL", "JPE", "XCHG", /* 350-353 */ -"CPE", "???", "XRI", "RST 5", /* 354-357 */ -"RP", "POP PSW", "JP", "DI", /* 360-363 */ -"CP", "PUSH PSW", "ORI", "RST 6", /* 364-367 */ -"RM", "SPHL", "JM", "EI", /* 370-373 */ -"CM", "???", "CPI", "RST 7", /* 374-377 */ - }; - -int32 oplen[256] = { -1,3,1,1,1,1,2,1,0,1,1,1,1,1,2,1,0,3,1,1,1,1,2,1,0,1,1,1,1,1,2,1, -0,3,3,1,1,1,2,1,0,1,3,1,1,1,2,1,0,3,3,1,1,1,2,1,0,1,3,1,1,1,2,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,3,3,3,1,2,1,1,1,3,0,3,3,2,1,1,1,3,2,3,1,2,1,1,0,3,2,3,0,2,1, -1,1,3,1,3,1,2,1,1,1,3,1,3,0,2,1,1,1,3,1,3,1,2,1,1,1,3,1,3,0,2,1 }; - -/* This is the binary loader. The input file is considered to be - a string of literal bytes with no format special format. The - load starts at the current value of the PC. -*/ - -int32 sim_load (FILE *fileref, char *cptr, char *fnam, int flag) -{ -int32 i, addr = 0, cnt = 0; - -if ((*cptr != 0) || (flag != 0)) return SCPE_ARG; -addr = saved_PC; -while ((i = getc (fileref)) != EOF) { - M[addr] = i; - addr++; - cnt++; - } /* end while */ -printf ("%d Bytes loaded.\n", cnt); -return (SCPE_OK); -} - -/* Symbolic output - - Inputs: - *of = output stream - addr = current PC - *val = pointer to values - *uptr = pointer to unit - sw = switches - Outputs: - status = error code -*/ - -int32 fprint_sym (FILE *of, int32 addr, unsigned int32 *val, - UNIT *uptr, int32 sw) -{ -int32 cflag, c1, c2, inst, adr; - -cflag = (uptr == NULL) || (uptr == &cpu_unit); -c1 = (val[0] >> 8) & 0177; -c2 = val[0] & 0177; -if (sw & SWMASK ('A')) { - fprintf (of, (c2 < 040)? "<%03o>": "%c", c2); - return SCPE_OK; } -if (sw & SWMASK ('C')) { - fprintf (of, (c1 < 040)? "<%03o>": "%c", c1); - fprintf (of, (c2 < 040)? "<%03o>": "%c", c2); - return SCPE_OK; } -if (!(sw & SWMASK ('M'))) return SCPE_ARG; -inst = val[0]; -fprintf (of, "%s", opcode[inst]); -if (oplen[inst] == 2) { - if (strchr(opcode[inst], ' ') != NULL) - fprintf (of, ","); - else fprintf (of, " "); - fprintf (of, "%o", val[1]); -} -if (oplen[inst] == 3) { - adr = val[1] & 0xFF; - adr |= (val[2] << 8) & 0xff00; - if (strchr(opcode[inst], ' ') != NULL) - fprintf (of, ","); - else fprintf (of, " "); - fprintf (of, "%o", adr); -} -return -(oplen[inst] - 1); -} - -/* 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 -*/ - -int32 parse_sym (char *cptr, int32 addr, UNIT *uptr, unsigned int32 *val, int32 sw) -{ -int32 cflag, i = 0, j, r; -char gbuf[CBUFSIZE]; - -cflag = (uptr == NULL) || (uptr == &cpu_unit); -while (isspace (*cptr)) cptr++; /* absorb spaces */ -if ((sw & SWMASK ('A')) || ((*cptr == '\'') && cptr++)) { /* ASCII char? */ - if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */ - val[0] = (unsigned int) cptr[0]; - return SCPE_OK; } -if ((sw & SWMASK ('C')) || ((*cptr == '"') && cptr++)) { /* ASCII string? */ - if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */ - val[0] = ((unsigned int) cptr[0] << 8) + (unsigned int) cptr[1]; - return SCPE_OK; } - -/* An instruction: get opcode (all characters until null, comma, - or numeric (including spaces). -*/ - -while (1) { - if (*cptr == ',' || *cptr == '\0' || - isdigit(*cptr)) - break; - gbuf[i] = toupper(*cptr); - cptr++; - i++; -} - -/* Allow for RST which has numeric as part of opcode */ - -if (toupper(gbuf[0]) == 'R' && - toupper(gbuf[1]) == 'S' && - toupper(gbuf[2]) == 'T') { - gbuf[i] = toupper(*cptr); - cptr++; - i++; -} - -/* Allow for 'MOV' which is only opcode that has comma in it. */ - -if (toupper(gbuf[0]) == 'M' && - toupper(gbuf[1]) == 'O' && - toupper(gbuf[2]) == 'V') { - gbuf[i] = toupper(*cptr); - cptr++; - i++; - gbuf[i] = toupper(*cptr); - cptr++; - i++; -} - -/* kill trailing spaces if any */ -gbuf[i] = '\0'; -for (j = i - 1; gbuf[j] == ' '; j--) { - gbuf[j] = '\0'; -} - -/* find opcode in table */ -for (j = 0; j < 256; j++) { - if (strcmp(gbuf, opcode[j]) == 0) - break; -} -if (j > 255) /* not found */ - return SCPE_ARG; - -val[0] = j; /* store opcode */ -if (oplen[j] < 2) /* if 1-byter we are done */ - return SCPE_OK; -if (*cptr == ',') cptr++; -cptr = get_glyph(cptr, gbuf, 0); /* get address */ -sscanf(gbuf, "%o", &r); -if (oplen[j] == 2) { - val[1] = r & 0xFF; - return (-1); -} -val[1] = r & 0xFF; -val[2] = (r >> 8) & 0xFF; -return (-2); -} diff --git a/AltairZ80/altairZ80.txt b/AltairZ80/altairZ80.txt deleted file mode 100644 index 48f83a1e..00000000 --- a/AltairZ80/altairZ80.txt +++ /dev/null @@ -1,895 +0,0 @@ -Altair 8800 Simulator with Z80 support -====================================== - -0. Revision History - -- 25-Feb-2003, Peter Schorn (added support for real time simulation) -- 9-Oct-2002, Peter Schorn (added support for simulated hard disk) -- 28-Sep-2002, Peter Schorn (number of tracks per disk can be configured) -- 19-Sep-2002, Peter Schorn (added WARNROM feature) -- 31-Aug-2002, Peter Schorn (added extended ROM features suggested - by Scott LaBombard) -- 4-May-2002, Peter Schorn (added description of MP/M II sample software) -- 28-Apr-2002, Peter Schorn (added periodic timer interrupts and three - additional consoles) -- 15-Apr-2002, Peter Schorn (added memory breakpoint) -- 7-Apr-2002, Peter Schorn (added ROM / NOROM switch) -Original version of this document written by Charles E Owen - - -1. Background. - - The MITS (Micro Instrumentation and Telemetry Systems) Altair 8800 was -announced on the January 1975 cover of Popular Electronics, which boasted -you could buy and build this powerful computer kit for only $397. The kit -consisted at that time of only the parts to build a case, power supply, -card cage (18 slots), CPU card, and memory card with 256 *bytes* of memory. -Still, thousands were ordered within the first few months after the -announcement, starting the personal computer revolution as we know it -today. - - Many laugh at the small size of the that first kit, noting there were no -peripherals and the 256 byte memory size. But the computer was an open -system, and by 1977 MITS and many other small startups had added many -expansion cards to make the Altair quite a respectable little computer. The -"Altair Bus" that made this possible was soon called the S-100 Bus, later -adopted as an industry standard, and eventually became the IEE-696 Bus. - - -2. Hardware - - We are simulating a fairly "loaded" Altair 8800 from about 1977, with the -following configuration: - - device simulates - name(s) - - CPU Altair 8800 with Intel 8080 CPU board, 62KB - of RAM, 2K of EPROM with start boot ROM. - SIO MITS 88-2SIO Dual Serial Interface Board. Port 1 - is assumed to be connected to a serial "glass - TTY" that is your terminal running the Simulator. - PTR Paper Tape Reader attached to port 2 of the 2SIO board. - PTP Paper Tape Punch attached to port 2 of the - 2SIO board. This also doubles as a printer port. - DSK MITS 88-DISK Floppy Disk controller with up - to eight drives. - - -2.1 CPU - - We have 2 CPU options that were not present on the original machine but -are useful in the simulator. We also allow you to select memory sizes, but -be aware that some sample software requires the full 64K (i.e. CP/M) and -the MITS Disk Basic and Altair DOS require about a minimum of 24K. - - SET CPU 8080 Simulates the 8080 CPU (normal) - SET CPU Z80 Simulates the Z80 CPU. Note that some software (e.g. most - original Altair software such as 4K Basic) requires an 8080 CPU and - will not or not properly run on a Z80. This is mainly due to the use - of the parity flag on the 8080 which has not always the same - semantics on the Z80. - - SET CPU ITRAP Causes the simulator to halt if an invalid opcode - is detected (depending on the chosen CPU). - SET CPU NOITRAP Does not stop on an invalid Opcode. This is - how the real 8080 works. - - SET CPU 4K - SET CPU 8K - SET CPU 12K - SET CPU 16K - ...... (in 4K steps) - SET CPU 64K All these set various CPU memory configurations. - - SET CPU BANKED Enables the banked memory support. The simulated memory - has eight banks with address range 0..'common' (see registers below) - and a common area from 'common' to 0xfff which is common to all - banks. The currently active bank is determined by register 'bank' - (see below). You can only switch to banked memory if the memory - is set to 64K. The banked memory is used by CP/M 3. - - SET CPU NONBANKED Disables banked memory support. - - SET CPU ROM Enables the ROM from address 'ROMLOW' to 'ROMHIGH' - (see below under CPU Registers) and prevents write access - to these locations. This is the default setting. - - SET CPU NOROM Disables the ROM. - - SET CPU ALTAIRROM Enables the slightly modified but downwards compatible - Altair boot ROM at addresses 0FF00 to 0FFFF. This is the default. - - SET CPU NOALTAIRROM Disables standard Altair ROM behavior. - - SET CPU WARNROM Enables warning messages to be printed when the CPU - attempts to write into ROM or into non-existing memory. Also prints - a warning message if the CPU attempts to read from non-existing - memory. - - SET CPU NOWARNROM Suppreses all warning message of "WARNROM". Note that - some software tries on purpose to write to ROM in order to detect - the available RAM. - - The BOOT EPROM card starts at address 0FF00 if it has been enabled by -'SET CPU ALTAIRROM'. Jumping to this address will boot drive 0 of the -floppy controller (CPU must be set to ROM or equivalent code must be -present). If no valid bootable software is present there the machine -crashes. This is historically accurate behavior. - - The real 8080, on receiving a HLT (Halt) instruction, freezes the -processor and only an interrupt or CPU hardware reset will restore it. The -simulator is alot nicer, it will halt but send you back to the simulator -command line. - -CPU Registers include the following: - - Name Size Comment - - PC 16 The Program Counter - AF 16 The accumulator and the flag register - F = S Z - AC - P/V N C - S = Sign flag. - Z = Zero Flag. - AC = Auxillary Carry flag. - P/V = Parity flag on 8080 - Parity / Overflow flag on Z80 - - = not used (undefined) - N = Internal sign flag - C = Carry flag. - BC 16 The BC register pair. - Register B is the high 8 bits, C is the lower 8 bits - DE 16 The DE register pair. - Register D is the high 8 bits, E is the lower 8 bits. - HL 16 The HL register pair. - Register H is the high 8 bits, L is the lower 8 bits. - AF1 16 The alternate AF register (on Z80 only) - BC1 16 The alternate BC register (on Z80 only) - DE1 16 The alternate DE register (on Z80 only) - HL1 16 The alternate HL register (on Z80 only) - IX 16 The IX index register (on Z80 only) - IY 16 The IY index register (on Z80 only) - IFF 8 Interrupt flag (on Z80 only) - INT 8 Interrupt register (on Z80 only) - - SR 16 The front panel switches (use D SR 8 for 4k Basic). - WRU 8 The interrupt character. This starts as 5 - (ctrl-E) but some Altair software uses this - keystroke so best to change this to something - exotic such as 035 (which is Ctl-]). - - BANK 3 The currently active memory bank (if banked memory - is activated - see memory options above) - COMMON 16 The starting address of common memory. Originally set - to 0xc000 (note this setting must agree with the - value supplied to GENCPM for CP/M 3 system generation) - ROMLOW 16 The starting address of the ROM. Default is 0FF00. - ROMHIGH 16 The final address of the ROM. Default is 0FFFF. - CLOCK 32 The clock speed of the simulated CPU in kHz or 0 to run - at maximum speed. To set the clock speed for a typical - 4 MHz Z80 CPU, use D CLOCK 4000. The CP/M utility SPEED - measures the clock speed of the simulated CPU. - - -2.2 The Serial I/O Card (2SIO) - - This simple programmed I/O device provides 2 serial ports to the outside -world, which could be hardware jumpered to support RS-232 plugs or a TTY -current loop interface. The standard I/O addresses assigned by MITS was -10-11 (hex) for the first port, and 12-13 (hex) for the second. We follow -this standard in the Simulator. - - The simulator directs I/O to/from the first port to the screen. The -second port reads from an attachable "tape reader" file on input, and -writes to an attachable "punch file" on output. These files are considered -a simple stream of 8-bit bytes. - - The SIO can be configured in SIMH with the following commands: - - SET SIO TTY Bit 8 is set to zero on console output - SET SIO ANSI Bit 8 is not touched on console output - - SET SIO ALL Console input support lower- and upper case - SET SIO UPPER Console input is transformed to upper case characters only - (This feature is useful for most Altair software) - - SET SIO BS Map the delete character to backspace - SET SIO DEL Map the backspace character to delete - - SET SIO QUIET Do not print warning messages - SET SIO VERBOSE Print warning messages (useful for debugging) - The register SIOWL determines how often the same warning - is displayed. The default is 3. - - You can also attach the SIO to a port: - - ATTACH SIO 23 Console IO goes via a Telnet connection on port 23 - DETACH SIO Console IO goes via the regular SIMH console - - -2.3 The SIMH pseudo device - - The SIMH pseudo device facilitates the communication between the -simulated ALTAIR and the simulator environment. This device defines a -number of (most R/O) registers (see source code) which are primarily useful -for debugging purposes. - - The SIMH pseudo device can be configured with - - SET SIMH QUIET Do not print warning messages - SET SIMH VERBOSE Print warning messages (useful for debugging) - - SET SIMH TIMERON Start periodic timer interrupts - SET SIMH TIMEROFF Stop the periodic timer interrupts - - The following variables determine the behavior of the timer: - - TIMD This is the delay between consecutive interrupts in milliseconds. - Use D TIMD 20 for a 50 Hz clock. - TIMH This is the address of the interrupt handler to call for a - timer interrupt. - - -2.4 The 88-DISK controller. - - The MITS 88-DISK is a simple programmed I/O interface to the MITS 8-inch -floppy drive, which was basically a Pertec FD-400 with a power supply and -buffer board builtin. The controller supports neither interrupts nor DMA, -so floppy access required the sustained attention of the CPU. The standard -I/O addresses were 8, 9, and 0A (hex), and we follow the standard. Details -on controlling this hardware are in the altair_dsk.c source file. - - The only difference is that the simulated disks may be larger than the -original ones: The original disk had 77 tracks while the simulated disks -support up to 254 tracks (only relevant for CP/M). You can change the -number of tracks per disk by setting the appropriate value in TRACKS[..]. -For example "D TRACKS[0] 77" sets the number of tracks for disk 0 to the -original number of 77. The command "D TRACKS[0-7] 77" changes the highest -track number for all disks to 77. - - For debugging purposes you can set the trace level of some disk I/O -functions. To do so the following bits in TRACE (a register of the disk) -have been defined with the following meaning: - - 1 Trace all IN and OUT instructions on the disk ports 8 and 9 - 2 Trace all read and writes to full sectors on the disk - 4 Print a message whenever an unnecessary step-in or step out of the - disk head occurs (often an indication of an infinite loop) - 8 Print a message whenever the disk head appears to be waiting for a - sector which does not show up (often an indication of an infinite - loop) - -For example the command "D TRACE 10" will trace options 2+8 from above. - - The DSK device can be configured with - - SET DSK QUIET Do not print warning messages for disk - SET DSK VERBOSE Print warning messages for disk - (useful for debugging) - The register DSKWL determines how often the - same warning is displayed. The default is 3. - - SET DSK WRITEENABLED Allow write operations for disk - SET DSK LOCKED Disk is locked, i.e. no write operations - will be allowed. - - -2.5 The simulated hard disk - - In order to increase the available storage capacity, the simulator -features 8 simulated hard disks with a capacity of 8MB (HDSK0 to HDSK7). -Currently only CP/M supports two hard disks as devices I: and J:. - - For debugging purposes one can set the trace flag by executing the -command "D HDTRACE 1". The default for "HDTRACE" is 0 (no trace). - - The HDSK device can be configured with - - SET HDSK QUIET Do not print warning messages for hard disk - SET HDSK VERBOSE Print warning messages for hard disk - (useful for debugging) - - SET HDSK WRITEENABLED Allow write operations for hard disk - SET HDSK LOCKED Hard disk is locked, i.e. no - write operations will be allowed. - - -3. Sample Software - - Running an Altair in 1977 you would be running either MITS Disk Extended -BASIC, or the brand new and sexy CP/M Operating System from Digital -Research. Or possibly, you ordered Altair DOS back when it was promised in -1975, and are still waiting for it to be delivered in early 1977. - - We have samples of all three for you to check out. We can't go into the -details of how they work, but we'll give you a few hints. - - -3.1 CP/M Version 2.2 - - This version is my own port of the standard CP/M to the Altair. There -were some "official" versions but I don't have them. None were endorsed or -sold by MITS to my knowledge, however. - - To boot CP/M: - - sim> attach dsk cpm2.dsk - sim> boot dsk - - CP/M feels like DOS, sort of. DIR will work. I have included all the -standard CP/M utilities, plus a few common public-domain ones. I also -include the sources to the customized BIOS and some other small programs. -TYPE will print an ASCII file. DUMP will dump a binary one. LS is a -better DIR than DIR. ASM will assemble .ASM files to Hex, LOAD will "load" -them to binary format (.COM). ED is a simple editor, #A command will bring -the source file to the buffer, T command will "type" lines, L will move -lines, E exits the editor. 20L20T will move down 20 lines, and type 20. -Very DECish. DDT is the debugger, DO is a batch-type command processor. A -sample batch file that will assemble and write out the bootable CP/M image -(on drive A) is "SYSCPM2.SUB". To run it, type "DO SYSCPM2". - - In order to efficiently transfer files into the CP/M environment use the -included program R . If you have a file named foo.ext in the -current directory (i.e. the directory where SIMH is), executing R FOO.EXT -under CP/M will transfer the file onto the CP/M disk. Transferring a file -from the CP/M environment to the SIMH environment is accomplished by -W for text files or by W B for binary files. -The simplest way for transferring multiple files is to create a ".SUB" -batch file which contains the necessary R resp. W commands. - - If you need more storage space you can use a simulated hard disk on -drives I: and J:. To use do "attach HDSK0 hdi.dsk" and issue the -"XFORMAT I:" resp. "XFORMAT J:" command from CP/M do initialize the disk -to an empty state. - -The disk "cpm2.dsk" contains the following files: -Name Ext Size Comment -ASM .COM 8K ; CP/M assembler -BDOS .MAC 68K ; Basic Disk Operating System assembler source code -BOOT .COM 1K ; transfer control to boot ROM -BOOT .MAC 2K ; source for BOOT.COM -BOOTGEN .COM 2K ; put a program on the boot sectors -CBIOSX .MAC 48K ; CP/M 2 BIOS source for Altair -CCP .MAC 26K ; Console Command Processor assembler source code -COPY .COM 2K ; copy disks -CPMBOOT .COM 12K ; CP/M operating system -CPU .COM 2K ; get and set the CPU type (8080 or Z80) -CPU .MAC 2K ; source for CPU.COM -CREF80 .COM 4K ; cross reference utility -DDT .COM 6K ; 8080 debugger -DDTZ .COM 10K ; Z80 debugger -DIF .COM 4K ; determine differences between two files -DO .COM 2K ; batch processing -DSKBOOT .MAC 8K ; source for boot ROM -DUMP .COM 2K ; hex dump a file -ED .COM 8K ; line editor -ELIZA .BAS 10K ; Eliza game in Basic -EX8080 .COM 12K ; exercise 8080 instruction set -EXZ80N .COM 12K ; exercise Z80 instruction set, No undefined status bits -EXZ80U .COM 12K ; exercise Z80 instruction set, Undefined status bits -EXZ80 .MAC 54K ; source for EX8080.COM, EXZ80N.COM, EXZ80U.COM -EX .SUB 2K ; benchmark execution of EX8080.COM, EXZ80N.COM, EXZ80U.COM -FORMAT .COM 2K ; format disks -GO .COM 0K ; start the currently loaded program at 100H -HDSKBOOT.MAC 6K ; boot code for hard disk -L80 .COM 12K ; Microsoft linker -LADDER .COM 40K ; game -LADDER .DAT 2K ; high score file for LADDER.COM -LIB80 .COM 6K ; library utility -LOAD .COM 2K ; load hex files -LS .COM 4K ; directory utility -LU .COM 20K ; library utility -M80 .COM 20K ; Microsoft macro assembler -MBASIC .COM 24K ; Microsoft Basic interpreter -MC .SUB 2K ; assemble and link an assembler program -MCC .SUB 2K ; read, assemble and link an assembler program -MCCL .SUB 2K ; assemble, link and produce listing -MEMCFG .LIB 2K ; defines the memory configuration -MOVER .MAC 2K ; moves operating system in place -OTHELLO .COM 12K ; Othello (Reversi) game -PIP .COM 8K ; Peripheral Interchange Program -PRELIM .COM 2K ; preliminary CPU tests -PRELIM .MAC 6K ; source code for PRELIM.COM -R .COM 4K ; read files from SIMH environment -RSETSIMH.COM 2K ; reset SIMH interface -RSETSIMH.MAC 2K ; assembler source for RSETSIMH.COM -SHOWSEC .COM 3K ; show sectors on a disk -SID .COM 8K ; debugger for 8080 -SPEED .COM 2K ; utility to measure the clock speed of the simulated CPU -STAT .COM 6K ; provide information about currently logged disks -SURVEY .COM 2K ; system survey -SURVEY .MAC 16K ; assembler source for SURVEY.COM -SYSCOPY .COM 2K ; copy system tracks between disks -SYSCPM2 .SUB 2K ; create CP/M 2 on drive A: -TIMER .COM 2K ; perform various timer operations -TIMER .MAC 2K ; source code for TIMER.COM -UNCR .COM 8K ; un-crunch utility -UNERA .COM 2K ; un-erase a file -UNERA .MAC 16K ; source for UNERA.COM -USQ .COM 2K ; un-squeeze utility -W .COM 4K ; write files to SIMH environment -WM .COM 12K ; word master screen editor -WM .HLP 3K ; help file for WM.COM -WORM .COM 4K ; worm game for VT100 terminal -XFORMAT .COM 2K ; initialise a drive (floppy or hard disk) -XSUB .COM 2K ; support for DO.COM -ZAP .COM 10K ; SuperZap 5.2 disk editor configured for VT100 -ZSID .COM 10K ; debugger for Z80 -ZTRAN4 .COM 4K ; translate 8080 mnemonics into Z80 equivalents - - -3.2 CP/M Version 3 with banked memory - - CP/M 3 is the successor to CP/M 2.2. A customised BIOS (BIOS3.MAC) is -included to facilitate modification if so desired. The defaults supplied in -GENCPM.DAT for system generation can be used. BOOTGEN.COM is used to place -the CP/M loader (LDR.COM) on the boot tracks of a disk. - - Running CP/M 3 with banked memory: - sim> attach dsk cpm3.dsk - sim> reset cpu - sim> set cpu banked - sim> set cpu itrap - sim> boot dsk - - Executing "DO SYSCPM3" will re-generate the banked version of CP/M 3. You -can boot CP/M 3 with or without a Z80 CPU. The Z80 CPU is needed for both -sysgens due to the use of BOOTGEN.COM which requires it. - -The disk "cpm3.dsk" contains the following files: -ASM .COM 8K ; CP/M assembler -ASSIGN .SYS 2K -BDOS3 .SPR 10K -BIOS3 .MAC 28K ; CP/M 3 BIOS source for Altair SIMH -BIOS3 .SPR 4K -BNKBDOS3.SPR 14K -BNKBIOS3.SPR 4K -BOOT .COM 2K ; transfer control to boot ROM -BOOTGEN .COM 2K ; put a program on the boot sectors -CCP .COM 4K -COPYSYS .COM 2K -CPM3 .SYS 18K -CPMLDR .MAC 38K ; CP/M 3 loader assembler source -DATE .COM 4K ; date utility -DDT .COM 6K ; 8080 debugger -DDTZ .COM 10K ; Z80 debugger -DEFS .LIB 2K ; include file for BIOS3.MAC to create banked CP/M 3 -DEVICE .COM 8K -DIF .COM 4K ; determine differences between two files -DIR .COM 16K ; directory utility -DO .COM 6K ; batch processing -DUMP .COM 2K -ED .COM 10K -ERASE .COM 4K -GENCOM .COM 16K -GENCPM .COM 22K -GENCPM .DAT 4K ; CP/M generation information for banked version -GENCPMNB.DAT 4K ; CP/M generation information for non-banked version -GET .COM 8K -HELP .COM 8K ; help utility -HELP .HLP 62K ; help files -HEXCOM .CPM 2K -HIST .UTL 2K -INITDIR .COM 32K -L80 .COM 12K ; Microsoft linker -LDR .COM 4K ; CP/M loader with optimised loader BIOS -LDRBIOS3.MAC 14K ; optimised (for space) loader BIOS -LIB .COM 8K ; Digital Research librarian -LINK .COM 16K ; Digital Research linker -LOAD .COM 2K -M80 .COM 20K ; Microsoft macro assembler -MC .SUB 2K ; assemble and link an assmbler program -MCC .SUB 2K ; read, assemble and link an assembler program -PATCH .COM 4K -PIP .COM 10K ; Peripheral Interchange Program -PROFILE .SUB 2K ; commands to be executed at start up -PUT .COM 8K -R .COM 4K ; read files from SIMH environment -RENAME .COM 4K -RESBDOS3.SPR 2K -RMAC .COM 14K ; Digital Research macro assembler -RSETSIMH.COM 2K ; reset SIMH interface -SAVE .COM 2K -SCB .MAC 2K -SET .COM 12K -SETDEF .COM 6K -SHOW .COM 10K -SHOWSEC .COM 4K ; show sectors on a disk -SID .COM 8K ; 8080 debugger -SYSCOPY .COM 2K ; copy system tracks between disks -SYSCPM3 .SUB 2K ; create banked CP/M 3 system -TRACE .UTL 2K -TSHOW .COM 2K ; show split time -TSTART .COM 2K ; create timer and start it -TSTOP .COM 2K ; show final time and stop timer -TYPE .COM 4K -UNERA .COM 2K ; un-erase a file -W .COM 4K ; write files to SIMH environment -XREF .COM 16K ; cross reference utility -ZSID .COM 10K ; Z80 debugger - - -3.3 MP/M II with banked memory - - MP/M II is an acronym for MultiProgramming Monitor Control Program for -Microprocessors. It is a multiuser operating system for an eight bit -microcomputer. MP/M II supports multiprogramming at each terminal. This -version supports four terminals available via Telnet. To boot: - - sim> attach dsk mpm.dsk - sim> set cpu itrap - sim> set cpu z80 - sim> set cpu rom - sim> set cpu banked - sim> attach sio 23 - sim> d common b000 - sim> boot dsk - - Now connect a Telnet session to the simulator and type "MPM" at the "A>" -prompt. Now you can connect up to three additional terminals via Telnet to -the Altair running MP/M II. To re-generate the system perform "DO SYSMPM" -in the CP/M environment (not possible under MP/M since XSUB is needed). - -The disk "mpm.dsk" contains the following files: -Name Ext Size Comment -ABORT .PRL 2K ; abort a process -ABORT .RSP 2K -ASM .PRL 10K ; MP/M assembler -BNKBDOS .SPR 12K ; banked BDOS -BNKXDOS .SPR 2K ; banked XDOS -BNKXIOS .SPR 4K ; banked XIOS -BOOTGEN .COM 2K ; copy an executable to the boot section -CONSOLE .PRL 2K ; print console number -CPM .COM 2K ; return to CP/M -CPM .MAC 2K ; source for CPM.COM -DDT .COM 6K ; MP/M DDT -DDT2 .COM 6K ; CP/M DDT -DDTZ .COM 10K ; CP/M DDT with Z80 support -DIF .COM 4K ; difference between two files -DIR .PRL 2K ; directory command -DO .COM 2K ; CP/M submit -DSKRESET.PRL 2K ; disk reset command -DUMP .MAC 6K ; source for DUMP.PRL -DUMP .PRL 2K ; dump command -ED .PRL 10K ; MP/M line editor -ERA .PRL 2K ; erase command -ERAQ .PRL 4K ; erase comand (verbose) -GENHEX .COM 2K -GENMOD .COM 2K -GENSYS .COM 10K -L80 .COM 12K ; Microsoft linker -LDRBIOS .MAC 14K ; loader BIOS -LIB .COM 8K ; library utility -LINK .COM 16K ; linker -LOAD .COM 2K ; loader -M80 .COM 20K ; Microsoft macro assembler -MC .SUB 2K ; assemble and link an assmbler program -MCC .SUB 2K ; read, assemble and link an assembler program -MPM .COM 8K ; start MP/M II -MPM .SYS 26K ; MP/M system file -MPMD .LIB 2K ; define a banked system -MPMLDR .COM 6K ; MP/M loader without LDRBIOS -MPMSTAT .BRS 6K ; status of MP/M system -MPMSTAT .PRL 6K -MPMSTAT .RSP 2K -MPMXIOS .MAC 26K ; XIOS for MP/M -PIP .PRL 10K ; MP/M peripheral interchange program -PIP2 .COM 8K ; CP/M peripheral interchange program -PRINTER .PRL 2K -PRLCOM .PRL 4K -R .COM 4K ; read a file from the SIMH environment -RDT .PRL 8K ; debugger for page relocatable programs -REN .PRL 4K ; rename a file -RESBDOS .SPR 4K ; non-banked BDOS -RMAC .COM 14K ; Digital Research macro assembler -RSETSIMH.COM 2K ; reset SIMH interface -SCHED .BRS 2K ; schedule a job -SCHED .PRL 4K -SCHED .RSP 2K -SDIR .PRL 18K ; fancy directory command -SET .PRL 8K ; set parameters -SHOW .PRL 8K ; show status of disks -SPOOL .BRS 4K ; spool utility -SPOOL .PRL 4K -SPOOL .RSP 2K -STAT .COM 6K ; CP/M stat command -STAT .PRL 10K ; MP/M stat command -STOPSPLR.PRL 2K ; stop spooler -SUBMIT .PRL 6K ; MP/M submit -SYSCOPY .COM 2K ; copy system tracks -SYSMPM .SUB 2K ; do a system generation -SYSTEM .DAT 2K ; default values for system generation -TMP .SPR 2K -TOD .PRL 4K ; time of day -TSHOW .COM 2K ; show split time -TSTART .COM 2K ; create timer and start it -TSTOP .COM 2K ; show final time and stop timer -TYPE .PRL 2K ; type a file on the screen -USER .PRL 2K ; set user area -W .COM 4K ; write a file to SIMH environment -XDOS .SPR 10K ; XDOS -XREF .COM 16K ; cross reference utility -XSUB .COM 2K ; for CP/M DO - - -3.4 CP/M application software - - There is also a small collection of sample application software -containing the following items: - -- SPL: a Small Programming Language with a suite of sample programs -- PROLOGZ: a Prolog interpreter written in SPL with sources -- PASCFORM: a Pascal pretty printer written in Pascal -- Pascal MT+: Pascal language system needed to compile PASCFORM - -The sample software comes on "app.dsk" and to use it do - - sim> attach dsk1 app.dsk - -before booting CP/M. - -The disk "app.dsk" contains the following files: -Name Ext Size Comment -BOOTGEN .COM 2K -BOOTGEN .SPL 6K ; SPL source for BOOTGEN.COM -C .SUB 2K ; batch file for compiling an SPL source file -CALC .PRO 4K ; Prolog demo program: Calculator -CC .SUB 2K ; compile an SPL source which is on the underlying - file system -DECLARAT. 12K ; common include file, SPL source -DIF .COM 4K -DIF .SPL 10K ; SPL source for DIF.COM -EDIT .SPL 10K ; screen editor for PROLOGZ, SPL source -FAMILY .PRO 4K ; Prolog demo program: Family relations -INTEGER .PRO 2K ; Prolog demo program: Integer arithmetic -KNAKE .PRO 2K ; Prolog demo program: Logic puzzle -LINKMT .COM 12K ; Pascal MT+ 5.5 linker -MAIN .SPL 14K ; main module for PROLOGZ, SPL source -MOVE .MAC 4K ; helper functions for PROLOGZ in assembler -MTERRS .TXT 6K ; Pascal MT+ error messages -MTPLUS .000 14K ; Pascal MT+ 5.5 compiler file -MTPLUS .001 12K ; Pascal MT+ 5.5 compiler file -MTPLUS .002 8K ; Pascal MT+ 5.5 compiler file -MTPLUS .003 8K ; Pascal MT+ 5.5 compiler file -MTPLUS .004 18K ; Pascal MT+ 5.5 compiler file -MTPLUS .005 8K ; Pascal MT+ 5.5 compiler file -MTPLUS .006 6K ; Pascal MT+ 5.5 compiler file -MTPLUS .COM 36K ; Pascal MT+ 5.5 compiler -PASCFORM.COM 36K ; Pascal formatter -PASCFORM.PAS 54K ; Pascal formatter source code -PASCFORM.SUB 2K ; create Pascal formatter -PASLIB .ERL 24K ; Pascal MT+ 5.5 run time library -PINST .COM 4K ; terminal installation program for PROLOGZ -PINST .SPL 16K ; terminal installation program for PROLOGZ, - SPL source -PROLOGZ .COM 18K ; PROLOGZ interpreter and screen editor -PROLOGZ .SPL 2K ; PROLOGZ main program, SPL source -PROLOGZ .TXT 40K ; PROLOGZ documentation in German -PROVE .SPL 16K ; backtrack theorem prover for PROLOGZ, SPL source -PZCLEAN .SUB 2K ; PROLOGZ: remove all created ".rel" and ".lst" files -PZLINK .SUB 2K ; PROLOGZ: create PINST, PROLOGZ and personalise the - serial number -PZMAKE .SUB 2K ; PROLOGZ: compiles the sources (you can ignore - any compiler errors) -QUEEN .PRO 2K ; Prolog demo program: N-queens problem -READ .COM 4K -READ .SPL 10K ; SPL source for R.COM -SHOWSEC .COM 4K -SHOWSEC .SPL 6K ; SPL source for SHOWSEC.COM -SPEED .COM 2K ; utility to measure the clock speed of the simulated CPU -SPEED .SPL 2K ; SPL source for SPEED.COM, requires SWLIB.MAC -SPL .COM 38K ; the SPL compiler itself -SPL .TXT 56K ; SPL language and compiler documentation in German -SPLERROR.DAT 12K ; error messages of the compiler (in German) -SPLIB .REL 6K ; SPL runtime library -STDIO . 2K ; include file for SPL programs -SWLIB .MAC 2K ; assembler utility routines needed by SPEED.SPL -SYSCOPY .COM 2K -SYSCOPY .SPL 6K ; SPL source for SYSCOPY.COM -TERMBDOS.SPL 2K ; terminal interface to CP/M for PROLOGZ, SPL source -UTIL .SPL 18K ; utility functions for PROLOGZ, SPL source -WRITE .COM 4K -WRITE .SPL 8K ; SPL source for W.COM -XFORMAT .COM 2K -XFORMAT .SPL 6K ; SPL source for XFORMAT.COM - - -3.5 MITS Disk Extended BASIC Version 4.1 - - This was the commonly used software for serious users of the Altair -computer. It is a powerful (but slow) BASIC with some extended commands to -allow it to access and manage the disk. There was no operating system it -ran under. To boot: - - sim> set cpu 8080 ;Z80 will not work - sim> attach dsk mbasic.dsk - sim> set sio upper - sim> go ff00 - - MEMORY SIZE? [return] - LINEPRINTER? [C return] - HIGHEST DISK NUMBER? [0 return] (0 here = 1 drive system) - NUMBER OF FILES? [3 return] - NUMBER OF RANDOM FILES? [2 return] - - 44041 BYTES FREE - ALTAIR BASIC REV. 4.1 - [DISK EXTENDED VERSION] - COPYRIGHT 1977 BY MITS INC. - OK - [MOUNT 0] - OK - [FILES] - - -3.6 Altair DOS Version 1.0 - - This was long promised but not delivered until it was almost irrelevant. -A short attempted tour will reveal it to be a dog, far inferior to CP/M. To -boot: - - sim> d tracks[0-7] 77 ;set to Altair settings - sim> set cpu altairrom - sim> attach dsk altdos.dsk - sim> set sio upper - sim> go ff00 - - MEMORY SIZE? [return] - INTERRUPTS? N [return] - HIGHEST DISK NUMBER? [0 return] (3 here = 4 drive system) - HOW MANY DISK FILES? [3 return] - HOW MANY RANDOM FILES? [2 return] - - 056449 BYTES AVAILABLE - DOS MONITOR VER 1.0 - COPYRIGHT 1977 BY MITS INC - .[MNT 0] - - .[DIR 0] - - -3.7 Altair Basic 3.2 (4k) - - In order to run the famous 4k Basic, use the following commands (the -trick is to get the Switch Register right). - - sim> set cpu 8080 ;note 4k Basic will not run on a Z80 CPU - sim> set sio upper ;4k Basic does not like lower case letters as input - sim> set sio ansi ;4k Basic produces 8-bit output, strip to seven bits - sim> d sr 8 ;good setting for the Switch Register - sim> load 4kbas.bin 0 ;load it at 0 - sim> go 0 ;and start it - MEMORY SIZE? [return] - TERMINAL WIDTH? [return] - WANT SIN? [Y] - - 61911 BYTES FREE - - BASIC VERSION 3.2 - [4K VERSION] - - OK - - -3.8 Altair 8k Basic - Running 8k Basic follows the procedure for 4k Basic. - - sim> set cpu 8080 ;note 8k Basic will not run on a Z80 CPU - sim> set sio upper ;8k Basic does not like lower case letters as input - sim> set sio ansi ;8k Basic produces 8-bit output, strip to seven bits - sim> d sr 8 ;good setting for the Switch Register - sim> load 8kbas.bin 0 ;load it at 0 - sim> go 0 ;and start it - MEMORY SIZE? [A] - - WRITTEN FOR ROYALTIES BY MICRO-SOFT - - MEMORY SIZE? [return] - TERMINAL WIDTH? [return] - WANT SIN-COS-TAN-ATN? [Y] - - 58756 BYTES FREE - ALTAIR BASIC REV. 4.0 - [EIGHT-K VERSION] - COPYRIGHT 1976 BY MITS INC. - OK - - -3.9 Altair Basic 4.0 - - Execute the following commands to run Altair Extended Basic: - - sim> set sio upper ;Extended Basic does not like lower case letters as input - sim> set sio ansi ;Extended Basic produces 8-bit output, strip to seven bits - sim> d sr 8 ;good setting for the Switch Register - sim> load exbas.bin 0 ;load it at 0 - sim> go 0 ;and start it - 16384 Bytes loaded at 0. - - MEMORY SIZE? [return] - WANT SIN-COS-TAN-ATN? [Y] - - 50606 BYTES FREE - ALTAIR BASIC REV. 4.0 - [EXTENDED VERSION] - COPYRIGHT 1977 BY MITS INC. - OK - - -3.10 Altair Disk Extended Basic Version 300-5-C - - This version of Basic was provided by Scott LaBombard. To execute use the -following commands: - - sim> d tracks[0-7] 77 ;set to Altair settings - sim> at dsk extbas5.dsk - sim> g 0 - - MEMORY SIZE? [return] - LINEPRINTER? [C] - HIGHEST DISK NUMBER? [0] - HOW MANY FILES? [3] - HOW MANY RANDOM FILES? [3] - - 42082 BYTES FREE - - ALTAIR DISK EXTENDED BASIC - VERSION 300-5-C [01NOV78] - COPYRIGHT 1978 BY MITS INC. - - OK - - -4. Special simulator features - - In addition to the regular SIMH features such as PC queue, breakpoints -etc., this simulator supports memory access breakpoints. A memory access -breakpoint is triggered when a pre-defined memory location is accessed -(read, write or update). To set a memory location breakpoint enter - -sim> break -m - - Execution will stop whenever an operation accesses . Note that -a memory access breakpoint is not triggered by fetching code from memory -(this is the job of regular breakpoints). This feature has been implemented -by using the typing facility of the SIMH breakpoints. - - -5. Brief summary of all major changes to the original Altair simulator -- Full support for Z80. CP/M software requiring a Z80 CPU now runs - properly. DDTZ and PROLOGZ are included for demonstration purposes. -- Added banked memory support. -- PC queue implemented. -- Full assembler and dis-assembler support for Z80 and 8080 mnemonics. - Depending on the current setting of the CPU, the appropriate mnemonics - are used. -- The BOOT ROM was changed to fully load the software from disk. The - original code basically loaded a copy of itself from the disk and - executed it. -- ROM and memory size settings are now fully honored. This means that you - cannot write into the ROM or outside the defined RAM (e.g. when the RAM size - was truncated with the SET CPU commands). This feature allows programs which - check for the size of available RAM to run properly (e.g. 4k Basic). In - addition one can enable and disable the ROM which is useful in special cases - (e.g. when testing a new version of the ROM). -- The console can also be used via Telnet. This is useful when a terminal is - needed which supports cursor control such as a VT100. PROLOGZ for example - has a built-in screen editor which works under Telnet. -- Simplified file exchange for CP/M. Using the READ program under CP/M one - can easily import files into CP/M from the regular file system. Note that PIP - does not work properly on non-text files on PTR. -- The WRITE program can be used to transfer files from the CP/M environment to - the regular environment (binary or ASCII transfer). -- The last character read from PTR is always Control-Z (the EOF character for - CP/M). This makes sure that PIP (Peripheral Interchange Program on CP/M) will - terminate properly. -- Fixed a bug in the BIOS warm boot routine which caused CP/M to crash. -- Modified the BIOS for CP/M to support 8 disks. -- Added CP/M 3 banked version as sample software -- Changed from octal to hex -- Made the DSK and SIO device more robust (previously malicious code could - crash the simulator) -- Added memory access break points -- Added periodic timer interrupts (useful for MP/M) -- Added additional consoles (useful for MP/M) -- Added MP/M II banked version as sample software diff --git a/AltairZ80/altairZ80_cpu.c b/AltairZ80/altairZ80_cpu.c deleted file mode 100644 index 0b119432..00000000 --- a/AltairZ80/altairZ80_cpu.c +++ /dev/null @@ -1,5605 +0,0 @@ -/* altairz80_cpu.c: MITS Altair CPU (8080 and Z80) - - Copyright (c) 2002-2003, Peter Schorn - - 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 - PETER SCHORN 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 Peter Schorn shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Peter Schorn. - - Based on work by Charles E Owen (c) 1997 - Code for Z80 CPU from Frank D. Cringle ((c) 1995 under GNU license) -*/ - -#include "altairz80_defs.h" - -#define PCQ_SIZE 64 /* must be 2**n */ -#define PCQ_SIZE_LOG2 6 /* log2 of PCQ_SIZE */ -#define PCQ_MASK (PCQ_SIZE - 1) -#define PCQ_ENTRY(PC) pcq[pcq_p = (pcq_p - 1) & PCQ_MASK] = PC - -/* simulator stop codes */ -#define STOP_HALT 0 /* HALT */ -#define STOP_IBKPT 1 /* breakpoint (program counter) */ -#define STOP_MEM 2 /* breakpoint (memory access) */ -#define STOP_OPCODE 3 /* unknown 8080 or Z80 instruction */ - -/*-------------------------------- definitions for memory space --------------------*/ - -static uint8 M[MAXMEMSIZE][MAXBANKS]; /* RAM which is present */ - -/* two sets of accumulator / flags */ -static uint16 af[2]; -static int af_sel; - -/* two sets of 16-bit registers */ -static struct ddregs { - uint16 bc; - uint16 de; - uint16 hl; -} regs[2]; -static int regs_sel; - -static uint16 ir; -static uint16 ix; -static uint16 iy; -static uint16 sp; -static uint16 pc; -static uint16 IFF; - -#define FLAG_C 1 -#define FLAG_N 2 -#define FLAG_P 4 -#define FLAG_H 16 -#define FLAG_Z 64 -#define FLAG_S 128 - -#define SETFLAG(f,c) AF = (c) ? AF | FLAG_ ## f : AF & ~FLAG_ ## f -#define TSTFLAG(f) ((AF & FLAG_ ## f) != 0) - -#define ldig(x) ((x) & 0xf) -#define hdig(x) (((x) >> 4) & 0xf) -#define lreg(x) ((x) & 0xff) -#define hreg(x) (((x) >> 8) & 0xff) - -#define Setlreg(x, v) x = (((x) & 0xff00) | ((v) & 0xff)) -#define Sethreg(x, v) x = (((x) & 0xff) | (((v) & 0xff) << 8)) - -#define parity(x) parityTable[(x) & 0xff] -/* SetPV and SetPV2 are used to provide correct parity flag semantics for the 8080 in cases - where the Z80 uses the overflow flag -*/ -#define SetPVS(s) ((cpu_unit.flags & UNIT_CHIP) ? (((cbits >> 6) ^ (cbits >> 5)) & 4) : (parity(s))) -#define SetPV (SetPVS(sum)) -#define SetPV2(x) ((cpu_unit.flags & UNIT_CHIP) ? (((temp == (x)) << 2)) : (parity(temp))) - -/* checkCPU8080 must be invoked whenever a Z80 only instruction is executed */ -#define checkCPU8080 \ - if (((cpu_unit.flags & UNIT_CHIP) == 0) && (cpu_unit.flags & UNIT_OPSTOP)) {\ - reason = STOP_OPCODE; \ - goto end_decode; \ - } - -/* checkCPUZ80 must be invoked whenever a non Z80 instruction is executed */ -#define checkCPUZ80 \ - if (cpu_unit.flags & UNIT_OPSTOP) { \ - reason = STOP_OPCODE; \ - goto end_decode; \ - } - -#define POP(x) do { \ - register uint32 y = RAM_pp(SP); \ - x = y + (RAM_pp(SP) << 8); \ -} while (0) - -#define JPC(cond) { \ - tStates += 10; \ - if (cond) { \ - PCQ_ENTRY(PC - 1); \ - PC = GetWORD(PC); \ - } \ - else { \ - PC += 2; \ - } \ -} - -#define CALLC(cond) { \ - if (cond) { \ - register uint32 adrr = GetWORD(PC); \ - CheckBreakWord(SP - 2); \ - PUSH(PC + 2); \ - PCQ_ENTRY(PC - 1); \ - PC = adrr; \ - tStates += 17; \ - } \ - else { \ - sim_brk_pend = FALSE; \ - PC += 2; \ - tStates += 10; \ - } \ -} - -extern int32 sim_int_char; -extern int32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */ -extern int32 sio0s (const int32 port, const int32 io, const int32 data); -extern int32 sio0d (const int32 port, const int32 io, const int32 data); -extern int32 sio1s (const int32 port, const int32 io, const int32 data); -extern int32 sio1d (const int32 port, const int32 io, const int32 data); -extern int32 dsk10 (const int32 port, const int32 io, const int32 data); -extern int32 dsk11 (const int32 port, const int32 io, const int32 data); -extern int32 dsk12 (const int32 port, const int32 io, const int32 data); -extern int32 nulldev (const int32 port, const int32 io, const int32 data); -extern int32 hdsk_io (const int32 port, const int32 io, const int32 data); -extern int32 simh_dev (const int32 port, const int32 io, const int32 data); -extern int32 sr_dev (const int32 port, const int32 io, const int32 data); -extern int32 bootrom[bootrom_size]; -extern char memoryAccessMessage[]; -extern char messageBuffer[]; -extern void printMessage(void); - -/* function prototypes */ -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); -static t_stat cpu_set_rom (UNIT *uptr, int32 value, char *cptr, void *desc); -static t_stat cpu_set_norom (UNIT *uptr, int32 value, char *cptr, void *desc); -static t_stat cpu_set_altairrom (UNIT *uptr, int32 value, char *cptr, void *desc); -static t_stat cpu_set_warnrom (UNIT *uptr, int32 value, char *cptr, void *desc); -static t_stat cpu_set_size (UNIT *uptr, int32 value, char *cptr, void *desc); -static t_stat cpu_set_banked (UNIT *uptr, int32 value, char *cptr, void *desc); -static t_stat cpu_set_nonbanked (UNIT *uptr, int32 value, char *cptr, void *desc); -static void prepareMemoryAccessMessage(t_addr loc); -static void checkROMBoundaries(void); -static void warnUnsuccessfulWriteAttempt(const uint32 Addr); -static uint8 warnUnsuccessfulReadAttempt(const uint32 Addr); -static void reset_memory(void); -static uint32 in(const uint32 Port); -static void out(const uint32 Port, const uint32 Value); -uint8 GetBYTE(register uint32 Addr); -void PutBYTEBasic(const uint32 Addr, const uint32 Bank, const uint32 Value); -void PutBYTE(register uint32 Addr, register uint32 Value); -void PutBYTEForced(register uint32 Addr, register uint32 Value); -int32 addressIsInROM(const uint32 Addr); -int32 addressExists(const uint32 Addr); -static uint16 GetWORD(register uint32 a); -static void PutWORD(register uint32 a, register uint32 v); -int32 sim_instr(void); -int32 install_bootrom(void); -static t_bool sim_brk_lookup (const t_addr bloc, const int32 btyp); -void protect(const int32 l, const int32 h); -static void resetCell(const int32 address, const int32 bank); -void printROMMessage(const uint32 cntROM); - -#ifndef NO_INLINE -/* in case of using inline we need to ensure that the GetBYTE and PutBYTE - are accessible externally */ -uint8 GetBYTEWrapper(register uint32 Addr); -void PutBYTEWrapper(register uint32 Addr, register uint32 Value); -#endif - -/* 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 + UNIT_ROM + UNIT_ALTAIRROM, MAXMEMSIZE) }; - - int32 PCX; /* external view of PC */ - int32 saved_PC = 0; /* program counter */ -static int32 AF_S; /* AF register */ -static int32 BC_S; /* BC register */ -static int32 DE_S; /* DE register */ -static int32 HL_S; /* HL register */ -static int32 IX_S; /* IX register */ -static int32 IY_S; /* IY register */ -static int32 SP_S; /* SP register */ -static int32 AF1_S; /* alternate AF register */ -static int32 BC1_S; /* alternate BC register */ -static int32 DE1_S; /* alternate DE register */ -static int32 HL1_S; /* alternate HL register */ -static int32 IFF_S; /* interrupt Flip Flop */ -static int32 IR_S; /* interrupt (upper)/refresh (lower) register */ - int32 SR = 0; /* switch register */ - int32 bankSelect = 0; /* determines selected memory bank */ - uint32 common = 0xc000; /* addresses >= 'common' are in common memory */ -static uint32 ROMLow = defaultROMLow; /* lowest address of ROM */ -static uint32 ROMHigh = defaultROMHigh; /* highest address of ROM */ -static uint32 previousCapacity= 0; /* safe for previous memory capacity */ -static uint32 clockFrequency = 0; /* in kHz, 0 means as fast as possible */ -static uint32 sliceLength = 10; /* length of time-slice for CPU speed */ - /* adjustment in milliseonds */ -static uint32 executedTStates = 0; /* executed t-states */ -static uint16 pcq[PCQ_SIZE] = { 0 }; /* PC queue */ -static int32 pcq_p = 0; /* PC queue ptr */ -static REG *pcq_r = NULL; /* PC queue reg ptr */ - - -REG cpu_reg[] = { - { HRDATA (PC, saved_PC, 16) }, - { HRDATA (AF, AF_S, 16) }, - { HRDATA (BC, BC_S, 16) }, - { HRDATA (DE, DE_S, 16) }, - { HRDATA (HL, HL_S, 16) }, - { HRDATA (IX, IX_S, 16) }, - { HRDATA (IY, IY_S, 16) }, - { HRDATA (SP, SP_S, 16) }, - { HRDATA (AF1, AF1_S, 16) }, - { HRDATA (BC1, BC1_S, 16) }, - { HRDATA (DE1, DE1_S, 16) }, - { HRDATA (HL1, HL1_S, 16) }, - { GRDATA (IFF, IFF_S, 2, 2, 0) }, - { FLDATA (IR, IR_S, 8) }, - { FLDATA (Z80, cpu_unit.flags, UNIT_V_CHIP), REG_HRO }, - { FLDATA (OPSTOP, cpu_unit.flags, UNIT_V_OPSTOP), REG_HRO }, - { HRDATA (SR, SR, 8) }, - { HRDATA (BANK, bankSelect, MAXBANKSLOG2) }, - { HRDATA (COMMON, common, 16) }, - { HRDATA (ROMLOW, ROMLow, 16) }, - { HRDATA (ROMHIGH, ROMHigh, 16) }, - { DRDATA (CLOCK, clockFrequency, 32) }, - { DRDATA (SLICE, sliceLength, 16) }, - { DRDATA (TSTATES, executedTStates, 32), REG_RO }, - { HRDATA (CAPACITY, cpu_unit.capac, 32), REG_RO }, - { HRDATA (PREVCAP, previousCapacity, 32), REG_RO }, - { BRDATA (PCQ, pcq, 16, 16, PCQ_SIZE), REG_RO + REG_CIRC }, - { DRDATA (PCQP, pcq_p, PCQ_SIZE_LOG2), REG_HRO }, - { HRDATA (WRU, sim_int_char, 8) }, - { NULL } }; - -static MTAB cpu_mod[] = { - { UNIT_CHIP, UNIT_CHIP, "Z80", "Z80", NULL }, - { UNIT_CHIP, 0, "8080", "8080", NULL }, - { UNIT_OPSTOP, UNIT_OPSTOP, "ITRAP", "ITRAP", NULL }, - { UNIT_OPSTOP, 0, "NOITRAP", "NOITRAP", NULL }, - { UNIT_BANKED, UNIT_BANKED, "BANKED", "BANKED", &cpu_set_banked }, - { UNIT_BANKED, 0, "NONBANKED", "NONBANKED", &cpu_set_nonbanked }, - { UNIT_ROM, UNIT_ROM, "ROM", "ROM", &cpu_set_rom }, - { UNIT_ROM, 0, "NOROM", "NOROM", &cpu_set_norom }, - { UNIT_ALTAIRROM, UNIT_ALTAIRROM, "ALTAIRROM", "ALTAIRROM", &cpu_set_altairrom }, - { UNIT_ALTAIRROM, 0, "NOALTAIRROM", "NOALTAIRROM", NULL }, - { UNIT_WARNROM, UNIT_WARNROM, "WARNROM", "WARNROM", &cpu_set_warnrom }, - { UNIT_WARNROM, 0, "NOWARNROM", "NOWARNROM", NULL }, - { UNIT_MSIZE, 4 * KB, NULL, "4K", &cpu_set_size }, - { UNIT_MSIZE, 8 * KB, NULL, "8K", &cpu_set_size }, - { UNIT_MSIZE, 12 * KB, NULL, "12K", &cpu_set_size }, - { UNIT_MSIZE, 16 * KB, NULL, "16K", &cpu_set_size }, - { UNIT_MSIZE, 20 * KB, NULL, "20K", &cpu_set_size }, - { UNIT_MSIZE, 24 * KB, NULL, "24K", &cpu_set_size }, - { UNIT_MSIZE, 28 * KB, NULL, "28K", &cpu_set_size }, - { UNIT_MSIZE, 32 * KB, NULL, "32K", &cpu_set_size }, - { UNIT_MSIZE, 36 * KB, NULL, "36K", &cpu_set_size }, - { UNIT_MSIZE, 40 * KB, NULL, "40K", &cpu_set_size }, - { UNIT_MSIZE, 44 * KB, NULL, "44K", &cpu_set_size }, - { UNIT_MSIZE, 48 * KB, NULL, "48K", &cpu_set_size }, - { UNIT_MSIZE, 52 * KB, NULL, "52K", &cpu_set_size }, - { UNIT_MSIZE, 56 * KB, NULL, "56K", &cpu_set_size }, - { UNIT_MSIZE, 60 * KB, NULL, "60K", &cpu_set_size }, - { UNIT_MSIZE, 64 * KB, NULL, "64K", &cpu_set_size }, - { 0 } }; - -DEVICE cpu_dev = { - "CPU", &cpu_unit, cpu_reg, cpu_mod, - 1, 16, 16, 1, 16, 8, - &cpu_ex, &cpu_dep, &cpu_reset, - NULL, NULL, NULL, NULL, 0, NULL, NULL }; - -/* data structure for IN/OUT instructions */ -struct idev { - int32 (*routine)(const int32, const int32, const int32); -}; - -/* This is the I/O configuration table. There are 255 possible - device addresses, if a device is plugged to a port it's routine - address is here, 'nulldev' means no device is available -*/ -static const struct idev dev_table[256] = { - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 00 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 04 */ - {&dsk10}, {&dsk11}, {&dsk12}, {&nulldev}, /* 08 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 0C */ - {&sio0s}, {&sio0d}, {&sio1s}, {&sio1d}, /* 10 */ - {&sio0s}, {&sio0d}, {&sio0s}, {&sio0d}, /* 14 */ - {&sio0s}, {&sio0d}, {&nulldev}, {&nulldev}, /* 18 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 1C */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 20 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 24 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 28 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 2C */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 30 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 34 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 38 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 3C */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 40 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 44 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 48 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 4C */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 50 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 54 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 58 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 5C */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 60 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 64 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 68 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 6C */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 70 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 74 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 78 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 7C */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 80 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 84 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 88 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 8C */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 90 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 94 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 98 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* 9C */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* A0 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* A4 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* A8 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* AC */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* B0 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* B4 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* B8 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* BC */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* C0 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* C4 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* C8 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* CC */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* D0 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* D4 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* D8 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* DC */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* D0 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* E4 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* E8 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* EC */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* F0 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* F4 */ - {&nulldev}, {&nulldev}, {&nulldev}, {&nulldev}, /* F8 */ - {&nulldev}, {&hdsk_io}, {&simh_dev}, {&sr_dev} /* FC */ -}; - -static INLINE void out(const uint32 Port, const uint32 Value) { - dev_table[Port].routine(Port, 1, Value); -} - -static INLINE uint32 in(const uint32 Port) { - return dev_table[Port].routine(Port, 0, 0); -} - -/* the following tables precompute some common subexpressions - parityTable[i] 0..255 (number of 1's in i is odd) ? 0 : 4 - incTable[i] 0..256! (i & 0xa8) | (((i & 0xff) == 0) << 6) | (((i & 0xf) == 0) << 4) - decTable[i] 0..255 (i & 0xa8) | (((i & 0xff) == 0) << 6) | (((i & 0xf) == 0xf) << 4) | 2 - cbitsTable[i] 0..511 (i & 0x10) | ((i >> 8) & 1) - cbitsDup8Table[i] 0..511 (i & 0x10) | ((i >> 8) & 1) | ((i & 0xff) << 8) | (i & 0xa8) | - (((i & 0xff) == 0) << 6) - cbitsDup16Table[i] 0..511 (i & 0x10) | ((i >> 8) & 1) | (i & 0x28) - cbits2Table[i] 0..511 (i & 0x10) | ((i >> 8) & 1) | 2 - rrcaTable[i] 0..255 ((i & 1) << 15) | ((i >> 1) << 8) | ((i >> 1) & 0x28) | (i & 1) - rraTable[i] 0..255 ((i >> 1) << 8) | ((i >> 1) & 0x28) | (i & 1) - addTable[i] 0..511 ((i & 0xff) << 8) | (i & 0xa8) | (((i & 0xff) == 0) << 6) - subTable[i] 0..255 ((i & 0xff) << 8) | (i & 0xa8) | (((i & 0xff) == 0) << 6) | 2 - andTable[i] 0..255 (i << 8) | (i & 0xa8) | ((i == 0) << 6) | 0x10 | parityTable[i] - xororTable[i] 0..255 (i << 8) | (i & 0xa8) | ((i == 0) << 6) | parityTable[i] - rotateShiftTable[i] 0..255 (i & 0xa8) | (((i & 0xff) == 0) << 6) | parityTable[i & 0xff] - incZ80Table[i] 0..256! (i & 0xa8) | (((i & 0xff) == 0) << 6) | - (((i & 0xf) == 0) << 4) | ((i == 0x80) << 2) - decZ80Table[i] 0..255 (i & 0xa8) | (((i & 0xff) == 0) << 6) | - (((i & 0xf) == 0xf) << 4) | ((i == 0x7f) << 2) | 2 - cbitsZ80Table[i] 0..511 (i & 0x10) | (((i >> 6) ^ (i >> 5)) & 4) | ((i >> 8) & 1) - cbitsZ80DupTable[i] 0..511 (i & 0x10) | (((i >> 6) ^ (i >> 5)) & 4) | - ((i >> 8) & 1) | (i & 0xa8) - cbits2Z80Table[i] 0..511 (i & 0x10) | (((i >> 6) ^ (i >> 5)) & 4) | ((i >> 8) & 1) | 2 - cbits2Z80DupTable[i] 0..511 (i & 0x10) | (((i >> 6) ^ (i >> 5)) & 4) | ((i >> 8) & 1) | 2 | - (i & 0xa8) - negTable[i] 0..255 (((i & 0x0f) != 0) << 4) | ((i == 0x80) << 2) | 2 | (i != 0) - rrdrldTable[i] 0..255 (i << 8) | (i & 0xa8) | (((i & 0xff) == 0) << 6) | parityTable[i] - cpTable[i] 0..255 (i & 0x80) | (((i & 0xff) == 0) << 6) -*/ - -/* parityTable[i] = (number of 1's in i is odd) ? 0 : 4, i = 0..255 */ -static const uint8 parityTable[256] = { - 4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4, - 0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0, - 0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0, - 4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4, - 0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0, - 4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4, - 4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4, - 0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0, - 0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0, - 4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4, - 4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4, - 0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0, - 4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4, - 0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0, - 0,4,4,0,4,0,0,4,4,0,0,4,0,4,4,0, - 4,0,0,4,0,4,4,0,0,4,4,0,4,0,0,4, -}; - -/* incTable[i] = (i & 0xa8) | (((i & 0xff) == 0) << 6) | (((i & 0xf) == 0) << 4), i = 0..256 */ -static const uint8 incTable[257] = { - 80, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, - 16, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, - 48, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 40, 40, 40, - 48, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 40, 40, 40, - 16, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, - 16, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, - 48, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 40, 40, 40, - 48, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 40, 40, 40, - 144,128,128,128,128,128,128,128,136,136,136,136,136,136,136,136, - 144,128,128,128,128,128,128,128,136,136,136,136,136,136,136,136, - 176,160,160,160,160,160,160,160,168,168,168,168,168,168,168,168, - 176,160,160,160,160,160,160,160,168,168,168,168,168,168,168,168, - 144,128,128,128,128,128,128,128,136,136,136,136,136,136,136,136, - 144,128,128,128,128,128,128,128,136,136,136,136,136,136,136,136, - 176,160,160,160,160,160,160,160,168,168,168,168,168,168,168,168, - 176,160,160,160,160,160,160,160,168,168,168,168,168,168,168,168, 80 -}; - -/* decTable[i] = (i & 0xa8) | (((i & 0xff) == 0) << 6) | (((i & 0xf) == 0xf) << 4) | 2, i = 0..255 */ -static const uint8 decTable[256] = { - 66, 2, 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 10, 10, 10, 26, - 2, 2, 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 10, 10, 10, 26, - 34, 34, 34, 34, 34, 34, 34, 34, 42, 42, 42, 42, 42, 42, 42, 58, - 34, 34, 34, 34, 34, 34, 34, 34, 42, 42, 42, 42, 42, 42, 42, 58, - 2, 2, 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 10, 10, 10, 26, - 2, 2, 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 10, 10, 10, 26, - 34, 34, 34, 34, 34, 34, 34, 34, 42, 42, 42, 42, 42, 42, 42, 58, - 34, 34, 34, 34, 34, 34, 34, 34, 42, 42, 42, 42, 42, 42, 42, 58, - 130,130,130,130,130,130,130,130,138,138,138,138,138,138,138,154, - 130,130,130,130,130,130,130,130,138,138,138,138,138,138,138,154, - 162,162,162,162,162,162,162,162,170,170,170,170,170,170,170,186, - 162,162,162,162,162,162,162,162,170,170,170,170,170,170,170,186, - 130,130,130,130,130,130,130,130,138,138,138,138,138,138,138,154, - 130,130,130,130,130,130,130,130,138,138,138,138,138,138,138,154, - 162,162,162,162,162,162,162,162,170,170,170,170,170,170,170,186, - 162,162,162,162,162,162,162,162,170,170,170,170,170,170,170,186, -}; - -/* cbitsTable[i] = (i & 0x10) | ((i >> 8) & 1), i = 0..511 */ -static const uint8 cbitsTable[512] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, -}; - -/* cbitsDup8Table[i] = (i & 0x10) | ((i >> 8) & 1) | ((i & 0xff) << 8) | (i & 0xa8) | - (((i & 0xff) == 0) << 6), i = 0..511 */ -static const uint16 cbitsDup8Table[512] = { - 0x0040,0x0100,0x0200,0x0300,0x0400,0x0500,0x0600,0x0700, - 0x0808,0x0908,0x0a08,0x0b08,0x0c08,0x0d08,0x0e08,0x0f08, - 0x1010,0x1110,0x1210,0x1310,0x1410,0x1510,0x1610,0x1710, - 0x1818,0x1918,0x1a18,0x1b18,0x1c18,0x1d18,0x1e18,0x1f18, - 0x2020,0x2120,0x2220,0x2320,0x2420,0x2520,0x2620,0x2720, - 0x2828,0x2928,0x2a28,0x2b28,0x2c28,0x2d28,0x2e28,0x2f28, - 0x3030,0x3130,0x3230,0x3330,0x3430,0x3530,0x3630,0x3730, - 0x3838,0x3938,0x3a38,0x3b38,0x3c38,0x3d38,0x3e38,0x3f38, - 0x4000,0x4100,0x4200,0x4300,0x4400,0x4500,0x4600,0x4700, - 0x4808,0x4908,0x4a08,0x4b08,0x4c08,0x4d08,0x4e08,0x4f08, - 0x5010,0x5110,0x5210,0x5310,0x5410,0x5510,0x5610,0x5710, - 0x5818,0x5918,0x5a18,0x5b18,0x5c18,0x5d18,0x5e18,0x5f18, - 0x6020,0x6120,0x6220,0x6320,0x6420,0x6520,0x6620,0x6720, - 0x6828,0x6928,0x6a28,0x6b28,0x6c28,0x6d28,0x6e28,0x6f28, - 0x7030,0x7130,0x7230,0x7330,0x7430,0x7530,0x7630,0x7730, - 0x7838,0x7938,0x7a38,0x7b38,0x7c38,0x7d38,0x7e38,0x7f38, - 0x8080,0x8180,0x8280,0x8380,0x8480,0x8580,0x8680,0x8780, - 0x8888,0x8988,0x8a88,0x8b88,0x8c88,0x8d88,0x8e88,0x8f88, - 0x9090,0x9190,0x9290,0x9390,0x9490,0x9590,0x9690,0x9790, - 0x9898,0x9998,0x9a98,0x9b98,0x9c98,0x9d98,0x9e98,0x9f98, - 0xa0a0,0xa1a0,0xa2a0,0xa3a0,0xa4a0,0xa5a0,0xa6a0,0xa7a0, - 0xa8a8,0xa9a8,0xaaa8,0xaba8,0xaca8,0xada8,0xaea8,0xafa8, - 0xb0b0,0xb1b0,0xb2b0,0xb3b0,0xb4b0,0xb5b0,0xb6b0,0xb7b0, - 0xb8b8,0xb9b8,0xbab8,0xbbb8,0xbcb8,0xbdb8,0xbeb8,0xbfb8, - 0xc080,0xc180,0xc280,0xc380,0xc480,0xc580,0xc680,0xc780, - 0xc888,0xc988,0xca88,0xcb88,0xcc88,0xcd88,0xce88,0xcf88, - 0xd090,0xd190,0xd290,0xd390,0xd490,0xd590,0xd690,0xd790, - 0xd898,0xd998,0xda98,0xdb98,0xdc98,0xdd98,0xde98,0xdf98, - 0xe0a0,0xe1a0,0xe2a0,0xe3a0,0xe4a0,0xe5a0,0xe6a0,0xe7a0, - 0xe8a8,0xe9a8,0xeaa8,0xeba8,0xeca8,0xeda8,0xeea8,0xefa8, - 0xf0b0,0xf1b0,0xf2b0,0xf3b0,0xf4b0,0xf5b0,0xf6b0,0xf7b0, - 0xf8b8,0xf9b8,0xfab8,0xfbb8,0xfcb8,0xfdb8,0xfeb8,0xffb8, - 0x0041,0x0101,0x0201,0x0301,0x0401,0x0501,0x0601,0x0701, - 0x0809,0x0909,0x0a09,0x0b09,0x0c09,0x0d09,0x0e09,0x0f09, - 0x1011,0x1111,0x1211,0x1311,0x1411,0x1511,0x1611,0x1711, - 0x1819,0x1919,0x1a19,0x1b19,0x1c19,0x1d19,0x1e19,0x1f19, - 0x2021,0x2121,0x2221,0x2321,0x2421,0x2521,0x2621,0x2721, - 0x2829,0x2929,0x2a29,0x2b29,0x2c29,0x2d29,0x2e29,0x2f29, - 0x3031,0x3131,0x3231,0x3331,0x3431,0x3531,0x3631,0x3731, - 0x3839,0x3939,0x3a39,0x3b39,0x3c39,0x3d39,0x3e39,0x3f39, - 0x4001,0x4101,0x4201,0x4301,0x4401,0x4501,0x4601,0x4701, - 0x4809,0x4909,0x4a09,0x4b09,0x4c09,0x4d09,0x4e09,0x4f09, - 0x5011,0x5111,0x5211,0x5311,0x5411,0x5511,0x5611,0x5711, - 0x5819,0x5919,0x5a19,0x5b19,0x5c19,0x5d19,0x5e19,0x5f19, - 0x6021,0x6121,0x6221,0x6321,0x6421,0x6521,0x6621,0x6721, - 0x6829,0x6929,0x6a29,0x6b29,0x6c29,0x6d29,0x6e29,0x6f29, - 0x7031,0x7131,0x7231,0x7331,0x7431,0x7531,0x7631,0x7731, - 0x7839,0x7939,0x7a39,0x7b39,0x7c39,0x7d39,0x7e39,0x7f39, - 0x8081,0x8181,0x8281,0x8381,0x8481,0x8581,0x8681,0x8781, - 0x8889,0x8989,0x8a89,0x8b89,0x8c89,0x8d89,0x8e89,0x8f89, - 0x9091,0x9191,0x9291,0x9391,0x9491,0x9591,0x9691,0x9791, - 0x9899,0x9999,0x9a99,0x9b99,0x9c99,0x9d99,0x9e99,0x9f99, - 0xa0a1,0xa1a1,0xa2a1,0xa3a1,0xa4a1,0xa5a1,0xa6a1,0xa7a1, - 0xa8a9,0xa9a9,0xaaa9,0xaba9,0xaca9,0xada9,0xaea9,0xafa9, - 0xb0b1,0xb1b1,0xb2b1,0xb3b1,0xb4b1,0xb5b1,0xb6b1,0xb7b1, - 0xb8b9,0xb9b9,0xbab9,0xbbb9,0xbcb9,0xbdb9,0xbeb9,0xbfb9, - 0xc081,0xc181,0xc281,0xc381,0xc481,0xc581,0xc681,0xc781, - 0xc889,0xc989,0xca89,0xcb89,0xcc89,0xcd89,0xce89,0xcf89, - 0xd091,0xd191,0xd291,0xd391,0xd491,0xd591,0xd691,0xd791, - 0xd899,0xd999,0xda99,0xdb99,0xdc99,0xdd99,0xde99,0xdf99, - 0xe0a1,0xe1a1,0xe2a1,0xe3a1,0xe4a1,0xe5a1,0xe6a1,0xe7a1, - 0xe8a9,0xe9a9,0xeaa9,0xeba9,0xeca9,0xeda9,0xeea9,0xefa9, - 0xf0b1,0xf1b1,0xf2b1,0xf3b1,0xf4b1,0xf5b1,0xf6b1,0xf7b1, - 0xf8b9,0xf9b9,0xfab9,0xfbb9,0xfcb9,0xfdb9,0xfeb9,0xffb9, -}; - -/* cbitsDup16Table[i] = (i & 0x10) | ((i >> 8) & 1) | (i & 0x28), i = 0..511 */ -static const uint8 cbitsDup16Table[512] = { - 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, - 16,16,16,16,16,16,16,16,24,24,24,24,24,24,24,24, - 32,32,32,32,32,32,32,32,40,40,40,40,40,40,40,40, - 48,48,48,48,48,48,48,48,56,56,56,56,56,56,56,56, - 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, - 16,16,16,16,16,16,16,16,24,24,24,24,24,24,24,24, - 32,32,32,32,32,32,32,32,40,40,40,40,40,40,40,40, - 48,48,48,48,48,48,48,48,56,56,56,56,56,56,56,56, - 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, - 16,16,16,16,16,16,16,16,24,24,24,24,24,24,24,24, - 32,32,32,32,32,32,32,32,40,40,40,40,40,40,40,40, - 48,48,48,48,48,48,48,48,56,56,56,56,56,56,56,56, - 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, - 16,16,16,16,16,16,16,16,24,24,24,24,24,24,24,24, - 32,32,32,32,32,32,32,32,40,40,40,40,40,40,40,40, - 48,48,48,48,48,48,48,48,56,56,56,56,56,56,56,56, - 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, - 17,17,17,17,17,17,17,17,25,25,25,25,25,25,25,25, - 33,33,33,33,33,33,33,33,41,41,41,41,41,41,41,41, - 49,49,49,49,49,49,49,49,57,57,57,57,57,57,57,57, - 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, - 17,17,17,17,17,17,17,17,25,25,25,25,25,25,25,25, - 33,33,33,33,33,33,33,33,41,41,41,41,41,41,41,41, - 49,49,49,49,49,49,49,49,57,57,57,57,57,57,57,57, - 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, - 17,17,17,17,17,17,17,17,25,25,25,25,25,25,25,25, - 33,33,33,33,33,33,33,33,41,41,41,41,41,41,41,41, - 49,49,49,49,49,49,49,49,57,57,57,57,57,57,57,57, - 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, - 17,17,17,17,17,17,17,17,25,25,25,25,25,25,25,25, - 33,33,33,33,33,33,33,33,41,41,41,41,41,41,41,41, - 49,49,49,49,49,49,49,49,57,57,57,57,57,57,57,57, -}; - -/* cbits2Table[i] = (i & 0x10) | ((i >> 8) & 1) | 2, i = 0..511 */ -static const uint8 cbits2Table[512] = { - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, -}; - -/* rrcaTable[i] = ((i & 1) << 15) | ((i >> 1) << 8) | ((i >> 1) & 0x28) | (i & 1), i = 0..255 */ -static const uint16 rrcaTable[256] = { - 0x0000,0x8001,0x0100,0x8101,0x0200,0x8201,0x0300,0x8301, - 0x0400,0x8401,0x0500,0x8501,0x0600,0x8601,0x0700,0x8701, - 0x0808,0x8809,0x0908,0x8909,0x0a08,0x8a09,0x0b08,0x8b09, - 0x0c08,0x8c09,0x0d08,0x8d09,0x0e08,0x8e09,0x0f08,0x8f09, - 0x1000,0x9001,0x1100,0x9101,0x1200,0x9201,0x1300,0x9301, - 0x1400,0x9401,0x1500,0x9501,0x1600,0x9601,0x1700,0x9701, - 0x1808,0x9809,0x1908,0x9909,0x1a08,0x9a09,0x1b08,0x9b09, - 0x1c08,0x9c09,0x1d08,0x9d09,0x1e08,0x9e09,0x1f08,0x9f09, - 0x2020,0xa021,0x2120,0xa121,0x2220,0xa221,0x2320,0xa321, - 0x2420,0xa421,0x2520,0xa521,0x2620,0xa621,0x2720,0xa721, - 0x2828,0xa829,0x2928,0xa929,0x2a28,0xaa29,0x2b28,0xab29, - 0x2c28,0xac29,0x2d28,0xad29,0x2e28,0xae29,0x2f28,0xaf29, - 0x3020,0xb021,0x3120,0xb121,0x3220,0xb221,0x3320,0xb321, - 0x3420,0xb421,0x3520,0xb521,0x3620,0xb621,0x3720,0xb721, - 0x3828,0xb829,0x3928,0xb929,0x3a28,0xba29,0x3b28,0xbb29, - 0x3c28,0xbc29,0x3d28,0xbd29,0x3e28,0xbe29,0x3f28,0xbf29, - 0x4000,0xc001,0x4100,0xc101,0x4200,0xc201,0x4300,0xc301, - 0x4400,0xc401,0x4500,0xc501,0x4600,0xc601,0x4700,0xc701, - 0x4808,0xc809,0x4908,0xc909,0x4a08,0xca09,0x4b08,0xcb09, - 0x4c08,0xcc09,0x4d08,0xcd09,0x4e08,0xce09,0x4f08,0xcf09, - 0x5000,0xd001,0x5100,0xd101,0x5200,0xd201,0x5300,0xd301, - 0x5400,0xd401,0x5500,0xd501,0x5600,0xd601,0x5700,0xd701, - 0x5808,0xd809,0x5908,0xd909,0x5a08,0xda09,0x5b08,0xdb09, - 0x5c08,0xdc09,0x5d08,0xdd09,0x5e08,0xde09,0x5f08,0xdf09, - 0x6020,0xe021,0x6120,0xe121,0x6220,0xe221,0x6320,0xe321, - 0x6420,0xe421,0x6520,0xe521,0x6620,0xe621,0x6720,0xe721, - 0x6828,0xe829,0x6928,0xe929,0x6a28,0xea29,0x6b28,0xeb29, - 0x6c28,0xec29,0x6d28,0xed29,0x6e28,0xee29,0x6f28,0xef29, - 0x7020,0xf021,0x7120,0xf121,0x7220,0xf221,0x7320,0xf321, - 0x7420,0xf421,0x7520,0xf521,0x7620,0xf621,0x7720,0xf721, - 0x7828,0xf829,0x7928,0xf929,0x7a28,0xfa29,0x7b28,0xfb29, - 0x7c28,0xfc29,0x7d28,0xfd29,0x7e28,0xfe29,0x7f28,0xff29, -}; - -/* rraTable[i] = ((i >> 1) << 8) | ((i >> 1) & 0x28) | (i & 1), i = 0..255 */ -static const uint16 rraTable[256] = { - 0x0000,0x0001,0x0100,0x0101,0x0200,0x0201,0x0300,0x0301, - 0x0400,0x0401,0x0500,0x0501,0x0600,0x0601,0x0700,0x0701, - 0x0808,0x0809,0x0908,0x0909,0x0a08,0x0a09,0x0b08,0x0b09, - 0x0c08,0x0c09,0x0d08,0x0d09,0x0e08,0x0e09,0x0f08,0x0f09, - 0x1000,0x1001,0x1100,0x1101,0x1200,0x1201,0x1300,0x1301, - 0x1400,0x1401,0x1500,0x1501,0x1600,0x1601,0x1700,0x1701, - 0x1808,0x1809,0x1908,0x1909,0x1a08,0x1a09,0x1b08,0x1b09, - 0x1c08,0x1c09,0x1d08,0x1d09,0x1e08,0x1e09,0x1f08,0x1f09, - 0x2020,0x2021,0x2120,0x2121,0x2220,0x2221,0x2320,0x2321, - 0x2420,0x2421,0x2520,0x2521,0x2620,0x2621,0x2720,0x2721, - 0x2828,0x2829,0x2928,0x2929,0x2a28,0x2a29,0x2b28,0x2b29, - 0x2c28,0x2c29,0x2d28,0x2d29,0x2e28,0x2e29,0x2f28,0x2f29, - 0x3020,0x3021,0x3120,0x3121,0x3220,0x3221,0x3320,0x3321, - 0x3420,0x3421,0x3520,0x3521,0x3620,0x3621,0x3720,0x3721, - 0x3828,0x3829,0x3928,0x3929,0x3a28,0x3a29,0x3b28,0x3b29, - 0x3c28,0x3c29,0x3d28,0x3d29,0x3e28,0x3e29,0x3f28,0x3f29, - 0x4000,0x4001,0x4100,0x4101,0x4200,0x4201,0x4300,0x4301, - 0x4400,0x4401,0x4500,0x4501,0x4600,0x4601,0x4700,0x4701, - 0x4808,0x4809,0x4908,0x4909,0x4a08,0x4a09,0x4b08,0x4b09, - 0x4c08,0x4c09,0x4d08,0x4d09,0x4e08,0x4e09,0x4f08,0x4f09, - 0x5000,0x5001,0x5100,0x5101,0x5200,0x5201,0x5300,0x5301, - 0x5400,0x5401,0x5500,0x5501,0x5600,0x5601,0x5700,0x5701, - 0x5808,0x5809,0x5908,0x5909,0x5a08,0x5a09,0x5b08,0x5b09, - 0x5c08,0x5c09,0x5d08,0x5d09,0x5e08,0x5e09,0x5f08,0x5f09, - 0x6020,0x6021,0x6120,0x6121,0x6220,0x6221,0x6320,0x6321, - 0x6420,0x6421,0x6520,0x6521,0x6620,0x6621,0x6720,0x6721, - 0x6828,0x6829,0x6928,0x6929,0x6a28,0x6a29,0x6b28,0x6b29, - 0x6c28,0x6c29,0x6d28,0x6d29,0x6e28,0x6e29,0x6f28,0x6f29, - 0x7020,0x7021,0x7120,0x7121,0x7220,0x7221,0x7320,0x7321, - 0x7420,0x7421,0x7520,0x7521,0x7620,0x7621,0x7720,0x7721, - 0x7828,0x7829,0x7928,0x7929,0x7a28,0x7a29,0x7b28,0x7b29, - 0x7c28,0x7c29,0x7d28,0x7d29,0x7e28,0x7e29,0x7f28,0x7f29, -}; - -/* addTable[i] = ((i & 0xff) << 8) | (i & 0xa8) | (((i & 0xff) == 0) << 6), i = 0..511 */ -static const uint16 addTable[512] = { - 0x0040,0x0100,0x0200,0x0300,0x0400,0x0500,0x0600,0x0700, - 0x0808,0x0908,0x0a08,0x0b08,0x0c08,0x0d08,0x0e08,0x0f08, - 0x1000,0x1100,0x1200,0x1300,0x1400,0x1500,0x1600,0x1700, - 0x1808,0x1908,0x1a08,0x1b08,0x1c08,0x1d08,0x1e08,0x1f08, - 0x2020,0x2120,0x2220,0x2320,0x2420,0x2520,0x2620,0x2720, - 0x2828,0x2928,0x2a28,0x2b28,0x2c28,0x2d28,0x2e28,0x2f28, - 0x3020,0x3120,0x3220,0x3320,0x3420,0x3520,0x3620,0x3720, - 0x3828,0x3928,0x3a28,0x3b28,0x3c28,0x3d28,0x3e28,0x3f28, - 0x4000,0x4100,0x4200,0x4300,0x4400,0x4500,0x4600,0x4700, - 0x4808,0x4908,0x4a08,0x4b08,0x4c08,0x4d08,0x4e08,0x4f08, - 0x5000,0x5100,0x5200,0x5300,0x5400,0x5500,0x5600,0x5700, - 0x5808,0x5908,0x5a08,0x5b08,0x5c08,0x5d08,0x5e08,0x5f08, - 0x6020,0x6120,0x6220,0x6320,0x6420,0x6520,0x6620,0x6720, - 0x6828,0x6928,0x6a28,0x6b28,0x6c28,0x6d28,0x6e28,0x6f28, - 0x7020,0x7120,0x7220,0x7320,0x7420,0x7520,0x7620,0x7720, - 0x7828,0x7928,0x7a28,0x7b28,0x7c28,0x7d28,0x7e28,0x7f28, - 0x8080,0x8180,0x8280,0x8380,0x8480,0x8580,0x8680,0x8780, - 0x8888,0x8988,0x8a88,0x8b88,0x8c88,0x8d88,0x8e88,0x8f88, - 0x9080,0x9180,0x9280,0x9380,0x9480,0x9580,0x9680,0x9780, - 0x9888,0x9988,0x9a88,0x9b88,0x9c88,0x9d88,0x9e88,0x9f88, - 0xa0a0,0xa1a0,0xa2a0,0xa3a0,0xa4a0,0xa5a0,0xa6a0,0xa7a0, - 0xa8a8,0xa9a8,0xaaa8,0xaba8,0xaca8,0xada8,0xaea8,0xafa8, - 0xb0a0,0xb1a0,0xb2a0,0xb3a0,0xb4a0,0xb5a0,0xb6a0,0xb7a0, - 0xb8a8,0xb9a8,0xbaa8,0xbba8,0xbca8,0xbda8,0xbea8,0xbfa8, - 0xc080,0xc180,0xc280,0xc380,0xc480,0xc580,0xc680,0xc780, - 0xc888,0xc988,0xca88,0xcb88,0xcc88,0xcd88,0xce88,0xcf88, - 0xd080,0xd180,0xd280,0xd380,0xd480,0xd580,0xd680,0xd780, - 0xd888,0xd988,0xda88,0xdb88,0xdc88,0xdd88,0xde88,0xdf88, - 0xe0a0,0xe1a0,0xe2a0,0xe3a0,0xe4a0,0xe5a0,0xe6a0,0xe7a0, - 0xe8a8,0xe9a8,0xeaa8,0xeba8,0xeca8,0xeda8,0xeea8,0xefa8, - 0xf0a0,0xf1a0,0xf2a0,0xf3a0,0xf4a0,0xf5a0,0xf6a0,0xf7a0, - 0xf8a8,0xf9a8,0xfaa8,0xfba8,0xfca8,0xfda8,0xfea8,0xffa8, - 0x0040,0x0100,0x0200,0x0300,0x0400,0x0500,0x0600,0x0700, - 0x0808,0x0908,0x0a08,0x0b08,0x0c08,0x0d08,0x0e08,0x0f08, - 0x1000,0x1100,0x1200,0x1300,0x1400,0x1500,0x1600,0x1700, - 0x1808,0x1908,0x1a08,0x1b08,0x1c08,0x1d08,0x1e08,0x1f08, - 0x2020,0x2120,0x2220,0x2320,0x2420,0x2520,0x2620,0x2720, - 0x2828,0x2928,0x2a28,0x2b28,0x2c28,0x2d28,0x2e28,0x2f28, - 0x3020,0x3120,0x3220,0x3320,0x3420,0x3520,0x3620,0x3720, - 0x3828,0x3928,0x3a28,0x3b28,0x3c28,0x3d28,0x3e28,0x3f28, - 0x4000,0x4100,0x4200,0x4300,0x4400,0x4500,0x4600,0x4700, - 0x4808,0x4908,0x4a08,0x4b08,0x4c08,0x4d08,0x4e08,0x4f08, - 0x5000,0x5100,0x5200,0x5300,0x5400,0x5500,0x5600,0x5700, - 0x5808,0x5908,0x5a08,0x5b08,0x5c08,0x5d08,0x5e08,0x5f08, - 0x6020,0x6120,0x6220,0x6320,0x6420,0x6520,0x6620,0x6720, - 0x6828,0x6928,0x6a28,0x6b28,0x6c28,0x6d28,0x6e28,0x6f28, - 0x7020,0x7120,0x7220,0x7320,0x7420,0x7520,0x7620,0x7720, - 0x7828,0x7928,0x7a28,0x7b28,0x7c28,0x7d28,0x7e28,0x7f28, - 0x8080,0x8180,0x8280,0x8380,0x8480,0x8580,0x8680,0x8780, - 0x8888,0x8988,0x8a88,0x8b88,0x8c88,0x8d88,0x8e88,0x8f88, - 0x9080,0x9180,0x9280,0x9380,0x9480,0x9580,0x9680,0x9780, - 0x9888,0x9988,0x9a88,0x9b88,0x9c88,0x9d88,0x9e88,0x9f88, - 0xa0a0,0xa1a0,0xa2a0,0xa3a0,0xa4a0,0xa5a0,0xa6a0,0xa7a0, - 0xa8a8,0xa9a8,0xaaa8,0xaba8,0xaca8,0xada8,0xaea8,0xafa8, - 0xb0a0,0xb1a0,0xb2a0,0xb3a0,0xb4a0,0xb5a0,0xb6a0,0xb7a0, - 0xb8a8,0xb9a8,0xbaa8,0xbba8,0xbca8,0xbda8,0xbea8,0xbfa8, - 0xc080,0xc180,0xc280,0xc380,0xc480,0xc580,0xc680,0xc780, - 0xc888,0xc988,0xca88,0xcb88,0xcc88,0xcd88,0xce88,0xcf88, - 0xd080,0xd180,0xd280,0xd380,0xd480,0xd580,0xd680,0xd780, - 0xd888,0xd988,0xda88,0xdb88,0xdc88,0xdd88,0xde88,0xdf88, - 0xe0a0,0xe1a0,0xe2a0,0xe3a0,0xe4a0,0xe5a0,0xe6a0,0xe7a0, - 0xe8a8,0xe9a8,0xeaa8,0xeba8,0xeca8,0xeda8,0xeea8,0xefa8, - 0xf0a0,0xf1a0,0xf2a0,0xf3a0,0xf4a0,0xf5a0,0xf6a0,0xf7a0, - 0xf8a8,0xf9a8,0xfaa8,0xfba8,0xfca8,0xfda8,0xfea8,0xffa8, -}; - -/* subTable[i] = ((i & 0xff) << 8) | (i & 0xa8) | (((i & 0xff) == 0) << 6) | 2, i = 0..255 */ -static const uint16 subTable[256] = { - 0x0042,0x0102,0x0202,0x0302,0x0402,0x0502,0x0602,0x0702, - 0x080a,0x090a,0x0a0a,0x0b0a,0x0c0a,0x0d0a,0x0e0a,0x0f0a, - 0x1002,0x1102,0x1202,0x1302,0x1402,0x1502,0x1602,0x1702, - 0x180a,0x190a,0x1a0a,0x1b0a,0x1c0a,0x1d0a,0x1e0a,0x1f0a, - 0x2022,0x2122,0x2222,0x2322,0x2422,0x2522,0x2622,0x2722, - 0x282a,0x292a,0x2a2a,0x2b2a,0x2c2a,0x2d2a,0x2e2a,0x2f2a, - 0x3022,0x3122,0x3222,0x3322,0x3422,0x3522,0x3622,0x3722, - 0x382a,0x392a,0x3a2a,0x3b2a,0x3c2a,0x3d2a,0x3e2a,0x3f2a, - 0x4002,0x4102,0x4202,0x4302,0x4402,0x4502,0x4602,0x4702, - 0x480a,0x490a,0x4a0a,0x4b0a,0x4c0a,0x4d0a,0x4e0a,0x4f0a, - 0x5002,0x5102,0x5202,0x5302,0x5402,0x5502,0x5602,0x5702, - 0x580a,0x590a,0x5a0a,0x5b0a,0x5c0a,0x5d0a,0x5e0a,0x5f0a, - 0x6022,0x6122,0x6222,0x6322,0x6422,0x6522,0x6622,0x6722, - 0x682a,0x692a,0x6a2a,0x6b2a,0x6c2a,0x6d2a,0x6e2a,0x6f2a, - 0x7022,0x7122,0x7222,0x7322,0x7422,0x7522,0x7622,0x7722, - 0x782a,0x792a,0x7a2a,0x7b2a,0x7c2a,0x7d2a,0x7e2a,0x7f2a, - 0x8082,0x8182,0x8282,0x8382,0x8482,0x8582,0x8682,0x8782, - 0x888a,0x898a,0x8a8a,0x8b8a,0x8c8a,0x8d8a,0x8e8a,0x8f8a, - 0x9082,0x9182,0x9282,0x9382,0x9482,0x9582,0x9682,0x9782, - 0x988a,0x998a,0x9a8a,0x9b8a,0x9c8a,0x9d8a,0x9e8a,0x9f8a, - 0xa0a2,0xa1a2,0xa2a2,0xa3a2,0xa4a2,0xa5a2,0xa6a2,0xa7a2, - 0xa8aa,0xa9aa,0xaaaa,0xabaa,0xacaa,0xadaa,0xaeaa,0xafaa, - 0xb0a2,0xb1a2,0xb2a2,0xb3a2,0xb4a2,0xb5a2,0xb6a2,0xb7a2, - 0xb8aa,0xb9aa,0xbaaa,0xbbaa,0xbcaa,0xbdaa,0xbeaa,0xbfaa, - 0xc082,0xc182,0xc282,0xc382,0xc482,0xc582,0xc682,0xc782, - 0xc88a,0xc98a,0xca8a,0xcb8a,0xcc8a,0xcd8a,0xce8a,0xcf8a, - 0xd082,0xd182,0xd282,0xd382,0xd482,0xd582,0xd682,0xd782, - 0xd88a,0xd98a,0xda8a,0xdb8a,0xdc8a,0xdd8a,0xde8a,0xdf8a, - 0xe0a2,0xe1a2,0xe2a2,0xe3a2,0xe4a2,0xe5a2,0xe6a2,0xe7a2, - 0xe8aa,0xe9aa,0xeaaa,0xebaa,0xecaa,0xedaa,0xeeaa,0xefaa, - 0xf0a2,0xf1a2,0xf2a2,0xf3a2,0xf4a2,0xf5a2,0xf6a2,0xf7a2, - 0xf8aa,0xf9aa,0xfaaa,0xfbaa,0xfcaa,0xfdaa,0xfeaa,0xffaa, -}; - -/* andTable[i] = (i << 8) | (i & 0xa8) | ((i == 0) << 6) | 0x10 | parityTable[i], i = 0..255 */ -static const uint16 andTable[256] = { - 0x0054,0x0110,0x0210,0x0314,0x0410,0x0514,0x0614,0x0710, - 0x0818,0x091c,0x0a1c,0x0b18,0x0c1c,0x0d18,0x0e18,0x0f1c, - 0x1010,0x1114,0x1214,0x1310,0x1414,0x1510,0x1610,0x1714, - 0x181c,0x1918,0x1a18,0x1b1c,0x1c18,0x1d1c,0x1e1c,0x1f18, - 0x2030,0x2134,0x2234,0x2330,0x2434,0x2530,0x2630,0x2734, - 0x283c,0x2938,0x2a38,0x2b3c,0x2c38,0x2d3c,0x2e3c,0x2f38, - 0x3034,0x3130,0x3230,0x3334,0x3430,0x3534,0x3634,0x3730, - 0x3838,0x393c,0x3a3c,0x3b38,0x3c3c,0x3d38,0x3e38,0x3f3c, - 0x4010,0x4114,0x4214,0x4310,0x4414,0x4510,0x4610,0x4714, - 0x481c,0x4918,0x4a18,0x4b1c,0x4c18,0x4d1c,0x4e1c,0x4f18, - 0x5014,0x5110,0x5210,0x5314,0x5410,0x5514,0x5614,0x5710, - 0x5818,0x591c,0x5a1c,0x5b18,0x5c1c,0x5d18,0x5e18,0x5f1c, - 0x6034,0x6130,0x6230,0x6334,0x6430,0x6534,0x6634,0x6730, - 0x6838,0x693c,0x6a3c,0x6b38,0x6c3c,0x6d38,0x6e38,0x6f3c, - 0x7030,0x7134,0x7234,0x7330,0x7434,0x7530,0x7630,0x7734, - 0x783c,0x7938,0x7a38,0x7b3c,0x7c38,0x7d3c,0x7e3c,0x7f38, - 0x8090,0x8194,0x8294,0x8390,0x8494,0x8590,0x8690,0x8794, - 0x889c,0x8998,0x8a98,0x8b9c,0x8c98,0x8d9c,0x8e9c,0x8f98, - 0x9094,0x9190,0x9290,0x9394,0x9490,0x9594,0x9694,0x9790, - 0x9898,0x999c,0x9a9c,0x9b98,0x9c9c,0x9d98,0x9e98,0x9f9c, - 0xa0b4,0xa1b0,0xa2b0,0xa3b4,0xa4b0,0xa5b4,0xa6b4,0xa7b0, - 0xa8b8,0xa9bc,0xaabc,0xabb8,0xacbc,0xadb8,0xaeb8,0xafbc, - 0xb0b0,0xb1b4,0xb2b4,0xb3b0,0xb4b4,0xb5b0,0xb6b0,0xb7b4, - 0xb8bc,0xb9b8,0xbab8,0xbbbc,0xbcb8,0xbdbc,0xbebc,0xbfb8, - 0xc094,0xc190,0xc290,0xc394,0xc490,0xc594,0xc694,0xc790, - 0xc898,0xc99c,0xca9c,0xcb98,0xcc9c,0xcd98,0xce98,0xcf9c, - 0xd090,0xd194,0xd294,0xd390,0xd494,0xd590,0xd690,0xd794, - 0xd89c,0xd998,0xda98,0xdb9c,0xdc98,0xdd9c,0xde9c,0xdf98, - 0xe0b0,0xe1b4,0xe2b4,0xe3b0,0xe4b4,0xe5b0,0xe6b0,0xe7b4, - 0xe8bc,0xe9b8,0xeab8,0xebbc,0xecb8,0xedbc,0xeebc,0xefb8, - 0xf0b4,0xf1b0,0xf2b0,0xf3b4,0xf4b0,0xf5b4,0xf6b4,0xf7b0, - 0xf8b8,0xf9bc,0xfabc,0xfbb8,0xfcbc,0xfdb8,0xfeb8,0xffbc, -}; - -/* xororTable[i] = (i << 8) | (i & 0xa8) | ((i == 0) << 6) | parityTable[i], i = 0..255 */ -static const uint16 xororTable[256] = { - 0x0044,0x0100,0x0200,0x0304,0x0400,0x0504,0x0604,0x0700, - 0x0808,0x090c,0x0a0c,0x0b08,0x0c0c,0x0d08,0x0e08,0x0f0c, - 0x1000,0x1104,0x1204,0x1300,0x1404,0x1500,0x1600,0x1704, - 0x180c,0x1908,0x1a08,0x1b0c,0x1c08,0x1d0c,0x1e0c,0x1f08, - 0x2020,0x2124,0x2224,0x2320,0x2424,0x2520,0x2620,0x2724, - 0x282c,0x2928,0x2a28,0x2b2c,0x2c28,0x2d2c,0x2e2c,0x2f28, - 0x3024,0x3120,0x3220,0x3324,0x3420,0x3524,0x3624,0x3720, - 0x3828,0x392c,0x3a2c,0x3b28,0x3c2c,0x3d28,0x3e28,0x3f2c, - 0x4000,0x4104,0x4204,0x4300,0x4404,0x4500,0x4600,0x4704, - 0x480c,0x4908,0x4a08,0x4b0c,0x4c08,0x4d0c,0x4e0c,0x4f08, - 0x5004,0x5100,0x5200,0x5304,0x5400,0x5504,0x5604,0x5700, - 0x5808,0x590c,0x5a0c,0x5b08,0x5c0c,0x5d08,0x5e08,0x5f0c, - 0x6024,0x6120,0x6220,0x6324,0x6420,0x6524,0x6624,0x6720, - 0x6828,0x692c,0x6a2c,0x6b28,0x6c2c,0x6d28,0x6e28,0x6f2c, - 0x7020,0x7124,0x7224,0x7320,0x7424,0x7520,0x7620,0x7724, - 0x782c,0x7928,0x7a28,0x7b2c,0x7c28,0x7d2c,0x7e2c,0x7f28, - 0x8080,0x8184,0x8284,0x8380,0x8484,0x8580,0x8680,0x8784, - 0x888c,0x8988,0x8a88,0x8b8c,0x8c88,0x8d8c,0x8e8c,0x8f88, - 0x9084,0x9180,0x9280,0x9384,0x9480,0x9584,0x9684,0x9780, - 0x9888,0x998c,0x9a8c,0x9b88,0x9c8c,0x9d88,0x9e88,0x9f8c, - 0xa0a4,0xa1a0,0xa2a0,0xa3a4,0xa4a0,0xa5a4,0xa6a4,0xa7a0, - 0xa8a8,0xa9ac,0xaaac,0xaba8,0xacac,0xada8,0xaea8,0xafac, - 0xb0a0,0xb1a4,0xb2a4,0xb3a0,0xb4a4,0xb5a0,0xb6a0,0xb7a4, - 0xb8ac,0xb9a8,0xbaa8,0xbbac,0xbca8,0xbdac,0xbeac,0xbfa8, - 0xc084,0xc180,0xc280,0xc384,0xc480,0xc584,0xc684,0xc780, - 0xc888,0xc98c,0xca8c,0xcb88,0xcc8c,0xcd88,0xce88,0xcf8c, - 0xd080,0xd184,0xd284,0xd380,0xd484,0xd580,0xd680,0xd784, - 0xd88c,0xd988,0xda88,0xdb8c,0xdc88,0xdd8c,0xde8c,0xdf88, - 0xe0a0,0xe1a4,0xe2a4,0xe3a0,0xe4a4,0xe5a0,0xe6a0,0xe7a4, - 0xe8ac,0xe9a8,0xeaa8,0xebac,0xeca8,0xedac,0xeeac,0xefa8, - 0xf0a4,0xf1a0,0xf2a0,0xf3a4,0xf4a0,0xf5a4,0xf6a4,0xf7a0, - 0xf8a8,0xf9ac,0xfaac,0xfba8,0xfcac,0xfda8,0xfea8,0xffac, -}; - -/* rotateShiftTable[i] = (i & 0xa8) | (((i & 0xff) == 0) << 6) | parityTable[i & 0xff], i = 0..255 */ -static const uint8 rotateShiftTable[256] = { - 68, 0, 0, 4, 0, 4, 4, 0, 8, 12, 12, 8, 12, 8, 8, 12, - 0, 4, 4, 0, 4, 0, 0, 4, 12, 8, 8, 12, 8, 12, 12, 8, - 32, 36, 36, 32, 36, 32, 32, 36, 44, 40, 40, 44, 40, 44, 44, 40, - 36, 32, 32, 36, 32, 36, 36, 32, 40, 44, 44, 40, 44, 40, 40, 44, - 0, 4, 4, 0, 4, 0, 0, 4, 12, 8, 8, 12, 8, 12, 12, 8, - 4, 0, 0, 4, 0, 4, 4, 0, 8, 12, 12, 8, 12, 8, 8, 12, - 36, 32, 32, 36, 32, 36, 36, 32, 40, 44, 44, 40, 44, 40, 40, 44, - 32, 36, 36, 32, 36, 32, 32, 36, 44, 40, 40, 44, 40, 44, 44, 40, - 128,132,132,128,132,128,128,132,140,136,136,140,136,140,140,136, - 132,128,128,132,128,132,132,128,136,140,140,136,140,136,136,140, - 164,160,160,164,160,164,164,160,168,172,172,168,172,168,168,172, - 160,164,164,160,164,160,160,164,172,168,168,172,168,172,172,168, - 132,128,128,132,128,132,132,128,136,140,140,136,140,136,136,140, - 128,132,132,128,132,128,128,132,140,136,136,140,136,140,140,136, - 160,164,164,160,164,160,160,164,172,168,168,172,168,172,172,168, - 164,160,160,164,160,164,164,160,168,172,172,168,172,168,168,172, -}; - -/* incZ80Table[i] = (i & 0xa8) | (((i & 0xff) == 0) << 6) | - (((i & 0xf) == 0) << 4) | ((i == 0x80) << 2), i = 0..256 */ -static const uint8 incZ80Table[257] = { - 80, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, - 16, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, - 48, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 40, 40, 40, - 48, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 40, 40, 40, - 16, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, - 16, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, - 48, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 40, 40, 40, - 48, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 40, 40, 40, - 148,128,128,128,128,128,128,128,136,136,136,136,136,136,136,136, - 144,128,128,128,128,128,128,128,136,136,136,136,136,136,136,136, - 176,160,160,160,160,160,160,160,168,168,168,168,168,168,168,168, - 176,160,160,160,160,160,160,160,168,168,168,168,168,168,168,168, - 144,128,128,128,128,128,128,128,136,136,136,136,136,136,136,136, - 144,128,128,128,128,128,128,128,136,136,136,136,136,136,136,136, - 176,160,160,160,160,160,160,160,168,168,168,168,168,168,168,168, - 176,160,160,160,160,160,160,160,168,168,168,168,168,168,168,168, 80, -}; - -/* decZ80Table[i] = (i & 0xa8) | (((i & 0xff) == 0) << 6) | - (((i & 0xf) == 0xf) << 4) | ((i == 0x7f) << 2) | 2, i = 0..255 */ -static const uint8 decZ80Table[256] = { - 66, 2, 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 10, 10, 10, 26, - 2, 2, 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 10, 10, 10, 26, - 34, 34, 34, 34, 34, 34, 34, 34, 42, 42, 42, 42, 42, 42, 42, 58, - 34, 34, 34, 34, 34, 34, 34, 34, 42, 42, 42, 42, 42, 42, 42, 58, - 2, 2, 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 10, 10, 10, 26, - 2, 2, 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 10, 10, 10, 26, - 34, 34, 34, 34, 34, 34, 34, 34, 42, 42, 42, 42, 42, 42, 42, 58, - 34, 34, 34, 34, 34, 34, 34, 34, 42, 42, 42, 42, 42, 42, 42, 62, - 130,130,130,130,130,130,130,130,138,138,138,138,138,138,138,154, - 130,130,130,130,130,130,130,130,138,138,138,138,138,138,138,154, - 162,162,162,162,162,162,162,162,170,170,170,170,170,170,170,186, - 162,162,162,162,162,162,162,162,170,170,170,170,170,170,170,186, - 130,130,130,130,130,130,130,130,138,138,138,138,138,138,138,154, - 130,130,130,130,130,130,130,130,138,138,138,138,138,138,138,154, - 162,162,162,162,162,162,162,162,170,170,170,170,170,170,170,186, - 162,162,162,162,162,162,162,162,170,170,170,170,170,170,170,186, -}; - -/* cbitsZ80Table[i] = (i & 0x10) | (((i >> 6) ^ (i >> 5)) & 4) | ((i >> 8) & 1), i = 0..511 */ -static const uint8 cbitsZ80Table[512] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, -}; - -/* cbitsZ80DupTable[i] = (i & 0x10) | (((i >> 6) ^ (i >> 5)) & 4) | - ((i >> 8) & 1) | (i & 0xa8), i = 0..511 */ -static const uint8 cbitsZ80DupTable[512] = { - 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, - 16, 16, 16, 16, 16, 16, 16, 16, 24, 24, 24, 24, 24, 24, 24, 24, - 32, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 40, 40, 40, - 48, 48, 48, 48, 48, 48, 48, 48, 56, 56, 56, 56, 56, 56, 56, 56, - 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, - 16, 16, 16, 16, 16, 16, 16, 16, 24, 24, 24, 24, 24, 24, 24, 24, - 32, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 40, 40, 40, - 48, 48, 48, 48, 48, 48, 48, 48, 56, 56, 56, 56, 56, 56, 56, 56, - 132,132,132,132,132,132,132,132,140,140,140,140,140,140,140,140, - 148,148,148,148,148,148,148,148,156,156,156,156,156,156,156,156, - 164,164,164,164,164,164,164,164,172,172,172,172,172,172,172,172, - 180,180,180,180,180,180,180,180,188,188,188,188,188,188,188,188, - 132,132,132,132,132,132,132,132,140,140,140,140,140,140,140,140, - 148,148,148,148,148,148,148,148,156,156,156,156,156,156,156,156, - 164,164,164,164,164,164,164,164,172,172,172,172,172,172,172,172, - 180,180,180,180,180,180,180,180,188,188,188,188,188,188,188,188, - 5, 5, 5, 5, 5, 5, 5, 5, 13, 13, 13, 13, 13, 13, 13, 13, - 21, 21, 21, 21, 21, 21, 21, 21, 29, 29, 29, 29, 29, 29, 29, 29, - 37, 37, 37, 37, 37, 37, 37, 37, 45, 45, 45, 45, 45, 45, 45, 45, - 53, 53, 53, 53, 53, 53, 53, 53, 61, 61, 61, 61, 61, 61, 61, 61, - 5, 5, 5, 5, 5, 5, 5, 5, 13, 13, 13, 13, 13, 13, 13, 13, - 21, 21, 21, 21, 21, 21, 21, 21, 29, 29, 29, 29, 29, 29, 29, 29, - 37, 37, 37, 37, 37, 37, 37, 37, 45, 45, 45, 45, 45, 45, 45, 45, - 53, 53, 53, 53, 53, 53, 53, 53, 61, 61, 61, 61, 61, 61, 61, 61, - 129,129,129,129,129,129,129,129,137,137,137,137,137,137,137,137, - 145,145,145,145,145,145,145,145,153,153,153,153,153,153,153,153, - 161,161,161,161,161,161,161,161,169,169,169,169,169,169,169,169, - 177,177,177,177,177,177,177,177,185,185,185,185,185,185,185,185, - 129,129,129,129,129,129,129,129,137,137,137,137,137,137,137,137, - 145,145,145,145,145,145,145,145,153,153,153,153,153,153,153,153, - 161,161,161,161,161,161,161,161,169,169,169,169,169,169,169,169, - 177,177,177,177,177,177,177,177,185,185,185,185,185,185,185,185, -}; - -/* cbits2Z80Table[i] = (i & 0x10) | (((i >> 6) ^ (i >> 5)) & 4) | ((i >> 8) & 1) | 2, i = 0..511 */ -static const uint8 cbits2Z80Table[512] = { - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, -}; - -/* cbits2Z80DupTable[i] = (i & 0x10) | (((i >> 6) ^ (i >> 5)) & 4) | ((i >> 8) & 1) | 2 | - (i & 0xa8), i = 0..511 */ -static const uint8 cbits2Z80DupTable[512] = { - 2, 2, 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 10, 10, 10, 10, - 18, 18, 18, 18, 18, 18, 18, 18, 26, 26, 26, 26, 26, 26, 26, 26, - 34, 34, 34, 34, 34, 34, 34, 34, 42, 42, 42, 42, 42, 42, 42, 42, - 50, 50, 50, 50, 50, 50, 50, 50, 58, 58, 58, 58, 58, 58, 58, 58, - 2, 2, 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 10, 10, 10, 10, - 18, 18, 18, 18, 18, 18, 18, 18, 26, 26, 26, 26, 26, 26, 26, 26, - 34, 34, 34, 34, 34, 34, 34, 34, 42, 42, 42, 42, 42, 42, 42, 42, - 50, 50, 50, 50, 50, 50, 50, 50, 58, 58, 58, 58, 58, 58, 58, 58, - 134,134,134,134,134,134,134,134,142,142,142,142,142,142,142,142, - 150,150,150,150,150,150,150,150,158,158,158,158,158,158,158,158, - 166,166,166,166,166,166,166,166,174,174,174,174,174,174,174,174, - 182,182,182,182,182,182,182,182,190,190,190,190,190,190,190,190, - 134,134,134,134,134,134,134,134,142,142,142,142,142,142,142,142, - 150,150,150,150,150,150,150,150,158,158,158,158,158,158,158,158, - 166,166,166,166,166,166,166,166,174,174,174,174,174,174,174,174, - 182,182,182,182,182,182,182,182,190,190,190,190,190,190,190,190, - 7, 7, 7, 7, 7, 7, 7, 7, 15, 15, 15, 15, 15, 15, 15, 15, - 23, 23, 23, 23, 23, 23, 23, 23, 31, 31, 31, 31, 31, 31, 31, 31, - 39, 39, 39, 39, 39, 39, 39, 39, 47, 47, 47, 47, 47, 47, 47, 47, - 55, 55, 55, 55, 55, 55, 55, 55, 63, 63, 63, 63, 63, 63, 63, 63, - 7, 7, 7, 7, 7, 7, 7, 7, 15, 15, 15, 15, 15, 15, 15, 15, - 23, 23, 23, 23, 23, 23, 23, 23, 31, 31, 31, 31, 31, 31, 31, 31, - 39, 39, 39, 39, 39, 39, 39, 39, 47, 47, 47, 47, 47, 47, 47, 47, - 55, 55, 55, 55, 55, 55, 55, 55, 63, 63, 63, 63, 63, 63, 63, 63, - 131,131,131,131,131,131,131,131,139,139,139,139,139,139,139,139, - 147,147,147,147,147,147,147,147,155,155,155,155,155,155,155,155, - 163,163,163,163,163,163,163,163,171,171,171,171,171,171,171,171, - 179,179,179,179,179,179,179,179,187,187,187,187,187,187,187,187, - 131,131,131,131,131,131,131,131,139,139,139,139,139,139,139,139, - 147,147,147,147,147,147,147,147,155,155,155,155,155,155,155,155, - 163,163,163,163,163,163,163,163,171,171,171,171,171,171,171,171, - 179,179,179,179,179,179,179,179,187,187,187,187,187,187,187,187, -}; - -/* negTable[i] = (((i & 0x0f) != 0) << 4) | ((i == 0x80) << 2) | 2 | (i != 0), i = 0..255 */ -static const uint8 negTable[256] = { - 2,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 7,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, - 3,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, -}; - -/* rrdrldTable[i] = (i << 8) | (i & 0xa8) | (((i & 0xff) == 0) << 6) | parityTable[i], i = 0..255 */ -static const uint16 rrdrldTable[256] = { - 0x0044,0x0100,0x0200,0x0304,0x0400,0x0504,0x0604,0x0700, - 0x0808,0x090c,0x0a0c,0x0b08,0x0c0c,0x0d08,0x0e08,0x0f0c, - 0x1000,0x1104,0x1204,0x1300,0x1404,0x1500,0x1600,0x1704, - 0x180c,0x1908,0x1a08,0x1b0c,0x1c08,0x1d0c,0x1e0c,0x1f08, - 0x2020,0x2124,0x2224,0x2320,0x2424,0x2520,0x2620,0x2724, - 0x282c,0x2928,0x2a28,0x2b2c,0x2c28,0x2d2c,0x2e2c,0x2f28, - 0x3024,0x3120,0x3220,0x3324,0x3420,0x3524,0x3624,0x3720, - 0x3828,0x392c,0x3a2c,0x3b28,0x3c2c,0x3d28,0x3e28,0x3f2c, - 0x4000,0x4104,0x4204,0x4300,0x4404,0x4500,0x4600,0x4704, - 0x480c,0x4908,0x4a08,0x4b0c,0x4c08,0x4d0c,0x4e0c,0x4f08, - 0x5004,0x5100,0x5200,0x5304,0x5400,0x5504,0x5604,0x5700, - 0x5808,0x590c,0x5a0c,0x5b08,0x5c0c,0x5d08,0x5e08,0x5f0c, - 0x6024,0x6120,0x6220,0x6324,0x6420,0x6524,0x6624,0x6720, - 0x6828,0x692c,0x6a2c,0x6b28,0x6c2c,0x6d28,0x6e28,0x6f2c, - 0x7020,0x7124,0x7224,0x7320,0x7424,0x7520,0x7620,0x7724, - 0x782c,0x7928,0x7a28,0x7b2c,0x7c28,0x7d2c,0x7e2c,0x7f28, - 0x8080,0x8184,0x8284,0x8380,0x8484,0x8580,0x8680,0x8784, - 0x888c,0x8988,0x8a88,0x8b8c,0x8c88,0x8d8c,0x8e8c,0x8f88, - 0x9084,0x9180,0x9280,0x9384,0x9480,0x9584,0x9684,0x9780, - 0x9888,0x998c,0x9a8c,0x9b88,0x9c8c,0x9d88,0x9e88,0x9f8c, - 0xa0a4,0xa1a0,0xa2a0,0xa3a4,0xa4a0,0xa5a4,0xa6a4,0xa7a0, - 0xa8a8,0xa9ac,0xaaac,0xaba8,0xacac,0xada8,0xaea8,0xafac, - 0xb0a0,0xb1a4,0xb2a4,0xb3a0,0xb4a4,0xb5a0,0xb6a0,0xb7a4, - 0xb8ac,0xb9a8,0xbaa8,0xbbac,0xbca8,0xbdac,0xbeac,0xbfa8, - 0xc084,0xc180,0xc280,0xc384,0xc480,0xc584,0xc684,0xc780, - 0xc888,0xc98c,0xca8c,0xcb88,0xcc8c,0xcd88,0xce88,0xcf8c, - 0xd080,0xd184,0xd284,0xd380,0xd484,0xd580,0xd680,0xd784, - 0xd88c,0xd988,0xda88,0xdb8c,0xdc88,0xdd8c,0xde8c,0xdf88, - 0xe0a0,0xe1a4,0xe2a4,0xe3a0,0xe4a4,0xe5a0,0xe6a0,0xe7a4, - 0xe8ac,0xe9a8,0xeaa8,0xebac,0xeca8,0xedac,0xeeac,0xefa8, - 0xf0a4,0xf1a0,0xf2a0,0xf3a4,0xf4a0,0xf5a4,0xf6a4,0xf7a0, - 0xf8a8,0xf9ac,0xfaac,0xfba8,0xfcac,0xfda8,0xfea8,0xffac, -}; - -/* cpTable[i] = (i & 0x80) | (((i & 0xff) == 0) << 6), i = 0..255 */ -static const uint8 cpTable[256] = { - 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, - 128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, - 128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, - 128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, - 128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, - 128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, - 128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, - 128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, -}; - -/* remove comments to generate table contents -static void altairz80_init(void); -void (*sim_vm_init) (void) = &altairz80_init; -static void altairz80_init(void) { -*/ -/* parityTable */ -/* - uint32 i, v; - for (i = 0; i < 256; i++) { - v = ((i & 1) + ((i & 2) >> 1) + ((i & 4) >> 2) + ((i & 8) >> 3) + - ((i & 16) >> 4) + ((i & 32) >> 5) + ((i & 64) >> 6) + ((i & 128) >> 7)) % 2 ? 0 : 4; - printf("%1d,", v); - if ( ((i+1) & 0xf) == 0) { - printf("\n"); - } - } -*/ -/* incTable */ -/* - uint32 temp, v; - for (temp = 0; temp <= 256; temp++) { - v = (temp & 0xa8) | (((temp & 0xff) == 0) << 6) | (((temp & 0xf) == 0) << 4); - printf("%3d,", v); - if ( ((temp+1) & 0xf) == 0) { - printf("\n"); - } - } -*/ -/* decTable */ -/* - uint32 temp, v; - for (temp = 0; temp < 256; temp++) { - v = (temp & 0xa8) | (((temp & 0xff) == 0) << 6) | (((temp & 0xf) == 0xf) << 4) | 2; - printf("%3d,", v); - if ( ((temp+1) & 0xf) == 0) { - printf("\n"); - } - } -*/ -/* cbitsTable */ -/* - uint32 cbits, v; - for (cbits = 0; cbits < 512; cbits++) { - v = (cbits & 0x10) | ((cbits >> 8) & 1); - printf("%2d,", v); - if ( ((cbits+1) & 0xf) == 0) { - printf("\n"); - } - } -*/ -/* cbitsDup8Table */ -/* - uint32 cbits, v; - for (cbits = 0; cbits < 512; cbits++) { - v = (cbits & 0x10) | ((cbits >> 8) & 1) | ((cbits & 0xff) << 8) | (cbits & 0xa8) | (((cbits & 0xff) == 0) << 6); - printf("0x%04x,", v); - if ( ((cbits+1) & 0x7) == 0) { - printf("\n"); - } - } -*/ -/* cbitsDup16Table */ -/* - uint32 cbits, v; - for (cbits = 0; cbits < 512; cbits++) { - v = (cbits & 0x10) | ((cbits >> 8) & 1) | (cbits & 0x28); - printf("%2d,", v); - if ( ((cbits+1) & 0xf) == 0) { - printf("\n"); - } - } -*/ -/* cbits2Table */ -/* - uint32 cbits, v; - for (cbits = 0; cbits < 512; cbits++) { - v = (cbits & 0x10) | ((cbits >> 8) & 1) | 2; - printf("%2d,", v); - if ( ((cbits+1) & 0xf) == 0) { - printf("\n"); - } - } -*/ -/* rrcaTable */ -/* - uint32 temp, sum, v; - for (temp = 0; temp < 256; temp++) { - sum = temp >> 1; - v = ((temp & 1) << 15) | (sum << 8) | (sum & 0x28) | (temp & 1); - printf("0x%04x,", v); - if ( ((temp+1) & 0x7) == 0) { - printf("\n"); - } - } -*/ -/* rraTable */ -/* - uint32 temp, sum, v; - for (temp = 0; temp < 256; temp++) { - sum = temp >> 1; - v = (sum << 8) | (sum & 0x28) | (temp & 1); - printf("0x%04x,", v); - if ( ((temp+1) & 0x7) == 0) { - printf("\n"); - } - } -*/ -/* addTable */ -/* - uint32 sum, v; - for (sum = 0; sum < 512; sum++) { - v = ((sum & 0xff) << 8) | (sum & 0xa8) | (((sum & 0xff) == 0) << 6); - printf("0x%04x,", v); - if ( ((sum+1) & 0x7) == 0) { - printf("\n"); - } - } -*/ -/* subTable */ -/* - uint32 sum, v; - for (sum = 0; sum < 256; sum++) { - v = ((sum & 0xff) << 8) | (sum & 0xa8) | (((sum & 0xff) == 0) << 6) | 2; - printf("0x%04x,", v); - if ( ((sum+1) & 0x7) == 0) { - printf("\n"); - } - } -*/ -/* andTable */ -/* - uint32 sum, v; - for (sum = 0; sum < 256; sum++) { - v = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | 0x10 | parityTable[sum]; - printf("0x%04x,", v); - if ( ((sum+1) & 0x7) == 0) { - printf("\n"); - } - } -*/ -/* xororTable */ -/* - uint32 sum, v; - for (sum = 0; sum < 256; sum++) { - v = (sum << 8) | (sum & 0xa8) | ((sum == 0) << 6) | parityTable[sum]; - printf("0x%04x,", v); - if ( ((sum+1) & 0x7) == 0) { - printf("\n"); - } - } -*/ -/* rotateShiftTable */ -/* - uint32 temp, v; - for (temp = 0; temp < 256; temp++) { - v = (temp & 0xa8) | (((temp & 0xff) == 0) << 6) | parity(temp); - printf("%3d,", v); - if ( ((temp+1) & 0xf) == 0) { - printf("\n"); - } - } -*/ -/* incZ80Table */ -/* - uint32 temp, v; - for (temp = 0; temp < 256; temp++) { - v = (temp & 0xa8) | (((temp & 0xff) == 0) << 6) | - (((temp & 0xf) == 0) << 4) | ((temp == 0x80) << 2); - printf("%3d,", v); - if ( ((temp+1) & 0xf) == 0) { - printf("\n"); - } - } -*/ -/* decZ80Table */ -/* - uint32 temp, v; - for (temp = 0; temp < 256; temp++) { - v = (temp & 0xa8) | (((temp & 0xff) == 0) << 6) | - (((temp & 0xf) == 0xf) << 4) | ((temp == 0x7f) << 2) | 2; - printf("%3d,", v); - if ( ((temp+1) & 0xf) == 0) { - printf("\n"); - } - } -*/ -/* cbitsZ80Table */ -/* - uint32 cbits, v; - for (cbits = 0; cbits < 512; cbits++) { - v = (cbits & 0x10) | (((cbits >> 6) ^ (cbits >> 5)) & 4) | - ((cbits >> 8) & 1); - printf("%2d,", v); - if ( ((cbits+1) & 0xf) == 0) { - printf("\n"); - } - } -*/ -/* cbitsZ80DupTable */ -/* - uint32 cbits, v; - for (cbits = 0; cbits < 512; cbits++) { - v = (cbits & 0x10) | (((cbits >> 6) ^ (cbits >> 5)) & 4) | - ((cbits >> 8) & 1) | (cbits & 0xa8); - printf("%3d,", v); - if ( ((cbits+1) & 0xf) == 0) { - printf("\n"); - } - } -*/ -/* cbits2Z80Table */ -/* - uint32 cbits, v; - for (cbits = 0; cbits < 512; cbits++) { - v = (((cbits >> 6) ^ (cbits >> 5)) & 4) | (cbits & 0x10) | 2 | ((cbits >> 8) & 1); - printf("%2d,", v); - if ( ((cbits+1) & 0xf) == 0) { - printf("\n"); - } - } -*/ -/* cbits2Z80DupTable */ -/* - uint32 cbits, v; - for (cbits = 0; cbits < 512; cbits++) { - v = (((cbits >> 6) ^ (cbits >> 5)) & 4) | (cbits & 0x10) | 2 | ((cbits >> 8) & 1) | - (cbits & 0xa8); - printf("%3d,", v); - if ( ((cbits+1) & 0xf) == 0) { - printf("\n"); - } - } -*/ -/* negTable */ -/* - uint32 temp, v; - for (temp = 0; temp < 256; temp++) { - v = (((temp & 0x0f) != 0) << 4) | ((temp == 0x80) << 2) | 2 | (temp != 0); - printf("%2d,", v); - if ( ((temp+1) & 0xf) == 0) { - printf("\n"); - } - } -*/ -/* rrdrldTable */ -/* - uint32 acu, v; - for (acu = 0; acu < 256; acu++) { - v = (acu << 8) | (acu & 0xa8) | (((acu & 0xff) == 0) << 6) | parityTable[acu]; - printf("0x%04x,", v); - if ( ((acu+1) & 0x7) == 0) { - printf("\n"); - } - } -*/ -/* cpTable */ -/* - uint32 sum, v; - for (sum = 0; sum < 256; sum++) { - v = (sum & 0x80) | (((sum & 0xff) == 0) << 6); - printf("%3d,", v); - if ( ((sum+1) & 0xf) == 0) { - printf("\n"); - } - } -*/ -/* remove comments to generate table contents -} -*/ - -static void warnUnsuccessfulWriteAttempt(const uint32 Addr) { - if (cpu_unit.flags & UNIT_WARNROM) { - if (addressIsInROM(Addr)) { - message2("Attempt to write to ROM " AddressFormat ".\n", Addr); - } - else { - message2("Attempt to write to non existing memory " AddressFormat ".\n", Addr); - } - } -} - -static uint8 warnUnsuccessfulReadAttempt(const uint32 Addr) { - if (cpu_unit.flags & UNIT_WARNROM) { - message2("Attempt to read from non existing memory " AddressFormat ".\n", Addr); - } - return 0xff; -} - -/* determine whether Addr points to Read Only Memory */ -int32 addressIsInROM(const uint32 Addr) { - uint32 addr = Addr & ADDRMASK; /* registers are NOT guaranteed to be always 16-bit values */ - return (cpu_unit.flags & UNIT_ROM) && ( /* must have ROM enabled */ - /* in banked case we have standard Altair ROM */ - ((cpu_unit.flags & UNIT_BANKED) && (defaultROMLow <= addr)) || - /* in non-banked case we check the bounds of the ROM */ - (((cpu_unit.flags & UNIT_BANKED) == 0) && (ROMLow <= addr) && (addr <= ROMHigh))); -} - -/* determine whether Addr points to a valid memory address */ -int32 addressExists(const uint32 Addr) { - uint32 addr = Addr & ADDRMASK; /* registers are NOT guaranteed to be always 16-bit values */ - return (cpu_unit.flags & UNIT_BANKED) || (addr < MEMSIZE) || - ((cpu_unit.flags & UNIT_BANKED) == 0) && (cpu_unit.flags & UNIT_ROM) - && (ROMLow <= addr) && (addr <= ROMHigh); -} - -INLINE uint8 GetBYTE(register uint32 Addr) { - Addr &= ADDRMASK; /* registers are NOT guaranteed to be always 16-bit values */ - if (cpu_unit.flags & UNIT_BANKED) { /* banked memory case */ - /* if Addr below "common" take from selected bank, otherwise from bank 0 */ - return Addr < common ? M[Addr][bankSelect] : M[Addr][0]; - } - else { /* non-banked memory case */ - return ((Addr < MEMSIZE) || - (cpu_unit.flags & UNIT_ROM) && (ROMLow <= Addr) && (Addr <= ROMHigh)) ? - M[Addr][0] : warnUnsuccessfulReadAttempt(Addr); - } -} - -INLINE void PutBYTE(register uint32 Addr, register uint32 Value) { - Addr &= ADDRMASK; /* registers are NOT guaranteed to be always 16-bit values */ - if (cpu_unit.flags & UNIT_BANKED) { - if (Addr < common) { - M[Addr][bankSelect] = Value; - } - else if ((Addr < defaultROMLow) || ((cpu_unit.flags & UNIT_ROM) == 0)) { - M[Addr][0] = Value; - } - else { - warnUnsuccessfulWriteAttempt(Addr); - } - } - else { - if ((Addr < MEMSIZE) && ((Addr < ROMLow) || (Addr > ROMHigh) || ((cpu_unit.flags & UNIT_ROM) == 0))) { - M[Addr][0] = Value; - } - else { - warnUnsuccessfulWriteAttempt(Addr); - } - } -} - -void PutBYTEBasic(const uint32 Addr, const uint32 Bank, const uint32 Value) { - M[Addr & ADDRMASK][Bank & BANKMASK] = Value; -} - -void PutBYTEForced(register uint32 Addr, register uint32 Value) { - Addr &= ADDRMASK; /* registers are NOT guaranteed to be always 16-bit values */ - if ((cpu_unit.flags & UNIT_BANKED) && (Addr < common)) { - M[Addr][bankSelect] = Value; - } - else { - M[Addr][0] = Value; - } -} - -static INLINE void PutWORD(register uint32 Addr, register uint32 Value) { - Addr &= ADDRMASK; /* registers are NOT guaranteed to be always 16-bit values */ - if (cpu_unit.flags & UNIT_BANKED) { - if (Addr < common) { - M[Addr][bankSelect] = Value; - } - else if ((Addr < defaultROMLow) || ((cpu_unit.flags & UNIT_ROM) == 0)) { - M[Addr][0] = Value; - } - else { - warnUnsuccessfulWriteAttempt(Addr); - } - Addr = (Addr + 1) & ADDRMASK; - if (Addr < common) { - M[Addr][bankSelect] = Value >> 8; - } - else if ((Addr < defaultROMLow) || ((cpu_unit.flags & UNIT_ROM) == 0)) { - M[Addr][0] = Value >> 8; - } - else { - warnUnsuccessfulWriteAttempt(Addr); - } - } - else { - if ((Addr < MEMSIZE) && ((Addr < ROMLow) || (Addr > ROMHigh) || ((cpu_unit.flags & UNIT_ROM) == 0))) { - M[Addr][0] = Value; - } - else { - warnUnsuccessfulWriteAttempt(Addr); - } - Addr = (Addr + 1) & ADDRMASK; - if ((Addr < MEMSIZE) && ((Addr < ROMLow) || (Addr > ROMHigh) || ((cpu_unit.flags & UNIT_ROM) == 0))) { - M[Addr][0] = Value >> 8; - } - else { - warnUnsuccessfulWriteAttempt(Addr); - } - } -} - -#ifndef NO_INLINE -uint8 GetBYTEWrapper(register uint32 Addr) { /* make sure that non-inlined version exists */ - return GetBYTE(Addr); -} - -void PutBYTEWrapper(register uint32 Addr, register uint32 Value) { - PutBYTE(Addr, Value); -} -#endif - -#define RAM_mm(a) GetBYTE(a--) -#define RAM_pp(a) GetBYTE(a++) - -#define PutBYTE_pp(a,v) PutBYTE(a++, v) -#define PutBYTE_mm(a,v) PutBYTE(a--, v) -#define mm_PutBYTE(a,v) PutBYTE(--a, v) - -static INLINE uint16 GetWORD(register uint32 a) { - return GetBYTE(a) | (GetBYTE(a + 1) << 8); -} - -#define MASK_BRK (TRUE + 1) - -/* this is a modified version of sim_brk_test with two differences: - 1) is does not set sim_brk_pend to FALSE (this if left to the instruction decode) - 2) it returns MASK_BRK if a breakpoint is found but should be ignored -*/ -static int32 sim_brk_lookup (const t_addr loc, const int32 btyp) { - extern t_bool sim_brk_pend; - extern t_addr sim_brk_ploc; - extern char *sim_brk_act; - BRKTAB *bp; - if ((bp = sim_brk_fnd (loc)) && /* entry in table? */ - (btyp & bp -> typ) && /* type match? */ - (!sim_brk_pend || (loc != sim_brk_ploc)) && /* new location? */ - (--(bp -> cnt) <= 0)) { /* count reach 0? */ - bp -> cnt = 0; /* reset count */ - sim_brk_ploc = loc; /* save location */ - sim_brk_act = bp -> act; /* set up actions */ - sim_brk_pend = TRUE; /* don't do twice */ - return TRUE; - } - return (sim_brk_pend && (loc == sim_brk_ploc)) ? MASK_BRK : FALSE; -} - -static void prepareMemoryAccessMessage(t_addr loc) { - sprintf(memoryAccessMessage, "Memory access breakpoint [%04xh]", loc); -} - -#define PUSH(x) do { \ - mm_PutBYTE(SP, (x) >> 8); \ - mm_PutBYTE(SP, x); \ -} while (0) - -#define CheckBreakByte(a) \ - if (sim_brk_summ && sim_brk_test(a, SWMASK('M'))) { \ - reason = STOP_MEM; \ - prepareMemoryAccessMessage(a); \ - goto end_decode; \ - } - -#define CheckBreakTwoBytesExtended(a1, a2, iCode) \ - if (sim_brk_summ) { \ - br1 = sim_brk_lookup(a1, SWMASK('M')); \ - br2 = br1 ? FALSE : sim_brk_lookup(a2, SWMASK('M')); \ - if ((br1 == MASK_BRK) || (br2 == MASK_BRK)) { \ - sim_brk_pend = FALSE; \ - } \ - else if (br1 || br2) { \ - reason = STOP_MEM; \ - if (br1) { \ - prepareMemoryAccessMessage(a1); \ - } \ - else { \ - prepareMemoryAccessMessage(a2); \ - } \ - iCode; \ - goto end_decode; \ - } \ - else { \ - sim_brk_pend = FALSE; \ - } \ - } - -#define CheckBreakTwoBytes(a1, a2) CheckBreakTwoBytesExtended(a1, a2,;) - -#define CheckBreakWord(a) CheckBreakTwoBytes(a, (a + 1)) - -int32 sim_instr (void) { - extern int32 sim_interval; - extern t_bool sim_brk_pend; - extern int32 timerInterrupt; - extern int32 timerInterruptHandler; - extern uint32 sim_os_msec(void); - extern t_bool rtc_avail; - int32 reason = 0; - register uint32 specialProcessing; - register uint32 AF; - register uint32 BC; - register uint32 DE; - register uint32 HL; - register uint32 PC; - register uint32 SP; - register uint32 IX; - register uint32 IY; - register uint32 temp, acu, sum, cbits; - register uint32 op, adr; - /* tStates contains the number of t-states executed. One t-state is executed - in one microsecond on a 1MHz CPU. tStates is used real-time simulation */ - register uint32 tStates; - uint32 tStatesInSlice; /* number of t-states in 10 mSec time-slice */ - uint32 startTime; - int32 br1, br2, tStateModifier; - - pc = saved_PC & ADDRMASK; /* load local PC */ - af[af_sel] = AF_S; - regs[regs_sel].bc = BC_S; - regs[regs_sel].de = DE_S; - regs[regs_sel].hl = HL_S; - ix = IX_S; - iy = IY_S; - sp = SP_S; - af[1 - af_sel] = AF1_S; - regs[1 - regs_sel].bc = BC1_S; - regs[1 - regs_sel].de = DE1_S; - regs[1 - regs_sel].hl = HL1_S; - IFF = IFF_S; - ir = IR_S; - - AF = af[af_sel]; - BC = regs[regs_sel].bc; - DE = regs[regs_sel].de; - HL = regs[regs_sel].hl; - PC = pc; - SP = sp; - IX = ix; - IY = iy; - specialProcessing = clockFrequency | timerInterrupt | sim_brk_summ; - tStates = 0; - if (rtc_avail) { - startTime = sim_os_msec(); - tStatesInSlice = sliceLength*clockFrequency; - } - else { /* make sure that sim_os_msec() is not called later */ - clockFrequency = startTime = tStatesInSlice = 0; - } - - /* main instruction fetch/decode loop */ - while (TRUE) { /* loop until halted */ - if (sim_interval <= 0) { /* check clock queue */ - if (reason = sim_process_event()) { - break; - } - else { - specialProcessing = clockFrequency | timerInterrupt | sim_brk_summ; - } - } - - if (specialProcessing) { /* quick check for special processing */ - if (clockFrequency && (tStates >= tStatesInSlice)) { - /* clockFrequency != 0 implies that real time clock is available */ - startTime += sliceLength; - tStates -= tStatesInSlice; - while (sim_os_msec() <= startTime) {} /* poor man's sleep */ - } - - if (timerInterrupt && (IFF & 1)) { - timerInterrupt = FALSE; - specialProcessing = clockFrequency | sim_brk_summ; - IFF = 0; /* disable interrupts */ - CheckBreakTwoBytesExtended(SP - 2, SP - 1, (timerInterrupt = TRUE, IFF |= 1)); - PUSH(PC); - PCQ_ENTRY(PC - 1); - PC = timerInterruptHandler & ADDRMASK; - } - - if (sim_brk_summ && (sim_brk_lookup(PC, SWMASK('E')) == TRUE)) { /* breakpoint? */ - reason = STOP_IBKPT; /* stop simulation */ - break; - } - } - - PCX = PC; - sim_interval--; - - /* make sure that each instructions properly sets sim_brk_pend: - 1) Either directly to FALSE if no memory access takes place or - 2) through a call to a Check... routine - */ - switch(RAM_pp(PC)) { - case 0x00: /* NOP */ - tStates += 4; - sim_brk_pend = FALSE; - break; - case 0x01: /* LD BC,nnnn */ - tStates += 10; - sim_brk_pend = FALSE; - BC = GetWORD(PC); - PC += 2; - break; - case 0x02: /* LD (BC),A */ - tStates += 7; - CheckBreakByte(BC) - PutBYTE(BC, hreg(AF)); - break; - case 0x03: /* INC BC */ - tStates += 6; - sim_brk_pend = FALSE; - ++BC; - break; - case 0x04: /* INC B */ - tStates += 4; - sim_brk_pend = FALSE; - BC += 0x100; - temp = hreg(BC); - AF = (AF & ~0xfe) | incTable[temp] | SetPV2(0x80); - break; - case 0x05: /* DEC B */ - tStates += 4; - sim_brk_pend = FALSE; - BC -= 0x100; - temp = hreg(BC); - AF = (AF & ~0xfe) | decTable[temp] | SetPV2(0x7f); - break; - case 0x06: /* LD B,nn */ - tStates += 7; - sim_brk_pend = FALSE; - Sethreg(BC, RAM_pp(PC)); - break; - case 0x07: /* RLCA */ - tStates += 4; - sim_brk_pend = FALSE; - AF = ((AF >> 7) & 0x0128) | ((AF << 1) & ~0x1ff) | - (AF & 0xc4) | ((AF >> 15) & 1); - break; - case 0x08: /* EX AF,AF' */ - tStates += 4; - sim_brk_pend = FALSE; - checkCPU8080; - af[af_sel] = AF; - af_sel = 1 - af_sel; - AF = af[af_sel]; - break; - case 0x09: /* ADD HL,BC */ - tStates += 11; - sim_brk_pend = FALSE; - HL &= ADDRMASK; - BC &= ADDRMASK; - sum = HL + BC; - AF = (AF & ~0x3b) | ((sum >> 8) & 0x28) | cbitsTable[(HL ^ BC ^ sum) >> 8]; - HL = sum; - break; - case 0x0a: /* LD A,(BC) */ - tStates += 7; - CheckBreakByte(BC) - Sethreg(AF, GetBYTE(BC)); - break; - case 0x0b: /* DEC BC */ - tStates += 6; - sim_brk_pend = FALSE; - --BC; - break; - case 0x0c: /* INC C */ - tStates += 4; - sim_brk_pend = FALSE; - temp = lreg(BC) + 1; - Setlreg(BC, temp); - AF = (AF & ~0xfe) | incTable[temp] | SetPV2(0x80); - break; - case 0x0d: /* DEC C */ - tStates += 4; - sim_brk_pend = FALSE; - temp = lreg(BC) - 1; - Setlreg(BC, temp); - AF = (AF & ~0xfe) | decTable[temp & 0xff] | SetPV2(0x7f); - break; - case 0x0e: /* LD C,nn */ - tStates += 7; - sim_brk_pend = FALSE; - Setlreg(BC, RAM_pp(PC)); - break; - case 0x0f: /* RRCA */ - tStates += 4; - sim_brk_pend = FALSE; - AF = (AF & 0xc4) | rrcaTable[hreg(AF)]; - break; - case 0x10: /* DJNZ dd */ - sim_brk_pend = FALSE; - checkCPU8080; - if ((BC -= 0x100) & 0xff00) { - PCQ_ENTRY(PC - 1); - PC += (signed char) GetBYTE(PC) + 1; - tStates += 13; - } - else { - PC++; - tStates += 8; - } - break; - case 0x11: /* LD DE,nnnn */ - tStates += 10; - sim_brk_pend = FALSE; - DE = GetWORD(PC); - PC += 2; - break; - case 0x12: /* LD (DE),A */ - tStates += 7; - CheckBreakByte(DE) - PutBYTE(DE, hreg(AF)); - break; - case 0x13: /* INC DE */ - tStates += 6; - sim_brk_pend = FALSE; - ++DE; - break; - case 0x14: /* INC D */ - tStates += 4; - sim_brk_pend = FALSE; - DE += 0x100; - temp = hreg(DE); - AF = (AF & ~0xfe) | incTable[temp] | SetPV2(0x80); - break; - case 0x15: /* DEC D */ - tStates += 4; - sim_brk_pend = FALSE; - DE -= 0x100; - temp = hreg(DE); - AF = (AF & ~0xfe) | decTable[temp] | SetPV2(0x7f); - break; - case 0x16: /* LD D,nn */ - tStates += 7; - sim_brk_pend = FALSE; - Sethreg(DE, RAM_pp(PC)); - break; - case 0x17: /* RLA */ - tStates += 4; - sim_brk_pend = FALSE; - AF = ((AF << 8) & 0x0100) | ((AF >> 7) & 0x28) | ((AF << 1) & ~0x01ff) | - (AF & 0xc4) | ((AF >> 15) & 1); - break; - case 0x18: /* JR dd */ - tStates += 12; - sim_brk_pend = FALSE; - checkCPU8080; - PCQ_ENTRY(PC - 1); - PC += (signed char) GetBYTE(PC) + 1; - break; - case 0x19: /* ADD HL,DE */ - tStates += 11; - sim_brk_pend = FALSE; - HL &= ADDRMASK; - DE &= ADDRMASK; - sum = HL + DE; - AF = (AF & ~0x3b) | ((sum >> 8) & 0x28) | cbitsTable[(HL ^ DE ^ sum) >> 8]; - HL = sum; - break; - case 0x1a: /* LD A,(DE) */ - tStates += 7; - CheckBreakByte(DE) - Sethreg(AF, GetBYTE(DE)); - break; - case 0x1b: /* DEC DE */ - tStates += 6; - sim_brk_pend = FALSE; - --DE; - break; - case 0x1c: /* INC E */ - tStates += 4; - sim_brk_pend = FALSE; - temp = lreg(DE) + 1; - Setlreg(DE, temp); - AF = (AF & ~0xfe) | incTable[temp] | SetPV2(0x80); - break; - case 0x1d: /* DEC E */ - tStates += 4; - sim_brk_pend = FALSE; - temp = lreg(DE) - 1; - Setlreg(DE, temp); - AF = (AF & ~0xfe) | decTable[temp & 0xff] | SetPV2(0x7f); - break; - case 0x1e: /* LD E,nn */ - tStates += 7; - sim_brk_pend = FALSE; - Setlreg(DE, RAM_pp(PC)); - break; - case 0x1f: /* RRA */ - tStates += 4; - sim_brk_pend = FALSE; - AF = ((AF & 1) << 15) | (AF & 0xc4) | rraTable[hreg(AF)]; - break; - case 0x20: /* JR NZ,dd */ - sim_brk_pend = FALSE; - checkCPU8080; - if (TSTFLAG(Z)) { - PC++; - tStates += 7; - } - else { - PCQ_ENTRY(PC - 1); - PC += (signed char) GetBYTE(PC) + 1; - tStates += 12; - } - break; - case 0x21: /* LD HL,nnnn */ - tStates += 10; - sim_brk_pend = FALSE; - HL = GetWORD(PC); - PC += 2; - break; - case 0x22: /* LD (nnnn),HL */ - tStates += 16; - temp = GetWORD(PC); - CheckBreakWord(temp); - PutWORD(temp, HL); - PC += 2; - break; - case 0x23: /* INC HL */ - tStates += 6; - sim_brk_pend = FALSE; - ++HL; - break; - case 0x24: /* INC H */ - tStates += 4; - sim_brk_pend = FALSE; - HL += 0x100; - temp = hreg(HL); - AF = (AF & ~0xfe) | incTable[temp] | SetPV2(0x80); - break; - case 0x25: /* DEC H */ - tStates += 4; - sim_brk_pend = FALSE; - HL -= 0x100; - temp = hreg(HL); - AF = (AF & ~0xfe) | decTable[temp] | SetPV2(0x7f); - break; - case 0x26: /* LD H,nn */ - tStates += 7; - sim_brk_pend = FALSE; - Sethreg(HL, RAM_pp(PC)); - break; - case 0x27: /* DAA */ - tStates += 4; - sim_brk_pend = FALSE; - acu = hreg(AF); - temp = ldig(acu); - cbits = TSTFLAG(C); - if (TSTFLAG(N)) { /* last operation was a subtract */ - int hd = cbits || acu > 0x99; - if (TSTFLAG(H) || (temp > 9)) { /* adjust low digit */ - if (temp > 5) { - SETFLAG(H, 0); - } - acu -= 6; - acu &= 0xff; - } - if (hd) { /* adjust high digit */ - acu -= 0x160; - } - } - else { /* last operation was an add */ - if (TSTFLAG(H) || (temp > 9)) { /* adjust low digit */ - SETFLAG(H, (temp > 9)); - acu += 6; - } - if (cbits || ((acu & 0x1f0) > 0x90)) { /* adjust high digit */ - acu += 0x60; - } - } - AF = (AF & 0x12) | rrdrldTable[acu & 0xff] | (acu >> 8) & 1 | cbits; - break; - case 0x28: /* JR Z,dd */ - sim_brk_pend = FALSE; - checkCPU8080; - if (TSTFLAG(Z)) { - PCQ_ENTRY(PC - 1); - PC += (signed char) GetBYTE(PC) + 1; - tStates += 12; - } - else { - PC++; - tStates += 7; - } - break; - case 0x29: /* ADD HL,HL */ - tStates += 11; - sim_brk_pend = FALSE; - HL &= ADDRMASK; - sum = HL + HL; - AF = (AF & ~0x3b) | cbitsDup16Table[sum >> 8]; - HL = sum; - break; - case 0x2a: /* LD HL,(nnnn) */ - tStates += 16; - temp = GetWORD(PC); - CheckBreakWord(temp); - HL = GetWORD(temp); - PC += 2; - break; - case 0x2b: /* DEC HL */ - tStates += 6; - sim_brk_pend = FALSE; - --HL; - break; - case 0x2c: /* INC L */ - tStates += 4; - sim_brk_pend = FALSE; - temp = lreg(HL) + 1; - Setlreg(HL, temp); - AF = (AF & ~0xfe) | incTable[temp] | SetPV2(0x80); - break; - case 0x2d: /* DEC L */ - tStates += 4; - sim_brk_pend = FALSE; - temp = lreg(HL) - 1; - Setlreg(HL, temp); - AF = (AF & ~0xfe) | decTable[temp & 0xff] | SetPV2(0x7f); - break; - case 0x2e: /* LD L,nn */ - tStates += 7; - sim_brk_pend = FALSE; - Setlreg(HL, RAM_pp(PC)); - break; - case 0x2f: /* CPL */ - tStates += 4; - sim_brk_pend = FALSE; - AF = (~AF & ~0xff) | (AF & 0xc5) | ((~AF >> 8) & 0x28) | 0x12; - break; - case 0x30: /* JR NC,dd */ - sim_brk_pend = FALSE; - checkCPU8080; - if (TSTFLAG(C)) { - PC++; - tStates += 7; - } - else { - PCQ_ENTRY(PC - 1); - PC += (signed char) GetBYTE(PC) + 1; - tStates += 12; - } - break; - case 0x31: /* LD SP,nnnn */ - tStates += 10; - sim_brk_pend = FALSE; - SP = GetWORD(PC); - PC += 2; - break; - case 0x32: /* LD (nnnn),A */ - tStates += 13; - temp = GetWORD(PC); - CheckBreakByte(temp); - PutBYTE(temp, hreg(AF)); - PC += 2; - break; - case 0x33: /* INC SP */ - tStates += 6; - sim_brk_pend = FALSE; - ++SP; - break; - case 0x34: /* INC (HL) */ - tStates += 11; - CheckBreakByte(HL); - temp = GetBYTE(HL) + 1; - PutBYTE(HL, temp); - AF = (AF & ~0xfe) | incTable[temp] | SetPV2(0x80); - break; - case 0x35: /* DEC (HL) */ - tStates += 11; - CheckBreakByte(HL); - temp = GetBYTE(HL) - 1; - PutBYTE(HL, temp); - AF = (AF & ~0xfe) | decTable[temp & 0xff] | SetPV2(0x7f); - break; - case 0x36: /* LD (HL),nn */ - tStates += 10; - CheckBreakByte(HL); - PutBYTE(HL, RAM_pp(PC)); - break; - case 0x37: /* SCF */ - tStates += 4; - sim_brk_pend = FALSE; - AF = (AF & ~0x3b) | ((AF >> 8) & 0x28) | 1; - break; - case 0x38: /* JR C,dd */ - sim_brk_pend = FALSE; - checkCPU8080; - if (TSTFLAG(C)) { - PCQ_ENTRY(PC - 1); - PC += (signed char) GetBYTE(PC) + 1; - tStates += 12; - } - else { - PC++; - tStates += 7; - } - break; - case 0x39: /* ADD HL,SP */ - tStates += 11; - sim_brk_pend = FALSE; - HL &= ADDRMASK; - SP &= ADDRMASK; - sum = HL + SP; - AF = (AF & ~0x3b) | ((sum >> 8) & 0x28) | cbitsTable[(HL ^ SP ^ sum) >> 8]; - HL = sum; - break; - case 0x3a: /* LD A,(nnnn) */ - tStates += 13; - temp = GetWORD(PC); - CheckBreakByte(temp); - Sethreg(AF, GetBYTE(temp)); - PC += 2; - break; - case 0x3b: /* DEC SP */ - tStates += 6; - sim_brk_pend = FALSE; - --SP; - break; - case 0x3c: /* INC A */ - tStates += 4; - sim_brk_pend = FALSE; - AF += 0x100; - temp = hreg(AF); - AF = (AF & ~0xfe) | incTable[temp] | SetPV2(0x80); - break; - case 0x3d: /* DEC A */ - tStates += 4; - sim_brk_pend = FALSE; - AF -= 0x100; - temp = hreg(AF); - AF = (AF & ~0xfe) | decTable[temp] | SetPV2(0x7f); - break; - case 0x3e: /* LD A,nn */ - tStates += 7; - sim_brk_pend = FALSE; - Sethreg(AF, RAM_pp(PC)); - break; - case 0x3f: /* CCF */ - tStates += 4; - sim_brk_pend = FALSE; - AF = (AF & ~0x3b) | ((AF >> 8) & 0x28) | ((AF & 1) << 4) | (~AF & 1); - break; - case 0x40: /* LD B,B */ - tStates += 4; - sim_brk_pend = FALSE; /* nop */ - break; - case 0x41: /* LD B,C */ - tStates += 4; - sim_brk_pend = FALSE; - BC = (BC & 0xff) | ((BC & 0xff) << 8); - break; - case 0x42: /* LD B,D */ - tStates += 4; - sim_brk_pend = FALSE; - BC = (BC & 0xff) | (DE & ~0xff); - break; - case 0x43: /* LD B,E */ - tStates += 4; - sim_brk_pend = FALSE; - BC = (BC & 0xff) | ((DE & 0xff) << 8); - break; - case 0x44: /* LD B,H */ - tStates += 4; - sim_brk_pend = FALSE; - BC = (BC & 0xff) | (HL & ~0xff); - break; - case 0x45: /* LD B,L */ - tStates += 4; - sim_brk_pend = FALSE; - BC = (BC & 0xff) | ((HL & 0xff) << 8); - break; - case 0x46: /* LD B,(HL) */ - tStates += 7; - CheckBreakByte(HL); - Sethreg(BC, GetBYTE(HL)); - break; - case 0x47: /* LD B,A */ - tStates += 4; - sim_brk_pend = FALSE; - BC = (BC & 0xff) | (AF & ~0xff); - break; - case 0x48: /* LD C,B */ - tStates += 4; - sim_brk_pend = FALSE; - BC = (BC & ~0xff) | ((BC >> 8) & 0xff); - break; - case 0x49: /* LD C,C */ - tStates += 4; - sim_brk_pend = FALSE; /* nop */ - break; - case 0x4a: /* LD C,D */ - tStates += 4; - sim_brk_pend = FALSE; - BC = (BC & ~0xff) | ((DE >> 8) & 0xff); - break; - case 0x4b: /* LD C,E */ - tStates += 4; - sim_brk_pend = FALSE; - BC = (BC & ~0xff) | (DE & 0xff); - break; - case 0x4c: /* LD C,H */ - tStates += 4; - sim_brk_pend = FALSE; - BC = (BC & ~0xff) | ((HL >> 8) & 0xff); - break; - case 0x4d: /* LD C,L */ - tStates += 4; - sim_brk_pend = FALSE; - BC = (BC & ~0xff) | (HL & 0xff); - break; - case 0x4e: /* LD C,(HL) */ - tStates += 7; - CheckBreakByte(HL); - Setlreg(BC, GetBYTE(HL)); - break; - case 0x4f: /* LD C,A */ - tStates += 4; - sim_brk_pend = FALSE; - BC = (BC & ~0xff) | ((AF >> 8) & 0xff); - break; - case 0x50: /* LD D,B */ - tStates += 4; - sim_brk_pend = FALSE; - DE = (DE & 0xff) | (BC & ~0xff); - break; - case 0x51: /* LD D,C */ - tStates += 4; - sim_brk_pend = FALSE; - DE = (DE & 0xff) | ((BC & 0xff) << 8); - break; - case 0x52: /* LD D,D */ - tStates += 4; - sim_brk_pend = FALSE; /* nop */ - break; - case 0x53: /* LD D,E */ - tStates += 4; - sim_brk_pend = FALSE; - DE = (DE & 0xff) | ((DE & 0xff) << 8); - break; - case 0x54: /* LD D,H */ - tStates += 4; - sim_brk_pend = FALSE; - DE = (DE & 0xff) | (HL & ~0xff); - break; - case 0x55: /* LD D,L */ - tStates += 4; - sim_brk_pend = FALSE; - DE = (DE & 0xff) | ((HL & 0xff) << 8); - break; - case 0x56: /* LD D,(HL) */ - tStates += 7; - CheckBreakByte(HL); - Sethreg(DE, GetBYTE(HL)); - break; - case 0x57: /* LD D,A */ - tStates += 4; - sim_brk_pend = FALSE; - DE = (DE & 0xff) | (AF & ~0xff); - break; - case 0x58: /* LD E,B */ - tStates += 4; - sim_brk_pend = FALSE; - DE = (DE & ~0xff) | ((BC >> 8) & 0xff); - break; - case 0x59: /* LD E,C */ - tStates += 4; - sim_brk_pend = FALSE; - DE = (DE & ~0xff) | (BC & 0xff); - break; - case 0x5a: /* LD E,D */ - tStates += 4; - sim_brk_pend = FALSE; - DE = (DE & ~0xff) | ((DE >> 8) & 0xff); - break; - case 0x5b: /* LD E,E */ - tStates += 4; - sim_brk_pend = FALSE; /* nop */ - break; - case 0x5c: /* LD E,H */ - tStates += 4; - sim_brk_pend = FALSE; - DE = (DE & ~0xff) | ((HL >> 8) & 0xff); - break; - case 0x5d: /* LD E,L */ - tStates += 4; - sim_brk_pend = FALSE; - DE = (DE & ~0xff) | (HL & 0xff); - break; - case 0x5e: /* LD E,(HL) */ - tStates += 7; - CheckBreakByte(HL); - Setlreg(DE, GetBYTE(HL)); - break; - case 0x5f: /* LD E,A */ - tStates += 4; - sim_brk_pend = FALSE; - DE = (DE & ~0xff) | ((AF >> 8) & 0xff); - break; - case 0x60: /* LD H,B */ - tStates += 4; - sim_brk_pend = FALSE; - HL = (HL & 0xff) | (BC & ~0xff); - break; - case 0x61: /* LD H,C */ - tStates += 4; - sim_brk_pend = FALSE; - HL = (HL & 0xff) | ((BC & 0xff) << 8); - break; - case 0x62: /* LD H,D */ - tStates += 4; - sim_brk_pend = FALSE; - HL = (HL & 0xff) | (DE & ~0xff); - break; - case 0x63: /* LD H,E */ - tStates += 4; - sim_brk_pend = FALSE; - HL = (HL & 0xff) | ((DE & 0xff) << 8); - break; - case 0x64: /* LD H,H */ - tStates += 4; - sim_brk_pend = FALSE; /* nop */ - break; - case 0x65: /* LD H,L */ - tStates += 4; - sim_brk_pend = FALSE; - HL = (HL & 0xff) | ((HL & 0xff) << 8); - break; - case 0x66: /* LD H,(HL) */ - tStates += 7; - CheckBreakByte(HL); - Sethreg(HL, GetBYTE(HL)); - break; - case 0x67: /* LD H,A */ - tStates += 4; - sim_brk_pend = FALSE; - HL = (HL & 0xff) | (AF & ~0xff); - break; - case 0x68: /* LD L,B */ - tStates += 4; - sim_brk_pend = FALSE; - HL = (HL & ~0xff) | ((BC >> 8) & 0xff); - break; - case 0x69: /* LD L,C */ - tStates += 4; - sim_brk_pend = FALSE; - HL = (HL & ~0xff) | (BC & 0xff); - break; - case 0x6a: /* LD L,D */ - tStates += 4; - sim_brk_pend = FALSE; - HL = (HL & ~0xff) | ((DE >> 8) & 0xff); - break; - case 0x6b: /* LD L,E */ - tStates += 4; - sim_brk_pend = FALSE; - HL = (HL & ~0xff) | (DE & 0xff); - break; - case 0x6c: /* LD L,H */ - tStates += 4; - sim_brk_pend = FALSE; - HL = (HL & ~0xff) | ((HL >> 8) & 0xff); - break; - case 0x6d: /* LD L,L */ - tStates += 4; - sim_brk_pend = FALSE; /* nop */ - break; - case 0x6e: /* LD L,(HL) */ - tStates += 7; - CheckBreakByte(HL); - Setlreg(HL, GetBYTE(HL)); - break; - case 0x6f: /* LD L,A */ - tStates += 4; - sim_brk_pend = FALSE; - HL = (HL & ~0xff) | ((AF >> 8) & 0xff); - break; - case 0x70: /* LD (HL),B */ - tStates += 7; - CheckBreakByte(HL); - PutBYTE(HL, hreg(BC)); - break; - case 0x71: /* LD (HL),C */ - tStates += 7; - CheckBreakByte(HL); - PutBYTE(HL, lreg(BC)); - break; - case 0x72: /* LD (HL),D */ - tStates += 7; - CheckBreakByte(HL); - PutBYTE(HL, hreg(DE)); - break; - case 0x73: /* LD (HL),E */ - tStates += 7; - CheckBreakByte(HL); - PutBYTE(HL, lreg(DE)); - break; - case 0x74: /* LD (HL),H */ - tStates += 7; - CheckBreakByte(HL); - PutBYTE(HL, hreg(HL)); - break; - case 0x75: /* LD (HL),L */ - tStates += 7; - CheckBreakByte(HL); - PutBYTE(HL, lreg(HL)); - break; - case 0x76: /* HALT */ - tStates += 4; - sim_brk_pend = FALSE; - reason = STOP_HALT; - PC--; - goto end_decode; - case 0x77: /* LD (HL),A */ - tStates += 7; - CheckBreakByte(HL); - PutBYTE(HL, hreg(AF)); - break; - case 0x78: /* LD A,B */ - tStates += 4; - sim_brk_pend = FALSE; - AF = (AF & 0xff) | (BC & ~0xff); - break; - case 0x79: /* LD A,C */ - tStates += 4; - sim_brk_pend = FALSE; - AF = (AF & 0xff) | ((BC & 0xff) << 8); - break; - case 0x7a: /* LD A,D */ - tStates += 4; - sim_brk_pend = FALSE; - AF = (AF & 0xff) | (DE & ~0xff); - break; - case 0x7b: /* LD A,E */ - tStates += 4; - sim_brk_pend = FALSE; - AF = (AF & 0xff) | ((DE & 0xff) << 8); - break; - case 0x7c: /* LD A,H */ - tStates += 4; - sim_brk_pend = FALSE; - AF = (AF & 0xff) | (HL & ~0xff); - break; - case 0x7d: /* LD A,L */ - tStates += 4; - sim_brk_pend = FALSE; - AF = (AF & 0xff) | ((HL & 0xff) << 8); - break; - case 0x7e: /* LD A,(HL) */ - tStates += 7; - CheckBreakByte(HL); - Sethreg(AF, GetBYTE(HL)); - break; - case 0x7f: /* LD A,A */ - tStates += 4; - sim_brk_pend = FALSE; /* nop */ - break; - case 0x80: /* ADD A,B */ - tStates += 4; - sim_brk_pend = FALSE; - temp = hreg(BC); - acu = hreg(AF); - sum = acu + temp; - cbits = acu ^ temp ^ sum; - AF = addTable[sum] | cbitsTable[cbits] | (SetPV); - break; - case 0x81: /* ADD A,C */ - tStates += 4; - sim_brk_pend = FALSE; - temp = lreg(BC); - acu = hreg(AF); - sum = acu + temp; - cbits = acu ^ temp ^ sum; - AF = addTable[sum] | cbitsTable[cbits] | (SetPV); - break; - case 0x82: /* ADD A,D */ - tStates += 4; - sim_brk_pend = FALSE; - temp = hreg(DE); - acu = hreg(AF); - sum = acu + temp; - cbits = acu ^ temp ^ sum; - AF = addTable[sum] | cbitsTable[cbits] | (SetPV); - break; - case 0x83: /* ADD A,E */ - tStates += 4; - sim_brk_pend = FALSE; - temp = lreg(DE); - acu = hreg(AF); - sum = acu + temp; - cbits = acu ^ temp ^ sum; - AF = addTable[sum] | cbitsTable[cbits] | (SetPV); - break; - case 0x84: /* ADD A,H */ - tStates += 4; - sim_brk_pend = FALSE; - temp = hreg(HL); - acu = hreg(AF); - sum = acu + temp; - cbits = acu ^ temp ^ sum; - AF = addTable[sum] | cbitsTable[cbits] | (SetPV); - break; - case 0x85: /* ADD A,L */ - tStates += 4; - sim_brk_pend = FALSE; - temp = lreg(HL); - acu = hreg(AF); - sum = acu + temp; - cbits = acu ^ temp ^ sum; - AF = addTable[sum] | cbitsTable[cbits] | (SetPV); - break; - case 0x86: /* ADD A,(HL) */ - tStates += 7; - CheckBreakByte(HL); - temp = GetBYTE(HL); - acu = hreg(AF); - sum = acu + temp; - cbits = acu ^ temp ^ sum; - AF = addTable[sum] | cbitsTable[cbits] | (SetPV); - break; - case 0x87: /* ADD A,A */ - tStates += 4; - sim_brk_pend = FALSE; - cbits = 2 * hreg(AF); - AF = cbitsDup8Table[cbits] | (SetPVS(cbits)); - break; - case 0x88: /* ADC A,B */ - tStates += 4; - sim_brk_pend = FALSE; - temp = hreg(BC); - acu = hreg(AF); - sum = acu + temp + TSTFLAG(C); - cbits = acu ^ temp ^ sum; - AF = addTable[sum] | cbitsTable[cbits] | (SetPV); - break; - case 0x89: /* ADC A,C */ - tStates += 4; - sim_brk_pend = FALSE; - temp = lreg(BC); - acu = hreg(AF); - sum = acu + temp + TSTFLAG(C); - cbits = acu ^ temp ^ sum; - AF = addTable[sum] | cbitsTable[cbits] | (SetPV); - break; - case 0x8a: /* ADC A,D */ - tStates += 4; - sim_brk_pend = FALSE; - temp = hreg(DE); - acu = hreg(AF); - sum = acu + temp + TSTFLAG(C); - cbits = acu ^ temp ^ sum; - AF = addTable[sum] | cbitsTable[cbits] | (SetPV); - break; - case 0x8b: /* ADC A,E */ - tStates += 4; - sim_brk_pend = FALSE; - temp = lreg(DE); - acu = hreg(AF); - sum = acu + temp + TSTFLAG(C); - cbits = acu ^ temp ^ sum; - AF = addTable[sum] | cbitsTable[cbits] | (SetPV); - break; - case 0x8c: /* ADC A,H */ - tStates += 4; - sim_brk_pend = FALSE; - temp = hreg(HL); - acu = hreg(AF); - sum = acu + temp + TSTFLAG(C); - cbits = acu ^ temp ^ sum; - AF = addTable[sum] | cbitsTable[cbits] | (SetPV); - break; - case 0x8d: /* ADC A,L */ - tStates += 4; - sim_brk_pend = FALSE; - temp = lreg(HL); - acu = hreg(AF); - sum = acu + temp + TSTFLAG(C); - cbits = acu ^ temp ^ sum; - AF = addTable[sum] | cbitsTable[cbits] | (SetPV); - break; - case 0x8e: /* ADC A,(HL) */ - tStates += 7; - CheckBreakByte(HL); - temp = GetBYTE(HL); - acu = hreg(AF); - sum = acu + temp + TSTFLAG(C); - cbits = acu ^ temp ^ sum; - AF = addTable[sum] | cbitsTable[cbits] | (SetPV); - break; - case 0x8f: /* ADC A,A */ - tStates += 4; - sim_brk_pend = FALSE; - cbits = 2 * hreg(AF) + TSTFLAG(C); - AF = cbitsDup8Table[cbits] | (SetPVS(cbits)); - break; - case 0x90: /* SUB B */ - tStates += 4; - sim_brk_pend = FALSE; - temp = hreg(BC); - acu = hreg(AF); - sum = acu - temp; - cbits = acu ^ temp ^ sum; - AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SetPV); - break; - case 0x91: /* SUB C */ - tStates += 4; - sim_brk_pend = FALSE; - temp = lreg(BC); - acu = hreg(AF); - sum = acu - temp; - cbits = acu ^ temp ^ sum; - AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SetPV); - break; - case 0x92: /* SUB D */ - tStates += 4; - sim_brk_pend = FALSE; - temp = hreg(DE); - acu = hreg(AF); - sum = acu - temp; - cbits = acu ^ temp ^ sum; - AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SetPV); - break; - case 0x93: /* SUB E */ - tStates += 4; - sim_brk_pend = FALSE; - temp = lreg(DE); - acu = hreg(AF); - sum = acu - temp; - cbits = acu ^ temp ^ sum; - AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SetPV); - break; - case 0x94: /* SUB H */ - tStates += 4; - sim_brk_pend = FALSE; - temp = hreg(HL); - acu = hreg(AF); - sum = acu - temp; - cbits = acu ^ temp ^ sum; - AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SetPV); - break; - case 0x95: /* SUB L */ - tStates += 4; - sim_brk_pend = FALSE; - temp = lreg(HL); - acu = hreg(AF); - sum = acu - temp; - cbits = acu ^ temp ^ sum; - AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SetPV); - break; - case 0x96: /* SUB (HL) */ - tStates += 7; - CheckBreakByte(HL); - temp = GetBYTE(HL); - acu = hreg(AF); - sum = acu - temp; - cbits = acu ^ temp ^ sum; - AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SetPV); - break; - case 0x97: /* SUB A */ - tStates += 4; - sim_brk_pend = FALSE; - AF = cpu_unit.flags & UNIT_CHIP ? 0x42 : 0x46; - break; - case 0x98: /* SBC A,B */ - tStates += 4; - sim_brk_pend = FALSE; - temp = hreg(BC); - acu = hreg(AF); - sum = acu - temp - TSTFLAG(C); - cbits = acu ^ temp ^ sum; - AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SetPV); - break; - case 0x99: /* SBC A,C */ - tStates += 4; - sim_brk_pend = FALSE; - temp = lreg(BC); - acu = hreg(AF); - sum = acu - temp - TSTFLAG(C); - cbits = acu ^ temp ^ sum; - AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SetPV); - break; - case 0x9a: /* SBC A,D */ - tStates += 4; - sim_brk_pend = FALSE; - temp = hreg(DE); - acu = hreg(AF); - sum = acu - temp - TSTFLAG(C); - cbits = acu ^ temp ^ sum; - AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SetPV); - break; - case 0x9b: /* SBC A,E */ - tStates += 4; - sim_brk_pend = FALSE; - temp = lreg(DE); - acu = hreg(AF); - sum = acu - temp - TSTFLAG(C); - cbits = acu ^ temp ^ sum; - AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SetPV); - break; - case 0x9c: /* SBC A,H */ - tStates += 4; - sim_brk_pend = FALSE; - temp = hreg(HL); - acu = hreg(AF); - sum = acu - temp - TSTFLAG(C); - cbits = acu ^ temp ^ sum; - AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SetPV); - break; - case 0x9d: /* SBC A,L */ - tStates += 4; - sim_brk_pend = FALSE; - temp = lreg(HL); - acu = hreg(AF); - sum = acu - temp - TSTFLAG(C); - cbits = acu ^ temp ^ sum; - AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SetPV); - break; - case 0x9e: /* SBC A,(HL) */ - tStates += 7; - CheckBreakByte(HL); - temp = GetBYTE(HL); - acu = hreg(AF); - sum = acu - temp - TSTFLAG(C); - cbits = acu ^ temp ^ sum; - AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SetPV); - break; - case 0x9f: /* SBC A,A */ - tStates += 4; - sim_brk_pend = FALSE; - cbits = -TSTFLAG(C); - AF = subTable[cbits & 0xff] | cbitsTable[cbits & 0x1ff] | (SetPVS(cbits)); - break; - case 0xa0: /* AND B */ - tStates += 4; - sim_brk_pend = FALSE; - AF = andTable[((AF & BC) >> 8) & 0xff]; - break; - case 0xa1: /* AND C */ - tStates += 4; - sim_brk_pend = FALSE; - AF = andTable[((AF >> 8) & BC) & 0xff]; - break; - case 0xa2: /* AND D */ - tStates += 4; - sim_brk_pend = FALSE; - AF = andTable[((AF & DE) >> 8) & 0xff]; - break; - case 0xa3: /* AND E */ - tStates += 4; - sim_brk_pend = FALSE; - AF = andTable[((AF >> 8) & DE) & 0xff]; - break; - case 0xa4: /* AND H */ - tStates += 4; - sim_brk_pend = FALSE; - AF = andTable[((AF & HL) >> 8) & 0xff]; - break; - case 0xa5: /* AND L */ - tStates += 4; - sim_brk_pend = FALSE; - AF = andTable[((AF >> 8) & HL) & 0xff]; - break; - case 0xa6: /* AND (HL) */ - tStates += 7; - CheckBreakByte(HL); - AF = andTable[((AF >> 8) & GetBYTE(HL)) & 0xff]; - break; - case 0xa7: /* AND A */ - tStates += 4; - sim_brk_pend = FALSE; - AF = andTable[(AF >> 8) & 0xff]; - break; - case 0xa8: /* XOR B */ - tStates += 4; - sim_brk_pend = FALSE; - AF = xororTable[((AF ^ BC) >> 8) & 0xff]; - break; - case 0xa9: /* XOR C */ - tStates += 4; - sim_brk_pend = FALSE; - AF = xororTable[((AF >> 8) ^ BC) & 0xff]; - break; - case 0xaa: /* XOR D */ - tStates += 4; - sim_brk_pend = FALSE; - AF = xororTable[((AF ^ DE) >> 8) & 0xff]; - break; - case 0xab: /* XOR E */ - tStates += 4; - sim_brk_pend = FALSE; - AF = xororTable[((AF >> 8) ^ DE) & 0xff]; - break; - case 0xac: /* XOR H */ - tStates += 4; - sim_brk_pend = FALSE; - AF = xororTable[((AF ^ HL) >> 8) & 0xff]; - break; - case 0xad: /* XOR L */ - tStates += 4; - sim_brk_pend = FALSE; - AF = xororTable[((AF >> 8) ^ HL) & 0xff]; - break; - case 0xae: /* XOR (HL) */ - tStates += 7; - CheckBreakByte(HL); - AF = xororTable[((AF >> 8) ^ GetBYTE(HL)) & 0xff]; - break; - case 0xaf: /* XOR A */ - tStates += 4; - sim_brk_pend = FALSE; - AF = 0x44; - break; - case 0xb0: /* OR B */ - tStates += 4; - sim_brk_pend = FALSE; - AF = xororTable[((AF | BC) >> 8) & 0xff]; - break; - case 0xb1: /* OR C */ - tStates += 4; - sim_brk_pend = FALSE; - AF = xororTable[((AF >> 8) | BC) & 0xff]; - break; - case 0xb2: /* OR D */ - tStates += 4; - sim_brk_pend = FALSE; - AF = xororTable[((AF | DE) >> 8) & 0xff]; - break; - case 0xb3: /* OR E */ - tStates += 4; - sim_brk_pend = FALSE; - AF = xororTable[((AF >> 8) | DE) & 0xff]; - break; - case 0xb4: /* OR H */ - tStates += 4; - sim_brk_pend = FALSE; - AF = xororTable[((AF | HL) >> 8) & 0xff]; - break; - case 0xb5: /* OR L */ - tStates += 4; - sim_brk_pend = FALSE; - AF = xororTable[((AF >> 8) | HL) & 0xff]; - break; - case 0xb6: /* OR (HL) */ - tStates += 7; - CheckBreakByte(HL); - AF = xororTable[((AF >> 8) | GetBYTE(HL)) & 0xff]; - break; - case 0xb7: /* OR A */ - tStates += 4; - sim_brk_pend = FALSE; - AF = xororTable[(AF >> 8) & 0xff]; - break; - case 0xb8: /* CP B */ - tStates += 4; - sim_brk_pend = FALSE; - temp = hreg(BC); - AF = (AF & ~0x28) | (temp & 0x28); - acu = hreg(AF); - sum = acu - temp; - cbits = acu ^ temp ^ sum; - AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) | - (SetPV) | cbits2Table[cbits & 0x1ff]; - break; - case 0xb9: /* CP C */ - tStates += 4; - sim_brk_pend = FALSE; - temp = lreg(BC); - AF = (AF & ~0x28) | (temp & 0x28); - acu = hreg(AF); - sum = acu - temp; - cbits = acu ^ temp ^ sum; - AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) | - (SetPV) | cbits2Table[cbits & 0x1ff]; - break; - case 0xba: /* CP D */ - tStates += 4; - sim_brk_pend = FALSE; - temp = hreg(DE); - AF = (AF & ~0x28) | (temp & 0x28); - acu = hreg(AF); - sum = acu - temp; - cbits = acu ^ temp ^ sum; - AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) | - (SetPV) | cbits2Table[cbits & 0x1ff]; - break; - case 0xbb: /* CP E */ - tStates += 4; - sim_brk_pend = FALSE; - temp = lreg(DE); - AF = (AF & ~0x28) | (temp & 0x28); - acu = hreg(AF); - sum = acu - temp; - cbits = acu ^ temp ^ sum; - AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) | - (SetPV) | cbits2Table[cbits & 0x1ff]; - break; - case 0xbc: /* CP H */ - tStates += 4; - sim_brk_pend = FALSE; - temp = hreg(HL); - AF = (AF & ~0x28) | (temp & 0x28); - acu = hreg(AF); - sum = acu - temp; - cbits = acu ^ temp ^ sum; - AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) | - (SetPV) | cbits2Table[cbits & 0x1ff]; - break; - case 0xbd: /* CP L */ - tStates += 4; - sim_brk_pend = FALSE; - temp = lreg(HL); - AF = (AF & ~0x28) | (temp & 0x28); - acu = hreg(AF); - sum = acu - temp; - cbits = acu ^ temp ^ sum; - AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) | - (SetPV) | cbits2Table[cbits & 0x1ff]; - break; - case 0xbe: /* CP (HL) */ - tStates += 7; - CheckBreakByte(HL); - temp = GetBYTE(HL); - AF = (AF & ~0x28) | (temp & 0x28); - acu = hreg(AF); - sum = acu - temp; - cbits = acu ^ temp ^ sum; - AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) | - (SetPV) | cbits2Table[cbits & 0x1ff]; - break; - case 0xbf: /* CP A */ - tStates += 4; - sim_brk_pend = FALSE; - Setlreg(AF, (hreg(AF) & 0x28) | (cpu_unit.flags & UNIT_CHIP ? 0x42 : 0x46)); - break; - case 0xc0: /* RET NZ */ - if (TSTFLAG(Z)) { - sim_brk_pend = FALSE; - tStates += 5; - } - else { - CheckBreakWord(SP); - PCQ_ENTRY(PC - 1); - POP(PC); - tStates += 11; - } - break; - case 0xc1: /* POP BC */ - tStates += 10; - CheckBreakWord(SP); - POP(BC); - break; - case 0xc2: /* JP NZ,nnnn */ - sim_brk_pend = FALSE; - JPC(!TSTFLAG(Z)); /* also updates tStates */ - break; - case 0xc3: /* JP nnnn */ - sim_brk_pend = FALSE; - JPC(1); /* also updates tStates */ - break; - case 0xc4: /* CALL NZ,nnnn */ - CALLC(!TSTFLAG(Z)); /* also updates tStates */ - break; - case 0xc5: /* PUSH BC */ - tStates += 11; - CheckBreakWord(SP - 2); - PUSH(BC); - break; - case 0xc6: /* ADD A,nn */ - tStates += 7; - sim_brk_pend = FALSE; - temp = RAM_pp(PC); - acu = hreg(AF); - sum = acu + temp; - cbits = acu ^ temp ^ sum; - AF = addTable[sum] | cbitsTable[cbits] | (SetPV); - break; - case 0xc7: /* RST 0 */ - tStates += 11; - CheckBreakWord(SP - 2); - PUSH(PC); - PCQ_ENTRY(PC - 1); - PC = 0; - break; - case 0xc8: /* RET Z */ - if (TSTFLAG(Z)) { - CheckBreakWord(SP); - PCQ_ENTRY(PC - 1); - POP(PC); - tStates += 11; - } - else { - sim_brk_pend = FALSE; - tStates += 5; - } - break; - case 0xc9: /* RET */ - tStates += 10; - CheckBreakWord(SP); - PCQ_ENTRY(PC - 1); - POP(PC); - break; - case 0xca: /* JP Z,nnnn */ - sim_brk_pend = FALSE; - JPC(TSTFLAG(Z)); /* also updates tStates */ - break; - case 0xcb: /* CB prefix */ - checkCPU8080; - adr = HL; - switch ((op = GetBYTE(PC)) & 7) { - case 0: - sim_brk_pend = tStateModifier = FALSE; - ++PC; - acu = hreg(BC); - tStates += 8; - break; - case 1: - sim_brk_pend = tStateModifier = FALSE; - ++PC; - acu = lreg(BC); - tStates += 8; - break; - case 2: - sim_brk_pend = tStateModifier = FALSE; - ++PC; - acu = hreg(DE); - tStates += 8; - break; - case 3: - sim_brk_pend = tStateModifier = FALSE; - ++PC; - acu = lreg(DE); - tStates += 8; - break; - case 4: - sim_brk_pend = tStateModifier = FALSE; - ++PC; - acu = hreg(HL); - tStates += 8; - break; - case 5: - sim_brk_pend = tStateModifier = FALSE; - ++PC; - acu = lreg(HL); - tStates += 8; - break; - case 6: - CheckBreakByte(adr); - ++PC; - acu = GetBYTE(adr); - tStateModifier = TRUE; - tStates += 15; - break; - case 7: - sim_brk_pend = tStateModifier = FALSE; - ++PC; - acu = hreg(AF); - tStates += 8; - break; - } - switch (op & 0xc0) { - case 0x00: /* shift/rotate */ - switch (op & 0x38) { - case 0x00: /* RLC */ - temp = (acu << 1) | (acu >> 7); - cbits = temp & 1; - goto cbshflg1; - case 0x08: /* RRC */ - temp = (acu >> 1) | (acu << 7); - cbits = temp & 0x80; - goto cbshflg1; - case 0x10: /* RL */ - temp = (acu << 1) | TSTFLAG(C); - cbits = acu & 0x80; - goto cbshflg1; - case 0x18: /* RR */ - temp = (acu >> 1) | (TSTFLAG(C) << 7); - cbits = acu & 1; - goto cbshflg1; - case 0x20: /* SLA */ - temp = acu << 1; - cbits = acu & 0x80; - goto cbshflg1; - case 0x28: /* SRA */ - temp = (acu >> 1) | (acu & 0x80); - cbits = acu & 1; - goto cbshflg1; - case 0x30: /* SLIA */ - temp = (acu << 1) | 1; - cbits = acu & 0x80; - goto cbshflg1; - case 0x38: /* SRL */ - temp = acu >> 1; - cbits = acu & 1; - cbshflg1: - AF = (AF & ~0xff) | rotateShiftTable[temp & 0xff] | !!cbits; - } - break; - case 0x40: /* BIT */ - if (tStateModifier) { - tStates -= 3; - } - if (acu & (1 << ((op >> 3) & 7))) { - AF = (AF & ~0xfe) | 0x10 | (((op & 0x38) == 0x38) << 7); - } - else { - AF = (AF & ~0xfe) | 0x54; - } - if ((op & 7) != 6) { - AF |= (acu & 0x28); - } - temp = acu; - break; - case 0x80: /* RES */ - temp = acu & ~(1 << ((op >> 3) & 7)); - break; - case 0xc0: /* SET */ - temp = acu | (1 << ((op >> 3) & 7)); - break; - } - switch (op & 7) { - case 0: - Sethreg(BC, temp); - break; - case 1: - Setlreg(BC, temp); - break; - case 2: - Sethreg(DE, temp); - break; - case 3: - Setlreg(DE, temp); - break; - case 4: - Sethreg(HL, temp); - break; - case 5: - Setlreg(HL, temp); - break; - case 6: - PutBYTE(adr, temp); - break; - case 7: - Sethreg(AF, temp); - break; - } - break; - case 0xcc: /* CALL Z,nnnn */ - CALLC(TSTFLAG(Z)); /* also updates tStates */ - break; - case 0xcd: /* CALL nnnn */ - CALLC(1); /* also updates tStates */ - break; - case 0xce: /* ADC A,nn */ - tStates += 7; - sim_brk_pend = FALSE; - temp = RAM_pp(PC); - acu = hreg(AF); - sum = acu + temp + TSTFLAG(C); - cbits = acu ^ temp ^ sum; - AF = addTable[sum] | cbitsTable[cbits] | (SetPV); - break; - case 0xcf: /* RST 8 */ - tStates += 11; - CheckBreakWord(SP - 2); - PUSH(PC); - PCQ_ENTRY(PC - 1); - PC = 8; - break; - case 0xd0: /* RET NC */ - if (TSTFLAG(C)) { - sim_brk_pend = FALSE; - tStates += 5; - } - else { - CheckBreakWord(SP); - PCQ_ENTRY(PC - 1); - POP(PC); - tStates += 11; - } - break; - case 0xd1: /* POP DE */ - tStates += 10; - CheckBreakWord(SP); - POP(DE); - break; - case 0xd2: /* JP NC,nnnn */ - sim_brk_pend = FALSE; - JPC(!TSTFLAG(C)); /* also updates tStates */ - break; - case 0xd3: /* OUT (nn),A */ - tStates += 11; - sim_brk_pend = FALSE; - out(RAM_pp(PC), hreg(AF)); - break; - case 0xd4: /* CALL NC,nnnn */ - CALLC(!TSTFLAG(C)); /* also updates tStates */ - break; - case 0xd5: /* PUSH DE */ - tStates += 11; - CheckBreakWord(SP - 2); - PUSH(DE); - break; - case 0xd6: /* SUB nn */ - tStates += 7; - sim_brk_pend = FALSE; - temp = RAM_pp(PC); - acu = hreg(AF); - sum = acu - temp; - cbits = acu ^ temp ^ sum; - AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SetPV); - break; - case 0xd7: /* RST 10H */ - tStates += 11; - CheckBreakWord(SP - 2); - PUSH(PC); - PCQ_ENTRY(PC - 1); - PC = 0x10; - break; - case 0xd8: /* RET C */ - if (TSTFLAG(C)) { - CheckBreakWord(SP); - PCQ_ENTRY(PC - 1); - POP(PC); - tStates += 11; - } - else { - sim_brk_pend = FALSE; - tStates += 5; - } - break; - case 0xd9: /* EXX */ - tStates += 4; - sim_brk_pend = FALSE; - checkCPU8080; - regs[regs_sel].bc = BC; - regs[regs_sel].de = DE; - regs[regs_sel].hl = HL; - regs_sel = 1 - regs_sel; - BC = regs[regs_sel].bc; - DE = regs[regs_sel].de; - HL = regs[regs_sel].hl; - break; - case 0xda: /* JP C,nnnn */ - sim_brk_pend = FALSE; - JPC(TSTFLAG(C)); /* also updates tStates */ - break; - case 0xdb: /* IN A,(nn) */ - tStates += 11; - sim_brk_pend = FALSE; - Sethreg(AF, in(RAM_pp(PC))); - break; - case 0xdc: /* CALL C,nnnn */ - CALLC(TSTFLAG(C)); /* also updates tStates */ - break; - case 0xdd: /* DD prefix */ - checkCPU8080; - switch (op = RAM_pp(PC)) { - case 0x09: /* ADD IX,BC */ - tStates += 15; - sim_brk_pend = FALSE; - IX &= ADDRMASK; - BC &= ADDRMASK; - sum = IX + BC; - AF = (AF & ~0x3b) | ((sum >> 8) & 0x28) | cbitsTable[(IX ^ BC ^ sum) >> 8]; - IX = sum; - break; - case 0x19: /* ADD IX,DE */ - tStates += 15; - sim_brk_pend = FALSE; - IX &= ADDRMASK; - DE &= ADDRMASK; - sum = IX + DE; - AF = (AF & ~0x3b) | ((sum >> 8) & 0x28) | cbitsTable[(IX ^ DE ^ sum) >> 8]; - IX = sum; - break; - case 0x21: /* LD IX,nnnn */ - tStates += 14; - sim_brk_pend = FALSE; - IX = GetWORD(PC); - PC += 2; - break; - case 0x22: /* LD (nnnn),IX */ - tStates += 20; - temp = GetWORD(PC); - CheckBreakWord(temp); - PutWORD(temp, IX); - PC += 2; - break; - case 0x23: /* INC IX */ - tStates += 10; - sim_brk_pend = FALSE; - ++IX; - break; - case 0x24: /* INC IXH */ - tStates += 9; - sim_brk_pend = FALSE; - IX += 0x100; - AF = (AF & ~0xfe) | incZ80Table[hreg(IX)]; - break; - case 0x25: /* DEC IXH */ - tStates += 9; - sim_brk_pend = FALSE; - IX -= 0x100; - AF = (AF & ~0xfe) | decZ80Table[hreg(IX)]; - break; - case 0x26: /* LD IXH,nn */ - tStates += 9; - sim_brk_pend = FALSE; - Sethreg(IX, RAM_pp(PC)); - break; - case 0x29: /* ADD IX,IX */ - tStates += 15; - sim_brk_pend = FALSE; - IX &= ADDRMASK; - sum = IX + IX; - AF = (AF & ~0x3b) | cbitsDup16Table[sum >> 8]; - IX = sum; - break; - case 0x2a: /* LD IX,(nnnn) */ - tStates += 20; - temp = GetWORD(PC); - CheckBreakWord(temp); - IX = GetWORD(temp); - PC += 2; - break; - case 0x2b: /* DEC IX */ - tStates += 10; - sim_brk_pend = FALSE; - --IX; - break; - case 0x2c: /* INC IXL */ - tStates += 9; - sim_brk_pend = FALSE; - temp = lreg(IX) + 1; - Setlreg(IX, temp); - AF = (AF & ~0xfe) | incZ80Table[temp]; - break; - case 0x2d: /* DEC IXL */ - tStates += 9; - sim_brk_pend = FALSE; - temp = lreg(IX) - 1; - Setlreg(IX, temp); - AF = (AF & ~0xfe) | decZ80Table[temp & 0xff]; - break; - case 0x2e: /* LD IXL,nn */ - tStates += 9; - sim_brk_pend = FALSE; - Setlreg(IX, RAM_pp(PC)); - break; - case 0x34: /* INC (IX+dd) */ - tStates += 23; - adr = IX + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - temp = GetBYTE(adr) + 1; - PutBYTE(adr, temp); - AF = (AF & ~0xfe) | incZ80Table[temp]; - break; - case 0x35: /* DEC (IX+dd) */ - tStates += 23; - adr = IX + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - temp = GetBYTE(adr) - 1; - PutBYTE(adr, temp); - AF = (AF & ~0xfe) | decZ80Table[temp & 0xff]; - break; - case 0x36: /* LD (IX+dd),nn */ - tStates += 19; - adr = IX + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - PutBYTE(adr, RAM_pp(PC)); - break; - case 0x39: /* ADD IX,SP */ - tStates += 15; - sim_brk_pend = FALSE; - IX &= ADDRMASK; - SP &= ADDRMASK; - sum = IX + SP; - AF = (AF & ~0x3b) | ((sum >> 8) & 0x28) | cbitsTable[(IX ^ SP ^ sum) >> 8]; - IX = sum; - break; - case 0x44: /* LD B,IXH */ - tStates += 9; - sim_brk_pend = FALSE; - Sethreg(BC, hreg(IX)); - break; - case 0x45: /* LD B,IXL */ - tStates += 9; - sim_brk_pend = FALSE; - Sethreg(BC, lreg(IX)); - break; - case 0x46: /* LD B,(IX+dd) */ - tStates += 19; - adr = IX + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - Sethreg(BC, GetBYTE(adr)); - break; - case 0x4c: /* LD C,IXH */ - tStates += 9; - sim_brk_pend = FALSE; - Setlreg(BC, hreg(IX)); - break; - case 0x4d: /* LD C,IXL */ - tStates += 9; - sim_brk_pend = FALSE; - Setlreg(BC, lreg(IX)); - break; - case 0x4e: /* LD C,(IX+dd) */ - tStates += 19; - adr = IX + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - Setlreg(BC, GetBYTE(adr)); - break; - case 0x54: /* LD D,IXH */ - tStates += 9; - sim_brk_pend = FALSE; - Sethreg(DE, hreg(IX)); - break; - case 0x55: /* LD D,IXL */ - tStates += 9; - sim_brk_pend = FALSE; - Sethreg(DE, lreg(IX)); - break; - case 0x56: /* LD D,(IX+dd) */ - tStates += 19; - adr = IX + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - Sethreg(DE, GetBYTE(adr)); - break; - case 0x5c: /* LD E,IXH */ - tStates += 9; - sim_brk_pend = FALSE; - Setlreg(DE, hreg(IX)); - break; - case 0x5d: /* LD E,IXL */ - tStates += 9; - sim_brk_pend = FALSE; - Setlreg(DE, lreg(IX)); - break; - case 0x5e: /* LD E,(IX+dd) */ - tStates += 19; - adr = IX + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - Setlreg(DE, GetBYTE(adr)); - break; - case 0x60: /* LD IXH,B */ - tStates += 9; - sim_brk_pend = FALSE; - Sethreg(IX, hreg(BC)); - break; - case 0x61: /* LD IXH,C */ - tStates += 9; - sim_brk_pend = FALSE; - Sethreg(IX, lreg(BC)); - break; - case 0x62: /* LD IXH,D */ - tStates += 9; - sim_brk_pend = FALSE; - Sethreg(IX, hreg(DE)); - break; - case 0x63: /* LD IXH,E */ - tStates += 9; - sim_brk_pend = FALSE; - Sethreg(IX, lreg(DE)); - break; - case 0x64: /* LD IXH,IXH */ - tStates += 9; - sim_brk_pend = FALSE; /* nop */ - break; - case 0x65: /* LD IXH,IXL */ - tStates += 9; - sim_brk_pend = FALSE; - Sethreg(IX, lreg(IX)); - break; - case 0x66: /* LD H,(IX+dd) */ - tStates += 19; - adr = IX + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - Sethreg(HL, GetBYTE(adr)); - break; - case 0x67: /* LD IXH,A */ - tStates += 9; - sim_brk_pend = FALSE; - Sethreg(IX, hreg(AF)); - break; - case 0x68: /* LD IXL,B */ - tStates += 9; - sim_brk_pend = FALSE; - Setlreg(IX, hreg(BC)); - break; - case 0x69: /* LD IXL,C */ - tStates += 9; - sim_brk_pend = FALSE; - Setlreg(IX, lreg(BC)); - break; - case 0x6a: /* LD IXL,D */ - tStates += 9; - sim_brk_pend = FALSE; - Setlreg(IX, hreg(DE)); - break; - case 0x6b: /* LD IXL,E */ - tStates += 9; - sim_brk_pend = FALSE; - Setlreg(IX, lreg(DE)); - break; - case 0x6c: /* LD IXL,IXH */ - tStates += 9; - sim_brk_pend = FALSE; - Setlreg(IX, hreg(IX)); - break; - case 0x6d: /* LD IXL,IXL */ - tStates += 9; - sim_brk_pend = FALSE; /* nop */ - break; - case 0x6e: /* LD L,(IX+dd) */ - tStates += 19; - adr = IX + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - Setlreg(HL, GetBYTE(adr)); - break; - case 0x6f: /* LD IXL,A */ - tStates += 9; - sim_brk_pend = FALSE; - Setlreg(IX, hreg(AF)); - break; - case 0x70: /* LD (IX+dd),B */ - tStates += 19; - adr = IX + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - PutBYTE(adr, hreg(BC)); - break; - case 0x71: /* LD (IX+dd),C */ - tStates += 19; - adr = IX + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - PutBYTE(adr, lreg(BC)); - break; - case 0x72: /* LD (IX+dd),D */ - tStates += 19; - adr = IX + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - PutBYTE(adr, hreg(DE)); - break; - case 0x73: /* LD (IX+dd),E */ - tStates += 19; - adr = IX + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - PutBYTE(adr, lreg(DE)); - break; - case 0x74: /* LD (IX+dd),H */ - tStates += 19; - adr = IX + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - PutBYTE(adr, hreg(HL)); - break; - case 0x75: /* LD (IX+dd),L */ - tStates += 19; - adr = IX + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - PutBYTE(adr, lreg(HL)); - break; - case 0x77: /* LD (IX+dd),A */ - tStates += 19; - adr = IX + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - PutBYTE(adr, hreg(AF)); - break; - case 0x7c: /* LD A,IXH */ - tStates += 9; - sim_brk_pend = FALSE; - Sethreg(AF, hreg(IX)); - break; - case 0x7d: /* LD A,IXL */ - tStates += 9; - sim_brk_pend = FALSE; - Sethreg(AF, lreg(IX)); - break; - case 0x7e: /* LD A,(IX+dd) */ - tStates += 19; - adr = IX + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - Sethreg(AF, GetBYTE(adr)); - break; - case 0x84: /* ADD A,IXH */ - tStates += 9; - sim_brk_pend = FALSE; - temp = hreg(IX); - acu = hreg(AF); - sum = acu + temp; - AF = addTable[sum] | cbitsZ80Table[acu ^ temp ^ sum]; - break; - case 0x85: /* ADD A,IXL */ - tStates += 9; - sim_brk_pend = FALSE; - temp = lreg(IX); - acu = hreg(AF); - sum = acu + temp; - AF = addTable[sum] | cbitsZ80Table[acu ^ temp ^ sum]; - break; - case 0x86: /* ADD A,(IX+dd) */ - tStates += 19; - adr = IX + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - temp = GetBYTE(adr); - acu = hreg(AF); - sum = acu + temp; - AF = addTable[sum] | cbitsZ80Table[acu ^ temp ^ sum]; - break; - case 0x8c: /* ADC A,IXH */ - tStates += 9; - sim_brk_pend = FALSE; - temp = hreg(IX); - acu = hreg(AF); - sum = acu + temp + TSTFLAG(C); - AF = addTable[sum] | cbitsZ80Table[acu ^ temp ^ sum]; - break; - case 0x8d: /* ADC A,IXL */ - tStates += 9; - sim_brk_pend = FALSE; - temp = lreg(IX); - acu = hreg(AF); - sum = acu + temp + TSTFLAG(C); - AF = addTable[sum] | cbitsZ80Table[acu ^ temp ^ sum]; - break; - case 0x8e: /* ADC A,(IX+dd) */ - tStates += 19; - adr = IX + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - temp = GetBYTE(adr); - acu = hreg(AF); - sum = acu + temp + TSTFLAG(C); - AF = addTable[sum] | cbitsZ80Table[acu ^ temp ^ sum]; - break; - case 0x96: /* SUB (IX+dd) */ - tStates += 19; - adr = IX + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - temp = GetBYTE(adr); - acu = hreg(AF); - sum = acu - temp; - AF = addTable[sum & 0xff] | cbits2Z80Table[(acu ^ temp ^ sum) & 0x1ff]; - break; - case 0x94: /* SUB IXH */ - SETFLAG(C, 0);/* fall through, a bit less efficient but smaller code */ - case 0x9c: /* SBC A,IXH */ - tStates += 9; - sim_brk_pend = FALSE; - temp = hreg(IX); - acu = hreg(AF); - sum = acu - temp - TSTFLAG(C); - AF = addTable[sum & 0xff] | cbits2Z80Table[(acu ^ temp ^ sum) & 0x1ff]; - break; - case 0x95: /* SUB IXL */ - SETFLAG(C, 0);/* fall through, a bit less efficient but smaller code */ - case 0x9d: /* SBC A,IXL */ - tStates += 9; - sim_brk_pend = FALSE; - temp = lreg(IX); - acu = hreg(AF); - sum = acu - temp - TSTFLAG(C); - AF = addTable[sum & 0xff] | cbits2Z80Table[(acu ^ temp ^ sum) & 0x1ff]; - break; - case 0x9e: /* SBC A,(IX+dd) */ - tStates += 19; - adr = IX + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - temp = GetBYTE(adr); - acu = hreg(AF); - sum = acu - temp - TSTFLAG(C); - AF = addTable[sum & 0xff] | cbits2Z80Table[(acu ^ temp ^ sum) & 0x1ff]; - break; - case 0xa4: /* AND IXH */ - tStates += 9; - sim_brk_pend = FALSE; - AF = andTable[((AF & IX) >> 8) & 0xff]; - break; - case 0xa5: /* AND IXL */ - tStates += 9; - sim_brk_pend = FALSE; - AF = andTable[((AF >> 8) & IX) & 0xff]; - break; - case 0xa6: /* AND (IX+dd) */ - tStates += 19; - adr = IX + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - AF = andTable[((AF >> 8) & GetBYTE(adr)) & 0xff]; - break; - case 0xac: /* XOR IXH */ - tStates += 9; - sim_brk_pend = FALSE; - AF = xororTable[((AF ^ IX) >> 8) & 0xff]; - break; - case 0xad: /* XOR IXL */ - tStates += 9; - sim_brk_pend = FALSE; - AF = xororTable[((AF >> 8) ^ IX) & 0xff]; - break; - case 0xae: /* XOR (IX+dd) */ - tStates += 19; - adr = IX + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - AF = xororTable[((AF >> 8) ^ GetBYTE(adr)) & 0xff]; - break; - case 0xb4: /* OR IXH */ - tStates += 9; - sim_brk_pend = FALSE; - AF = xororTable[((AF | IX) >> 8) & 0xff]; - break; - case 0xb5: /* OR IXL */ - tStates += 9; - sim_brk_pend = FALSE; - AF = xororTable[((AF >> 8) | IX) & 0xff]; - break; - case 0xb6: /* OR (IX+dd) */ - tStates += 19; - adr = IX + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - AF = xororTable[((AF >> 8) | GetBYTE(adr)) & 0xff]; - break; - case 0xbc: /* CP IXH */ - tStates += 9; - sim_brk_pend = FALSE; - temp = hreg(IX); - AF = (AF & ~0x28) | (temp & 0x28); - acu = hreg(AF); - sum = acu - temp; - AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) | - cbits2Z80Table[(acu ^ temp ^ sum) & 0x1ff]; - break; - case 0xbd: /* CP IXL */ - tStates += 9; - sim_brk_pend = FALSE; - temp = lreg(IX); - AF = (AF & ~0x28) | (temp & 0x28); - acu = hreg(AF); - sum = acu - temp; - AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) | - cbits2Z80Table[(acu ^ temp ^ sum) & 0x1ff]; - break; - case 0xbe: /* CP (IX+dd) */ - tStates += 19; - adr = IX + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - temp = GetBYTE(adr); - AF = (AF & ~0x28) | (temp & 0x28); - acu = hreg(AF); - sum = acu - temp; - AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) | - cbits2Z80Table[(acu ^ temp ^ sum) & 0x1ff]; - break; - case 0xcb: /* CB prefix */ - adr = IX + (signed char) RAM_pp(PC); - switch ((op = GetBYTE(PC)) & 7) { - case 0: - sim_brk_pend = FALSE; - ++PC; - acu = hreg(BC); - break; - case 1: - sim_brk_pend = FALSE; - ++PC; - acu = lreg(BC); - break; - case 2: - sim_brk_pend = FALSE; - ++PC; - acu = hreg(DE); - break; - case 3: - sim_brk_pend = FALSE; - ++PC; - acu = lreg(DE); - break; - case 4: - sim_brk_pend = FALSE; - ++PC; - acu = hreg(HL); - break; - case 5: - sim_brk_pend = FALSE; - ++PC; - acu = lreg(HL); - break; - case 6: - CheckBreakByte(adr); - ++PC; - acu = GetBYTE(adr); - break; - case 7: - sim_brk_pend = FALSE; - ++PC; - acu = hreg(AF); - break; - } - switch (op & 0xc0) { - case 0x00: /* shift/rotate */ - tStates += 23; - switch (op & 0x38) { - case 0x00: /* RLC */ - temp = (acu << 1) | (acu >> 7); - cbits = temp & 1; - goto cbshflg2; - case 0x08: /* RRC */ - temp = (acu >> 1) | (acu << 7); - cbits = temp & 0x80; - goto cbshflg2; - case 0x10: /* RL */ - temp = (acu << 1) | TSTFLAG(C); - cbits = acu & 0x80; - goto cbshflg2; - case 0x18: /* RR */ - temp = (acu >> 1) | (TSTFLAG(C) << 7); - cbits = acu & 1; - goto cbshflg2; - case 0x20: /* SLA */ - temp = acu << 1; - cbits = acu & 0x80; - goto cbshflg2; - case 0x28: /* SRA */ - temp = (acu >> 1) | (acu & 0x80); - cbits = acu & 1; - goto cbshflg2; - case 0x30: /* SLIA */ - temp = (acu << 1) | 1; - cbits = acu & 0x80; - goto cbshflg2; - case 0x38: /* SRL */ - temp = acu >> 1; - cbits = acu & 1; - cbshflg2: - AF = (AF & ~0xff) | rotateShiftTable[temp & 0xff] | !!cbits; - } - break; - case 0x40: /* BIT */ - tStates += 20; - if (acu & (1 << ((op >> 3) & 7))) { - AF = (AF & ~0xfe) | 0x10 | (((op & 0x38) == 0x38) << 7); - } - else { - AF = (AF & ~0xfe) | 0x54; - } - if ((op & 7) != 6) { - AF |= (acu & 0x28); - } - temp = acu; - break; - case 0x80: /* RES */ - tStates += 23; - temp = acu & ~(1 << ((op >> 3) & 7)); - break; - case 0xc0: /* SET */ - tStates += 23; - temp = acu | (1 << ((op >> 3) & 7)); - break; - } - switch (op & 7) { - case 0: - Sethreg(BC, temp); - break; - case 1: - Setlreg(BC, temp); - break; - case 2: - Sethreg(DE, temp); - break; - case 3: - Setlreg(DE, temp); - break; - case 4: - Sethreg(HL, temp); - break; - case 5: - Setlreg(HL, temp); - break; - case 6: - PutBYTE(adr, temp); - break; - case 7: - Sethreg(AF, temp); - break; - } - break; - case 0xe1: /* POP IX */ - tStates += 14; - CheckBreakWord(SP); - POP(IX); - break; - case 0xe3: /* EX (SP),IX */ - tStates += 23; - CheckBreakWord(SP); - temp = IX; - POP(IX); - PUSH(temp); - break; - case 0xe5: /* PUSH IX */ - tStates += 15; - CheckBreakWord(SP - 2); - PUSH(IX); - break; - case 0xe9: /* JP (IX) */ - tStates += 8; - sim_brk_pend = FALSE; - PCQ_ENTRY(PC - 2); - PC = IX; - break; - case 0xf9: /* LD SP,IX */ - tStates += 10; - sim_brk_pend = FALSE; - SP = IX; - break; - default: /* ignore DD */ - sim_brk_pend = FALSE; - checkCPUZ80; - PC--; - } - break; - case 0xde: /* SBC A,nn */ - tStates += 7; - sim_brk_pend = FALSE; - temp = RAM_pp(PC); - acu = hreg(AF); - sum = acu - temp - TSTFLAG(C); - cbits = acu ^ temp ^ sum; - AF = subTable[sum & 0xff] | cbitsTable[cbits & 0x1ff] | (SetPV); - break; - case 0xdf: /* RST 18H */ - tStates += 11; - CheckBreakWord(SP - 2); - PUSH(PC); - PCQ_ENTRY(PC - 1); - PC = 0x18; - break; - case 0xe0: /* RET PO */ - if (TSTFLAG(P)) { - sim_brk_pend = FALSE; - tStates += 5; - } - else { - CheckBreakWord(SP); - PCQ_ENTRY(PC - 1); - POP(PC); - tStates += 11; - } - break; - case 0xe1: /* POP HL */ - tStates += 10; - CheckBreakWord(SP); - POP(HL); - break; - case 0xe2: /* JP PO,nnnn */ - sim_brk_pend = FALSE; - JPC(!TSTFLAG(P)); /* also updates tStates */ - break; - case 0xe3: /* EX (SP),HL */ - tStates += 19; - CheckBreakWord(SP); - temp = HL; - POP(HL); - PUSH(temp); - break; - case 0xe4: /* CALL PO,nnnn */ - CALLC(!TSTFLAG(P)); /* also updates tStates */ - break; - case 0xe5: /* PUSH HL */ - tStates += 11; - CheckBreakWord(SP - 2); - PUSH(HL); - break; - case 0xe6: /* AND nn */ - tStates += 7; - sim_brk_pend = FALSE; - AF = andTable[((AF >> 8) & RAM_pp(PC)) & 0xff]; - break; - case 0xe7: /* RST 20H */ - tStates += 11; - CheckBreakWord(SP - 2); - PUSH(PC); - PCQ_ENTRY(PC - 1); - PC = 0x20; - break; - case 0xe8: /* RET PE */ - if (TSTFLAG(P)) { - CheckBreakWord(SP); - PCQ_ENTRY(PC - 1); - POP(PC); - tStates += 11; - } - else { - sim_brk_pend = FALSE; - tStates += 5; - } - break; - case 0xe9: /* JP (HL) */ - tStates += 4; - sim_brk_pend = FALSE; - PCQ_ENTRY(PC - 1); - PC = HL; - break; - case 0xea: /* JP PE,nnnn */ - sim_brk_pend = FALSE; - JPC(TSTFLAG(P)); /* also updates tStates */ - break; - case 0xeb: /* EX DE,HL */ - tStates += 4; - sim_brk_pend = FALSE; - temp = HL; - HL = DE; - DE = temp; - break; - case 0xec: /* CALL PE,nnnn */ - CALLC(TSTFLAG(P)); /* also updates tStates */ - break; - case 0xed: /* ED prefix */ - checkCPU8080; - switch (op = RAM_pp(PC)) { - case 0x40: /* IN B,(C) */ - tStates += 12; - sim_brk_pend = FALSE; - temp = in(lreg(BC)); - Sethreg(BC, temp); - AF = (AF & ~0xfe) | rotateShiftTable[temp & 0xff]; - break; - case 0x41: /* OUT (C),B */ - tStates += 12; - sim_brk_pend = FALSE; - out(lreg(BC), hreg(BC)); - break; - case 0x42: /* SBC HL,BC */ - tStates += 15; - sim_brk_pend = FALSE; - HL &= ADDRMASK; - BC &= ADDRMASK; - sum = HL - BC - TSTFLAG(C); - AF = (AF & ~0xff) | ((sum >> 8) & 0xa8) | (((sum & ADDRMASK) == 0) << 6) | - cbits2Z80Table[((HL ^ BC ^ sum) >> 8) & 0x1ff]; - HL = sum; - break; - case 0x43: /* LD (nnnn),BC */ - tStates += 20; - temp = GetWORD(PC); - CheckBreakWord(temp); - PutWORD(temp, BC); - PC += 2; - break; - case 0x44: /* NEG */ - case 0x4C: /* NEG, unofficial */ - case 0x54: /* NEG, unofficial */ - case 0x5C: /* NEG, unofficial */ - case 0x64: /* NEG, unofficial */ - case 0x6C: /* NEG, unofficial */ - case 0x74: /* NEG, unofficial */ - case 0x7C: /* NEG, unofficial */ - tStates += 8; - sim_brk_pend = FALSE; - temp = hreg(AF); - AF = ((~(AF & 0xff00) + 1) & 0xff00); /* AF = (-(AF & 0xff00) & 0xff00); */ - AF |= ((AF >> 8) & 0xa8) | (((AF & 0xff00) == 0) << 6) | negTable[temp]; - break; - case 0x45: /* RETN */ - case 0x55: /* RETN, unofficial */ - case 0x5D: /* RETN, unofficial */ - case 0x65: /* RETN, unofficial */ - case 0x6D: /* RETN, unofficial */ - case 0x75: /* RETN, unofficial */ - case 0x7D: /* RETN, unofficial */ - tStates += 14; - IFF |= IFF >> 1; - CheckBreakWord(SP); - PCQ_ENTRY(PC - 2); - POP(PC); - break; - case 0x46: /* IM 0 */ - tStates += 8; - sim_brk_pend = FALSE; - /* interrupt mode 0 */ - break; - case 0x47: /* LD I,A */ - tStates += 9; - sim_brk_pend = FALSE; - ir = (ir & 0xff) | (AF & ~0xff); - break; - case 0x48: /* IN C,(C) */ - tStates += 12; - sim_brk_pend = FALSE; - temp = in(lreg(BC)); - Setlreg(BC, temp); - AF = (AF & ~0xfe) | rotateShiftTable[temp & 0xff]; - break; - case 0x49: /* OUT (C),C */ - tStates += 12; - sim_brk_pend = FALSE; - out(lreg(BC), lreg(BC)); - break; - case 0x4a: /* ADC HL,BC */ - tStates += 15; - sim_brk_pend = FALSE; - HL &= ADDRMASK; - BC &= ADDRMASK; - sum = HL + BC + TSTFLAG(C); - AF = (AF & ~0xff) | ((sum >> 8) & 0xa8) | (((sum & ADDRMASK) == 0) << 6) | - cbitsZ80Table[(HL ^ BC ^ sum) >> 8]; - HL = sum; - break; - case 0x4b: /* LD BC,(nnnn) */ - tStates += 20; - temp = GetWORD(PC); - CheckBreakWord(temp); - BC = GetWORD(temp); - PC += 2; - break; - case 0x4d: /* RETI */ - tStates += 14; - IFF |= IFF >> 1; - CheckBreakWord(SP); - PCQ_ENTRY(PC - 2); - POP(PC); - break; - case 0x4f: /* LD R,A */ - tStates += 9; - sim_brk_pend = FALSE; - ir = (ir & ~0xff) | ((AF >> 8) & 0xff); - break; - case 0x50: /* IN D,(C) */ - tStates += 12; - sim_brk_pend = FALSE; - temp = in(lreg(BC)); - Sethreg(DE, temp); - AF = (AF & ~0xfe) | rotateShiftTable[temp & 0xff]; - break; - case 0x51: /* OUT (C),D */ - tStates += 12; - sim_brk_pend = FALSE; - out(lreg(BC), hreg(DE)); - break; - case 0x52: /* SBC HL,DE */ - tStates += 15; - sim_brk_pend = FALSE; - HL &= ADDRMASK; - DE &= ADDRMASK; - sum = HL - DE - TSTFLAG(C); - AF = (AF & ~0xff) | ((sum >> 8) & 0xa8) | (((sum & ADDRMASK) == 0) << 6) | - cbits2Z80Table[((HL ^ DE ^ sum) >> 8) & 0x1ff]; - HL = sum; - break; - case 0x53: /* LD (nnnn),DE */ - tStates += 20; - temp = GetWORD(PC); - CheckBreakWord(temp); - PutWORD(temp, DE); - PC += 2; - break; - case 0x56: /* IM 1 */ - tStates += 8; - sim_brk_pend = FALSE; - /* interrupt mode 1 */ - break; - case 0x57: /* LD A,I */ - tStates += 9; - sim_brk_pend = FALSE; - AF = (AF & 0x29) | (ir & ~0xff) | ((ir >> 8) & 0x80) | (((ir & ~0xff) == 0) << 6) | ((IFF & 2) << 1); - break; - case 0x58: /* IN E,(C) */ - tStates += 12; - sim_brk_pend = FALSE; - temp = in(lreg(BC)); - Setlreg(DE, temp); - AF = (AF & ~0xfe) | rotateShiftTable[temp & 0xff]; - break; - case 0x59: /* OUT (C),E */ - tStates += 12; - sim_brk_pend = FALSE; - out(lreg(BC), lreg(DE)); - break; - case 0x5a: /* ADC HL,DE */ - tStates += 15; - sim_brk_pend = FALSE; - HL &= ADDRMASK; - DE &= ADDRMASK; - sum = HL + DE + TSTFLAG(C); - AF = (AF & ~0xff) | ((sum >> 8) & 0xa8) | (((sum & ADDRMASK) == 0) << 6) | - cbitsZ80Table[(HL ^ DE ^ sum) >> 8]; - HL = sum; - break; - case 0x5b: /* LD DE,(nnnn) */ - tStates += 20; - temp = GetWORD(PC); - CheckBreakWord(temp); - DE = GetWORD(temp); - PC += 2; - break; - case 0x5e: /* IM 2 */ - tStates += 8; - sim_brk_pend = FALSE; - /* interrupt mode 2 */ - break; - case 0x5f: /* LD A,R */ - tStates += 9; - sim_brk_pend = FALSE; - AF = (AF & 0x29) | ((ir & 0xff) << 8) | (ir & 0x80) | - (((ir & 0xff) == 0) << 6) | ((IFF & 2) << 1); - break; - case 0x60: /* IN H,(C) */ - tStates += 12; - sim_brk_pend = FALSE; - temp = in(lreg(BC)); - Sethreg(HL, temp); - AF = (AF & ~0xfe) | rotateShiftTable[temp & 0xff]; - break; - case 0x61: /* OUT (C),H */ - tStates += 12; - sim_brk_pend = FALSE; - out(lreg(BC), hreg(HL)); - break; - case 0x62: /* SBC HL,HL */ - tStates += 15; - sim_brk_pend = FALSE; - HL &= ADDRMASK; - sum = HL - HL - TSTFLAG(C); - AF = (AF & ~0xff) | (((sum & ADDRMASK) == 0) << 6) | - cbits2Z80DupTable[(sum >> 8) & 0x1ff]; - HL = sum; - break; - case 0x63: /* LD (nnnn),HL */ - tStates += 20; - temp = GetWORD(PC); - CheckBreakWord(temp); - PutWORD(temp, HL); - PC += 2; - break; - case 0x67: /* RRD */ - tStates += 18; - sim_brk_pend = FALSE; - temp = GetBYTE(HL); - acu = hreg(AF); - PutBYTE(HL, hdig(temp) | (ldig(acu) << 4)); - AF = rrdrldTable[(acu & 0xf0) | ldig(temp)] | (AF & 1); - break; - case 0x68: /* IN L,(C) */ - tStates += 12; - sim_brk_pend = FALSE; - temp = in(lreg(BC)); - Setlreg(HL, temp); - AF = (AF & ~0xfe) | rotateShiftTable[temp & 0xff]; - break; - case 0x69: /* OUT (C),L */ - tStates += 12; - sim_brk_pend = FALSE; - out(lreg(BC), lreg(HL)); - break; - case 0x6a: /* ADC HL,HL */ - tStates += 15; - sim_brk_pend = FALSE; - HL &= ADDRMASK; - sum = HL + HL + TSTFLAG(C); - AF = (AF & ~0xff) | (((sum & ADDRMASK) == 0) << 6) | - cbitsZ80DupTable[sum >> 8]; - HL = sum; - break; - case 0x6b: /* LD HL,(nnnn) */ - tStates += 20; - temp = GetWORD(PC); - CheckBreakWord(temp); - HL = GetWORD(temp); - PC += 2; - break; - case 0x6f: /* RLD */ - tStates += 18; - sim_brk_pend = FALSE; - temp = GetBYTE(HL); - acu = hreg(AF); - PutBYTE(HL, (ldig(temp) << 4) | ldig(acu)); - AF = rrdrldTable[(acu & 0xf0) | hdig(temp)] | (AF & 1); - break; - case 0x70: /* IN (C) */ - tStates += 12; - sim_brk_pend = FALSE; - temp = in(lreg(BC)); - Setlreg(temp, temp); - AF = (AF & ~0xfe) | rotateShiftTable[temp & 0xff]; - break; - case 0x71: /* OUT (C),0 */ - tStates += 12; - sim_brk_pend = FALSE; - out(lreg(BC), 0); - break; - case 0x72: /* SBC HL,SP */ - tStates += 15; - sim_brk_pend = FALSE; - HL &= ADDRMASK; - SP &= ADDRMASK; - sum = HL - SP - TSTFLAG(C); - AF = (AF & ~0xff) | ((sum >> 8) & 0xa8) | (((sum & ADDRMASK) == 0) << 6) | - cbits2Z80Table[((HL ^ SP ^ sum) >> 8) & 0x1ff]; - HL = sum; - break; - case 0x73: /* LD (nnnn),SP */ - tStates += 20; - temp = GetWORD(PC); - CheckBreakWord(temp); - PutWORD(temp, SP); - PC += 2; - break; - case 0x78: /* IN A,(C) */ - tStates += 12; - sim_brk_pend = FALSE; - temp = in(lreg(BC)); - Sethreg(AF, temp); - AF = (AF & ~0xfe) | rotateShiftTable[temp & 0xff]; - break; - case 0x79: /* OUT (C),A */ - tStates += 12; - sim_brk_pend = FALSE; - out(lreg(BC), hreg(AF)); - break; - case 0x7a: /* ADC HL,SP */ - tStates += 15; - sim_brk_pend = FALSE; - HL &= ADDRMASK; - SP &= ADDRMASK; - sum = HL + SP + TSTFLAG(C); - AF = (AF & ~0xff) | ((sum >> 8) & 0xa8) | (((sum & ADDRMASK) == 0) << 6) | - cbitsZ80Table[(HL ^ SP ^ sum) >> 8]; - HL = sum; - break; - case 0x7b: /* LD SP,(nnnn) */ - tStates += 20; - temp = GetWORD(PC); - CheckBreakWord(temp); - SP = GetWORD(temp); - PC += 2; - break; - case 0xa0: /* LDI */ - tStates += 16; - CheckBreakTwoBytes(HL, DE); - acu = RAM_pp(HL); - PutBYTE_pp(DE, acu); - acu += hreg(AF); - AF = (AF & ~0x3e) | (acu & 8) | ((acu & 2) << 4) | - (((--BC & ADDRMASK) != 0) << 2); - break; - case 0xa1: /* CPI */ - tStates += 16; - CheckBreakByte(HL); - acu = hreg(AF); - temp = RAM_pp(HL); - sum = acu - temp; - cbits = acu ^ temp ^ sum; - AF = (AF & ~0xfe) | (sum & 0x80) | (!(sum & 0xff) << 6) | - (((sum - ((cbits & 16) >> 4)) & 2) << 4) | (cbits & 16) | - ((sum - ((cbits >> 4) & 1)) & 8) | - ((--BC & ADDRMASK) != 0) << 2 | 2; - if ((sum & 15) == 8 && (cbits & 16) != 0) { - AF &= ~8; - } - break; - case 0xa2: /* INI */ - tStates += 16; - CheckBreakByte(HL); - PutBYTE(HL, in(lreg(BC))); - ++HL; - SETFLAG(N, 1); - SETFLAG(P, (--BC & ADDRMASK) != 0); - break; - case 0xa3: /* OUTI */ - tStates += 16; - CheckBreakByte(HL); - out(lreg(BC), GetBYTE(HL)); - ++HL; - SETFLAG(N, 1); - Sethreg(BC, lreg(BC) - 1); - SETFLAG(Z, lreg(BC) == 0); - break; - case 0xa8: /* LDD */ - tStates += 16; - CheckBreakTwoBytes(HL, DE); - acu = RAM_mm(HL); - PutBYTE_mm(DE, acu); - acu += hreg(AF); - AF = (AF & ~0x3e) | (acu & 8) | ((acu & 2) << 4) | - (((--BC & ADDRMASK) != 0) << 2); - break; - case 0xa9: /* CPD */ - tStates += 16; - CheckBreakByte(HL); - acu = hreg(AF); - temp = RAM_mm(HL); - sum = acu - temp; - cbits = acu ^ temp ^ sum; - AF = (AF & ~0xfe) | (sum & 0x80) | (!(sum & 0xff) << 6) | - (((sum - ((cbits & 16) >> 4)) & 2) << 4) | (cbits & 16) | - ((sum - ((cbits >> 4) & 1)) & 8) | - ((--BC & ADDRMASK) != 0) << 2 | 2; - if ((sum & 15) == 8 && (cbits & 16) != 0) { - AF &= ~8; - } - break; - case 0xaa: /* IND */ - tStates += 16; - CheckBreakByte(HL); - PutBYTE(HL, in(lreg(BC))); - --HL; - SETFLAG(N, 1); - Sethreg(BC, lreg(BC) - 1); - SETFLAG(Z, lreg(BC) == 0); - break; - case 0xab: /* OUTD */ - tStates += 16; - CheckBreakByte(HL); - out(lreg(BC), GetBYTE(HL)); - --HL; - SETFLAG(N, 1); - Sethreg(BC, lreg(BC) - 1); - SETFLAG(Z, lreg(BC) == 0); - break; - case 0xb0: /* LDIR */ - tStates -= 5; - acu = hreg(AF); - BC &= ADDRMASK; - do { - tStates += 21; - CheckBreakTwoBytes(HL, DE); - acu = RAM_pp(HL); - PutBYTE_pp(DE, acu); - } while (--BC); - acu += hreg(AF); - AF = (AF & ~0x3e) | (acu & 8) | ((acu & 2) << 4); - break; - case 0xb1: /* CPIR */ - tStates -= 5; - acu = hreg(AF); - BC &= ADDRMASK; - do { - tStates += 21; - CheckBreakByte(HL); - temp = RAM_pp(HL); - op = --BC != 0; - sum = acu - temp; - } while (op && sum != 0); - cbits = acu ^ temp ^ sum; - AF = (AF & ~0xfe) | (sum & 0x80) | (!(sum & 0xff) << 6) | - (((sum - ((cbits & 16) >> 4)) & 2) << 4) | - (cbits & 16) | ((sum - ((cbits >> 4) & 1)) & 8) | - op << 2 | 2; - if ((sum & 15) == 8 && (cbits & 16) != 0) { - AF &= ~8; - } - break; - case 0xb2: /* INIR */ - tStates -= 5; - temp = hreg(BC); - do { - tStates += 21; - CheckBreakByte(HL); - PutBYTE(HL, in(lreg(BC))); - ++HL; - } while (--temp); - Sethreg(BC, 0); - SETFLAG(N, 1); - SETFLAG(Z, 1); - break; - case 0xb3: /* OTIR */ - tStates -= 5; - temp = hreg(BC); - do { - tStates += 21; - CheckBreakByte(HL); - out(lreg(BC), GetBYTE(HL)); - ++HL; - } while (--temp); - Sethreg(BC, 0); - SETFLAG(N, 1); - SETFLAG(Z, 1); - break; - case 0xb8: /* LDDR */ - tStates -= 5; - BC &= ADDRMASK; - do { - tStates += 21; - CheckBreakTwoBytes(HL, DE); - acu = RAM_mm(HL); - PutBYTE_mm(DE, acu); - } while (--BC); - acu += hreg(AF); - AF = (AF & ~0x3e) | (acu & 8) | ((acu & 2) << 4); - break; - case 0xb9: /* CPDR */ - tStates -= 5; - acu = hreg(AF); - BC &= ADDRMASK; - do { - tStates += 21; - CheckBreakByte(HL); - temp = RAM_mm(HL); - op = --BC != 0; - sum = acu - temp; - } while (op && sum != 0); - cbits = acu ^ temp ^ sum; - AF = (AF & ~0xfe) | (sum & 0x80) | (!(sum & 0xff) << 6) | - (((sum - ((cbits & 16) >> 4)) & 2) << 4) | - (cbits & 16) | ((sum - ((cbits >> 4) & 1)) & 8) | - op << 2 | 2; - if ((sum & 15) == 8 && (cbits & 16) != 0) { - AF &= ~8; - } - break; - case 0xba: /* INDR */ - tStates -= 5; - temp = hreg(BC); - do { - tStates += 21; - CheckBreakByte(HL); - PutBYTE(HL, in(lreg(BC))); - --HL; - } while (--temp); - Sethreg(BC, 0); - SETFLAG(N, 1); - SETFLAG(Z, 1); - break; - case 0xbb: /* OTDR */ - tStates -= 5; - temp = hreg(BC); - do { - tStates += 21; - CheckBreakByte(HL); - out(lreg(BC), GetBYTE(HL)); - --HL; - } while (--temp); - Sethreg(BC, 0); - SETFLAG(N, 1); - SETFLAG(Z, 1); - break; - default: /* ignore ED and following byte */ - sim_brk_pend = FALSE; - checkCPUZ80; - } - break; - case 0xee: /* XOR nn */ - tStates += 7; - sim_brk_pend = FALSE; - AF = xororTable[((AF >> 8) ^ RAM_pp(PC)) & 0xff]; - break; - case 0xef: /* RST 28H */ - tStates += 11; - CheckBreakWord(SP - 2); - PUSH(PC); - PCQ_ENTRY(PC - 1); - PC = 0x28; - break; - case 0xf0: /* RET P */ - if (TSTFLAG(S)) { - sim_brk_pend = FALSE; - tStates += 5; - } - else { - CheckBreakWord(SP); - PCQ_ENTRY(PC - 1); - POP(PC); - tStates += 11; - } - break; - case 0xf1: /* POP AF */ - tStates += 10; - CheckBreakWord(SP); - POP(AF); - break; - case 0xf2: /* JP P,nnnn */ - sim_brk_pend = FALSE; - JPC(!TSTFLAG(S)); /* also updates tStates */ - break; - case 0xf3: /* DI */ - tStates += 4; - sim_brk_pend = FALSE; - IFF = 0; - break; - case 0xf4: /* CALL P,nnnn */ - CALLC(!TSTFLAG(S)); /* also updates tStates */ - break; - case 0xf5: /* PUSH AF */ - tStates += 11; - CheckBreakWord(SP - 2); - PUSH(AF); - break; - case 0xf6: /* OR nn */ - tStates += 7; - sim_brk_pend = FALSE; - AF = xororTable[((AF >> 8) | RAM_pp(PC)) & 0xff]; - break; - case 0xf7: /* RST 30H */ - tStates += 11; - CheckBreakWord(SP - 2); - PUSH(PC); - PCQ_ENTRY(PC - 1); - PC = 0x30; - break; - case 0xf8: /* RET M */ - if (TSTFLAG(S)) { - CheckBreakWord(SP); - PCQ_ENTRY(PC - 1); - POP(PC); - tStates += 11; - } - else { - sim_brk_pend = FALSE; - tStates += 5; - } - break; - case 0xf9: /* LD SP,HL */ - tStates += 6; - sim_brk_pend = FALSE; - SP = HL; - break; - case 0xfa: /* JP M,nnnn */ - sim_brk_pend = FALSE; - JPC(TSTFLAG(S)); /* also updates tStates */ - break; - case 0xfb: /* EI */ - tStates += 4; - sim_brk_pend = FALSE; - IFF = 3; - break; - case 0xfc: /* CALL M,nnnn */ - CALLC(TSTFLAG(S)); /* also updates tStates */ - break; - case 0xfd: /* FD prefix */ - checkCPU8080; - switch (op = RAM_pp(PC)) { - case 0x09: /* ADD IY,BC */ - tStates += 15; - sim_brk_pend = FALSE; - IY &= ADDRMASK; - BC &= ADDRMASK; - sum = IY + BC; - AF = (AF & ~0x3b) | ((sum >> 8) & 0x28) | cbitsTable[(IY ^ BC ^ sum) >> 8]; - IY = sum; - break; - case 0x19: /* ADD IY,DE */ - tStates += 15; - sim_brk_pend = FALSE; - IY &= ADDRMASK; - DE &= ADDRMASK; - sum = IY + DE; - AF = (AF & ~0x3b) | ((sum >> 8) & 0x28) | cbitsTable[(IY ^ DE ^ sum) >> 8]; - IY = sum; - break; - case 0x21: /* LD IY,nnnn */ - tStates += 14; - sim_brk_pend = FALSE; - IY = GetWORD(PC); - PC += 2; - break; - case 0x22: /* LD (nnnn),IY */ - tStates += 20; - temp = GetWORD(PC); - CheckBreakWord(temp); - PutWORD(temp, IY); - PC += 2; - break; - case 0x23: /* INC IY */ - tStates += 10; - sim_brk_pend = FALSE; - ++IY; - break; - case 0x24: /* INC IYH */ - tStates += 9; - sim_brk_pend = FALSE; - IY += 0x100; - AF = (AF & ~0xfe) | incZ80Table[hreg(IY)]; - break; - case 0x25: /* DEC IYH */ - tStates += 9; - sim_brk_pend = FALSE; - IY -= 0x100; - AF = (AF & ~0xfe) | decZ80Table[hreg(IY)]; - break; - case 0x26: /* LD IYH,nn */ - tStates += 9; - sim_brk_pend = FALSE; - Sethreg(IY, RAM_pp(PC)); - break; - case 0x29: /* ADD IY,IY */ - tStates += 15; - sim_brk_pend = FALSE; - IY &= ADDRMASK; - sum = IY + IY; - AF = (AF & ~0x3b) | cbitsDup16Table[sum >> 8]; - IY = sum; - break; - case 0x2a: /* LD IY,(nnnn) */ - tStates += 20; - temp = GetWORD(PC); - CheckBreakWord(temp); - IY = GetWORD(temp); - PC += 2; - break; - case 0x2b: /* DEC IY */ - tStates += 10; - sim_brk_pend = FALSE; - --IY; - break; - case 0x2c: /* INC IYL */ - tStates += 9; - sim_brk_pend = FALSE; - temp = lreg(IY) + 1; - Setlreg(IY, temp); - AF = (AF & ~0xfe) | incZ80Table[temp]; - break; - case 0x2d: /* DEC IYL */ - tStates += 9; - sim_brk_pend = FALSE; - temp = lreg(IY) - 1; - Setlreg(IY, temp); - AF = (AF & ~0xfe) | decZ80Table[temp & 0xff]; - break; - case 0x2e: /* LD IYL,nn */ - tStates += 9; - sim_brk_pend = FALSE; - Setlreg(IY, RAM_pp(PC)); - break; - case 0x34: /* INC (IY+dd) */ - tStates += 23; - adr = IY + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - temp = GetBYTE(adr) + 1; - PutBYTE(adr, temp); - AF = (AF & ~0xfe) | incZ80Table[temp]; - break; - case 0x35: /* DEC (IY+dd) */ - tStates += 23; - adr = IY + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - temp = GetBYTE(adr) - 1; - PutBYTE(adr, temp); - AF = (AF & ~0xfe) | decZ80Table[temp & 0xff]; - break; - case 0x36: /* LD (IY+dd),nn */ - tStates += 19; - adr = IY + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - PutBYTE(adr, RAM_pp(PC)); - break; - case 0x39: /* ADD IY,SP */ - tStates += 15; - sim_brk_pend = FALSE; - IY &= ADDRMASK; - SP &= ADDRMASK; - sum = IY + SP; - AF = (AF & ~0x3b) | ((sum >> 8) & 0x28) | cbitsTable[(IY ^ SP ^ sum) >> 8]; - IY = sum; - break; - case 0x44: /* LD B,IYH */ - tStates += 9; - sim_brk_pend = FALSE; - Sethreg(BC, hreg(IY)); - break; - case 0x45: /* LD B,IYL */ - tStates += 9; - sim_brk_pend = FALSE; - Sethreg(BC, lreg(IY)); - break; - case 0x46: /* LD B,(IY+dd) */ - tStates += 19; - adr = IY + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - Sethreg(BC, GetBYTE(adr)); - break; - case 0x4c: /* LD C,IYH */ - tStates += 9; - sim_brk_pend = FALSE; - Setlreg(BC, hreg(IY)); - break; - case 0x4d: /* LD C,IYL */ - tStates += 9; - sim_brk_pend = FALSE; - Setlreg(BC, lreg(IY)); - break; - case 0x4e: /* LD C,(IY+dd) */ - tStates += 19; - adr = IY + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - Setlreg(BC, GetBYTE(adr)); - break; - case 0x54: /* LD D,IYH */ - tStates += 9; - sim_brk_pend = FALSE; - Sethreg(DE, hreg(IY)); - break; - case 0x55: /* LD D,IYL */ - tStates += 9; - sim_brk_pend = FALSE; - Sethreg(DE, lreg(IY)); - break; - case 0x56: /* LD D,(IY+dd) */ - tStates += 19; - adr = IY + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - Sethreg(DE, GetBYTE(adr)); - break; - case 0x5c: /* LD E,IYH */ - tStates += 9; - sim_brk_pend = FALSE; - Setlreg(DE, hreg(IY)); - break; - case 0x5d: /* LD E,IYL */ - tStates += 9; - sim_brk_pend = FALSE; - Setlreg(DE, lreg(IY)); - break; - case 0x5e: /* LD E,(IY+dd) */ - tStates += 19; - adr = IY + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - Setlreg(DE, GetBYTE(adr)); - break; - case 0x60: /* LD IYH,B */ - tStates += 9; - sim_brk_pend = FALSE; - Sethreg(IY, hreg(BC)); - break; - case 0x61: /* LD IYH,C */ - tStates += 9; - sim_brk_pend = FALSE; - Sethreg(IY, lreg(BC)); - break; - case 0x62: /* LD IYH,D */ - tStates += 9; - sim_brk_pend = FALSE; - Sethreg(IY, hreg(DE)); - break; - case 0x63: /* LD IYH,E */ - tStates += 9; - sim_brk_pend = FALSE; - Sethreg(IY, lreg(DE)); - break; - case 0x64: /* LD IYH,IYH */ - tStates += 9; - sim_brk_pend = FALSE; /* nop */ - break; - case 0x65: /* LD IYH,IYL */ - tStates += 9; - sim_brk_pend = FALSE; - Sethreg(IY, lreg(IY)); - break; - case 0x66: /* LD H,(IY+dd) */ - tStates += 19; - adr = IY + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - Sethreg(HL, GetBYTE(adr)); - break; - case 0x67: /* LD IYH,A */ - tStates += 9; - sim_brk_pend = FALSE; - Sethreg(IY, hreg(AF)); - break; - case 0x68: /* LD IYL,B */ - tStates += 9; - sim_brk_pend = FALSE; - Setlreg(IY, hreg(BC)); - break; - case 0x69: /* LD IYL,C */ - tStates += 9; - sim_brk_pend = FALSE; - Setlreg(IY, lreg(BC)); - break; - case 0x6a: /* LD IYL,D */ - tStates += 9; - sim_brk_pend = FALSE; - Setlreg(IY, hreg(DE)); - break; - case 0x6b: /* LD IYL,E */ - tStates += 9; - sim_brk_pend = FALSE; - Setlreg(IY, lreg(DE)); - break; - case 0x6c: /* LD IYL,IYH */ - tStates += 9; - sim_brk_pend = FALSE; - Setlreg(IY, hreg(IY)); - break; - case 0x6d: /* LD IYL,IYL */ - tStates += 9; - sim_brk_pend = FALSE; /* nop */ - break; - case 0x6e: /* LD L,(IY+dd) */ - tStates += 19; - adr = IY + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - Setlreg(HL, GetBYTE(adr)); - break; - case 0x6f: /* LD IYL,A */ - tStates += 9; - sim_brk_pend = FALSE; - Setlreg(IY, hreg(AF)); - break; - case 0x70: /* LD (IY+dd),B */ - tStates += 19; - adr = IY + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - PutBYTE(adr, hreg(BC)); - break; - case 0x71: /* LD (IY+dd),C */ - tStates += 19; - adr = IY + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - PutBYTE(adr, lreg(BC)); - break; - case 0x72: /* LD (IY+dd),D */ - tStates += 19; - adr = IY + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - PutBYTE(adr, hreg(DE)); - break; - case 0x73: /* LD (IY+dd),E */ - tStates += 19; - adr = IY + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - PutBYTE(adr, lreg(DE)); - break; - case 0x74: /* LD (IY+dd),H */ - tStates += 19; - adr = IY + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - PutBYTE(adr, hreg(HL)); - break; - case 0x75: /* LD (IY+dd),L */ - tStates += 19; - adr = IY + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - PutBYTE(adr, lreg(HL)); - break; - case 0x77: /* LD (IY+dd),A */ - tStates += 19; - adr = IY + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - PutBYTE(adr, hreg(AF)); - break; - case 0x7c: /* LD A,IYH */ - tStates += 9; - sim_brk_pend = FALSE; - Sethreg(AF, hreg(IY)); - break; - case 0x7d: /* LD A,IYL */ - tStates += 9; - sim_brk_pend = FALSE; - Sethreg(AF, lreg(IY)); - break; - case 0x7e: /* LD A,(IY+dd) */ - tStates += 19; - adr = IY + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - Sethreg(AF, GetBYTE(adr)); - break; - case 0x84: /* ADD A,IYH */ - tStates += 9; - sim_brk_pend = FALSE; - temp = hreg(IY); - acu = hreg(AF); - sum = acu + temp; - AF = addTable[sum] | cbitsZ80Table[acu ^ temp ^ sum]; - break; - case 0x85: /* ADD A,IYL */ - tStates += 9; - sim_brk_pend = FALSE; - temp = lreg(IY); - acu = hreg(AF); - sum = acu + temp; - AF = addTable[sum] | cbitsZ80Table[acu ^ temp ^ sum]; - break; - case 0x86: /* ADD A,(IY+dd) */ - tStates += 19; - adr = IY + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - temp = GetBYTE(adr); - acu = hreg(AF); - sum = acu + temp; - AF = addTable[sum] | cbitsZ80Table[acu ^ temp ^ sum]; - break; - case 0x8c: /* ADC A,IYH */ - tStates += 9; - sim_brk_pend = FALSE; - temp = hreg(IY); - acu = hreg(AF); - sum = acu + temp + TSTFLAG(C); - AF = addTable[sum] | cbitsZ80Table[acu ^ temp ^ sum]; - break; - case 0x8d: /* ADC A,IYL */ - tStates += 9; - sim_brk_pend = FALSE; - temp = lreg(IY); - acu = hreg(AF); - sum = acu + temp + TSTFLAG(C); - AF = addTable[sum] | cbitsZ80Table[acu ^ temp ^ sum]; - break; - case 0x8e: /* ADC A,(IY+dd) */ - tStates += 19; - adr = IY + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - temp = GetBYTE(adr); - acu = hreg(AF); - sum = acu + temp + TSTFLAG(C); - AF = addTable[sum] | cbitsZ80Table[acu ^ temp ^ sum]; - break; - case 0x96: /* SUB (IY+dd) */ - tStates += 19; - adr = IY + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - temp = GetBYTE(adr); - acu = hreg(AF); - sum = acu - temp; - AF = addTable[sum & 0xff] | cbits2Z80Table[(acu ^ temp ^ sum) & 0x1ff]; - break; - case 0x94: /* SUB IYH */ - SETFLAG(C, 0);/* fall through, a bit less efficient but smaller code */ - case 0x9c: /* SBC A,IYH */ - tStates += 9; - sim_brk_pend = FALSE; - temp = hreg(IY); - acu = hreg(AF); - sum = acu - temp - TSTFLAG(C); - AF = addTable[sum & 0xff] | cbits2Z80Table[(acu ^ temp ^ sum) & 0x1ff]; - break; - case 0x95: /* SUB IYL */ - SETFLAG(C, 0);/* fall through, a bit less efficient but smaller code */ - case 0x9d: /* SBC A,IYL */ - tStates += 9; - sim_brk_pend = FALSE; - temp = lreg(IY); - acu = hreg(AF); - sum = acu - temp - TSTFLAG(C); - AF = addTable[sum & 0xff] | cbits2Z80Table[(acu ^ temp ^ sum) & 0x1ff]; - break; - case 0x9e: /* SBC A,(IY+dd) */ - tStates += 19; - adr = IY + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - temp = GetBYTE(adr); - acu = hreg(AF); - sum = acu - temp - TSTFLAG(C); - AF = addTable[sum & 0xff] | cbits2Z80Table[(acu ^ temp ^ sum) & 0x1ff]; - break; - case 0xa4: /* AND IYH */ - tStates += 9; - sim_brk_pend = FALSE; - AF = andTable[((AF & IY) >> 8) & 0xff]; - break; - case 0xa5: /* AND IYL */ - tStates += 9; - sim_brk_pend = FALSE; - AF = andTable[((AF >> 8) & IY) & 0xff]; - break; - case 0xa6: /* AND (IY+dd) */ - tStates += 19; - adr = IY + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - AF = andTable[((AF >> 8) & GetBYTE(adr)) & 0xff]; - break; - case 0xac: /* XOR IYH */ - tStates += 9; - sim_brk_pend = FALSE; - AF = xororTable[((AF ^ IY) >> 8) & 0xff]; - break; - case 0xad: /* XOR IYL */ - tStates += 9; - sim_brk_pend = FALSE; - AF = xororTable[((AF >> 8) ^ IY) & 0xff]; - break; - case 0xae: /* XOR (IY+dd) */ - tStates += 19; - adr = IY + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - AF = xororTable[((AF >> 8) ^ GetBYTE(adr)) & 0xff]; - break; - case 0xb4: /* OR IYH */ - tStates += 9; - sim_brk_pend = FALSE; - AF = xororTable[((AF | IY) >> 8) & 0xff]; - break; - case 0xb5: /* OR IYL */ - tStates += 9; - sim_brk_pend = FALSE; - AF = xororTable[((AF >> 8) | IY) & 0xff]; - break; - case 0xb6: /* OR (IY+dd) */ - tStates += 19; - adr = IY + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - AF = xororTable[((AF >> 8) | GetBYTE(adr)) & 0xff]; - break; - case 0xbc: /* CP IYH */ - tStates += 9; - sim_brk_pend = FALSE; - temp = hreg(IY); - AF = (AF & ~0x28) | (temp & 0x28); - acu = hreg(AF); - sum = acu - temp; - AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) | - cbits2Z80Table[(acu ^ temp ^ sum) & 0x1ff]; - break; - case 0xbd: /* CP IYL */ - tStates += 9; - sim_brk_pend = FALSE; - temp = lreg(IY); - AF = (AF & ~0x28) | (temp & 0x28); - acu = hreg(AF); - sum = acu - temp; - AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) | - cbits2Z80Table[(acu ^ temp ^ sum) & 0x1ff]; - break; - case 0xbe: /* CP (IY+dd) */ - tStates += 19; - adr = IY + (signed char) RAM_pp(PC); - CheckBreakByte(adr); - temp = GetBYTE(adr); - AF = (AF & ~0x28) | (temp & 0x28); - acu = hreg(AF); - sum = acu - temp; - AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) | - cbits2Z80Table[(acu ^ temp ^ sum) & 0x1ff]; - break; - case 0xcb: /* CB prefix */ - adr = IY + (signed char) RAM_pp(PC); - switch ((op = GetBYTE(PC)) & 7) { - case 0: - sim_brk_pend = FALSE; - ++PC; - acu = hreg(BC); - break; - case 1: - sim_brk_pend = FALSE; - ++PC; - acu = lreg(BC); - break; - case 2: - sim_brk_pend = FALSE; - ++PC; - acu = hreg(DE); - break; - case 3: - sim_brk_pend = FALSE; - ++PC; - acu = lreg(DE); - break; - case 4: - sim_brk_pend = FALSE; - ++PC; - acu = hreg(HL); - break; - case 5: - sim_brk_pend = FALSE; - ++PC; - acu = lreg(HL); - break; - case 6: - CheckBreakByte(adr); - ++PC; - acu = GetBYTE(adr); - break; - case 7: - sim_brk_pend = FALSE; - ++PC; - acu = hreg(AF); - break; - } - switch (op & 0xc0) { - case 0x00: /* shift/rotate */ - tStates += 23; - switch (op & 0x38) { - case 0x00: /* RLC */ - temp = (acu << 1) | (acu >> 7); - cbits = temp & 1; - goto cbshflg3; - case 0x08: /* RRC */ - temp = (acu >> 1) | (acu << 7); - cbits = temp & 0x80; - goto cbshflg3; - case 0x10: /* RL */ - temp = (acu << 1) | TSTFLAG(C); - cbits = acu & 0x80; - goto cbshflg3; - case 0x18: /* RR */ - temp = (acu >> 1) | (TSTFLAG(C) << 7); - cbits = acu & 1; - goto cbshflg3; - case 0x20: /* SLA */ - temp = acu << 1; - cbits = acu & 0x80; - goto cbshflg3; - case 0x28: /* SRA */ - temp = (acu >> 1) | (acu & 0x80); - cbits = acu & 1; - goto cbshflg3; - case 0x30: /* SLIA */ - temp = (acu << 1) | 1; - cbits = acu & 0x80; - goto cbshflg3; - case 0x38: /* SRL */ - temp = acu >> 1; - cbits = acu & 1; - cbshflg3: - AF = (AF & ~0xff) | rotateShiftTable[temp & 0xff] | !!cbits; - } - break; - case 0x40: /* BIT */ - tStates += 20; - if (acu & (1 << ((op >> 3) & 7))) { - AF = (AF & ~0xfe) | 0x10 | (((op & 0x38) == 0x38) << 7); - } - else { - AF = (AF & ~0xfe) | 0x54; - } - if ((op & 7) != 6) { - AF |= (acu & 0x28); - } - temp = acu; - break; - case 0x80: /* RES */ - tStates += 23; - temp = acu & ~(1 << ((op >> 3) & 7)); - break; - case 0xc0: /* SET */ - tStates += 23; - temp = acu | (1 << ((op >> 3) & 7)); - break; - } - switch (op & 7) { - case 0: - Sethreg(BC, temp); - break; - case 1: - Setlreg(BC, temp); - break; - case 2: - Sethreg(DE, temp); - break; - case 3: - Setlreg(DE, temp); - break; - case 4: - Sethreg(HL, temp); - break; - case 5: - Setlreg(HL, temp); - break; - case 6: - PutBYTE(adr, temp); - break; - case 7: - Sethreg(AF, temp); - break; - } - break; - case 0xe1: /* POP IY */ - tStates += 14; - CheckBreakWord(SP); - POP(IY); - break; - case 0xe3: /* EX (SP),IY */ - tStates += 23; - CheckBreakWord(SP); - temp = IY; - POP(IY); - PUSH(temp); - break; - case 0xe5: /* PUSH IY */ - tStates += 15; - CheckBreakWord(SP - 2); - PUSH(IY); - break; - case 0xe9: /* JP (IY) */ - tStates += 8; - sim_brk_pend = FALSE; - PCQ_ENTRY(PC - 2); - PC = IY; - break; - case 0xf9: /* LD SP,IY */ - tStates += 10; - sim_brk_pend = FALSE; - SP = IY; - break; - default: /* ignore FD */ - sim_brk_pend = FALSE; - checkCPUZ80; - PC--; - } - break; - case 0xfe: /* CP nn */ - tStates += 7; - sim_brk_pend = FALSE; - temp = RAM_pp(PC); - AF = (AF & ~0x28) | (temp & 0x28); - acu = hreg(AF); - sum = acu - temp; - cbits = acu ^ temp ^ sum; - AF = (AF & ~0xff) | cpTable[sum & 0xff] | (temp & 0x28) | - (SetPV) | cbits2Table[cbits & 0x1ff]; - break; - case 0xff: /* RST 38H */ - tStates += 11; - CheckBreakWord(SP - 2); - PUSH(PC); - PCQ_ENTRY(PC - 1); - PC = 0x38; - } - } - end_decode: - pc = PC; - af[af_sel] = AF; - regs[regs_sel].bc = BC; - regs[regs_sel].de = DE; - regs[regs_sel].hl = HL; - ix = IX; - iy = IY; - sp = SP; - - /* simulation halted */ - saved_PC = ((reason == STOP_OPCODE) || (reason == STOP_MEM)) ? PCX : pc; - pcq_r -> qptr = pcq_p; /* update pc q ptr */ - AF_S = af[af_sel]; - BC_S = regs[regs_sel].bc; - DE_S = regs[regs_sel].de; - HL_S = regs[regs_sel].hl; - IX_S = ix; - IY_S = iy; - SP_S = sp; - AF1_S = af[1 - af_sel]; - BC1_S = regs[1 - regs_sel].bc; - DE1_S = regs[1 - regs_sel].de; - HL1_S = regs[1 - regs_sel].hl; - IFF_S = IFF; - IR_S = ir; - executedTStates = tStates; - return reason; -} - -int32 install_bootrom(void) { - int32 i, cnt = 0; - for (i = 0; i < bootrom_size; i++) { - if (M[i + defaultROMLow][0] != (bootrom[i] & 0xff)) { - cnt++; - M[i + defaultROMLow][0] = bootrom[i] & 0xff; - } - } - return cnt; -} - -static int32 lowProtect; -static int32 highProtect; -static int32 isProtected = FALSE; - -void protect(const int32 l, const int32 h) { - isProtected = TRUE; - lowProtect = l; - highProtect = h; -} - -static void resetCell(const int32 address, const int32 bank) { - if (!(isProtected && (bank == 0) && (lowProtect <= address) && (address <= highProtect))) { - M[address][bank] = 0; - } -} - -static void reset_memory(void) { - uint32 i, j; - checkROMBoundaries(); - if (cpu_unit.flags & UNIT_BANKED) { - for (i = 0; i < MAXMEMSIZE; i++) { - for (j = 0; j < MAXBANKS; j++) { - resetCell(i, j); - } - } - } - else if (cpu_unit.flags & UNIT_ROM) { - for (i = 0; i < ROMLow; i++) { - resetCell(i, 0); - } - for (i = ROMHigh + 1; i < MAXMEMSIZE; i++) { - resetCell(i, 0); - } - } - else { - for (i = 0; i < MAXMEMSIZE; i++) { - resetCell(i, 0); - } - } - if (cpu_unit.flags & (UNIT_ALTAIRROM | UNIT_BANKED)) { - install_bootrom(); - } - isProtected = FALSE; -} - -void printROMMessage(const uint32 cntROM) { - if (cntROM) { - printf("Warning: %d bytes written to ROM [%04X - %04X].\n", cntROM, ROMLow, ROMHigh); - } -} - -/* reset routine */ - -t_stat cpu_reset(DEVICE *dptr) { - int32 i; - AF_S = AF1_S = 0; - af_sel = 0; - BC_S = DE_S = HL_S = 0; - regs_sel = 0; - BC1_S = DE1_S = HL1_S = 0; - IR_S = IX_S = IY_S = SP_S = 0; - IFF_S = 3; - bankSelect = 0; - reset_memory(); - sim_brk_types = (SWMASK('E') | SWMASK('M')); - sim_brk_dflt = SWMASK('E'); - for (i = 0; i < PCQ_SIZE; i++) { - pcq[i] = 0; - } - pcq_p = 0; - pcq_r = find_reg("PCQ", NULL, dptr); - 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) { - *vptr = M[addr & ADDRMASK][(addr >> 16) & BANKMASK]; - return SCPE_OK; -} - -/* memory deposit */ -t_stat cpu_dep(t_value val, t_addr addr, UNIT *uptr, int32 sw) { - M[addr & ADDRMASK][(addr >> 16) & BANKMASK] = val & 0xff; - return SCPE_OK; -} - -static void checkROMBoundaries(void) { - uint32 temp; - if (ROMLow > ROMHigh) { - printf("ROMLOW [%04X] must be less than or equal to ROMHIGH [%04X]. Values exchanged.\n", - ROMLow, ROMHigh); - temp = ROMLow; - ROMLow = ROMHigh; - ROMHigh = temp; - } - if (cpu_unit.flags & UNIT_ALTAIRROM) { - if (defaultROMLow < ROMLow) { - printf("ROMLOW [%04X] reset to %04X since Altair ROM was desired.\n", ROMLow, defaultROMLow); - ROMLow = defaultROMLow; - } - if (ROMHigh < defaultROMHigh) { - printf("ROMHIGH [%04X] reset to %04X since Altair ROM was desired.\n", ROMHigh, defaultROMHigh); - ROMHigh = defaultROMHigh; - } - } -} - -static t_stat cpu_set_rom(UNIT *uptr, int32 value, char *cptr, void *desc) { - checkROMBoundaries(); - return SCPE_OK; -} - -static t_stat cpu_set_norom(UNIT *uptr, int32 value, char *cptr, void *desc) { - if (cpu_unit.flags & UNIT_ALTAIRROM) { - printf("\"SET CPU NOALTAIRROM\" also executed.\n"); - cpu_unit.flags &= ~UNIT_ALTAIRROM; - } - return SCPE_OK; -} - -static t_stat cpu_set_altairrom(UNIT *uptr, int32 value, char *cptr, void *desc) { - install_bootrom(); - if (ROMLow != defaultROMLow) { - printf("\"D ROMLOW %04X\" also executed.\n", defaultROMLow); - ROMLow = defaultROMLow; - } - if (ROMHigh != defaultROMHigh) { - printf("\"D ROMHIGH %04X\" also executed.\n", defaultROMHigh); - ROMHigh = defaultROMHigh; - } - if (!(cpu_unit.flags & UNIT_ROM)) { - printf("\"SET CPU ROM\" also executed.\n"); - cpu_unit.flags |= UNIT_ROM; - } - return SCPE_OK; -} - -static t_stat cpu_set_warnrom(UNIT *uptr, int32 value, char *cptr, void *desc) { - if ((!(cpu_unit.flags & UNIT_ROM)) && (MEMSIZE >= 64*KB)) { - printf("CPU has currently no ROM - no warning to be expected.\n"); - } - return SCPE_OK; -} - -static t_stat cpu_set_banked(UNIT *uptr, int32 value, char *cptr, void *desc) { - if (common > defaultROMLow) { - printf("Warning: COMMON [%04X] must not be greater than %04X. Reset to %04X.\n", - common, defaultROMLow, defaultROMLow); - common = defaultROMLow; - } - if (MEMSIZE != (MAXBANKS * MAXMEMSIZE)) { - previousCapacity = MEMSIZE; - } - MEMSIZE = MAXBANKS * MAXMEMSIZE; - cpu_dev.awidth = 16 + MAXBANKSLOG2; - return SCPE_OK; -} - -static t_stat cpu_set_nonbanked(UNIT *uptr, int32 value, char *cptr, void *desc) { - if (MEMSIZE == (MAXBANKS * MAXMEMSIZE)) { - MEMSIZE = previousCapacity ? previousCapacity : 64*KB; - } - cpu_dev.awidth = 16; - return SCPE_OK; -} - -static t_stat cpu_set_size(UNIT *uptr, int32 value, char *cptr, void *desc) { - if (cpu_unit.flags & UNIT_BANKED) { - printf("\"SET CPU NONBANKED\" also executed.\n"); - cpu_unit.flags &= ~UNIT_BANKED; - } - MEMSIZE = value; - cpu_dev.awidth = 16; - reset_memory(); - return SCPE_OK; -} diff --git a/AltairZ80/altairZ80_defs.h b/AltairZ80/altairZ80_defs.h deleted file mode 100644 index fe5cbc83..00000000 --- a/AltairZ80/altairZ80_defs.h +++ /dev/null @@ -1,90 +0,0 @@ -/* altairz80_defs.h: MITS Altair simulator definitions - - Copyright (c) 2002-2003, Peter Schorn - - 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 - PETER SCHORN 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 Peter Schorn shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Peter Schorn. - - Based on work by Charles E Owen (c) 1997 -*/ - -#include "sim_defs.h" /* simulator definitions */ - -#define MAXMEMSIZE 65536 /* maximum memory size */ -#define ADDRMASK (MAXMEMSIZE - 1) /* address mask */ -#define bootrom_size 256 /* size of boot rom */ -#define MAXBANKS 8 /* max number of memory banks */ -#define MAXBANKSLOG2 3 /* log2 of MAXBANKS */ -#define BANKMASK (MAXBANKS-1) /* bank mask */ -#define MEMSIZE (cpu_unit.capac) /* actual memory size */ -#define KB 1024 /* kilo byte */ -#define defaultROMLow 0xff00 /* default for lowest addres of ROM */ -#define defaultROMHigh 0xffff /* default for highest addres of ROM */ - -#define NUM_OF_DSK 8 /* NUM_OF_DSK must be power of two */ -#define LDAInstruction 0x3e /* op-code for LD A,<8-bit value> instruction */ -#define unitNoOffset1 0x37 /* LD A, */ -#define unitNoOffset2 0xb4 /* LD a,80h | */ - -#define UNIT_V_OPSTOP (UNIT_V_UF+0) /* stop on nvalid operation */ -#define UNIT_OPSTOP (1 << UNIT_V_OPSTOP) -#define UNIT_V_CHIP (UNIT_V_UF+1) /* 8080 or Z80 CPU */ -#define UNIT_CHIP (1 << UNIT_V_CHIP) -#define UNIT_V_MSIZE (UNIT_V_UF+2) /* memory size */ -#define UNIT_MSIZE (1 << UNIT_V_MSIZE) -#define UNIT_V_BANKED (UNIT_V_UF+3) /* banked memory is used */ -#define UNIT_BANKED (1 << UNIT_V_BANKED) -#define UNIT_V_ROM (UNIT_V_UF+4) /* ROM exists */ -#define UNIT_ROM (1 << UNIT_V_ROM) -#define UNIT_V_ALTAIRROM (UNIT_V_UF+5) /* ALTAIR ROM exists */ -#define UNIT_ALTAIRROM (1 << UNIT_V_ALTAIRROM) -#define UNIT_V_WARNROM (UNIT_V_UF+6) /* warn if ROM is written to */ -#define UNIT_WARNROM (1 << UNIT_V_WARNROM) - -#define AddressFormat "[%04xh]" -#define PCformat "\n" AddressFormat " " -#define message1(p1) \ - sprintf(messageBuffer,PCformat p1,PCX); printMessage() -#define message2(p1,p2) \ - sprintf(messageBuffer,PCformat p1,PCX,p2); printMessage() -#define message3(p1,p2,p3) \ - sprintf(messageBuffer,PCformat p1,PCX,p2,p3); printMessage() -#define message4(p1,p2,p3,p4) \ - sprintf(messageBuffer,PCformat p1,PCX,p2,p3,p4); printMessage() -#define message5(p1,p2,p3,p4,p5) \ - sprintf(messageBuffer,PCformat p1,PCX,p2,p3,p4,p5); printMessage() -#define message6(p1,p2,p3,p4,p5,p6) \ - sprintf(messageBuffer,PCformat p1,PCX,p2,p3,p4,p5,p6); printMessage() - -/* The Default is to use "inline". In this case the wrapper functions for - GetBYTE and PutBYTE need to be created. Otherwise they are not needed - and the calls map to the original functions. */ -#ifdef NO_INLINE -#define INLINE -#define GetBYTEWrapper GetBYTE -#define PutBYTEWrapper PutBYTE -#else -#if defined(__DECC) && defined(VMS) -#define INLINE __inline -#else -#define INLINE inline -#endif -#endif diff --git a/AltairZ80/altairZ80_dsk.c b/AltairZ80/altairZ80_dsk.c deleted file mode 100644 index 8856e9cd..00000000 --- a/AltairZ80/altairZ80_dsk.c +++ /dev/null @@ -1,569 +0,0 @@ -/* altairz80_dsk.c: MITS Altair 88-DISK Simulator - - Copyright (c) 2002-2003, Peter Schorn - - 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 - PETER SCHORN 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 Peter Schorn shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Peter Schorn. - - Based on work by Charles E Owen (c) 1997 - - The 88_DISK is a 8-inch floppy controller which can control up - to 16 daisy-chained Pertec FD-400 hard-sectored floppy drives. - Each diskette has physically 77 tracks of 32 137-byte sectors - each. - - The controller is interfaced to the CPU by use of 3 I/O addreses, - standardly, these are device numbers 10, 11, and 12 (octal). - - Address Mode Function - ------- ---- -------- - - 10 Out Selects and enables Controller and Drive - 10 In Indicates status of Drive and Controller - 11 Out Controls Disk Function - 11 In Indicates current sector position of disk - 12 Out Write data - 12 In Read data - - Drive Select Out (Device 10 OUT): - - +---+---+---+---+---+---+---+---+ - | C | X | X | X | Device | - +---+---+---+---+---+---+---+---+ - - C = If this bit is 1, the disk controller selected by 'device' is - cleared. If the bit is zero, 'device' is selected as the - device being controlled by subsequent I/O operations. - X = not used - Device = value zero thru 15, selects drive to be controlled. - - Drive Status In (Device 10 IN): - - +---+---+---+---+---+---+---+---+ - | R | Z | I | X | X | H | M | W | - +---+---+---+---+---+---+---+---+ - - W - When 0, write circuit ready to write another byte. - M - When 0, head movement is allowed - H - When 0, indicates head is loaded for read/write - X - not used (will be 0) - I - When 0, indicates interrupts enabled (not used by this simulator) - Z - When 0, indicates head is on track 0 - R - When 0, indicates that read circuit has new byte to read - - Drive Control (Device 11 OUT): - - +---+---+---+---+---+---+---+---+ - | W | C | D | E | U | H | O | I | - +---+---+---+---+---+---+---+---+ - - I - When 1, steps head IN one track - O - When 1, steps head OUT one track - H - When 1, loads head to drive surface - U - When 1, unloads head - E - Enables interrupts (ignored by this simulator) - D - Disables interrupts (ignored by this simulator) - C - When 1 lowers head current (ignored by this simulator) - W - When 1, starts Write Enable sequence: W bit on device 10 - (see above) will go 1 and data will be read from port 12 - until 137 bytes have been read by the controller from - that port. The W bit will go off then, and the sector data - will be written to disk. Before you do this, you must have - stepped the track to the desired number, and waited until - the right sector number is presented on device 11 IN, then - set this bit. - - Sector Position (Device 11 IN): - - As the sectors pass by the read head, they are counted and the - number of the current one is available in this register. - - +---+---+---+---+---+---+---+---+ - | X | X | Sector Number | T | - +---+---+---+---+---+---+---+---+ - - X = Not used - Sector number = binary of the sector number currently under the - head, 0-31. - T = Sector True, is a 1 when the sector is positioned to read or - write. - -*/ - -#include "altairz80_defs.h" - -#define UNIT_V_DSKWLK (UNIT_V_UF + 0) /* write locked */ -#define UNIT_DSKWLK (1 << UNIT_V_DSKWLK) -#define UNIT_V_DSK_VERBOSE (UNIT_V_UF + 1) /* verbose mode, i.e. show error messages */ -#define UNIT_DSK_VERBOSE (1 << UNIT_V_DSK_VERBOSE) -#define DSK_SECTSIZE 137 /* size of sector */ -#define DSK_SECT 32 /* sectors per track */ -#define MAX_TRACKS 254 /* number of tracks, - original Altair has 77 tracks only */ -#define DSK_TRACSIZE (DSK_SECTSIZE * DSK_SECT) -#define MAX_DSK_SIZE (DSK_TRACSIZE * MAX_TRACKS) -#define TRACE_IN_OUT 1 -#define TRACE_READ_WRITE 2 -#define TRACE_SECTOR_STUCK 4 -#define TRACE_TRACK_STUCK 8 -#define NUM_OF_DSK_MASK (NUM_OF_DSK - 1) - -int32 dsk10(const int32 port, const int32 io, const int32 data); -int32 dsk11(const int32 port, const int32 io, const int32 data); -int32 dsk12(const int32 port, const int32 io, const int32 data); -static int32 dskseek(const UNIT *xptr); -static t_stat dsk_boot(int32 unitno, DEVICE *dptr); -static t_stat dsk_reset(DEVICE *dptr); -static t_stat dsk_svc(UNIT *uptr); -static void writebuf(void); -static t_stat dsk_set_verbose(UNIT *uptr, int32 value, char *cptr, void *desc); -static void resetDSKWarningFlags(void); -static int32 hasVerbose(void); -static char* selectInOut(const int32 io); - -extern int32 PCX; -extern int32 saved_PC; -extern FILE *sim_log; -extern void PutBYTEWrapper(register uint32 Addr, register uint32 Value); -extern void printMessage(void); -extern char messageBuffer[]; -extern int32 install_bootrom(void); -extern UNIT cpu_unit; - -/* global data on status */ - -static int32 current_disk = NUM_OF_DSK; /* currently selected drive (values are 0 .. NUM_OF_DSK) - current_disk < NUM_OF_DSK implies that the corresponding disk is attached to a file */ -static int32 current_track [NUM_OF_DSK] = {0, 0, 0, 0, 0, 0, 0, 0}; -static int32 current_sector [NUM_OF_DSK] = {0, 0, 0, 0, 0, 0, 0, 0}; -static int32 current_byte [NUM_OF_DSK] = {0, 0, 0, 0, 0, 0, 0, 0}; -static int32 current_flag [NUM_OF_DSK] = {0, 0, 0, 0, 0, 0, 0, 0}; -static uint8 tracks [NUM_OF_DSK] = { MAX_TRACKS, MAX_TRACKS, MAX_TRACKS, MAX_TRACKS, - MAX_TRACKS, MAX_TRACKS, MAX_TRACKS, MAX_TRACKS }; -static int32 trace_flag = 0; -static int32 in9_count = 0; -static int32 in9_message = FALSE; -static int32 dirty = FALSE; /* TRUE when buffer has unwritten data in it */ -static int32 warnLevelDSK = 3; -static int32 warnLock [NUM_OF_DSK] = {0, 0, 0, 0, 0, 0, 0, 0}; -static int32 warnAttached [NUM_OF_DSK] = {0, 0, 0, 0, 0, 0, 0, 0}; -static int32 warnDSK10 = 0; -static int32 warnDSK11 = 0; -static int32 warnDSK12 = 0; -static int8 dskbuf[DSK_SECTSIZE]; /* data Buffer */ - -/* Altair MITS modified BOOT EPROM, fits in upper 256 byte of memory */ -int32 bootrom[bootrom_size] = { - 0xf3, 0x06, 0x80, 0x3e, 0x0e, 0xd3, 0xfe, 0x05, /* ff00-ff07 */ - 0xc2, 0x05, 0xff, 0x3e, 0x16, 0xd3, 0xfe, 0x3e, /* ff08-ff0f */ - 0x12, 0xd3, 0xfe, 0xdb, 0xfe, 0xb7, 0xca, 0x20, /* ff10-ff17 */ - 0xff, 0x3e, 0x0c, 0xd3, 0xfe, 0xaf, 0xd3, 0xfe, /* ff18-ff1f */ - 0x21, 0x00, 0x5c, 0x11, 0x33, 0xff, 0x0e, 0x88, /* ff20-ff27 */ - 0x1a, 0x77, 0x13, 0x23, 0x0d, 0xc2, 0x28, 0xff, /* ff28-ff2f */ - 0xc3, 0x00, 0x5c, 0x31, 0x21, 0x5d, 0x3e, 0x00, /* ff30-ff37 */ - 0xd3, 0x08, 0x3e, 0x04, 0xd3, 0x09, 0xc3, 0x19, /* ff38-ff3f */ - 0x5c, 0xdb, 0x08, 0xe6, 0x02, 0xc2, 0x0e, 0x5c, /* ff40-ff47 */ - 0x3e, 0x02, 0xd3, 0x09, 0xdb, 0x08, 0xe6, 0x40, /* ff48-ff4f */ - 0xc2, 0x0e, 0x5c, 0x11, 0x00, 0x00, 0x06, 0x08, /* ff50-ff57 */ - 0xc5, 0xd5, 0x11, 0x86, 0x80, 0x21, 0x88, 0x5c, /* ff58-ff5f */ - 0xdb, 0x09, 0x1f, 0xda, 0x2d, 0x5c, 0xe6, 0x1f, /* ff60-ff67 */ - 0xb8, 0xc2, 0x2d, 0x5c, 0xdb, 0x08, 0xb7, 0xfa, /* ff68-ff6f */ - 0x39, 0x5c, 0xdb, 0x0a, 0x77, 0x23, 0x1d, 0xc2, /* ff70-ff77 */ - 0x39, 0x5c, 0xd1, 0x21, 0x8b, 0x5c, 0x06, 0x80, /* ff78-ff7f */ - 0x7e, 0x12, 0x23, 0x13, 0x05, 0xc2, 0x4d, 0x5c, /* ff80-ff87 */ - 0xc1, 0x21, 0x00, 0x5c, 0x7a, 0xbc, 0xc2, 0x60, /* ff88-ff8f */ - 0x5c, 0x7b, 0xbd, 0xd2, 0x80, 0x5c, 0x04, 0x04, /* ff90-ff97 */ - 0x78, 0xfe, 0x20, 0xda, 0x25, 0x5c, 0x06, 0x01, /* ff98-ff9f */ - 0xca, 0x25, 0x5c, 0xdb, 0x08, 0xe6, 0x02, 0xc2, /* ffa0-ffa7 */ - 0x70, 0x5c, 0x3e, 0x01, 0xd3, 0x09, 0x06, 0x00, /* ffa8-ffaf */ - 0xc3, 0x25, 0x5c, 0x3e, 0x80, 0xd3, 0x08, 0xfb, /* ffb0-ffb7 */ - 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ffb8-ffbf */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ffc0-ffc7 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ffc8-ffcf */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ffd0-ffd7 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ffd8-ffdf */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ffe0-ffe7 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ffe8-ffef */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* fff0-fff7 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* fff8-ffff */ -}; - -/* 88DSK Standard I/O Data Structures */ - -static UNIT dsk_unit[] = { - { UDATA (&dsk_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, MAX_DSK_SIZE) }, - { UDATA (&dsk_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, MAX_DSK_SIZE) }, - { UDATA (&dsk_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, MAX_DSK_SIZE) }, - { UDATA (&dsk_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, MAX_DSK_SIZE) }, - { UDATA (&dsk_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, MAX_DSK_SIZE) }, - { UDATA (&dsk_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, MAX_DSK_SIZE) }, - { UDATA (&dsk_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, MAX_DSK_SIZE) }, - { UDATA (&dsk_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, MAX_DSK_SIZE) } }; - -static REG dsk_reg[] = { - { DRDATA (DISK, current_disk, 4) }, - { BRDATA (CURTRACK, current_track, 10, 32, NUM_OF_DSK), REG_CIRC + REG_RO }, - { BRDATA (CURSECTOR, current_sector, 10, 32, NUM_OF_DSK), REG_CIRC + REG_RO }, - { BRDATA (CURBYTE, current_byte, 10, 32, NUM_OF_DSK), REG_CIRC + REG_RO }, - { BRDATA (CURFLAG, current_flag, 10, 32, NUM_OF_DSK), REG_CIRC + REG_RO }, - { BRDATA (TRACKS, tracks, 10, 8, NUM_OF_DSK), REG_CIRC }, - { ORDATA (TRACE, trace_flag, 8) }, - { DRDATA (IN9COUNT, in9_count, 4), REG_RO }, - { DRDATA (IN9MESSAGE, in9_message, 4), REG_RO }, - { DRDATA (DIRTY, dirty, 4), REG_RO }, - { DRDATA (DSKWL, warnLevelDSK, 32) }, - { BRDATA (WARNLOCK, warnLock, 10, 32, NUM_OF_DSK), REG_CIRC + REG_RO }, - { BRDATA (WARNATTACHED, warnAttached, 10, 32, NUM_OF_DSK), REG_CIRC + REG_RO }, - { DRDATA (WARNDSK10, warnDSK10, 4), REG_RO }, - { DRDATA (WARNDSK11, warnDSK11, 4), REG_RO }, - { DRDATA (WARNDSK12, warnDSK12, 4), REG_RO }, - { BRDATA (DISKBUFFER, dskbuf, 10, 8, DSK_SECTSIZE), REG_CIRC + REG_RO }, - { NULL } }; - -static MTAB dsk_mod[] = { - { UNIT_DSKWLK, 0, "write enabled", "WRITEENABLED", NULL }, - { UNIT_DSKWLK, UNIT_DSKWLK, "write locked", "LOCKED", NULL }, - /* quiet, no warning messages */ - { UNIT_DSK_VERBOSE, 0, "QUIET", "QUIET", NULL }, - /* verbose, show warning messages */ - { UNIT_DSK_VERBOSE, UNIT_DSK_VERBOSE, "VERBOSE", "VERBOSE", &dsk_set_verbose }, - { 0 } }; - -DEVICE dsk_dev = { - "DSK", dsk_unit, dsk_reg, dsk_mod, - 8, 10, 31, 1, 8, 8, - NULL, NULL, &dsk_reset, - &dsk_boot, NULL, NULL, NULL, 0, NULL, NULL }; - -static void resetDSKWarningFlags(void) { - int32 i; - for (i = 0; i < NUM_OF_DSK; i++) { - warnLock[i] = 0; - warnAttached[i] = 0; - } - warnDSK10 = 0; - warnDSK11 = 0; - warnDSK12 = 0; -} - -static t_stat dsk_set_verbose(UNIT *uptr, int32 value, char *cptr, void *desc) { - resetDSKWarningFlags(); - return SCPE_OK; -} - -/* returns TRUE iff there exists a disk with VERBOSE */ -static int32 hasVerbose(void) { - int32 i; - for (i = 0; i < NUM_OF_DSK; i++) { - if (((dsk_dev.units + i) -> flags) & UNIT_DSK_VERBOSE) { - return TRUE; - } - } - return FALSE; -} - -static char* selectInOut(const int32 io) { - return io == 0 ? "IN" : "OUT"; -} - -/* service routines to handle simulator functions */ - -/* service routine - actually gets char & places in buffer */ - -static t_stat dsk_svc(UNIT *uptr) { - return SCPE_OK; -} - -/* reset routine */ - -static t_stat dsk_reset(DEVICE *dptr) { - resetDSKWarningFlags(); - current_disk = NUM_OF_DSK; - trace_flag = 0; - in9_count = 0; - in9_message = FALSE; - return SCPE_OK; -} - -/* The boot routine modifies the boot ROM in such a way that subsequently - the specified disk is used for boot purposes. -*/ -static t_stat dsk_boot(int32 unitno, DEVICE *dptr) { - if (cpu_unit.flags & (UNIT_ALTAIRROM | UNIT_BANKED)) { - if (install_bootrom()) { - printf("ALTAIR boot ROM installed.\n"); - } - /* check whether we are really modifying an LD A,<> instruction */ - if ((bootrom[unitNoOffset1 - 1] == LDAInstruction) && (bootrom[unitNoOffset2 - 1] == LDAInstruction)) { - bootrom[unitNoOffset1] = unitno & 0xff; /* LD A, */ - bootrom[unitNoOffset2] = 0x80 | (unitno & 0xff); /* LD a,80h | */ - } - else { /* Attempt to modify non LD A,<> instructions is refused. */ - printf("Incorrect boot ROM offsets detected.\n"); - return SCPE_IERR; - } - } - saved_PC = defaultROMLow; - return SCPE_OK; -} - -/* I/O instruction handlers, called from the CPU module when an - IN or OUT instruction is issued. - - Each function is passed an 'io' flag, where 0 means a read from - the port, and 1 means a write to the port. On input, the actual - input is passed as the return value, on output, 'data' is written - to the device. -*/ - -/* Disk Controller Status/Select */ - -/* IMPORTANT: The status flags read by port 8 IN instruction are - INVERTED, that is, 0 is true and 1 is false. To handle this, the - simulator keeps it's own status flags as 0=false, 1=true; and - returns the COMPLEMENT of the status flags when read. This makes - setting/testing of the flag bits more logical, yet meets the - simulation requirement that they are reversed in hardware. -*/ - -int32 dsk10(const int32 port, const int32 io, const int32 data) { - int32 current_disk_flags; - in9_count = 0; - if (io == 0) { /* IN: return flags */ - if (current_disk >= NUM_OF_DSK) { - if (hasVerbose() && (warnDSK10 < warnLevelDSK)) { - warnDSK10++; -/*01*/ message1("Attempt of IN 0x08 on unattached disk - ignored.\n"); - } - return 0xff; /* no drive selected - can do nothing */ - } - return (~current_flag[current_disk]) & 0xff; /* return the COMPLEMENT! */ - } - - /* OUT: Controller set/reset/enable/disable */ - if (dirty) { /* implies that current_disk < NUM_OF_DSK */ - writebuf(); - } - if (trace_flag & TRACE_IN_OUT) { - message2("OUT 0x08: %x\n", data); - } - current_disk = data & NUM_OF_DSK_MASK; /* 0 <= current_disk < NUM_OF_DSK */ - current_disk_flags = (dsk_dev.units + current_disk) -> flags; - if ((current_disk_flags & UNIT_ATT) == 0) { /* nothing attached? */ - if ( (current_disk_flags & UNIT_DSK_VERBOSE) && (warnAttached[current_disk] < warnLevelDSK) ) { - warnAttached[current_disk]++; -/*02*/message2("Attempt to select unattached DSK%d - ignored.\n", current_disk); - } - current_disk = NUM_OF_DSK; - } - else { - current_sector[current_disk] = 0xff; /* reset internal counters */ - current_byte[current_disk] = 0xff; - current_flag[current_disk] = data & 0x80 ? 0 /* disable drive */ : - (current_track[current_disk] == 0 ? 0x5a /* enable: head move true, track 0 if there */ : - 0x1a);/* enable: head move true */ - } - return 0; /* ignored since OUT */ -} - -/* Disk Drive Status/Functions */ - -int32 dsk11(const int32 port, const int32 io, const int32 data) { - if (current_disk >= NUM_OF_DSK) { - if (hasVerbose() && (warnDSK11 < warnLevelDSK)) { - warnDSK11++; -/*03*/message2("Attempt of %s 0x09 on unattached disk - ignored.\n", selectInOut(io)); - } - return 0; /* no drive selected - can do nothing */ - } - - /* now current_disk < NUM_OF_DSK */ - if (io == 0) { /* read sector position */ - in9_count++; - if ((trace_flag & TRACE_SECTOR_STUCK) && (in9_count > 2 * DSK_SECT) && (!in9_message)) { - in9_message = TRUE; - message2("Looping on sector find %d.\n", current_disk); - } - if (trace_flag & TRACE_IN_OUT) { - message1("IN 0x09\n"); - } - if (dirty) {/* implies that current_disk < NUM_OF_DSK */ - writebuf(); - } - if (current_flag[current_disk] & 0x04) { /* head loaded? */ - current_sector[current_disk]++; - if (current_sector[current_disk] >= DSK_SECT) { - current_sector[current_disk] = 0; - } - current_byte[current_disk] = 0xff; - return (((current_sector[current_disk] << 1) & 0x3e) /* return 'sector true' bit = 0 (true) */ - | 0xc0); /* set on 'unused' bits */ - } else { - return 0; /* head not loaded - return 0 */ - } - } - - in9_count = 0; - /* drive functions */ - - if (trace_flag & TRACE_IN_OUT) { - message2("OUT 0x09: %x\n", data); - } - if (data & 0x01) { /* step head in */ - if (trace_flag & TRACE_TRACK_STUCK) { - if (current_track[current_disk] == (tracks[current_disk] - 1)) { - message2("Unnecessary step in for disk %d\n", current_disk); - } - } - current_track[current_disk]++; - if (current_track[current_disk] > (tracks[current_disk] - 1)) { - current_track[current_disk] = (tracks[current_disk] - 1); - } - if (dirty) { /* implies that current_disk < NUM_OF_DSK */ - writebuf(); - } - current_sector[current_disk] = 0xff; - current_byte[current_disk] = 0xff; - } - - if (data & 0x02) { /* step head out */ - if (trace_flag & TRACE_TRACK_STUCK) { - if (current_track[current_disk] == 0) { - message2("Unnecessary step out for disk %d\n", current_disk); - } - } - current_track[current_disk]--; - if (current_track[current_disk] < 0) { - current_track[current_disk] = 0; - current_flag[current_disk] |= 0x40; /* track 0 if there */ - } - if (dirty) { /* implies that current_disk < NUM_OF_DSK */ - writebuf(); - } - current_sector[current_disk] = 0xff; - current_byte[current_disk] = 0xff; - } - - if (dirty) { /* implies that current_disk < NUM_OF_DSK */ - writebuf(); - } - - if (data & 0x04) { /* head load */ - current_flag[current_disk] |= 0x04; /* turn on head loaded bit */ - current_flag[current_disk] |= 0x80; /* turn on 'read data available' */ - } - - if (data & 0x08) { /* head unload */ - current_flag[current_disk] &= 0xfb; /* turn off 'head loaded' bit */ - current_flag[current_disk] &= 0x7f; /* turn off 'read data available' */ - current_sector[current_disk] = 0xff; - current_byte[current_disk] = 0xff; - } - - /* interrupts & head current are ignored */ - - if (data & 0x80) { /* write sequence start */ - current_byte[current_disk] = 0; - current_flag[current_disk] |= 0x01; /* enter new write data on */ - } - return 0; /* ignored since OUT */ -} - -/* Disk Data In/Out */ - -static INLINE int32 dskseek(const UNIT *xptr) { - return fseek(xptr -> fileref, DSK_TRACSIZE * current_track[current_disk] + - DSK_SECTSIZE * current_sector[current_disk], SEEK_SET); -} - -int32 dsk12(const int32 port, const int32 io, const int32 data) { - int32 i; - UNIT *uptr; - - if (current_disk >= NUM_OF_DSK) { - if (hasVerbose() && (warnDSK12 < warnLevelDSK)) { - warnDSK12++; -/*04*/message2("Attempt of %s 0x0a on unattached disk - ignored.\n", selectInOut(io)); - } - return 0; - } - - /* now current_disk < NUM_OF_DSK */ - in9_count = 0; - uptr = dsk_dev.units + current_disk; - if (io == 0) { - if (current_byte[current_disk] >= DSK_SECTSIZE) { - /* physically read the sector */ - if (trace_flag & TRACE_READ_WRITE) { - message4("IN 0x0a (READ) D%d T%d S%d\n", current_disk, current_track[current_disk], current_sector[current_disk]); - } - for (i = 0; i < DSK_SECTSIZE; i++) { - dskbuf[i] = 0; - } - dskseek(uptr); - fread(dskbuf, DSK_SECTSIZE, 1, uptr -> fileref); - current_byte[current_disk] = 0; - } - return dskbuf[current_byte[current_disk]++] & 0xff; - } - else { - if (current_byte[current_disk] >= DSK_SECTSIZE) { - writebuf(); /* from above we have that current_disk < NUM_OF_DSK */ - } - else { - dirty = TRUE; /* this guarantees for the next call to writebuf that current_disk < NUM_OF_DSK */ - dskbuf[current_byte[current_disk]++] = data & 0xff; - } - return 0; /* ignored since OUT */ - } -} - -/* precondition: current_disk < NUM_OF_DSK */ -static void writebuf(void) { - int32 i, rtn; - UNIT *uptr; - i = current_byte[current_disk]; /* null-fill rest of sector if any */ - while (i < DSK_SECTSIZE) { - dskbuf[i++] = 0; - } - uptr = dsk_dev.units + current_disk; - if (((uptr -> flags) & UNIT_DSKWLK) == 0) { /* write enabled */ - if (trace_flag & TRACE_READ_WRITE) { - message4("OUT 0x0a (WRITE) D%d T%d S%d\n", current_disk, current_track[current_disk], current_sector[current_disk]); - } - if (dskseek(uptr)) { - message4("fseek failed D%d T%d S%d\n", current_disk, current_track[current_disk], current_sector[current_disk]); - } - rtn = fwrite(dskbuf, DSK_SECTSIZE, 1, uptr -> fileref); - if (rtn != 1) { - message4("fwrite failed T%d S%d Return=%d\n", current_track[current_disk], current_sector[current_disk], rtn); - } - } - else if ( ((uptr -> flags) & UNIT_DSK_VERBOSE) && (warnLock[current_disk] < warnLevelDSK) ) { - /* write locked - print warning message if required */ - warnLock[current_disk]++; -/*05*/ - message2("Attempt to write to locked DSK%d - ignored.\n", current_disk); - } - current_flag[current_disk] &= 0xfe; /* ENWD off */ - current_byte[current_disk] = 0xff; - dirty = FALSE; -} diff --git a/AltairZ80/altairZ80_sio.c b/AltairZ80/altairZ80_sio.c deleted file mode 100644 index e640e5df..00000000 --- a/AltairZ80/altairZ80_sio.c +++ /dev/null @@ -1,1105 +0,0 @@ -/* altairz80_sio: MITS Altair serial I/O card - - Copyright (c) 2002-2003, Peter Schorn - - 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 - PETER SCHORN 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 Peter Schorn shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Peter Schorn. - - Based on work by Charles E Owen (c) 1997 - - These functions support a simulated MITS 2SIO interface card. - The card had two physical I/O ports which could be connected - to any serial I/O device that would connect to a current loop, - RS232, or TTY interface. Available baud rates were jumper - selectable for each port from 110 to 9600. - - All I/O is via programmed I/O. Each device has a status port - and a data port. A write to the status port can select - some options for the device (0x03 will reset the port). - A read of the status port gets the port status: - - +---+---+---+---+---+---+---+---+ - | X | X | X | X | X | X | O | I | - +---+---+---+---+---+---+---+---+ - - I - A 1 in this bit position means a character has been received - on the data port and is ready to be read. - O - A 1 in this bit means the port is ready to receive a character - on the data port and transmit it out over the serial line. - - A read to the data port gets the buffered character, a write - to the data port writes the character to the device. -*/ - -#include - -#include "altairz80_defs.h" -#include "sim_sock.h" -#include "sim_tmxr.h" -#include - -#define UNIT_V_ANSI (UNIT_V_UF + 0) /* ANSI mode, strip bit 8 on output */ -#define UNIT_ANSI (1 << UNIT_V_ANSI) -#define UNIT_V_UPPER (UNIT_V_UF + 1) /* uppper case mode */ -#define UNIT_UPPER (1 << UNIT_V_UPPER) -#define UNIT_V_BS (UNIT_V_UF + 2) /* map delete to backspace */ -#define UNIT_BS (1 << UNIT_V_BS) -#define UNIT_V_SIO_VERBOSE (UNIT_V_UF + 3) /* verbose mode, i.e. show error messages */ -#define UNIT_SIO_VERBOSE (1 << UNIT_V_SIO_VERBOSE) - -#define UNIT_V_SIMH_VERBOSE (UNIT_V_UF + 0) /* verbose mode for SIMH pseudo device */ -#define UNIT_SIMH_VERBOSE (1 << UNIT_V_SIMH_VERBOSE) -#define UNIT_V_SIMH_TIMERON (UNIT_V_UF + 1) /* SIMH pseudo device timer generate interrupts */ -#define UNIT_SIMH_TIMERON (1 << UNIT_V_SIMH_VERBOSE) - -#define Terminals 4 /* lines per mux */ - -#define BACKSPACE_CHAR 0x08 /* backspace character */ -#define DELETE_CHAR 0x7f /* delete character */ -#define CONTROLZ_CHAR 0x1a /* control Z character */ - -static void resetSIOWarningFlags(void); -static t_stat sio_set_verbose (UNIT *uptr, int32 value, char *cptr, void *desc); -static t_stat simh_dev_set_timeron (UNIT *uptr, int32 value, char *cptr, void *desc); -static t_stat simh_dev_set_timeroff (UNIT *uptr, int32 value, char *cptr, void *desc); -static t_stat sio_svc(UNIT *uptr); -static t_stat sio_reset(DEVICE *dptr); -static t_stat sio_attach(UNIT *uptr, char *cptr); -static t_stat sio_detach(UNIT *uptr); -static t_stat ptr_reset(DEVICE *dptr); -static t_stat ptp_reset(DEVICE *dptr); -int32 nulldev (const int32 port, const int32 io, const int32 data); -int32 sr_dev (const int32 port, const int32 io, const int32 data); -int32 simh_dev(const int32 port, const int32 io, const int32 data); -int32 sio0d (const int32 port, const int32 io, const int32 data); -int32 sio0s (const int32 port, const int32 io, const int32 data); -int32 sio1d (const int32 port, const int32 io, const int32 data); -int32 sio1s (const int32 port, const int32 io, const int32 data); -static void reset_sio_terminals(const int32 useDefault); -static t_stat simh_dev_reset(DEVICE *dptr); -static t_stat simh_svc(UNIT *uptr); -static int32 simh_in(const int32 port); -static int32 simh_out(const int32 port, const int32 data); -static void attachCPM(UNIT *uptr); -static void setClockZSDOS(void); -static void setClockCPM3(void); -static time_t mkCPM3Origin(void); -static int32 toBCD(const int32 x); -static int32 fromBCD(const int32 x); -void printMessage(void); -static void warnNoRealTimeClock(void); - -extern t_stat sim_activate(UNIT *uptr, int32 interval); -extern t_stat sim_cancel(UNIT *uptr); -extern t_stat sim_poll_kbd(void); -extern t_stat sim_putchar(int32 out); -extern t_stat attach_unit(UNIT *uptr, char *cptr); -extern t_bool rtc_avail; -extern FILE *sim_log; -extern int32 PCX; -extern int32 sim_switches; -extern uint32 sim_os_msec(void); -extern const char *scp_error_messages[]; -extern int32 SR; -extern int32 bankSelect; -extern int32 common; -extern uint8 GetBYTEWrapper(register uint32 Addr); -extern UNIT cpu_unit; - -/* SIMH pseudo device status registers */ -/* ZSDOS clock definitions */ -static time_t ClockZSDOSDelta = 0; /* delta between real clock and Altair clock */ -static int32 setClockZSDOSPos = 0; /* determines state for receiving address of parameter block */ -static int32 setClockZSDOSAdr = 0; /* address in M of 6 byte parameter block for setting time */ -static int32 getClockZSDOSPos = 0; /* determines state for sending clock information */ - -/* CPM3 clock definitions */ -static time_t ClockCPM3Delta = 0; /* delta between real clock and Altair clock */ -static int32 setClockCPM3Pos = 0; /* determines state for receiving address of parameter block */ -static int32 setClockCPM3Adr = 0; /* address in M of 5 byte parameter block for setting time */ -static int32 getClockCPM3Pos = 0; /* determines state for sending clock information */ -static int32 daysCPM3SinceOrg = 0; /* days since 1 Jan 1978 */ - -/* interrupt related */ -static uint32 timeOfNextInterrupt; /* time when next interrupt is scheduled */ - int32 timerInterrupt = FALSE; /* timer interrupt pending */ - int32 timerInterruptHandler = 0x0fc00;/* default address of interrupt handling routine */ -static int32 setTimerInterruptAdrPos= 0; /* determines state for receiving timerInterruptHandler */ -static int32 timerDelta = 100; /* interrupt every 100 ms */ -static int32 setTimerDeltaPos = 0; /* determines state for receiving timerDelta */ - -/* stop watch and timer related */ -static uint32 stopWatchDelta = 0; /* stores elapsed time of stop watch */ -static int32 getStopWatchDeltaPos = 0; /* determines the state for receiving stopWatchDelta */ -static uint32 stopWatchNow = 0; /* stores starting time of stop watch */ -static int32 markTimeSP = 0; /* stack pointer for timer stack */ - -/* miscellaneous */ -static int32 versionPos = 0; /* determines state for sending device identifier */ -static int32 lastCPMStatus = 0; /* result of last attachCPM command */ -static int32 lastCommand = 0; /* most recent command processed on port 0xfeh */ -static int32 getCommonPos = 0; /* determines state for sending the 'common' register */ - -/* SIO status registers */ -static int32 warnLevelSIO = 3; /* display at most 'warnLevelSIO' times the same warning */ -static int32 warnUnattachedPTP = 0; /* display a warning message if < warnLevel and SIO set to - VERBOSE and output to PTP without an attached file */ -static int32 warnUnattachedPTR = 0; /* display a warning message if < warnLevel and SIO set to - VERBOSE and attempt to read from PTR without an attached file */ -static int32 warnPTREOF = 0; /* display a warning message if < warnLevel and SIO set to - VERBOSE and attempt to read from PTR past EOF */ -static int32 warnUnassignedPort = 0; /* display a warning message if < warnLevel and SIO set to - VERBOSE andattempt to perform IN or OUT on an unassigned PORT */ -struct sio_terminal { - int32 data; /* data for this terminal */ - int32 status; /* status information for this terminal */ - int32 statusPort; /* status port of this terminal */ - int32 dataPort; /* data port of this terminal */ - int32 defaultStatus; /* default status value for this terminal */ -}; - -typedef struct sio_terminal SIO_TERMINAL; - -static SIO_TERMINAL sio_terminals[Terminals] = - { {0, 0, 0x10, 0x11, 0x02}, - {0, 0, 0x14, 0x15, 0x00}, - {0, 0, 0x16, 0x17, 0x00}, - {0, 0, 0x18, 0x19, 0x00} }; -static TMLN TerminalLines[Terminals] = { {0} }; /* four terminals */ -static TMXR altairTMXR = {Terminals, 0, 0 }; /* mux descriptor */ - -static UNIT sio_unit = { UDATA (&sio_svc, UNIT_ATTABLE, 0), KBD_POLL_WAIT }; - -static REG sio_reg[] = { - { HRDATA (DATA0, sio_terminals[0].data, 8) }, - { HRDATA (STAT0, sio_terminals[0].status, 8) }, - { HRDATA (DATA1, sio_terminals[1].data, 8) }, - { HRDATA (STAT1, sio_terminals[1].status, 8) }, - { HRDATA (DATA2, sio_terminals[2].data, 8) }, - { HRDATA (STAT2, sio_terminals[2].status, 8) }, - { HRDATA (DATA3, sio_terminals[3].data, 8) }, - { HRDATA (STAT3, sio_terminals[3].status, 8) }, - { DRDATA (SIOWL, warnLevelSIO, 32) }, - { DRDATA (WUPTP, warnUnattachedPTP, 32) }, - { DRDATA (WUPTR, warnUnattachedPTR, 32) }, - { DRDATA (WPTREOF, warnPTREOF, 32) }, - { DRDATA (WUPORT, warnUnassignedPort, 32) }, - { NULL } }; - -static MTAB sio_mod[] = { - { UNIT_ANSI, 0, "TTY", "TTY", NULL }, /* keep bit 8 as is for output */ - { UNIT_ANSI, UNIT_ANSI, "ANSI", "ANSI", NULL }, /* set bit 8 to 0 before output */ - { UNIT_UPPER, 0, "ALL", "ALL", NULL }, /* do not change case of input characters */ - { UNIT_UPPER, UNIT_UPPER, "UPPER", "UPPER", NULL }, /* change input characters to upper case */ - { UNIT_BS, 0, "BS", "BS", NULL }, /* map delete to backspace */ - { UNIT_BS, UNIT_BS, "DEL", "DEL", NULL }, /* map backspace to delete */ - { UNIT_SIO_VERBOSE, 0, "QUIET", "QUIET", NULL }, /* quiet, no error messages */ - { UNIT_SIO_VERBOSE, UNIT_SIO_VERBOSE, "VERBOSE", "VERBOSE", &sio_set_verbose }, - /* verbose, display warning messages */ - { 0 } }; - -DEVICE sio_dev = { - "SIO", &sio_unit, sio_reg, sio_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &sio_reset, - NULL, &sio_attach, &sio_detach, NULL, 0, NULL, NULL }; - -static UNIT ptr_unit = { UDATA (NULL, UNIT_SEQ + UNIT_ATTABLE + UNIT_ROABLE, 0), - KBD_POLL_WAIT }; - -static REG ptr_reg[] = { - { HRDATA (DATA, ptr_unit.buf, 8) }, - { HRDATA (STAT, ptr_unit.u3, 8) }, - { DRDATA (POS, ptr_unit.pos, 32) }, - { NULL } }; - -DEVICE ptr_dev = { - "PTR", &ptr_unit, ptr_reg, NULL, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &ptr_reset, - NULL, NULL, NULL, NULL, 0, NULL, NULL }; - -static UNIT ptp_unit = { UDATA (NULL, UNIT_SEQ + UNIT_ATTABLE, 0), - KBD_POLL_WAIT }; - -static REG ptp_reg[] = { - { HRDATA (DATA, ptp_unit.buf, 8) }, - { HRDATA (STAT, ptp_unit.u3, 8) }, - { DRDATA (POS, ptp_unit.pos, 32) }, - { 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, NULL, NULL }; - -/* Synthetic device SIMH for communication - between Altair and SIMH environment using port 0xfe */ -static UNIT simh_unit = { UDATA (&simh_svc, 0, 0), KBD_POLL_WAIT }; - -static REG simh_reg[] = { - { DRDATA (CZD, ClockZSDOSDelta, 32) }, - { DRDATA (SCZP, setClockZSDOSPos, 8), REG_RO }, - { HRDATA (SCZA, setClockZSDOSAdr, 16), REG_RO }, - { DRDATA (GCZP, getClockZSDOSPos, 8), REG_RO }, - - { DRDATA (CC3D, ClockCPM3Delta, 32) }, - { DRDATA (SC3DP, setClockCPM3Pos, 8), REG_RO }, - { HRDATA (SC3DA, setClockCPM3Adr, 16), REG_RO }, - { DRDATA (GC3DP, getClockCPM3Pos, 8), REG_RO }, - { DRDATA (D3DO, daysCPM3SinceOrg, 32), REG_RO }, - - { DRDATA (TOFNI, timeOfNextInterrupt, 32), REG_RO }, - { DRDATA (TIMI, timerInterrupt, 3) }, - { HRDATA (TIMH, timerInterruptHandler, 16) }, - { DRDATA (STIAP, setTimerInterruptAdrPos,8), REG_RO }, - { DRDATA (TIMD, timerDelta, 32) }, - { DRDATA (STDP, setTimerDeltaPos, 8), REG_RO }, - - { DRDATA (STPDT, stopWatchDelta, 32), REG_RO }, - { DRDATA (STPOS, getStopWatchDeltaPos, 8), REG_RO }, - { DRDATA (STPNW, stopWatchNow, 32), REG_RO }, - { DRDATA (MTSP, markTimeSP, 8), REG_RO }, - - { DRDATA (VPOS, versionPos, 8), REG_RO }, - { DRDATA (LCPMS, lastCPMStatus, 8), REG_RO }, - { DRDATA (LCMD, lastCommand, 8), REG_RO }, - { DRDATA (CPOS, getCommonPos, 8), REG_RO }, - { NULL } }; - -static MTAB simh_mod[] = { - /* quiet, no warning messages */ - { UNIT_SIMH_VERBOSE, 0, "QUIET", "QUIET", NULL }, - /* verbose, display warning messages */ - { UNIT_SIMH_VERBOSE, UNIT_SIMH_VERBOSE, "VERBOSE", "VERBOSE", NULL }, - /* timer generated interrupts are off */ - { UNIT_SIMH_TIMERON, 0, "TIMEROFF", "TIMEROFF", &simh_dev_set_timeroff }, - /* timer generated interrupts are on */ - { UNIT_SIMH_TIMERON, UNIT_SIMH_TIMERON, "TIMERON", "TIMERON", &simh_dev_set_timeron }, - { 0 } }; - -DEVICE simh_device = { - "SIMH", &simh_unit, simh_reg, simh_mod, - 1, 10, 31, 1, 16, 4, - NULL, NULL, &simh_dev_reset, - NULL, NULL, NULL, NULL, 0, NULL, NULL }; - -char messageBuffer[256]; - -void printMessage(void) { - printf(messageBuffer); - if (sim_log) { - fprintf(sim_log, messageBuffer); - } -} - -static void resetSIOWarningFlags(void) { - warnUnattachedPTP = 0; - warnUnattachedPTR = 0; - warnPTREOF = 0; - warnUnassignedPort = 0; -} - -static t_stat sio_set_verbose(UNIT *uptr, int32 value, char *cptr, void *desc) { - resetSIOWarningFlags(); - return SCPE_OK; -} - -static t_stat sio_attach(UNIT *uptr, char *cptr) { - int32 i; - for (i = 0; i < Terminals; i++) { - altairTMXR.ldsc[i] = &TerminalLines[i]; - } - reset_sio_terminals(FALSE); - return tmxr_attach(&altairTMXR, uptr, cptr); /* attach mux */ -} - -static void reset_sio_terminals(const int32 useDefault) { - int32 i; - for (i = 0; i < Terminals; i++) { - sio_terminals[i].status = useDefault ? sio_terminals[i].defaultStatus : 0; /* status */ - sio_terminals[i].data = 0x00; /* data */ - } -} - -/* detach */ -static t_stat sio_detach(UNIT *uptr) { - reset_sio_terminals(TRUE); - return tmxr_detach(&altairTMXR, uptr); -} - -/* service routines to handle simulator functions */ - -/* service routine - actually gets char & places in buffer */ - -static t_stat sio_svc(UNIT *uptr) { - int32 temp; - - sim_activate(&sio_unit, sio_unit.wait); /* continue poll */ - - if (sio_unit.flags & UNIT_ATT) { - if (sim_poll_kbd() == SCPE_STOP) { /* listen for ^E */ - return SCPE_STOP; - } - temp = tmxr_poll_conn(&altairTMXR); /* poll connection */ - if (temp >= 0) { - altairTMXR.ldsc[temp] -> rcve = 1; /* enable receive */ - } - tmxr_poll_rx(&altairTMXR); /* poll input */ - tmxr_poll_tx(&altairTMXR); /* poll output */ - } - else { - if ((temp = sim_poll_kbd()) < SCPE_KFLAG) { - return temp; /* no char or error? */ - } - sio_terminals[0].data = temp & 0xff; /* save character */ - sio_terminals[0].status |= 0x01; /* set status */ - } - return SCPE_OK; -} - - -/* reset routines */ - -static t_stat sio_reset(DEVICE *dptr) { - int32 i; - resetSIOWarningFlags(); - if (sio_unit.flags & UNIT_ATT) { - for (i = 0; i < Terminals; i++) { - if (altairTMXR.ldsc[i] -> conn > 0) { - tmxr_reset_ln(altairTMXR.ldsc[i]); - } - } - reset_sio_terminals(FALSE); - } - else { - reset_sio_terminals(TRUE); - } - sim_activate(&sio_unit, sio_unit.wait); /* activate unit */ - return SCPE_OK; -} - -static t_stat ptr_reset(DEVICE *dptr) { - resetSIOWarningFlags(); - ptr_unit.buf = 0; - ptr_unit.u3 = 0; - ptr_unit.pos = 0; - if (ptr_unit.flags & UNIT_ATT) { /* attached? */ - rewind(ptr_dev.units -> fileref); - } - sim_cancel(&ptp_unit); /* deactivate unit */ - return SCPE_OK; -} - -static t_stat ptp_reset(DEVICE *dptr) { - resetSIOWarningFlags(); - ptp_unit.buf = 0; - ptp_unit.u3 = 0x02; - sim_cancel(&ptp_unit); /* deactivate unit */ - return SCPE_OK; -} - - -/* I/O instruction handlers, called from the CPU module when an - IN or OUT instruction is issued. - - Each function is passed an 'io' flag, where 0 means a read from - the port, and 1 means a write to the port. On input, the actual - input is passed as the return value, on output, 'data' is written - to the device. - - Port 1 controls console I/O. We distinguish two cases: - 1) SIO attached to a port (i.e. Telnet console I/O) - 2) SIO not attached to a port (i.e. "regular" console I/O) -*/ - -int32 sio0s(const int32 port, const int32 io, const int32 data) { - int32 ti; - for (ti = 0; ti < Terminals; ti++) { - if (sio_terminals[ti].statusPort == port) { - break; - } - } - if (io == 0) { /* IN */ - if (sio_unit.flags & UNIT_ATT) { - sio_terminals[ti].status = - (((tmxr_rqln(altairTMXR.ldsc[ti]) > 0 ? 0x01 : 0) | - /* read possible if character available */ - ((altairTMXR.ldsc[ti] -> conn) && (altairTMXR.ldsc[ti] -> xmte) ? 0x02 : 0x00))); - /* write possible if connected and transmit enabled */ - } - return sio_terminals[ti].status; - } - else { /* OUT */ - if (sio_unit.flags & UNIT_ATT) { - if (data == 0x03) { /* reset port! */ - sio_terminals[ti].status = 0x00; - sio_terminals[ti].data = 0; - } - } - else { - if (data == 0x03) { /* reset port! */ - sio_terminals[ti].status = sio_terminals[ti].defaultStatus; - sio_terminals[ti].data = 0; - } - } - return 0; /* ignored since OUT */ - } -} - -int32 sio0d(const int32 port, const int32 io, const int32 data) { - int32 ti; - for (ti = 0; ti < Terminals; ti++) { - if (sio_terminals[ti].dataPort == port) { - break; - } - } - if (io == 0) { /* IN */ - if (sio_unit.flags & UNIT_ATT) { - sio_terminals[ti].data = tmxr_getc_ln(altairTMXR.ldsc[ti]) & 0xff; - } - sio_terminals[ti].status &= 0xfe; - if (sio_unit.flags & UNIT_BS) { - if (sio_terminals[ti].data == BACKSPACE_CHAR) { - sio_terminals[ti].data = DELETE_CHAR; - } - } - else { - if (sio_terminals[ti].data == DELETE_CHAR) { - sio_terminals[ti].data = BACKSPACE_CHAR; - } - } - return (sio_unit.flags & UNIT_UPPER) ? toupper(sio_terminals[ti].data) : sio_terminals[ti].data; - } - else { /* OUT */ - int32 d = sio_unit.flags & UNIT_ANSI ? data & 0x7f : data; - if (sio_unit.flags & UNIT_ATT) { - tmxr_putc_ln(altairTMXR.ldsc[ti], d); - } - else { - sim_putchar(d); - } - return 0; /* ignored since OUT */ - } -} - -/* port 2 controls the PTR/PTP devices */ - -int32 sio1s(const int32 port, const int32 io, const int32 data) { - if (io == 0) { - /* reset I bit iff PTR unit not attached or no more data available. */ - /* O bit is always set since write always possible. */ - if ((ptr_unit.flags & UNIT_ATT) == 0) { - if ((sio_unit.flags & UNIT_SIO_VERBOSE) && (warnUnattachedPTR < warnLevelSIO)) { - warnUnattachedPTR++; -/*06*/ message1("Attempt to test status of unattached PTR. 0x02 returned.\n"); - } - return 0x02; - } - return ptr_unit.u3 ? 0x02 : 0x03; - } - else { /* OUT */ - if (data == 0x03) { - ptr_unit.u3 = 0; - ptr_unit.buf = 0; - ptr_unit.pos = 0; - ptp_unit.u3 = 0; - ptp_unit.buf = 0; - ptp_unit.pos = 0; - } - return 0; /* ignored since OUT */ - } -} - -int32 sio1d(const int32 port, const int32 io, const int32 data) { - int32 temp; - if (io == 0) { /* IN */ - if (ptr_unit.u3) { /* no more data available */ - if ((sio_unit.flags & UNIT_SIO_VERBOSE) && (warnPTREOF < warnLevelSIO)) { - warnPTREOF++; -/*07*/ message1("PTR attempted to read past EOF. 0x00 returned.\n"); - } - return 0; - } - if ((ptr_unit.flags & UNIT_ATT) == 0) { /* not attached */ - if ((sio_unit.flags & UNIT_SIO_VERBOSE) && (warnUnattachedPTR < warnLevelSIO)) { - warnUnattachedPTR++; -/*08*/ message1("Attempt to read from unattached PTR. 0x00 returned.\n"); - } - return 0; - } - if ((temp = getc(ptr_dev.units -> fileref)) == EOF) { /* end of file? */ - ptr_unit.u3 = 0x01; - return CONTROLZ_CHAR; /* control Z denotes end of text file in CP/M */ - } - ptr_unit.pos++; - return temp & 0xff; - } - else { /* OUT */ - if (ptp_unit.flags & UNIT_ATT) { /* unit must be attached */ - putc(data, ptp_dev.units -> fileref); - } /* else ignore data */ - else if ((sio_unit.flags & UNIT_SIO_VERBOSE) && (warnUnattachedPTP < warnLevelSIO)) { - warnUnattachedPTP++; -/*09*/message2("Attempt to output '0x%02x' to unattached PTP - ignored.\n", data); - } - ptp_unit.pos++; - return 0; /* ignored since OUT */ - } -} - -int32 nulldev(const int32 port, const int32 io, const int32 data) { - if ((sio_unit.flags & UNIT_SIO_VERBOSE) && (warnUnassignedPort < warnLevelSIO)) { - warnUnassignedPort++; - if (io == 0) { - message2("Unassigned IN(%2xh) - ignored.\n", port); - } - else { - message3("Unassigned OUT(%2xh) -> %2xh - ignored.\n", port, data); - } - } - return io == 0 ? 0xff : 0; -} - -int32 sr_dev(const int32 port, const int32 io, const int32 data) { - return io == 0 ? SR : 0; -} - -static int32 toBCD(const int32 x) { - return (x / 10) * 16 + (x % 10); -} - -static int32 fromBCD(const int32 x) { - return 10 * ((0xf0 & x) >> 4) + (0x0f & x); -} - -/* Z80 or 8080 programs communicate with the SIMH pseudo device via port 0xfe. - The following principles apply: - - 1) For commands that do not require parameters and do not return results - ld a, - out (0feh),a - Special case is the reset command which needs to be send 128 times to make - sure that the internal state is properly reset. - - 2) For commands that require parameters and do not return results - ld a, - out (0feh),a - ld a, - out (0feh),a - ld a, - out (0feh),a - ... - Note: The calling program must send all parameter bytes. Otherwise - the pseudo device is left in an unexpected state. - - 3) For commands that do not require parameters and return results - ld a, - out (0feh),a - in a,(0feh) ; contains first byte of result - in a,(0feh) ; contains second byte of result - ... - Note: The calling program must request all bytes of the result. Otherwise - the pseudo device is left in an unexpected state. - - 4) Commands requiring parameters and returning results do not exist currently. - -*/ - -enum simhPseudoDeviceCommands { /* do not change order or remove commands, add only at the end */ - printTimeCmd, /* 0 print the current time in milliseconds */ - startTimerCmd, /* 1 start a new timer on the top of the timer stack */ - stopTimerCmd, /* 2 stop timer on top of timer stack and show time difference */ - resetPTRCmd, /* 3 reset the PTR device */ - attachPTRCmd, /* 4 attach the PTR device */ - detachPTRCmd, /* 5 detach the PTR device */ - getSIMHVersionCmd, /* 6 get the current version of the SIMH pseudo device */ - getClockZSDOSCmd, /* 7 get the current time in ZSDOS format */ - setClockZSDOSCmd, /* 8 set the current time in ZSDOS format */ - getClockCPM3Cmd, /* 9 get the current time in CP/M 3 format */ - setClockCPM3Cmd, /* 10 set the current time in CP/M 3 format */ - getBankSelectCmd, /* 11 get the selected bank */ - setBankSelectCmd, /* 12 set the selected bank */ - getCommonCmd, /* 13 get the base address of the common memory segment */ - resetSIMHInterfaceCmd, /* 14 reset the SIMH pseudo device */ - showTimerCmd, /* 15 show time difference to timer on top of stack */ - attachPTPCmd, /* 16 attach PTP to the file with name at beginning of CP/M command line*/ - detachPTPCmd, /* 17 detach PTP */ - hasBankedMemoryCmd, /* 18 determines whether machine has banked memory */ - setZ80CPUCmd, /* 19 set the CPU to a Z80 */ - set8080CPUCmd, /* 20 set the CPU to an 8080 */ - startTimerInterruptsCmd,/* 21 start timer interrupts */ - stopTimerInterruptsCmd, /* 22 stop timer interrupts */ - setTimerDeltaCmd, /* 23 set the timer interval in which interrupts occur */ - setTimerInterruptAdrCmd,/* 24 set the address to call by timer interrupts */ - resetStopWatchCmd, /* 25 reset the millisecond stop watch */ - readStopWatchCmd /* 26 read the millisecond stop watch */ -}; - -#define cpmCommandLineLength 128 -#define splimit 10 /* stack depth of timer stack */ -static uint32 markTime[splimit]; /* timer stack */ -static struct tm currentTime; -static int32 currentTimeValid = FALSE; -static char version[] = "SIMH002"; - -static t_stat simh_dev_reset(DEVICE *dptr) { - currentTimeValid = FALSE; - ClockZSDOSDelta = 0; - setClockZSDOSPos = 0; - getClockZSDOSPos = 0; - ClockCPM3Delta = 0; - setClockCPM3Pos = 0; - getClockCPM3Pos = 0; - getStopWatchDeltaPos = 0; - getCommonPos = 0; - setTimerDeltaPos = 0; - setTimerInterruptAdrPos = 0; - markTimeSP = 0; - versionPos = 0; - lastCommand = 0; - lastCPMStatus = SCPE_OK; - timerInterrupt = FALSE; - if (simh_unit.flags & UNIT_SIMH_TIMERON) { - simh_dev_set_timeron(NULL, 0, NULL, NULL); - } - return SCPE_OK; -} - -static void warnNoRealTimeClock(void) { - if (simh_unit.flags & UNIT_SIMH_VERBOSE) { - printf("Sorry - no real time clock available.\n"); - } -} - -static t_stat simh_dev_set_timeron(UNIT *uptr, int32 value, char *cptr, void *desc) { - if (rtc_avail) { - timeOfNextInterrupt = sim_os_msec() + timerDelta; - return sim_activate(&simh_unit, simh_unit.wait); /* activate unit */ - } - else { - warnNoRealTimeClock(); - return SCPE_ARG; - } -} - -static t_stat simh_dev_set_timeroff(UNIT *uptr, int32 value, char *cptr, void *desc) { - timerInterrupt = FALSE; - sim_cancel(&simh_unit); - return SCPE_OK; -} - -static t_stat simh_svc(UNIT *uptr) { - uint32 n = sim_os_msec(); - if (n >= timeOfNextInterrupt) { - timerInterrupt = TRUE; - timeOfNextInterrupt += timerDelta; - if (n >= timeOfNextInterrupt) { /* time of next interrupt is not in the future */ - timeOfNextInterrupt = n + timerDelta; /* make sure it is in the future! */ - } - } - if (simh_unit.flags & UNIT_SIMH_TIMERON) { - sim_activate(&simh_unit, simh_unit.wait); /* activate unit */ - } - return SCPE_OK; -} - -/* The CP/M commandline is used as the name of a file and UNIT* uptr is attached to it. */ -static void attachCPM(UNIT *uptr) { - char cpmCommandLine[cpmCommandLineLength]; - uint32 i, len = (GetBYTEWrapper(0x80) & 0x7f) - 1; /* 0x80 contains length of commandline, discard first char */ - for (i = 0; i < len; i++) { - cpmCommandLine[i] = (char)GetBYTEWrapper(0x82 + i); /* the first char, typically ' ', is discarded */ - } - cpmCommandLine[i] = 0; /* make C string */ - if (uptr == &ptr_unit) { - sim_switches = SWMASK('R'); - } - else if (uptr == &ptp_unit) { - sim_switches = SWMASK('W'); - } - lastCPMStatus = attach_unit(uptr, cpmCommandLine); - if ((lastCPMStatus != SCPE_OK) && (simh_unit.flags & UNIT_SIMH_VERBOSE)) { - message3("Cannot open '%s' (%s).\n", cpmCommandLine, scp_error_messages[lastCPMStatus - SCPE_BASE]); - } -} - -/* setClockZSDOSAdr points to 6 byte block in M: YY MM DD HH MM SS in BCD notation */ -static void setClockZSDOS(void) { - struct tm newTime; - int32 year = fromBCD(GetBYTEWrapper(setClockZSDOSAdr)); - newTime.tm_year = year < 50 ? year + 100 : year; - newTime.tm_mon = fromBCD(GetBYTEWrapper(setClockZSDOSAdr + 1)) - 1; - newTime.tm_mday = fromBCD(GetBYTEWrapper(setClockZSDOSAdr + 2)); - newTime.tm_hour = fromBCD(GetBYTEWrapper(setClockZSDOSAdr + 3)); - newTime.tm_min = fromBCD(GetBYTEWrapper(setClockZSDOSAdr + 4)); - newTime.tm_sec = fromBCD(GetBYTEWrapper(setClockZSDOSAdr + 5)); - ClockZSDOSDelta = mktime(&newTime) - time(NULL); -} - -#define secondsPerMinute 60 -#define secondsPerHour (60 * secondsPerMinute) -#define secondsPerDay (24 * secondsPerHour) -static time_t mkCPM3Origin(void) { - struct tm date; - date.tm_year = 77; - date.tm_mon = 11; - date.tm_mday = 31; - date.tm_hour = 0; - date.tm_min = 0; - date.tm_sec = 0; - return mktime(&date); -} - -/* setClockCPM3Adr points to 5 byte block in M: - 0 - 1 int16: days since 31 Dec 77 - 2 BCD byte: HH - 3 BCD byte: MM - 4 BCD byte: SS */ -static void setClockCPM3(void) { - ClockCPM3Delta = mkCPM3Origin() + - (GetBYTEWrapper(setClockCPM3Adr) + GetBYTEWrapper(setClockCPM3Adr + 1) * 256) * secondsPerDay + - fromBCD(GetBYTEWrapper(setClockCPM3Adr + 2)) * secondsPerHour + - fromBCD(GetBYTEWrapper(setClockCPM3Adr + 3)) * secondsPerMinute + - fromBCD(GetBYTEWrapper(setClockCPM3Adr + 4)) - time(NULL); -} - -static int32 simh_in(const int32 port) { - int32 result = 0; - switch(lastCommand) { - case attachPTRCmd: - case attachPTPCmd: - result = lastCPMStatus; - lastCommand = 0; - break; - case getClockZSDOSCmd: - if (currentTimeValid) { - switch(getClockZSDOSPos) { - case 0: - result = toBCD(currentTime.tm_year > 99 ? - currentTime.tm_year - 100 : currentTime.tm_year); - getClockZSDOSPos = 1; - break; - case 1: - result = toBCD(currentTime.tm_mon + 1); - getClockZSDOSPos = 2; - break; - case 2: - result = toBCD(currentTime.tm_mday); - getClockZSDOSPos = 3; - break; - case 3: - result = toBCD(currentTime.tm_hour); - getClockZSDOSPos = 4; - break; - case 4: - result = toBCD(currentTime.tm_min); - getClockZSDOSPos = 5; - break; - case 5: - result = toBCD(currentTime.tm_sec); - getClockZSDOSPos = lastCommand = 0; - break; - } - } - else { - result = getClockZSDOSPos = lastCommand = 0; - } - break; - case getClockCPM3Cmd: - if (currentTimeValid) { - switch(getClockCPM3Pos) { - case 0: - result = daysCPM3SinceOrg & 0xff; - getClockCPM3Pos = 1; - break; - case 1: - result = (daysCPM3SinceOrg >> 8) & 0xff; - getClockCPM3Pos = 2; - break; - case 2: - result = toBCD(currentTime.tm_hour); - getClockCPM3Pos = 3; - break; - case 3: - result = toBCD(currentTime.tm_min); - getClockCPM3Pos = 4; - break; - case 4: - result = toBCD(currentTime.tm_sec); - getClockCPM3Pos = lastCommand = 0; - break; - } - } - else { - result = getClockCPM3Pos = lastCommand = 0; - } - break; - case getSIMHVersionCmd: - result = version[versionPos++]; - if (result == 0) { - versionPos = lastCommand = 0; - } - break; - case getBankSelectCmd: - if (cpu_unit.flags & UNIT_BANKED) { - result = bankSelect; - } - else { - result = 0; - if (simh_unit.flags & UNIT_SIMH_VERBOSE) { - message1("Get selected bank ignored for non-banked memory."); - } - } - lastCommand = 0; - break; - case getCommonCmd: - if (getCommonPos == 0) { - result = common & 0xff; - getCommonPos = 1; - } - else { - result = (common >> 8) & 0xff; - getCommonPos = lastCommand = 0; - } - break; - case hasBankedMemoryCmd: - result = cpu_unit.flags & UNIT_BANKED ? MAXBANKS : 0; - lastCommand = 0; - break; - case readStopWatchCmd: - if (getStopWatchDeltaPos == 0) { - result = stopWatchDelta & 0xff; - getStopWatchDeltaPos = 1; - } - else { - result = (stopWatchDelta >> 8) & 0xff; - getStopWatchDeltaPos = lastCommand = 0; - } - break; - default: - if (simh_unit.flags & UNIT_SIMH_VERBOSE) { - message2("Unnecessary IN from SIMH pseudo device on port %03xh ignored.\n", - port); - } - result = lastCommand = 0; - } - return result; -} - -static int32 simh_out(const int32 port, const int32 data) { - time_t now; - switch(lastCommand) { - case setClockZSDOSCmd: - if (setClockZSDOSPos == 0) { - setClockZSDOSAdr = data; - setClockZSDOSPos = 1; - } - else { - setClockZSDOSAdr |= (data << 8); - setClockZSDOS(); - setClockZSDOSPos = lastCommand = 0; - } - break; - case setClockCPM3Cmd: - if (setClockCPM3Pos == 0) { - setClockCPM3Adr = data; - setClockCPM3Pos = 1; - } - else { - setClockCPM3Adr |= (data << 8); - setClockCPM3(); - setClockCPM3Pos = lastCommand = 0; - } - break; - case setBankSelectCmd: - if (cpu_unit.flags & UNIT_BANKED) { - bankSelect = data & BANKMASK; - } - else if (simh_unit.flags & UNIT_SIMH_VERBOSE) { - message2("Set selected bank to %i ignored for non-banked memory.", data & 3); - } - lastCommand = 0; - break; - case setTimerDeltaCmd: - if (setTimerDeltaPos == 0) { - timerDelta = data; - setTimerDeltaPos = 1; - } - else { - timerDelta |= (data << 8); - setTimerDeltaPos = lastCommand = 0; - } - break; - case setTimerInterruptAdrCmd: - if (setTimerInterruptAdrPos == 0) { - timerInterruptHandler = data; - setTimerInterruptAdrPos = 1; - } - else { - timerInterruptHandler |= (data << 8); - setTimerInterruptAdrPos = lastCommand = 0; - } - break; - default: - lastCommand = data; - switch(data) { - case printTimeCmd: /* print time */ - if (rtc_avail) { - message2("Current time in milliseconds = %d.\n", sim_os_msec()); - } - else { - warnNoRealTimeClock(); - } - break; - case startTimerCmd: /* create a new timer on top of stack */ - if (rtc_avail) { - if (markTimeSP < splimit) { - markTime[markTimeSP++] = sim_os_msec(); - } - else { - message1("Timer stack overflow.\n"); - } - } - else { - warnNoRealTimeClock(); - } - break; - case stopTimerCmd: /* stop timer on top of stack and show time difference */ - if (rtc_avail) { - if (markTimeSP > 0) { - uint32 delta = sim_os_msec() - markTime[--markTimeSP]; - message2("Timer stopped. Elapsed time in milliseconds = %d.\n", delta); - } - else { - message1("No timer active.\n"); - } - } - else { - warnNoRealTimeClock(); - } - break; - case resetPTRCmd: /* reset ptr device */ - ptr_reset(NULL); - break; - case attachPTRCmd: /* attach ptr to the file with name at beginning of CP/M command line */ - attachCPM(&ptr_unit); - break; - case detachPTRCmd: /* detach ptr */ - detach_unit(&ptr_unit); - break; - case getSIMHVersionCmd: - versionPos = 0; - break; - case getClockZSDOSCmd: - time(&now); - now += ClockZSDOSDelta; - currentTime = *localtime(&now); - currentTimeValid = TRUE; - getClockZSDOSPos = 0; - break; - case setClockZSDOSCmd: - setClockZSDOSPos = 0; - break; - case getClockCPM3Cmd: - time(&now); - now += ClockCPM3Delta; - currentTime = *localtime(&now); - currentTimeValid = TRUE; - daysCPM3SinceOrg = (now - mkCPM3Origin()) / secondsPerDay; - getClockCPM3Pos = 0; - break; - case setClockCPM3Cmd: - setClockCPM3Pos = 0; - break; - case getBankSelectCmd: - case setBankSelectCmd: - case getCommonCmd: - case hasBankedMemoryCmd: - break; - case resetSIMHInterfaceCmd: - markTimeSP = 0; - lastCommand = 0; - break; - case showTimerCmd: /* show time difference to timer on top of stack */ - if (rtc_avail) { - if (markTimeSP > 0) { - uint32 delta = sim_os_msec() - markTime[markTimeSP - 1]; - message2("Timer running. Elapsed in milliseconds = %d.\n", delta); - } - else { - message1("No timer active.\n"); - } - } - else { - warnNoRealTimeClock(); - } - break; - case attachPTPCmd: /* attach ptp to the file with name at beginning of CP/M command line */ - attachCPM(&ptp_unit); - break; - case detachPTPCmd: /* detach ptp */ - detach_unit(&ptp_unit); - break; - case setZ80CPUCmd: - cpu_unit.flags |= UNIT_CHIP; - break; - case set8080CPUCmd: - cpu_unit.flags &= ~UNIT_CHIP; - break; - case startTimerInterruptsCmd: - 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(NULL, 0, NULL, NULL); - break; - case setTimerDeltaCmd: - setTimerDeltaPos = 0; - break; - case setTimerInterruptAdrCmd: - setTimerInterruptAdrPos = 0; - break; - case resetStopWatchCmd: - stopWatchNow = rtc_avail ? sim_os_msec() : 0; - break; - case readStopWatchCmd: - getStopWatchDeltaPos = 0; - stopWatchDelta = rtc_avail ? sim_os_msec() - stopWatchNow : 0; - break; - default: - if (simh_unit.flags & UNIT_SIMH_VERBOSE) { - message3("Unknown command (%i) to SIMH pseudo device on port %03xh ignored.\n", - data, port); - } - } - } - return 0; /* ignored, since OUT */ -} - -/* port 0xfe is a device for communication SIMH <--> Altair machine */ -int32 simh_dev(const int32 port, const int32 io, const int32 data) { - return io == 0 ? simh_in(port) : simh_out(port, data); -} diff --git a/AltairZ80/altairZ80_sys.c b/AltairZ80/altairZ80_sys.c deleted file mode 100644 index 9cc29210..00000000 --- a/AltairZ80/altairZ80_sys.c +++ /dev/null @@ -1,782 +0,0 @@ -/* altairz80_sys.c: MITS Altair system interface - - Copyright (c) 2002-2003, Peter Schorn - - 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 - PETER SCHORN 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 Peter Schorn shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Peter Schorn. - - Based on work by Charles E Owen (c) 1997 - Disassembler from Marat Fayzullin ((c) 1995, 1996, 1997 - Commercial use prohibited) -*/ - -#include -#include "altairz80_defs.h" - -extern DEVICE cpu_dev; -extern DEVICE dsk_dev; -extern DEVICE hdsk_dev; -extern UNIT cpu_unit; -extern REG cpu_reg[]; -extern DEVICE sio_dev; -extern DEVICE simh_device; -extern DEVICE ptr_dev; -extern DEVICE ptp_dev; -extern int32 saved_PC; -extern void PutBYTEWrapper(register uint32 Addr, register uint32 Value); -extern void PutBYTEForced(register uint32 Addr, register uint32 Value); -extern uint8 GetBYTEWrapper(register uint32 Addr); -extern int32 addressIsInROM(const uint32 Addr); -extern int32 addressExists(const uint32 Addr); -extern void printROMMessage(const uint32 cntROM); - -int32 sim_load(FILE *fileref, char *cptr, char *fnam, int32 flag); -int32 fprint_sym(FILE *of, int32 addr, uint32 *val, UNIT *uptr, int32 sw); -static int32 checkbase(char ch, const char *numString); -static int32 numok(char ch, const char **numString, const int32 minvalue, - const int32 maxvalue, const int32 requireSign, int32 *result); -static int32 match(const char *pattern, const char *input, char *xyFirst, char *xy, int32 *number, int32 *star, int32 *at, - int32 *hat, int32 *dollar); -static int32 parse_X80(const char *cptr, const int32 addr, uint32 *val, char *const Mnemonics[]); -int32 parse_sym(char *cptr, int32 addr, UNIT *uptr, uint32 *val, int32 sw); -static int32 DAsm(char *S, const uint32 *val, const int32 useZ80Mnemonics, const int32 addr); -static int32 checkXY(const char xy); - -/* SCP data structures - sim_name simulator name string - sim_PC pointer to saved PC register descriptor - sim_emax number of words needed 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[] = "Altair 8800 (Z80)"; -REG *sim_PC = &cpu_reg[0]; -int32 sim_emax = 4; -DEVICE *sim_devices[] = { &cpu_dev, &sio_dev, &simh_device, &ptr_dev, &ptp_dev, &dsk_dev, &hdsk_dev, NULL }; - -char memoryAccessMessage[80]; -const char *sim_stop_messages[] = { - "HALT instruction", - "Breakpoint", - memoryAccessMessage, - "Invalid Opcode" }; - -static char *const Mnemonics8080[] = { -/*0/8 1/9 2/A 3/B 4/C 5/D 6/E 7/F */ - "NOP", "LXI B,#h", "STAX B", "INX B", "INR B", "DCR B", "MVI B,*h", "RLC", /* 00-07 */ - "DB 09h", "DAD B", "LDAX B", "DCX B", "INR C", "DCR C", "MVI C,*h", "RRC", /* 08-0f */ - "DB 10h", "LXI D,#h", "STAX D", "INX D", "INR D", "DCR D", "MVI D,*h", "RAL", /* 10-17 */ - "DB 18h", "DAD D", "LDAX D", "DCX D", "INR E", "DCR E", "MVI E,*h", "RAR", /* 18-1f */ - "DB 20h", "LXI H,#h", "SHLD #h", "INX H", "INR H", "DCR H", "MVI H,*h", "DAA", /* 20-27 */ - "DB 28h", "DAD H", "LHLD #h", "DCX H", "INR L", "DCR L", "MVI L,*h", "CMA", /* 28-2f */ - "DB 30h", "LXI SP,#h", "STA #h", "INX SP", "INR M", "DCR M", "MVI M,*h", "STC", /* 30-37 */ - "DB 38h", "DAD SP", "LDA #h", "DCX SP", "INR A", "DCR A", "MVI A,*h", "CMC", /* 38-3f */ - "MOV B,B", "MOV B,C", "MOV B,D", "MOV B,E", "MOV B,H", "MOV B,L", "MOV B,M", "MOV B,A", /* 40-47 */ - "MOV C,B", "MOV C,C", "MOV C,D", "MOV C,E", "MOV C,H", "MOV C,L", "MOV C,M", "MOV C,A", /* 48-4f */ - "MOV D,B", "MOV D,C", "MOV D,D", "MOV D,E", "MOV D,H", "MOV D,L", "MOV D,M", "MOV D,A", /* 50-57 */ - "MOV E,B", "MOV E,C", "MOV E,D", "MOV E,E", "MOV E,H", "MOV E,L", "MOV E,M", "MOV E,A", /* 58-5f */ - "MOV H,B", "MOV H,C", "MOV H,D", "MOV H,E", "MOV H,H", "MOV H,L", "MOV H,M", "MOV H,A", /* 60-67 */ - "MOV L,B", "MOV L,C", "MOV L,D", "MOV L,E", "MOV L,H", "MOV L,L", "MOV L,M", "MOV L,A", /* 68-6f */ - "MOV M,B", "MOV M,C", "MOV M,D", "MOV M,E", "MOV M,H", "MOV M,L", "HLT", "MOV M,A", /* 70-77 */ - "MOV A,B", "MOV A,C", "MOV A,D", "MOV A,E", "MOV A,H", "MOV A,L", "MOV A,M", "MOV A,A", /* 78-7f */ - "ADD B", "ADD C", "ADD D", "ADD E", "ADD H", "ADD L", "ADD M", "ADD A", /* 80-87 */ - "ADC B", "ADC C", "ADC D", "ADC E", "ADC H", "ADC L", "ADC M", "ADC A", /* 88-8f */ - "SUB B", "SUB C", "SUB D", "SUB E", "SUB H", "SUB L", "SUB M", "SUB A", /* 90-97 */ - "SBB B", "SBB C", "SBB D", "SBB E", "SBB H", "SBB L", "SBB M", "SBB A", /* 98-9f */ - "ANA B", "ANA C", "ANA D", "ANA E", "ANA H", "ANA L", "ANA M", "ANA A", /* a0-a7 */ - "XRA B", "XRA C", "XRA D", "XRA E", "XRA H", "XRA L", "XRA M", "XRA A", /* a8-af */ - "ORA B", "ORA C", "ORA D", "ORA E", "ORA H", "ORA L", "ORA M", "ORA A", /* b0-b7 */ - "CMP B", "CMP C", "CMP D", "CMP E", "CMP H", "CMP L", "CMP M", "CMP A", /* b8-bf */ - "RNZ", "POP B", "JNZ #h", "JMP #h", "CNZ #h", "PUSH B", "ADI *h", "RST 0", /* c0-c7 */ - "RZ", "RET", "JZ #h", "DB CBh", "CZ #h", "CALL #h", "ACI *h", "RST 1", /* c8-cf */ - "RNC", "POP D", "JNC #h", "OUT *h", "CNC #h", "PUSH D", "SUI *h", "RST 2", /* d0-d7 */ - "RC", "DB D9h", "JC #h", "IN *h", "CC #h", "DB DDh", "SBI *h", "RST 3", /* d8-df */ - "RPO", "POP H", "JPO #h", "XTHL", "CPO #h", "PUSH H", "ANI *h", "RST 4", /* e0-e7 */ - "RPE", "PCHL", "JPE #h", "XCHG", "CPE #h", "DB EDh", "XRI *h", "RST 5", /* e8-ef */ - "RP", "POP PSW", "JP #h", "DI", "CP #h", "PUSH PSW", "ORI *h", "RST 6", /* f0-f7 */ - "RM", "SPHL", "JM #h", "EI", "CM #h", "DB FDh", "CPI *h", "RST 7" /* f8-ff */ - }; - -static char *const MnemonicsZ80[256] = { -/*0/8 1/9 2/A 3/B 4/C 5/D 6/E 7/F */ - "NOP", "LD BC,#h", "LD (BC),A", "INC BC", "INC B", "DEC B", "LD B,*h", "RLCA", /* 00-07 */ - "EX AF,AF'", "ADD HL,BC", "LD A,(BC)", "DEC BC", "INC C", "DEC C", "LD C,*h", "RRCA", /* 08-0f */ - "DJNZ $h", "LD DE,#h", "LD (DE),A", "INC DE", "INC D", "DEC D", "LD D,*h", "RLA", /* 10-17 */ - "JR $h", "ADD HL,DE", "LD A,(DE)", "DEC DE", "INC E", "DEC E", "LD E,*h", "RRA", /* 18-1f */ - "JR NZ,$h", "LD HL,#h", "LD (#h),HL", "INC HL", "INC H", "DEC H", "LD H,*h", "DAA", /* 20-27 */ - "JR Z,$h", "ADD HL,HL", "LD HL,(#h)", "DEC HL", "INC L", "DEC L", "LD L,*h", "CPL", /* 28-2f */ - "JR NC,$h", "LD SP,#h", "LD (#h),A", "INC SP", "INC (HL)", "DEC (HL)", "LD (HL),*h", "SCF", /* 30-37 */ - "JR C,$h", "ADD HL,SP", "LD A,(#h)", "DEC SP", "INC A", "DEC A", "LD A,*h", "CCF", /* 38-3f */ - "LD B,B", "LD B,C", "LD B,D", "LD B,E", "LD B,H", "LD B,L", "LD B,(HL)", "LD B,A", /* 40-47 */ - "LD C,B", "LD C,C", "LD C,D", "LD C,E", "LD C,H", "LD C,L", "LD C,(HL)", "LD C,A", /* 48-4f */ - "LD D,B", "LD D,C", "LD D,D", "LD D,E", "LD D,H", "LD D,L", "LD D,(HL)", "LD D,A", /* 50-57 */ - "LD E,B", "LD E,C", "LD E,D", "LD E,E", "LD E,H", "LD E,L", "LD E,(HL)", "LD E,A", /* 58-5f */ - "LD H,B", "LD H,C", "LD H,D", "LD H,E", "LD H,H", "LD H,L", "LD H,(HL)", "LD H,A", /* 60-67 */ - "LD L,B", "LD L,C", "LD L,D", "LD L,E", "LD L,H", "LD L,L", "LD L,(HL)", "LD L,A", /* 68-6f */ - "LD (HL),B", "LD (HL),C", "LD (HL),D", "LD (HL),E", "LD (HL),H", "LD (HL),L", "HALT", "LD (HL),A", /* 70-77 */ - "LD A,B", "LD A,C", "LD A,D", "LD A,E", "LD A,H", "LD A,L", "LD A,(HL)", "LD A,A", /* 78-7f */ - "ADD A,B", "ADD A,C", "ADD A,D", "ADD A,E", "ADD A,H", "ADD A,L", "ADD A,(HL)", "ADD A,A", /* 80-87 */ - "ADC A,B", "ADC A,C", "ADC A,D", "ADC A,E", "ADC A,H", "ADC A,L", "ADC A,(HL)", "ADC A,A", /* 88-8f */ - "SUB B", "SUB C", "SUB D", "SUB E", "SUB H", "SUB L", "SUB (HL)", "SUB A", /* 90-97 */ - "SBC A,B", "SBC A,C", "SBC A,D", "SBC A,E", "SBC A,H", "SBC A,L", "SBC A,(HL)", "SBC A,A", /* 98-9f */ - "AND B", "AND C", "AND D", "AND E", "AND H", "AND L", "AND (HL)", "AND A", /* a0-a7 */ - "XOR B", "XOR C", "XOR D", "XOR E", "XOR H", "XOR L", "XOR (HL)", "XOR A", /* a8-af */ - "OR B", "OR C", "OR D", "OR E", "OR H", "OR L", "OR (HL)", "OR A", /* b0-b7 */ - "CP B", "CP C", "CP D", "CP E", "CP H", "CP L", "CP (HL)", "CP A", /* b8-bf */ - "RET NZ", "POP BC", "JP NZ,#h", "JP #h", "CALL NZ,#h", "PUSH BC", "ADD A,*h", "RST 00h", /* c0-c7 */ - "RET Z", "RET", "JP Z,#h", "PFX_CB", "CALL Z,#h", "CALL #h", "ADC A,*h", "RST 08h", /* c8-cf */ - "RET NC", "POP DE", "JP NC,#h", "OUT (*h),A", "CALL NC,#h", "PUSH DE", "SUB *h", "RST 10h", /* d0-d7 */ - "RET C", "EXX", "JP C,#h", "IN A,(*h)", "CALL C,#h", "PFX_DD", "SBC A,*h", "RST 18h", /* d8-df */ - "RET PO", "POP HL", "JP PO,#h", "EX (SP),HL", "CALL PO,#h", "PUSH HL", "AND *h", "RST 20h", /* e0-e7 */ - "RET PE", "LD PC,HL", "JP PE,#h", "EX DE,HL", "CALL PE,#h", "PFX_ED", "XOR *h", "RST 28h", /* e8-ef */ - "RET P", "POP AF", "JP P,#h", "DI", "CALL P,#h", "PUSH AF", "OR *h", "RST 30h", /* f0-f7 */ - "RET M", "LD SP,HL", "JP M,#h", "EI", "CALL M,#h", "PFX_FD", "CP *h", "RST 38h" /* f8-ff */ -}; - -static char *const MnemonicsCB[256] = { -/*0/8 1/9 2/A 3/B 4/C 5/D 6/E 7/F */ - "RLC B", "RLC C", "RLC D", "RLC E", "RLC H", "RLC L", "RLC (HL)", "RLC A", /* 00-07 */ - "RRC B", "RRC C", "RRC D", "RRC E", "RRC H", "RRC L", "RRC (HL)", "RRC A", /* 08-0f */ - "RL B", "RL C", "RL D", "RL E", "RL H", "RL L", "RL (HL)", "RL A", /* 10-17 */ - "RR B", "RR C", "RR D", "RR E", "RR H", "RR L", "RR (HL)", "RR A", /* 18-1f */ - "SLA B", "SLA C", "SLA D", "SLA E", "SLA H", "SLA L", "SLA (HL)", "SLA A", /* 20-27 */ - "SRA B", "SRA C", "SRA D", "SRA E", "SRA H", "SRA L", "SRA (HL)", "SRA A", /* 28-2f */ - "SLL B", "SLL C", "SLL D", "SLL E", "SLL H", "SLL L", "SLL (HL)", "SLL A", /* 30-37 */ - "SRL B", "SRL C", "SRL D", "SRL E", "SRL H", "SRL L", "SRL (HL)", "SRL A", /* 38-3f */ - "BIT 0,B", "BIT 0,C", "BIT 0,D", "BIT 0,E", "BIT 0,H", "BIT 0,L", "BIT 0,(HL)", "BIT 0,A", /* 40-47 */ - "BIT 1,B", "BIT 1,C", "BIT 1,D", "BIT 1,E", "BIT 1,H", "BIT 1,L", "BIT 1,(HL)", "BIT 1,A", /* 48-4f */ - "BIT 2,B", "BIT 2,C", "BIT 2,D", "BIT 2,E", "BIT 2,H", "BIT 2,L", "BIT 2,(HL)", "BIT 2,A", /* 50-57 */ - "BIT 3,B", "BIT 3,C", "BIT 3,D", "BIT 3,E", "BIT 3,H", "BIT 3,L", "BIT 3,(HL)", "BIT 3,A", /* 58-5f */ - "BIT 4,B", "BIT 4,C", "BIT 4,D", "BIT 4,E", "BIT 4,H", "BIT 4,L", "BIT 4,(HL)", "BIT 4,A", /* 60-67 */ - "BIT 5,B", "BIT 5,C", "BIT 5,D", "BIT 5,E", "BIT 5,H", "BIT 5,L", "BIT 5,(HL)", "BIT 5,A", /* 68-6f */ - "BIT 6,B", "BIT 6,C", "BIT 6,D", "BIT 6,E", "BIT 6,H", "BIT 6,L", "BIT 6,(HL)", "BIT 6,A", /* 70-77 */ - "BIT 7,B", "BIT 7,C", "BIT 7,D", "BIT 7,E", "BIT 7,H", "BIT 7,L", "BIT 7,(HL)", "BIT 7,A", /* 78-7f */ - "RES 0,B", "RES 0,C", "RES 0,D", "RES 0,E", "RES 0,H", "RES 0,L", "RES 0,(HL)", "RES 0,A", /* 80-87 */ - "RES 1,B", "RES 1,C", "RES 1,D", "RES 1,E", "RES 1,H", "RES 1,L", "RES 1,(HL)", "RES 1,A", /* 88-8f */ - "RES 2,B", "RES 2,C", "RES 2,D", "RES 2,E", "RES 2,H", "RES 2,L", "RES 2,(HL)", "RES 2,A", /* 90-97 */ - "RES 3,B", "RES 3,C", "RES 3,D", "RES 3,E", "RES 3,H", "RES 3,L", "RES 3,(HL)", "RES 3,A", /* 98-9f */ - "RES 4,B", "RES 4,C", "RES 4,D", "RES 4,E", "RES 4,H", "RES 4,L", "RES 4,(HL)", "RES 4,A", /* a0-a7 */ - "RES 5,B", "RES 5,C", "RES 5,D", "RES 5,E", "RES 5,H", "RES 5,L", "RES 5,(HL)", "RES 5,A", /* a8-af */ - "RES 6,B", "RES 6,C", "RES 6,D", "RES 6,E", "RES 6,H", "RES 6,L", "RES 6,(HL)", "RES 6,A", /* b0-b7 */ - "RES 7,B", "RES 7,C", "RES 7,D", "RES 7,E", "RES 7,H", "RES 7,L", "RES 7,(HL)", "RES 7,A", /* b8-bf */ - "SET 0,B", "SET 0,C", "SET 0,D", "SET 0,E", "SET 0,H", "SET 0,L", "SET 0,(HL)", "SET 0,A", /* c0-c7 */ - "SET 1,B", "SET 1,C", "SET 1,D", "SET 1,E", "SET 1,H", "SET 1,L", "SET 1,(HL)", "SET 1,A", /* c8-cf */ - "SET 2,B", "SET 2,C", "SET 2,D", "SET 2,E", "SET 2,H", "SET 2,L", "SET 2,(HL)", "SET 2,A", /* d0-d7 */ - "SET 3,B", "SET 3,C", "SET 3,D", "SET 3,E", "SET 3,H", "SET 3,L", "SET 3,(HL)", "SET 3,A", /* d8-df */ - "SET 4,B", "SET 4,C", "SET 4,D", "SET 4,E", "SET 4,H", "SET 4,L", "SET 4,(HL)", "SET 4,A", /* e0-e7 */ - "SET 5,B", "SET 5,C", "SET 5,D", "SET 5,E", "SET 5,H", "SET 5,L", "SET 5,(HL)", "SET 5,A", /* e8-ef */ - "SET 6,B", "SET 6,C", "SET 6,D", "SET 6,E", "SET 6,H", "SET 6,L", "SET 6,(HL)", "SET 6,A", /* f0-f7 */ - "SET 7,B", "SET 7,C", "SET 7,D", "SET 7,E", "SET 7,H", "SET 7,L", "SET 7,(HL)", "SET 7,A" /* f8-ff */ -}; - -static char *const MnemonicsED[256] = { -/*0/8 1/9 2/A 3/B 4/C 5/D 6/E 7/F */ - "DB EDh,00h", "DB EDh,01h", "DB EDh,02h", "DB EDh,03h", "DB EDh,04h", "DB EDh,05h", "DB EDh,06h", "DB EDh,07h", /* 00-07 */ - "DB EDh,08h", "DB EDh,09h", "DB EDh,0Ah", "DB EDh,0Bh", "DB EDh,0Ch", "DB EDh,0Dh", "DB EDh,0Eh", "DB EDh,0Fh", /* 08-0f */ - "DB EDh,10h", "DB EDh,11h", "DB EDh,12h", "DB EDh,13h", "DB EDh,14h", "DB EDh,15h", "DB EDh,16h", "DB EDh,17h", /* 10-17 */ - "DB EDh,18h", "DB EDh,19h", "DB EDh,1Ah", "DB EDh,1Bh", "DB EDh,1Ch", "DB EDh,1Dh", "DB EDh,1Eh", "DB EDh,1Fh", /* 18-1f */ - "DB EDh,20h", "DB EDh,21h", "DB EDh,22h", "DB EDh,23h", "DB EDh,24h", "DB EDh,25h", "DB EDh,26h", "DB EDh,27h", /* 20-27 */ - "DB EDh,28h", "DB EDh,29h", "DB EDh,2Ah", "DB EDh,2Bh", "DB EDh,2Ch", "DB EDh,2Dh", "DB EDh,2Eh", "DB EDh,2Fh", /* 28-2f */ - "DB EDh,30h", "DB EDh,31h", "DB EDh,32h", "DB EDh,33h", "DB EDh,34h", "DB EDh,35h", "DB EDh,36h", "DB EDh,37h", /* 30-37 */ - "DB EDh,38h", "DB EDh,39h", "DB EDh,3Ah", "DB EDh,3Bh", "DB EDh,3Ch", "DB EDh,3Dh", "DB EDh,3Eh", "DB EDh,3Fh", /* 38-3f */ - "IN B,(C)", "OUT (C),B", "SBC HL,BC", "LD (#h),BC", "NEG", "RETN", "IM 0", "LD I,A", /* 40-47 */ - "IN C,(C)", "OUT (C),C", "ADC HL,BC", "LD BC,(#h)", "DB EDh,4Ch", "RETI", "DB EDh,4Eh", "LD R,A", /* 48-4f */ - "IN D,(C)", "OUT (C),D", "SBC HL,DE", "LD (#h),DE", "DB EDh,54h", "DB EDh,55h", "IM 1", "LD A,I", /* 50-57 */ - "IN E,(C)", "OUT (C),E", "ADC HL,DE", "LD DE,(#h)", "DB EDh,5Ch", "DB EDh,5Dh", "IM 2", "LD A,R", /* 58-5f */ - "IN H,(C)", "OUT (C),H", "SBC HL,HL", "LD (#h),HL", "DB EDh,64h", "DB EDh,65h", "DB EDh,66h", "RRD", /* 60-67 */ - "IN L,(C)", "OUT (C),L", "ADC HL,HL", "LD HL,(#h)", "DB EDh,6Ch", "DB EDh,6Dh", "DB EDh,6Eh", "RLD", /* 68-6f */ - "IN F,(C)", "DB EDh,71h", "SBC HL,SP", "LD (#h),SP", "DB EDh,74h", "DB EDh,75h", "DB EDh,76h", "DB EDh,77h", /* 70-77 */ - "IN A,(C)", "OUT (C),A", "ADC HL,SP", "LD SP,(#h)", "DB EDh,7Ch", "DB EDh,7Dh", "DB EDh,7Eh", "DB EDh,7Fh", /* 78-7f */ - "DB EDh,80h", "DB EDh,81h", "DB EDh,82h", "DB EDh,83h", "DB EDh,84h", "DB EDh,85h", "DB EDh,86h", "DB EDh,87h", /* 80-87 */ - "DB EDh,88h", "DB EDh,89h", "DB EDh,8Ah", "DB EDh,8Bh", "DB EDh,8Ch", "DB EDh,8Dh", "DB EDh,8Eh", "DB EDh,8Fh", /* 88-8f */ - "DB EDh,90h", "DB EDh,91h", "DB EDh,92h", "DB EDh,93h", "DB EDh,94h", "DB EDh,95h", "DB EDh,96h", "DB EDh,97h", /* 90-97 */ - "DB EDh,98h", "DB EDh,99h", "DB EDh,9Ah", "DB EDh,9Bh", "DB EDh,9Ch", "DB EDh,9Dh", "DB EDh,9Eh", "DB EDh,9Fh", /* 98-9f */ - "LDI", "CPI", "INI", "OUTI", "DB EDh,A4h", "DB EDh,A5h", "DB EDh,A6h", "DB EDh,A7h", /* a0-a7 */ - "LDD", "CPD", "IND", "OUTD", "DB EDh,ACh", "DB EDh,ADh", "DB EDh,AEh", "DB EDh,AFh", /* a8-af */ - "LDIR", "CPIR", "INIR", "OTIR", "DB EDh,B4h", "DB EDh,B5h", "DB EDh,B6h", "DB EDh,B7h", /* b0-b7 */ - "LDDR", "CPDR", "INDR", "OTDR", "DB EDh,BCh", "DB EDh,BDh", "DB EDh,BEh", "DB EDh,BFh", /* b8-bf */ - "DB EDh,C0h", "DB EDh,C1h", "DB EDh,C2h", "DB EDh,C3h", "DB EDh,C4h", "DB EDh,C5h", "DB EDh,C6h", "DB EDh,C7h", /* c0-c7 */ - "DB EDh,C8h", "DB EDh,C9h", "DB EDh,CAh", "DB EDh,CBh", "DB EDh,CCh", "DB EDh,CDh", "DB EDh,CEh", "DB EDh,CFh", /* c8-cf */ - "DB EDh,D0h", "DB EDh,D1h", "DB EDh,D2h", "DB EDh,D3h", "DB EDh,D4h", "DB EDh,D5h", "DB EDh,D6h", "DB EDh,D7h", /* d0-d7 */ - "DB EDh,D8h", "DB EDh,D9h", "DB EDh,DAh", "DB EDh,DBh", "DB EDh,DCh", "DB EDh,DDh", "DB EDh,DEh", "DB EDh,DFh", /* d8-df */ - "DB EDh,E0h", "DB EDh,E1h", "DB EDh,E2h", "DB EDh,E3h", "DB EDh,E4h", "DB EDh,E5h", "DB EDh,E6h", "DB EDh,E7h", /* e0-e7 */ - "DB EDh,E8h", "DB EDh,E9h", "DB EDh,EAh", "DB EDh,EBh", "DB EDh,ECh", "DB EDh,EDh", "DB EDh,EEh", "DB EDh,EFh", /* e8-ef */ - "DB EDh,F0h", "DB EDh,F1h", "DB EDh,F2h", "DB EDh,F3h", "DB EDh,F4h", "DB EDh,F5h", "DB EDh,F6h", "DB EDh,F7h", /* f0-f7 */ - "DB EDh,F8h", "DB EDh,F9h", "DB EDh,FAh", "DB EDh,FBh", "DB EDh,FCh", "DB EDh,FDh", "DB EDh,FEh", "DB EDh,FFh" /* f8-ff */ -}; - -static char *const MnemonicsXX[256] = { -/*0/8 1/9 2/A 3/B 4/C 5/D 6/E 7/F */ - "NOP", "LD BC,#h", "LD (BC),A", "INC BC", "INC B", "DEC B", "LD B,*h", "RLCA", /* 00-07 */ - "EX AF,AF'", "ADD I%,BC", "LD A,(BC)", "DEC BC", "INC C", "DEC C", "LD C,*h", "RRCA", /* 08-0f */ - "DJNZ $h", "LD DE,#h", "LD (DE),A", "INC DE", "INC D", "DEC D", "LD D,*h", "RLA", /* 10-17 */ - "JR $h", "ADD I%,DE", "LD A,(DE)", "DEC DE", "INC E", "DEC E", "LD E,*h", "RRA", /* 18-1f */ - "JR NZ,$h", "LD I%,#h", "LD (#h),I%", "INC I%", "INC I%H", "DEC I%H", "LD I%H,*h", "DAA", /* 20-27 */ - "JR Z,$h", "ADD I%,I%", "LD I%,(#h)", "DEC I%", "INC I%L", "DEC I%L", "LD I%L,*h", "CPL", /* 28-2f */ - "JR NC,$h", "LD SP,#h", "LD (#h),A", "INC SP", "INC (I%+^h)", "DEC (I%+^h)", "LD (I%+^h),*h", "SCF", /* 30-37 */ - "JR C,$h", "ADD I%,SP", "LD A,(#h)", "DEC SP", "INC A", "DEC A", "LD A,*h", "CCF", /* 38-3f */ - "LD B,B", "LD B,C", "LD B,D", "LD B,E", "LD B,I%H", "LD B,I%L", "LD B,(I%+^h)", "LD B,A", /* 40-47 */ - "LD C,B", "LD C,C", "LD C,D", "LD C,E", "LD C,I%H", "LD C,I%L", "LD C,(I%+^h)", "LD C,A", /* 48-4f */ - "LD D,B", "LD D,C", "LD D,D", "LD D,E", "LD D,I%H", "LD D,I%L", "LD D,(I%+^h)", "LD D,A", /* 50-57 */ - "LD E,B", "LD E,C", "LD E,D", "LD E,E", "LD E,I%H", "LD E,I%L", "LD E,(I%+^h)", "LD E,A", /* 58-5f */ - "LD I%H,B", "LD I%H,C", "LD I%H,D", "LD I%H,E", "LD I%H,I%H", "LD I%H,I%L", "LD H,(I%+^h)", "LD I%H,A", /* 60-67 */ - "LD I%L,B", "LD I%L,C", "LD I%L,D", "LD I%L,E", "LD I%L,I%H", "LD I%L,I%L", "LD L,(I%+^h)", "LD I%L,A", /* 68-6f */ - "LD (I%+^h),B", "LD (I%+^h),C", "LD (I%+^h),D", "LD (I%+^h),E", "LD (I%+^h),H", "LD (I%+^h),L", "HALT", "LD (I%+^h),A", /* 70-77 */ - "LD A,B", "LD A,C", "LD A,D", "LD A,E", "LD A,I%H", "LD A,I%L", "LD A,(I%+^h)", "LD A,A", /* 78-7f */ - "ADD A,B", "ADD A,C", "ADD A,D", "ADD A,E", "ADD A,I%H", "ADD A,I%L", "ADD A,(I%+^h)", "ADD A,A", /* 80-87 */ - "ADC A,B", "ADC A,C", "ADC A,D", "ADC A,E", "ADC A,I%H", "ADC A,I%L", "ADC A,(I%+^h)", "ADC A,A", /* 88-8f */ - "SUB B", "SUB C", "SUB D", "SUB E", "SUB I%H", "SUB I%L", "SUB (I%+^h)", "SUB A", /* 90-97 */ - "SBC A,B", "SBC A,C", "SBC A,D", "SBC A,E", "SBC A,I%H", "SBC A,I%L", "SBC A,(I%+^h)", "SBC A,A", /* 98-9f */ - "AND B", "AND C", "AND D", "AND E", "AND I%H", "AND I%L", "AND (I%+^h)", "AND A", /* a0-a7 */ - "XOR B", "XOR C", "XOR D", "XOR E", "XOR I%H", "XOR I%L", "XOR (I%+^h)", "XOR A", /* a8-af */ - "OR B", "OR C", "OR D", "OR E", "OR I%H", "OR I%L", "OR (I%+^h)", "OR A", /* b0-b7 */ - "CP B", "CP C", "CP D", "CP E", "CP I%H", "CP I%L", "CP (I%+^h)", "CP A", /* b8-bf */ - "RET NZ", "POP BC", "JP NZ,#h", "JP #h", "CALL NZ,#h", "PUSH BC", "ADD A,*h", "RST 00h", /* c8-cf */ - "RET Z", "RET", "JP Z,#h", "PFX_CB", "CALL Z,#h", "CALL #h", "ADC A,*h", "RST 08h", /* c8-cf */ - "RET NC", "POP DE", "JP NC,#h", "OUT (*h),A", "CALL NC,#h", "PUSH DE", "SUB *h", "RST 10h", /* d0-d7 */ - "RET C", "EXX", "JP C,#h", "IN A,(*h)", "CALL C,#h", "PFX_DD", "SBC A,*h", "RST 18h", /* d8-df */ - "RET PO", "POP I%", "JP PO,#h", "EX (SP),I%", "CALL PO,#h", "PUSH I%", "AND *h", "RST 20h", /* e0-e7 */ - "RET PE", "LD PC,I%", "JP PE,#h", "EX DE,I%", "CALL PE,#h", "PFX_ED", "XOR *h", "RST 28h", /* e8-ef */ - "RET P", "POP AF", "JP P,#h", "DI", "CALL P,#h", "PUSH AF", "OR *h", "RST 30h", /* f0-f7 */ - "RET M", "LD SP,I%", "JP M,#h", "EI", "CALL M,#h", "PFX_FD", "CP *h", "RST 38h" /* f8-ff */ -}; - -static char *const MnemonicsXCB[256] = { -/*0/8 1/9 2/A 3/B 4/C 5/D 6/E 7/F */ - "RLC B", "RLC C", "RLC D", "RLC E", "RLC H", "RLC L", "RLC (I%@h)", "RLC A", /* 00-07 */ - "RRC B", "RRC C", "RRC D", "RRC E", "RRC H", "RRC L", "RRC (I%@h)", "RRC A", /* 08-0f */ - "RL B", "RL C", "RL D", "RL E", "RL H", "RL L", "RL (I%@h)", "RL A", /* 10-17 */ - "RR B", "RR C", "RR D", "RR E", "RR H", "RR L", "RR (I%@h)", "RR A", /* 18-1f */ - "SLA B", "SLA C", "SLA D", "SLA E", "SLA H", "SLA L", "SLA (I%@h)", "SLA A", /* 20-27 */ - "SRA B", "SRA C", "SRA D", "SRA E", "SRA H", "SRA L", "SRA (I%@h)", "SRA A", /* 28-2f */ - "SLL B", "SLL C", "SLL D", "SLL E", "SLL H", "SLL L", "SLL (I%@h)", "SLL A", /* 30-37 */ - "SRL B", "SRL C", "SRL D", "SRL E", "SRL H", "SRL L", "SRL (I%@h)", "SRL A", /* 38-3f */ - "BIT 0,B", "BIT 0,C", "BIT 0,D", "BIT 0,E", "BIT 0,H", "BIT 0,L", "BIT 0,(I%@h)", "BIT 0,A", /* 40-47 */ - "BIT 1,B", "BIT 1,C", "BIT 1,D", "BIT 1,E", "BIT 1,H", "BIT 1,L", "BIT 1,(I%@h)", "BIT 1,A", /* 48-4f */ - "BIT 2,B", "BIT 2,C", "BIT 2,D", "BIT 2,E", "BIT 2,H", "BIT 2,L", "BIT 2,(I%@h)", "BIT 2,A", /* 50-57 */ - "BIT 3,B", "BIT 3,C", "BIT 3,D", "BIT 3,E", "BIT 3,H", "BIT 3,L", "BIT 3,(I%@h)", "BIT 3,A", /* 58-5f */ - "BIT 4,B", "BIT 4,C", "BIT 4,D", "BIT 4,E", "BIT 4,H", "BIT 4,L", "BIT 4,(I%@h)", "BIT 4,A", /* 60-67 */ - "BIT 5,B", "BIT 5,C", "BIT 5,D", "BIT 5,E", "BIT 5,H", "BIT 5,L", "BIT 5,(I%@h)", "BIT 5,A", /* 68-6f */ - "BIT 6,B", "BIT 6,C", "BIT 6,D", "BIT 6,E", "BIT 6,H", "BIT 6,L", "BIT 6,(I%@h)", "BIT 6,A", /* 70-77 */ - "BIT 7,B", "BIT 7,C", "BIT 7,D", "BIT 7,E", "BIT 7,H", "BIT 7,L", "BIT 7,(I%@h)", "BIT 7,A", /* 78-7f */ - "RES 0,B", "RES 0,C", "RES 0,D", "RES 0,E", "RES 0,H", "RES 0,L", "RES 0,(I%@h)", "RES 0,A", /* 80-87 */ - "RES 1,B", "RES 1,C", "RES 1,D", "RES 1,E", "RES 1,H", "RES 1,L", "RES 1,(I%@h)", "RES 1,A", /* 88-8f */ - "RES 2,B", "RES 2,C", "RES 2,D", "RES 2,E", "RES 2,H", "RES 2,L", "RES 2,(I%@h)", "RES 2,A", /* 90-97 */ - "RES 3,B", "RES 3,C", "RES 3,D", "RES 3,E", "RES 3,H", "RES 3,L", "RES 3,(I%@h)", "RES 3,A", /* 98-9f */ - "RES 4,B", "RES 4,C", "RES 4,D", "RES 4,E", "RES 4,H", "RES 4,L", "RES 4,(I%@h)", "RES 4,A", /* a0-a7 */ - "RES 5,B", "RES 5,C", "RES 5,D", "RES 5,E", "RES 5,H", "RES 5,L", "RES 5,(I%@h)", "RES 5,A", /* a8-af */ - "RES 6,B", "RES 6,C", "RES 6,D", "RES 6,E", "RES 6,H", "RES 6,L", "RES 6,(I%@h)", "RES 6,A", /* b0-b7 */ - "RES 7,B", "RES 7,C", "RES 7,D", "RES 7,E", "RES 7,H", "RES 7,L", "RES 7,(I%@h)", "RES 7,A", /* b8-bf */ - "SET 0,B", "SET 0,C", "SET 0,D", "SET 0,E", "SET 0,H", "SET 0,L", "SET 0,(I%@h)", "SET 0,A", /* c0-c7 */ - "SET 1,B", "SET 1,C", "SET 1,D", "SET 1,E", "SET 1,H", "SET 1,L", "SET 1,(I%@h)", "SET 1,A", /* c8-cf */ - "SET 2,B", "SET 2,C", "SET 2,D", "SET 2,E", "SET 2,H", "SET 2,L", "SET 2,(I%@h)", "SET 2,A", /* d0-d7 */ - "SET 3,B", "SET 3,C", "SET 3,D", "SET 3,E", "SET 3,H", "SET 3,L", "SET 3,(I%@h)", "SET 3,A", /* d8-df */ - "SET 4,B", "SET 4,C", "SET 4,D", "SET 4,E", "SET 4,H", "SET 4,L", "SET 4,(I%@h)", "SET 4,A", /* e0-e7 */ - "SET 5,B", "SET 5,C", "SET 5,D", "SET 5,E", "SET 5,H", "SET 5,L", "SET 5,(I%@h)", "SET 5,A", /* e8-ef */ - "SET 6,B", "SET 6,C", "SET 6,D", "SET 6,E", "SET 6,H", "SET 6,L", "SET 6,(I%@h)", "SET 6,A", /* f0-f7 */ - "SET 7,B", "SET 7,C", "SET 7,D", "SET 7,E", "SET 7,H", "SET 7,L", "SET 7,(I%@h)", "SET 7,A" /* f8-ff */ -}; - -/* symbolic disassembler - - Inputs: - *val = instructions to disassemble - useZ80Mnemonics = > 0 iff Z80 mnemonics are to be used - addr = current PC - Outputs: - *S = output text - - DAsm is Copyright (C) Marat Fayzullin 1995,1996,1997 - You are not allowed to distribute this software - commercially. - -*/ - -static int32 DAsm(char *S, const uint32 *val, const int32 useZ80Mnemonics, const int32 addr) { - char R[128], H[10], C = '\0', *T, *P; - uint8 J = 0, Offset = 0; - uint16 B = 0; - - if (useZ80Mnemonics) { - switch(val[B]) { - case 0xcb: - B++; - T = MnemonicsCB[val[B++]]; - break; - case 0xed: - B++; - T = MnemonicsED[val[B++]]; - break; - case 0xdd: - case 0xfd: - C = (val[B++] == 0xdd) ? 'X' : 'Y'; - if (val[B] == 0xcb) { - B++; - Offset = val[B++]; - J = 1; - T = MnemonicsXCB[val[B++]]; - } - else { - T = MnemonicsXX[val[B++]]; - } - break; - default: - T = MnemonicsZ80[val[B++]]; - } - } - else { - T = Mnemonics8080[val[B++]]; - } - - if (P = strchr(T, '^')) { - strncpy(R, T, P - T); - R[P - T] = '\0'; - sprintf(H, "%02X", val[B++]); - strcat(R, H); - strcat(R, P + 1); - } - else { - strcpy(R, T); - } - if (P = strchr(R, '%')) { - *P = C; - if (P = strchr(P + 1, '%')) { - *P = C; - } - } - - if(P = strchr(R, '*')) { - strncpy(S, R, P - R); - S[P - R] = '\0'; - sprintf(H, "%02X", val[B++]); - strcat(S, H); - strcat(S, P + 1); - } - else if (P = strchr(R, '@')) { - strncpy(S, R, P - R); - S[P - R] = '\0'; - if(!J) { - Offset = val[B++]; - } - strcat(S, Offset & 0x80 ? "-" : "+"); - J = Offset & 0x80 ? 256 - Offset : Offset; - sprintf(H, "%02X", J); - strcat(S, H); - strcat(S, P + 1); - } - else if (P = strchr(R, '$')) { - strncpy(S, R, P - R); - S[P - R] = '\0'; - Offset = val[B++]; - sprintf(H, "%04X", addr + 2 + (Offset & 0x80 ? (Offset - 256) : Offset)); - strcat(S, H); - strcat(S, P + 1); - } - else if (P = strchr(R, '#')) { - strncpy(S, R, P - R); - S[P - R] = '\0'; - sprintf(H, "%04X", val[B] + 256 * val[B + 1]); - strcat(S, H); - strcat(S, P + 1); - B += 2; - } - else { - strcpy(S, R); - } - return(B); -} - -/* symbolic output - - Inputs: - *of = output stream - addr = current PC - *val = pointer to values - *uptr = pointer to unit - sw = switches - Outputs: - status = error code -*/ - -int32 fprint_sym(FILE *of, int32 addr, uint32 *val, UNIT *uptr, int32 sw) { - char disasm[128]; - int32 ch = val[0] & 0x7f; - if (sw & (SWMASK('A') | SWMASK('C'))) { - fprintf(of, ((0x20 <= ch) && (ch < 0x7f)) ? "'%c'" : "%02x", ch); - return SCPE_OK; - } - if (!(sw & SWMASK('M'))) { - return SCPE_ARG; - } - ch = DAsm(disasm, val, cpu_unit.flags & UNIT_CHIP, addr); - fprintf(of, "%s", disasm); - return 1 - ch; /* need to return additional bytes */ -} - -/* numString checks determines the base of the number (ch, *numString) - and returns FALSE if the number is bad */ -static int32 checkbase(char ch, const char *numString) { - int32 decimal = (ch <= '9'); - if (toupper(ch) == 'H') { - return FALSE; - } - while (isxdigit(ch = *numString++)) { - if (ch > '9') { - decimal = FALSE; - } - } - return toupper(ch) == 'H' ? 16 : (decimal ? 10 : FALSE); -} - -static int32 numok(char ch, const char **numString, const int32 minvalue, - const int32 maxvalue, const int32 requireSign, int32 *result) { - int32 sign = 1, value = 0, base; - if (requireSign) { - if (ch == '+') { - ch = *(*numString)++; - } - else if (ch == '-') { - sign = -1; - ch = *(*numString)++; - } - else { - return FALSE; - } - } - if (!(base = checkbase(ch, *numString))) { - return FALSE; - } - while (isxdigit(ch)) { - value = base * value + ((ch <= '9') ? (ch - '0') : (toupper(ch) - 'A' + 10)); - ch = *(*numString)++; - } - if (toupper(ch) != 'H') { - (*numString)--; - } - *result = value * sign; - return (minvalue <= value) && (value <= maxvalue); -} - -static int32 match(const char *pattern, const char *input, char *xyFirst, char *xy, int32 *number, int32 *star, - int32 *at, int32 *hat, int32 *dollar) { - char pat = *pattern++; - char inp = *input++; - while ((pat) && (inp)) { - switch(pat) { - case '_': /* patterns containting '_' should never match */ - return FALSE; - case ',': - if (inp == ' ') { - inp = *input++; - continue; - } /* otherwise fall through */ - case ' ': - if (inp != pat) { - return FALSE; - } - pat = *pattern++; - inp = *input++; - while (inp == ' ') { - inp = *input++; - } - continue; - case '%': - inp = toupper(inp); - if ((inp == 'X') || (inp == 'Y')) { - if (*xyFirst) { /* make sure that second '%' corresponds to first */ - if (*xyFirst == inp) { - *xy = inp; - } - else { - return FALSE; - } - } - else { /* take note of first '%' for later */ - *xyFirst = inp; - *xy = inp; - } - } - else { - return FALSE; - } - break; - case '#': - if (numok(inp, &input, 0, 65535, FALSE, number)) { - pattern++; /* skip h */ - } - else { - return FALSE; - } - break; - case '*': - if (numok(inp, &input, 0, 255, FALSE, star)) { - pattern++; /* skip h */ - } - else { - return FALSE; - } - break; - case '@': - if (numok(inp, &input, -128, 65535, TRUE, at)) { - pattern++; /* skip h */ - } - else { - return FALSE; - } - break; - case '$': - if (numok(inp, &input, 0, 65535, FALSE, dollar)) { - pattern++; /* skip h */ - } - else { - return FALSE; - } - break; - case '^': - if (numok(inp, &input, 0, 255, FALSE, hat)) { - pattern++; /* skip h */ - } - else { - return FALSE; - } - break; - default: - if (toupper(pat) != toupper(inp)) { - return FALSE; - } - } - pat = *pattern++; - inp = *input++; - } - while (inp == ' ') { - inp = *input++; - } - return (pat == 0) && (inp == 0); -} - -static INLINE int32 checkXY(const char xy) { - return xy == 'X' ? 0xdd : 0xfd; /* else is 'Y' */ -} - -static int32 parse_X80(const char *cptr, const int32 addr, uint32 *val, char *const Mnemonics[]) { - char xyFirst = 0, xy; - int32 op, number, star, at, hat, dollar; - for (op = 0; op < 256; op++) { - number = star = at = dollar = -129; - if (match(Mnemonics[op], cptr, &xyFirst, &xy, &number, &star, &at, &hat, &dollar)) { - val[0] = op; - if (number >= 0) { - val[1] = (0xff) & number; - val[2] = (0xff) & (number >> 8); - return -2; /* two additional bytes returned */ - } - else if (star >= 0) { - val[1] = (0xff) & star; - return -1; /* one additional byte returned */ - } - else if (at > -129) { - if ((-128 <= at) && (at <= 127)) { - val[1] = (int8)(at); - return -1; /* one additional byte returned */ - } - else { - return SCPE_ARG; - } - } - else if (dollar >= 0) { - dollar -= addr + 2; /* relative translation */ - if ((-128 <= dollar) && (dollar <= 127)) { - val[1] = (int8)(dollar); - return -1; /* one additional byte returned */ - } - else { - return SCPE_ARG; - } - } - else { - return SCPE_OK; - } - } - } - if (Mnemonics == Mnemonics8080) { - return SCPE_ARG; - } - - for (op = 0; op < 256; op++) { - if (match(MnemonicsCB[op], cptr, &xyFirst, &xy, &number, &star, &at, &hat, &dollar)) { - val[0] = 0xcb; - val[1] = op; - return -1; /* one additional byte returned */ - } - } - - for (op = 0; op < 256; op++) { - number = -1; - if (match(MnemonicsED[op], cptr, &xyFirst, &xy, &number, &star, &at, &hat, &dollar)) { - val[0] = 0xed; - val[1] = op; - if (number >= 0) { - val[2] = (0xff) & number; - val[3] = (0xff) & (number >> 8); - return -3; /* three additional bytes returned */ - } - else { - return -1; /* one additional byte returned */ - } - } - } - - for (op = 0; op < 256; op++) { - number = star = hat = -1; - xy = 0; - if (match(MnemonicsXX[op], cptr, &xyFirst, &xy, &number, &star, &at, &hat, &dollar)) { - /* all matches must have contained a '%' character */ - if (!(val[0] = checkXY(xy))) { - return SCPE_ARG; - } - val[1] = op; - if (number >= 0) { - val[2] = (0xff) & number; - val[3] = (0xff) & (number >> 8); - return -3; /* three additional bytes returned */ - } - else if ((star >= 0) && (hat >= 0)) { - val[2] = (0xff) & hat; - val[3] = (0xff) & star; - return -3; /* three additional bytes returned */ - } - else if (star >= 0) { - val[2] = (0xff) & star; - return -2; /* two additional bytes returned */ - } - else if (hat >= 0) { - val[2] = (0xff) & hat; - return -2; /* two additional bytes returned */ - } - else { - return -1; /* one additional byte returned */ - } - } - } - - for (op = 0; op < 256; op++) { - at = -129; - xy = 0; - if (match(MnemonicsXCB[op], cptr, &xyFirst, &xy, &number, &star, &at, &hat, &dollar)) { - /* all matches must have contained a '%' character */ - if (!(val[0] = checkXY(xy))) { - return SCPE_ARG; - } - val[1] = 0xcb; - if (at > -129) { - val[2] = (int8) (at); - } - else { - printf("Offset expected.\n"); - return SCPE_ARG; - } - val[3] = op; - return -3; /* three additional bytes returned */ - } - } - return SCPE_ARG; -} - - -/* 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 -*/ -int32 parse_sym(char *cptr, int32 addr, UNIT *uptr, uint32 *val, int32 sw) { - while (isspace(*cptr)) cptr++; /* absorb spaces */ - if ((sw & (SWMASK('A') | SWMASK('C'))) || ((*cptr == '\'') && cptr++)) { /* ASCII char? */ - if (cptr[0] == 0) { - return SCPE_ARG; /* must have one char */ - } - val[0] = (uint32) cptr[0]; - return SCPE_OK; - } - return parse_X80(cptr, addr, val, cpu_unit.flags & UNIT_CHIP ? MnemonicsZ80 : Mnemonics8080); -} - - -/* This is the binary loader. The input file is considered to be - a string of literal bytes with no format special format. The - load starts at the current value of the PC. ROM/NOROM and - ALTAIRROM/NOALTAIRROM settings are ignored. -*/ - -int32 sim_load(FILE *fileref, char *cptr, char *fnam, int32 flag) { - int32 i, addr = 0, cnt = 0, org, cntROM = 0, cntNonExist = 0; - t_addr j, lo, hi; - char *result; - t_stat status; - if (flag) { - result = get_range(cptr, &lo, &hi, 16, ADDRMASK, 0); - if (result == NULL) { - return SCPE_ARG; - } - for (j = lo; j <= hi; j++) { - if (putc(GetBYTEWrapper(j), fileref) == EOF) { - return SCPE_IOERR; - } - } - printf("%d bytes dumped [%x - %x].\n", hi + 1 - lo, lo, hi); - } - else { - if (*cptr == 0) { - addr = saved_PC; - } - else { - addr = get_uint(cptr, 16, ADDRMASK, &status); - if (status != SCPE_OK) { - return status; - } - } - org = addr; - while ((addr < MAXMEMSIZE) && ((i = getc(fileref)) != EOF)) { - PutBYTEForced(addr, i); - if (addressIsInROM(addr)) { - cntROM++; - } - if (!addressExists(addr)) { - cntNonExist++; - } - addr++; - cnt++; - } /* end while */ - printf("%d bytes [%d page%s] loaded at %x.\n", cnt, (cnt + 255) >> 8, - ((cnt + 255) >> 8) == 1 ? "" : "s", org); - printROMMessage(cntROM); - if (cntNonExist) { - printf("Warning: %d bytes written to non-existing memory (for this configuration).\n", cntNonExist); - } - } - return SCPE_OK; -} diff --git a/AltairZ80/altairz80_hdsk.c b/AltairZ80/altairz80_hdsk.c deleted file mode 100644 index 9794098b..00000000 --- a/AltairZ80/altairz80_hdsk.c +++ /dev/null @@ -1,386 +0,0 @@ -/* altairz80_hdsk.c: simulated hard disk device to increase capacity - - Copyright (c) 2002-2003, Peter Schorn - - 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 - PETER SCHORN 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 Peter Schorn shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Peter Schorn. -*/ - -#include "altairz80_defs.h" - -#define UNIT_V_HDSKWLK (UNIT_V_UF + 0) /* write locked */ -#define UNIT_HDSKWLK (1 << UNIT_V_HDSKWLK) -#define UNIT_V_HDSK_VERBOSE (UNIT_V_UF + 1) /* verbose mode, i.e. show error messages */ -#define UNIT_HDSK_VERBOSE (1 << UNIT_V_HDSK_VERBOSE) -#define HDSK_SECTOR_SIZE 128 /* size of sector */ -#define HDSK_SECTORS_PER_TRACK 32 /* sectors per track */ -#define HDS_MAX_TRACKS 2048 /* number of tracks */ -#define HDSK_TRACK_SIZE (HDSK_SECTOR_SIZE * HDSK_SECTORS_PER_TRACK) -#define HDSK_CAPACITY (HDSK_TRACK_SIZE * HDS_MAX_TRACKS) -#define HDSK_NUMBER 8 /* number of hard disks */ -#define CPM_OK 0 /* indicates to CP/M everything ok */ -#define CPM_ERROR 1 /* indicates to CP/M an error condition */ -#define CPM_EMPTY 0xe5 /* default value for non-existing bytes */ -#define hdsk_none 0 -#define hdsk_reset 1 -#define hdsk_read 2 -#define hdsk_write 3 -#define hdsk_boot_address 0x5c00 - -extern char messageBuffer[]; -extern int32 PCX; -extern UNIT cpu_unit; -extern uint8 M[MAXMEMSIZE][MAXBANKS]; -extern int32 saved_PC; - -extern int32 install_bootrom(void); -extern void printMessage(void); -extern void PutBYTEBasic(const uint32 Addr, const uint32 Bank, const uint32 Value); -extern void PutBYTEWrapper(register uint32 Addr, register uint32 Value); -extern void protect(const int32 l, const int32 h); -extern uint8 GetBYTEWrapper(register uint32 Addr); -extern int32 bootrom[bootrom_size]; - -static t_stat hdsk_svc(UNIT *uptr); -static t_stat hdsk_boot(int32 unitno, DEVICE *dptr); -static int32 hdsk_hasVerbose(void); -int32 hdsk_io(const int32 port, const int32 io, const int32 data); -static int32 hdsk_in(const int32 port); -static int32 hdsk_out(const int32 data); -static int32 checkParameters(void); -static int32 doSeek(void); -static int32 doRead(void); -static int32 doWrite(void); - -static int32 hdskLastCommand = hdsk_none; -static int32 hdskCommandPosition = 0; -static int32 selectedDisk; -static int32 selectedSector; -static int32 selectedTrack; -static int32 selectedDMA; -static int32 hdskTrace; - -static UNIT hdsk_unit[] = { - { UDATA (&hdsk_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, HDSK_CAPACITY) }, - { UDATA (&hdsk_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, HDSK_CAPACITY) }, - { UDATA (&hdsk_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, HDSK_CAPACITY) }, - { UDATA (&hdsk_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, HDSK_CAPACITY) }, - { UDATA (&hdsk_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, HDSK_CAPACITY) }, - { UDATA (&hdsk_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, HDSK_CAPACITY) }, - { UDATA (&hdsk_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, HDSK_CAPACITY) }, - { UDATA (&hdsk_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, HDSK_CAPACITY) } }; - -static REG hdsk_reg[] = { - { DRDATA (HDCMD, hdskLastCommand, 32), REG_RO }, - { DRDATA (HDPOS, hdskCommandPosition, 32), REG_RO }, - { DRDATA (HDDSK, selectedDisk, 32), REG_RO }, - { DRDATA (HDSEC, selectedSector, 32), REG_RO }, - { DRDATA (HDTRK, selectedTrack, 32), REG_RO }, - { DRDATA (HDDMA, selectedDMA, 32), REG_RO }, - { DRDATA (HDTRACE, hdskTrace, 8), }, - { NULL } }; - -static MTAB hdsk_mod[] = { - { UNIT_HDSKWLK, 0, "write enabled", "WRITEENABLED", NULL }, - { UNIT_HDSKWLK, UNIT_HDSKWLK, "write locked", "LOCKED", NULL }, - /* quiet, no warning messages */ - { UNIT_HDSK_VERBOSE, 0, "QUIET", "QUIET", NULL }, - /* verbose, show warning messages */ - { UNIT_HDSK_VERBOSE, UNIT_HDSK_VERBOSE, "VERBOSE", "VERBOSE", NULL }, - { 0 } }; - -DEVICE hdsk_dev = { - "HDSK", hdsk_unit, hdsk_reg, hdsk_mod, - 8, 10, 31, 1, 8, 8, - NULL, NULL, NULL, - &hdsk_boot, NULL, NULL, NULL, 0, NULL, NULL }; - -static t_stat hdsk_svc(UNIT *uptr) { - return SCPE_OK; -} - -static const int32 hdskBoot[bootrom_size] = { - 0xf3, 0x06, 0x80, 0x3e, 0x0e, 0xd3, 0xfe, 0x05, /* 5c00-5c07 */ - 0xc2, 0x05, 0x5c, 0x3e, 0x16, 0xd3, 0xfe, 0x3e, /* 5c08-5c0f */ - 0x12, 0xd3, 0xfe, 0xdb, 0xfe, 0xb7, 0xca, 0x20, /* 5c10-5c17 */ - 0x5c, 0x3e, 0x0c, 0xd3, 0xfe, 0xaf, 0xd3, 0xfe, /* 5c18-5c1f */ - 0x06, 0x20, 0x3e, 0x01, 0xd3, 0xfd, 0x05, 0xc2, /* 5c20-5c27 */ - 0x24, 0x5c, 0x11, 0x08, 0x00, 0x21, 0x00, 0x00, /* 5c28-5c2f */ - 0x0e, 0xb8, 0x3e, 0x02, 0xd3, 0xfd, 0x3a, 0x37, /* 5c30-5c37 */ - 0xff, 0xd6, 0x08, 0xd3, 0xfd, 0x7b, 0xd3, 0xfd, /* 5c38-5c3f */ - 0x7a, 0xd3, 0xfd, 0xaf, 0xd3, 0xfd, 0x7d, 0xd3, /* 5c40-5c47 */ - 0xfd, 0x7c, 0xd3, 0xfd, 0xdb, 0xfd, 0xb7, 0xca, /* 5c48-5c4f */ - 0x53, 0x5c, 0x76, 0x79, 0x0e, 0x80, 0x09, 0x4f, /* 5c50-5c57 */ - 0x0d, 0xc2, 0x60, 0x5c, 0xfb, 0xc3, 0x00, 0x00, /* 5c58-5c5f */ - 0x1c, 0x1c, 0x7b, 0xfe, 0x20, 0xca, 0x73, 0x5c, /* 5c60-5c67 */ - 0xfe, 0x21, 0xc2, 0x32, 0x5c, 0x1e, 0x00, 0x14, /* 5c68-5c6f */ - 0xc3, 0x32, 0x5c, 0x1e, 0x01, 0xc3, 0x32, 0x5c, /* 5c70-5c77 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 5c78-5c7f */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 5c80-5c87 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 5c88-5c8f */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 5c90-5c97 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 5c98-5c9f */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 5ca0-5ca7 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 5ca8-5caf */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 5cb0-5cb7 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 5cb8-5cbf */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 5cc0-5cc7 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 5cc8-5ccf */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 5cd0-5cd7 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 5cd8-5cdf */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 5ce0-5ce7 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 5ce8-5cef */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 5cf0-5cf7 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 5cf8-5cff */ -}; - -static t_stat hdsk_boot(int32 unitno, DEVICE *dptr) { - int32 i; - if (MEMSIZE < 24*KB) { - printf("Need at least 24KB RAM to boot from hard disk.\n"); - return SCPE_ARG; - } - if (cpu_unit.flags & (UNIT_ALTAIRROM | UNIT_BANKED)) { - if (install_bootrom()) { - printf("ALTAIR boot ROM installed.\n"); - } - /* check whether we are really modifying an LD A,<> instruction */ - if (bootrom[unitNoOffset1 - 1] == LDAInstruction) { - bootrom[unitNoOffset1] = (unitno + NUM_OF_DSK) & 0xff; /* LD A, */ - } - else { /* Attempt to modify non LD A,<> instructions is refused. */ - printf("Incorrect boot ROM offset detected.\n"); - return SCPE_IERR; - } - } - for (i = 0; i < bootrom_size; i++) { - PutBYTEBasic(i + hdsk_boot_address, 0, hdskBoot[i] & 0xff); - } - saved_PC = hdsk_boot_address; - protect(hdsk_boot_address, hdsk_boot_address + bootrom_size - 1); - return SCPE_OK; -} - -/* returns TRUE iff there exists a disk with VERBOSE */ -static int32 hdsk_hasVerbose(void) { - int32 i; - for (i = 0; i < HDSK_NUMBER; i++) { - if (((hdsk_dev.units + i) -> flags) & UNIT_HDSK_VERBOSE) { - return TRUE; - } - } - return FALSE; -} - -/* The hard disk port is 0xfd. It understands the following commands. - -1. reset - ld b,32 - ld a,hdsk_reset -l out (0fdh),a - dec b - jp nz,l - -2. read / write - ; parameter block - cmd: db hdsk_read or hdsk_write - hd: db 0 ; 0 .. 7, defines hard disk to be used - sector: db 0 ; 0 .. 31, defines sector - track: dw 0 ; 0 .. 2047, defines track - dma: dw 0 ; defines where result is placed in memory - - ; routine to execute - ld b,7 ; size of parameter block - ld hl,cmd ; start address of parameter block -l ld a,(hl) ; get byte of parameter block - out (0fdh),a ; send it to port - inc hl ; point to next byte - dec b ; decrement counter - jp nz,l ; again, if not done - in a,(0fdh) ; get result code - -*/ - -/* check the parameters and return TRUE iff parameters are correct or have been repaired */ -static int32 checkParameters(void) { - int32 currentFlag; - if ((selectedDisk < 0) || (selectedDisk >= HDSK_NUMBER)) { - if (hdsk_hasVerbose()) { - message2("HDSK%d does not exist, will use HDSK0 instead.\n", selectedDisk); - } - selectedDisk = 0; - } - currentFlag = (hdsk_dev.units + selectedDisk) -> flags; - if ((currentFlag & UNIT_ATT) == 0) { - if (currentFlag & UNIT_HDSK_VERBOSE) { - message2("HDSK%d is not attached.\n", selectedDisk); - } - return FALSE; /* cannot read or write */ - } - if ((selectedSector < 0) || (selectedSector >= HDSK_SECTORS_PER_TRACK)) { - if (currentFlag & UNIT_HDSK_VERBOSE) { - message4("HDSK%d: 0 <= Sector=%02d < %d violated, will use 0 instead.\n", - selectedDisk, selectedSector, HDSK_SECTORS_PER_TRACK); - } - selectedSector = 0; - } - if ((selectedTrack < 0) || (selectedTrack >= HDS_MAX_TRACKS)) { - if (currentFlag & UNIT_HDSK_VERBOSE) { - message4("HDSK%d: 0 <= Track=%04d < %04d violated, will use 0 instead.\n", - selectedDisk, selectedTrack, HDS_MAX_TRACKS); - } - selectedTrack = 0; - } - selectedDMA &= ADDRMASK; - if (hdskTrace) { - message6("%s HDSK%d Sector=%02d Track=%04d DMA=%04x\n", - (hdskLastCommand == hdsk_read) ? "Read" : "Write", - selectedDisk, selectedSector, selectedTrack, selectedDMA); - } - return TRUE; -} - -static int32 doSeek(void) { - UNIT *uptr = hdsk_dev.units + selectedDisk; - if (fseek(uptr -> fileref, - HDSK_TRACK_SIZE * selectedTrack + HDSK_SECTOR_SIZE * selectedSector, SEEK_SET)) { - if ((uptr -> flags) & UNIT_HDSK_VERBOSE) { - message4("Could not access HDSK%d Sector=%02d Track=%04d.\n", - selectedDisk, selectedSector, selectedTrack); - } - return CPM_ERROR; - } - else { - return CPM_OK; - } -} - -static int32 doRead(void) { - int32 i; - uint8 hdskbuf[HDSK_SECTOR_SIZE]; /* data buffer */ - UNIT *uptr = hdsk_dev.units + selectedDisk; - if (doSeek()) { - return CPM_ERROR; - } - if (fread(hdskbuf, HDSK_SECTOR_SIZE, 1, uptr -> fileref) != 1) { - for (i = 0; i < HDSK_SECTOR_SIZE; i++) { - hdskbuf[i] = CPM_EMPTY; - } - if ((uptr -> flags) & UNIT_HDSK_VERBOSE) { - message4("Could not read HDSK%d Sector=%02d Track=%04d.\n", - selectedDisk, selectedSector, selectedTrack); - } - return CPM_OK; /* allows the creation of empty hard disks */ - } - for (i = 0; i < HDSK_SECTOR_SIZE; i++) { - PutBYTEWrapper(selectedDMA + i, hdskbuf[i]); - } - return CPM_OK; -} - -static int32 doWrite(void) { - int32 i; - uint8 hdskbuf[HDSK_SECTOR_SIZE]; /* data buffer */ - UNIT *uptr = hdsk_dev.units + selectedDisk; - if (((uptr -> flags) & UNIT_HDSKWLK) == 0) { /* write enabled */ - if (doSeek()) { - return CPM_ERROR; - } - for (i = 0; i < HDSK_SECTOR_SIZE; i++) { - hdskbuf[i] = GetBYTEWrapper(selectedDMA + i); - } - if (fwrite(hdskbuf, HDSK_SECTOR_SIZE, 1, uptr -> fileref) != 1) { - if ((uptr -> flags) & UNIT_HDSK_VERBOSE) { - message4("Could not write HDSK%d Sector=%02d Track=%04d.\n", - selectedDisk, selectedSector, selectedTrack); - } - return CPM_ERROR; - } - } - else { - if ((uptr -> flags) & UNIT_HDSK_VERBOSE) { - message4("Could not write to locked HDSK%d Sector=%02d Track=%04d.\n", - selectedDisk, selectedSector, selectedTrack); - } - return CPM_ERROR; - } - return CPM_OK; -} - -static int32 hdsk_in(const int32 port) { - int32 result; - if ((hdskCommandPosition == 6) && ((hdskLastCommand == hdsk_read) || (hdskLastCommand == hdsk_write))) { - result = checkParameters() ? ((hdskLastCommand == hdsk_read) ? doRead() : doWrite()) : CPM_ERROR; - hdskLastCommand = hdsk_none; - hdskCommandPosition = 0; - return result; - } - else if (hdsk_hasVerbose()) { - message4("Illegal IN command detected (port=%03xh, cmd=%d, pos=%d).\n", - port, hdskLastCommand, hdskCommandPosition); - } - return CPM_OK; -} - -static int32 hdsk_out(const int32 data) { - switch(hdskLastCommand) { - case hdsk_read: - case hdsk_write: - switch(hdskCommandPosition) { - case 0: - selectedDisk = data; - hdskCommandPosition++; - break; - case 1: - selectedSector = data; - hdskCommandPosition++; - break; - case 2: - selectedTrack = data; - hdskCommandPosition++; - break; - case 3: - selectedTrack += (data << 8); - hdskCommandPosition++; - break; - case 4: - selectedDMA = data; - hdskCommandPosition++; - break; - case 5: - selectedDMA += (data << 8); - hdskCommandPosition++; - break; - default: - hdskLastCommand = hdsk_none; - hdskCommandPosition = 0; - } - break; - default: - hdskLastCommand = data; - hdskCommandPosition = 0; - } - return 0; /* ignored, since OUT */ -} - -int32 hdsk_io(const int32 port, const int32 io, const int32 data) { - return io == 0 ? hdsk_in(port) : hdsk_out(data); -} diff --git a/GRI/gri_cpu.c b/GRI/gri_cpu.c deleted file mode 100644 index f6166100..00000000 --- a/GRI/gri_cpu.c +++ /dev/null @@ -1,890 +0,0 @@ -/* gri_cpu.c: GRI-909 CPU 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. - - cpu GRI-909 CPU - - 14-Mar-03 RMS Fixed bug in SC queue tracking - - The system state for the GRI-909 is: - - AX<0:15> arithmetic input - AY<0:15> arithmetic input - BSW<0:15> byte swapper - BPK<0:15> byte packer - GR[0:5]<0:15> extended general registers - MSR<0:15> machine status register - TRP<0:15> trap register (subroutine return) - SC<0:14> sequence counter - - The GRI-909 has, nominally, just one instruction format: move. - - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | source | op | destination | move - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - <6:9> operation - - xx1x complement - 01xx add 1 - 10xx rotate left 1 - 11xx rotate right 1 - - In fact, certain of the source and destination operators have side - effects, yielding four additional instruction formats: function out, - skip on function, memory reference, and conditional jump. -*/ - -/* The function out format is: - - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | 0 0 0 0 1 0| pulse | destination | function out - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - The skip on function format is: - - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | source | skip |rv| 0 0 0 0 1 0| skip function - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - The memory reference format is (src and/or dst = 006): - - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | source | op | mode| destination | memory ref - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | address or immediate | - +-----------------------------------------------+ - - <6:9> operation - - xx0x direct, ea = M[SC+1] - xx1x immediate, ea = SC+1 - xxx1 indirect, M[ea] = M[ea]+1, then ea = M[ea] - 01xx add 1 - 10xx rotate left 1 - 11xx rotate right 1 - - The conditional jump format is (src != 006): - - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | source | cond|rv|df| 0 0 0 0 1 1| cond jump - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | jump address | - +-----------------------------------------------+ - - <6:9> operation - - xxx0 direct, ea = M[SC+1] - xxx1 indirect, ea = M[SC+1], M[ea] = M[ea]+1, - then ea = M[ea] - xx1x reverse conditional sense - x1xx jump if src == 0 - 1xxx jump if src < 0 -*/ - -/* This routine is the instruction decode routine for the GRI-909. - 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 - unknown source or destination and STOP_OPR flag set - I/O error in I/O simulator - - 2. Interrupts. The interrupt structure is kept in two parallel variables: - - dev_done device done flags - ISR interrupt status register (enables) - - In addition, there is a master interrupt enable, and a one cycle - interrupt defer, both kept in dev_done. - - 3. Non-existent memory. On the GRI-909, 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: - - gri_defs.h add interrupt request definition - gri_cpu.c add dev_tab table entry - gri_sys.c add sim_devices table entry -*/ - -#include "gri_defs.h" - -#define SCQ_SIZE 64 /* must be 2**n */ -#define SCQ_MASK (SCQ_SIZE - 1) -#define SCQ_ENTRY scq[scq_p = (scq_p - 1) & SCQ_MASK] = SC -#define UNIT_V_NOEAO (UNIT_V_UF) /* EAO absent */ -#define UNIT_NOEAO (1 << UNIT_V_NOEAO) -#define UNIT_V_MSIZE (UNIT_V_UF + 1) /* dummy mask */ -#define UNIT_MSIZE (1 << UNIT_V_MSIZE) - -uint16 M[MAXMEMSIZE] = { 0 }; /* memory */ -uint32 SC; /* sequence cntr */ -uint32 AX, AY, AO; /* arithmetic unit */ -uint32 IR; /* instr reg */ -uint32 MA; /* memory addr */ -uint32 TRP; /* subr return */ -uint32 MSR; /* machine status */ -uint32 ISR; /* interrupt status */ -uint32 BSW, BPK; /* byte swap, pack */ -uint32 GR[6]; /* extended general regs */ -uint32 SWR; /* switch reg */ -uint32 DR; /* display register */ -uint32 thwh = 0; /* thumbwheel */ -uint32 dev_done = 0; /* device flags */ -uint32 bkp = 0; /* bkpt pending */ -uint32 stop_opr = 1; /* stop ill operator */ -int16 scq[SCQ_SIZE] = { 0 }; /* PC queue */ -int32 scq_p = 0; /* PC queue ptr */ -REG *scq_r = NULL; /* PC queue reg ptr */ - -extern int32 sim_interval; -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); -t_stat bus_op (uint32 src, uint32 op, uint32 dst); - -/* Dispatch tables for source, dest, function out, skip on function */ - -uint32 no_rd (uint32 src); -t_stat no_wr (uint32 dst, uint32 val); -t_stat no_fo (uint32 op); -uint32 no_sf (uint32 op); -uint32 zero_rd (uint32 src); -t_stat zero_wr (uint32 dst, uint32 val); -t_stat zero_fo (uint32 op); -uint32 zero_sf (uint32 op); -uint32 ir_rd (uint32 op); -t_stat ir_fo (uint32 op); -uint32 trp_rd (uint32 src); -uint32 isr_rd (uint32 src); -t_stat isr_wr (uint32 dst, uint32 val); -t_stat isr_fo (uint32 op); -uint32 isr_sf (uint32 op); -uint32 ma_rd (uint32 src); -uint32 mem_rd (uint32 src); -t_stat mem_wr (uint32 dst, uint32 val); -uint32 sc_rd (uint32 src); -t_stat sc_wr (uint32 dst, uint32 val); -uint32 swr_rd (uint32 src); -uint32 ax_rd (uint32 src); -t_stat ax_wr (uint32 dst, uint32 val); -uint32 ay_rd (uint32 src); -t_stat ay_wr (uint32 dst, uint32 val); -uint32 ao_rd (uint32 src); -t_stat ao_fo (uint32 op); -uint32 ao_sf (uint32 op); -uint32 ao_update (void); -t_stat eao_fo (uint32 op); -uint32 msr_rd (uint32 src); -t_stat msr_wr (uint32 dst, uint32 val); -uint32 bsw_rd (uint32 src); -t_stat bsw_wr (uint32 dst, uint32 val); -uint32 bpk_rd (uint32 src); -t_stat bpk_wr (uint32 dst, uint32 val); -uint32 gr_rd (uint32 src); -t_stat gr_wr (uint32 dst, uint32 val); - -extern t_stat rtc_fo (uint32 op); -extern uint32 rtc_sf (uint32 op); -extern uint32 hsrp_rd (uint32 src); -extern t_stat hsrp_wr (uint32 dst, uint32 val); -extern t_stat hsrp_fo (uint32 op); -extern uint32 hsrp_sf (uint32 op); -extern uint32 tty_rd (uint32 src); -extern t_stat tty_wr (uint32 dst, uint32 val); -extern t_stat tty_fo (uint32 op); -extern uint32 tty_sf (uint32 op); - -struct gdev dev_tab[64] = { - { &zero_rd, &zero_wr, &zero_fo, &zero_sf }, /* 00: zero */ - { &ir_rd, &zero_wr, &ir_fo, &zero_sf }, /* ir */ - { &no_rd, &no_wr, &no_fo, &no_sf }, /* fo/sf */ - { &trp_rd, &no_wr, &zero_fo, &zero_sf }, /* trp */ - { &isr_rd, &isr_wr, &isr_fo, &isr_sf }, /* isr */ - { &ma_rd, &no_wr, &no_fo, &no_sf }, /* MA */ - { &mem_rd, &mem_wr, &zero_fo, &zero_sf }, /* memory */ - { &sc_rd, &sc_wr, &zero_fo, &zero_sf }, /* sc */ - { &swr_rd, &no_wr, &no_fo, &no_sf }, /* swr */ - { &ax_rd, &ax_wr, &zero_fo, &zero_sf }, /* ax */ - { &ay_rd, &ay_wr, &zero_fo, &zero_sf }, /* ay */ - { &ao_rd, &zero_wr, &ao_fo, &ao_sf }, /* ao */ - { &zero_rd, &zero_wr, &eao_fo, &zero_sf }, /* eao */ - { &no_rd, &no_wr, &no_fo, &no_sf }, - { &no_rd, &no_wr, &no_fo, &no_sf }, - { &msr_rd, &msr_wr, &zero_fo, &zero_sf }, /* msr */ - { &no_rd, &no_wr, &no_fo, &no_sf }, /* 20 */ - { &no_rd, &no_wr, &no_fo, &no_sf }, - { &no_rd, &no_wr, &no_fo, &no_sf }, - { &no_rd, &no_wr, &no_fo, &no_sf }, - { &bsw_rd, &bsw_wr, &no_fo, &no_sf }, /* bsw */ - { &bpk_rd, &bpk_wr, &no_fo, &no_sf }, /* bpk */ - { &no_rd, &no_wr, &no_fo, &no_sf }, - { &no_rd, &no_wr, &no_fo, &no_sf }, - { &gr_rd, &gr_wr, &zero_fo, &zero_sf }, /* 30: gr1 */ - { &gr_rd, &gr_wr, &zero_fo, &zero_sf }, /* gr2 */ - { &gr_rd, &gr_wr, &zero_fo, &zero_sf }, /* gr3 */ - { &gr_rd, &gr_wr, &zero_fo, &zero_sf }, /* gr4 */ - { &gr_rd, &gr_wr, &zero_fo, &zero_sf }, /* gr5 */ - { &gr_rd, &gr_wr, &zero_fo, &zero_sf }, /* gr6 */ - { &no_rd, &no_wr, &no_fo, &no_sf }, - { &no_rd, &no_wr, &no_fo, &no_sf }, - { &no_rd, &no_wr, &no_fo, &no_sf }, /* 40 */ - { &no_rd, &no_wr, &no_fo, &no_sf }, - { &no_rd, &no_wr, &no_fo, &no_sf }, - { &no_rd, &no_wr, &no_fo, &no_sf }, - { &no_rd, &no_wr, &no_fo, &no_sf }, - { &no_rd, &no_wr, &no_fo, &no_sf }, - { &no_rd, &no_wr, &no_fo, &no_sf }, - { &no_rd, &no_wr, &no_fo, &no_sf }, - { &no_rd, &no_wr, &no_fo, &no_sf }, /* 50 */ - { &no_rd, &no_wr, &no_fo, &no_sf }, - { &no_rd, &no_wr, &no_fo, &no_sf }, - { &no_rd, &no_wr, &no_fo, &no_sf }, - { &no_rd, &no_wr, &no_fo, &no_sf }, - { &no_rd, &no_wr, &no_fo, &no_sf }, - { &no_rd, &no_wr, &no_fo, &no_sf }, - { &no_rd, &no_wr, &no_fo, &no_sf }, - { &no_rd, &no_wr, &no_fo, &no_sf }, /* 60 */ - { &no_rd, &no_wr, &no_fo, &no_sf }, - { &no_rd, &no_wr, &no_fo, &no_sf }, - { &no_rd, &no_wr, &no_fo, &no_sf }, - { &no_rd, &no_wr, &no_fo, &no_sf }, - { &no_rd, &no_wr, &no_fo, &no_sf }, - { &no_rd, &no_wr, &no_fo, &no_sf }, - { &no_rd, &no_wr, &no_fo, &no_sf }, - { &no_rd, &no_wr, &no_fo, &no_sf }, /* 70 */ - { &no_rd, &no_wr, &no_fo, &no_sf }, - { &no_rd, &no_wr, &no_fo, &no_sf }, - { &no_rd, &no_wr, &no_fo, &no_sf }, - { &no_rd, &no_wr, &no_fo, &no_sf }, - { &zero_rd, &zero_wr, &rtc_fo, &rtc_sf }, /* rtc */ - { &hsrp_rd, &hsrp_wr, &hsrp_fo, &hsrp_sf }, /* hsrp */ - { &tty_rd, &tty_wr, &tty_fo, &tty_sf } }; /* tty */ - -static const int32 vec_map[16] = { - VEC_TTO, VEC_TTI, VEC_HSP, VEC_HSR, - -1, -1, -1, -1, - -1, -1, -1, VEC_RTC, - -1, -1, -1, -1 }; - -/* 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 (SC, SC, 15) }, - { ORDATA (AX, AX, 16) }, - { ORDATA (AY, AY, 16) }, - { ORDATA (AO, AO, 16), REG_RO }, - { ORDATA (TRP, TRP, 16) }, - { ORDATA (MSR, MSR, 16) }, - { ORDATA (ISR, ISR, 16) }, - { ORDATA (BSW, BSW, 16) }, - { ORDATA (BPK, BPK, 16) }, - { ORDATA (GR1, GR[0], 16) }, - { ORDATA (GR2, GR[1], 16) }, - { ORDATA (GR3, GR[2], 16) }, - { ORDATA (GR4, GR[3], 16) }, - { ORDATA (GR5, GR[4], 16) }, - { ORDATA (GR6, GR[5], 16) }, - { FLDATA (BOV, MSR, MSR_V_BOV) }, - { FLDATA (L, MSR, MSR_V_L) }, - { GRDATA (FOA, MSR, 8, 2, MSR_V_FOA) }, - { FLDATA (AOV, MSR, MSR_V_AOV) }, - { ORDATA (IR, IR, 16), REG_RO }, - { ORDATA (MA, MA, 16), REG_RO }, - { ORDATA (SWR, SWR, 16) }, - { ORDATA (DR, DR, 16) }, - { ORDATA (THW, thwh, 6) }, - { ORDATA (IREQ, dev_done, INT_V_NODEF) }, - { FLDATA (ION, dev_done, INT_V_ON) }, - { FLDATA (INODEF, dev_done, INT_V_NODEF) }, - { FLDATA (BKP, bkp, 0) }, - { BRDATA (SCQ, scq, 8, 15, SCQ_SIZE), REG_RO + REG_CIRC }, - { ORDATA (SCQP, scq_p, 6), REG_HRO }, - { FLDATA (STOP_OPR, stop_opr, 0) }, - { ORDATA (WRU, sim_int_char, 8) }, - { NULL } }; - -MTAB cpu_mod[] = { - { UNIT_NOEAO, UNIT_NOEAO, "no EAO", "NOEAO", NULL }, - { UNIT_NOEAO, 0, "EAO", "EAO", 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 }, - { 0 } }; - -DEVICE cpu_dev = { - "CPU", &cpu_unit, cpu_reg, cpu_mod, - 1, 8, 15, 1, 8, 16, - &cpu_ex, &cpu_dep, &cpu_reset, - NULL, NULL, NULL }; - -t_stat sim_instr (void) -{ -uint32 src, dst, op, t, jmp; -t_stat reason; -extern UNIT rtc_unit; - -/* Restore register state */ - -SC = SC & AMASK; /* load local PC */ -reason = 0; -AO = ao_update (); /* update AO */ -sim_rtc_init (rtc_unit.wait); /* init calibration */ - -/* Main instruction fetch/decode loop */ - -while (reason == 0) { /* loop until halted */ - -if (sim_interval <= 0) { /* check clock queue */ - if (reason = sim_process_event ()) break; } - -if (bkp) { /* breakpoint? */ - bkp = 0; /* clear request */ - dev_done = dev_done & ~INT_ON; /* int off */ - M[VEC_BKP] = SC; /* save SC */ - SC = VEC_BKP + 1; } /* new SC */ - -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 ((i < 0) || ((vec = vec_map[i]) < 0)) { /* undefined? */ - reason = STOP_ILLINT; /* stop */ - break; } - dev_done = dev_done & ~INT_ON; /* int off */ - M[vec] = SC; /* save SC */ - SC = vec + 1; /* new SC */ - continue; } - -if (sim_brk_summ && sim_brk_test (SC, SWMASK ('E'))) { /* breakpoint? */ - reason = STOP_IBKPT; /* stop simulation */ - break; } - -MA = SC; /* set mem addr */ -IR = M[MA]; /* fetch instr */ -dev_done = dev_done | INT_NODEF; /* clr ion defer */ -sim_interval = sim_interval - 1; - -/* Decode instruction types */ - -src = I_GETSRC (IR); /* src unit */ -dst = I_GETDST (IR); /* dst unit */ -op = I_GETOP (IR); /* bus op */ - -if (src == U_FSK) { /* func out? */ - reason = dev_tab[dst].FO (op); /* send function */ - SC = (SC + 1) & AMASK; } /* incr SC */ - -else if (dst == U_FSK) { /* skip func? */ - t = dev_tab[src].SF (op & ~1); /* issue SF */ - reason = t >> SF_V_REASON; - if ((t ^ op) & 1) SC = SC + 2; /* skip? */ - SC = (SC + 1) & AMASK; } /* incr SC */ - -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; - case 01: /* always */ - jmp = 1; - break; - case 02: /* src == 0 */ - jmp = (t == 0); - break; - case 03: /* src != 0 */ - jmp = (t != 0); - break; - case 04: /* src < 0 */ - jmp = (t >= SIGN); - break; - case 05: /* src >= 0 */ - 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 */ - else SC = (SC + 2) & AMASK; } /* incr SC twice */ - -else if ((src != U_MEM) && (dst != U_MEM)) { /* reg-reg? */ - reason = bus_op (src, op, dst); /* xmt and modify */ - SC = (SC + 1) & AMASK; } /* incr SC */ - -/* Memory reference. The second SC increment occurs after the first - execution cycle. For direct, defer, and immediate defer, this is - after the first memory read and before the bus transfer; but for - immediate, it is after the bus transfer. -*/ - -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; - 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; - 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; - 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 */ - } /* end mem ref */ -} /* end while */ - -/* Simulation halted */ - -AO = ao_update (); /* update AO */ -scq_r->qptr = scq_p; /* update sc q ptr */ -return reason; -} - -/* Bus operations */ - -t_stat bus_op (uint32 src, uint32 op, uint32 dst) -{ -uint32 t, old_t; - -t = dev_tab[src].Src (src); /* get src */ -if (op & BUS_COM) t = t ^ DMASK; /* complement? */ -switch (op & BUS_FNC) { /* case op */ -case BUS_P1: /* plus 1 */ - t = t + 1; /* do add */ - if (t & CBIT) MSR = MSR | MSR_BOV; /* set cry out */ - else MSR = MSR & ~MSR_BOV; - break; -case BUS_L1: /* left 1 */ - t = (t << 1) | ((MSR & MSR_L)? 1: 0); /* rotate */ - if (t & CBIT) MSR = MSR | MSR_L; /* set link out */ - else MSR = MSR & ~MSR_L; - break; -case BUS_R1: /* right 1 */ - old_t = t; - t = (t >> 1) | ((MSR & MSR_L)? SIGN: 0); /* rotate */ - if (old_t & 1) MSR = MSR | MSR_L; /* set link out */ - else MSR = MSR & ~MSR_L; - break; } /* end case op */ -if (dst == thwh) DR = t & DMASK; /* display dst? */ -return dev_tab[dst].Dst (dst, t & DMASK); /* store dst */ -} - -/* Non-existent device */ - -uint32 no_rd (uint32 src) -{ -return 0; -} - -t_stat no_wr (uint32 dst, uint32 dat) -{ -return stop_opr; -} - -t_stat no_fo (uint32 fnc) -{ -return stop_opr; -} - -uint32 no_sf (uint32 fnc) -{ -return (stop_opr << SF_V_REASON); -} - -/* Zero device */ - -uint32 zero_rd (uint32 src) -{ -return 0; -} - -t_stat zero_wr (uint32 dst, uint32 val) -{ -return SCPE_OK; -} - -t_stat zero_fo (uint32 op) -{ -switch (op & 3) { /* FOM link */ -case 1: /* CLL */ - MSR = MSR & ~MSR_L; - break; -case 2: /* STL */ - MSR = MSR | MSR_L; - break; -case 3: /* CML */ - MSR = MSR ^ MSR_L; - break; } -if (op & 4) return STOP_HALT; /* HALT */ -return SCPE_OK; -} - -uint32 zero_sf (uint32 op) -{ -if ((op & 010) || /* power always ok */ - ((op & 4) && (MSR & MSR_L)) || /* link set? */ - ((op & 2) && (MSR & MSR_BOV))) return 1; /* BOV set? */ -return 0; -} - -/* Instruction register (01) */ - -uint32 ir_rd (uint32 src) -{ -return IR; -} - -t_stat ir_fo (uint32 op) -{ -if (op & 2) bkp = 1; -return SCPE_OK; -} - -/* Trap register (03) */ - -uint32 trp_rd (uint32 src) -{ -return TRP; -} - -/* Interrupt status register (04) */ - -uint32 isr_rd (uint32 src) -{ -return ISR; -} - -t_stat isr_wr (uint32 dst, uint32 dat) -{ -ISR = dat; -return SCPE_OK; -} - -t_stat isr_fo (uint32 op) -{ -if (op & ISR_ON) dev_done = (dev_done | INT_ON) & ~INT_NODEF; -if (op & ISR_OFF) dev_done = dev_done & ~INT_ON; -return SCPE_OK; -} - -uint32 isr_sf (uint32 op) -{ -return 0; -} - -/* Memory address (05) */ - -uint32 ma_rd (uint32 src) -{ -return MA; -} - -/* Memory (06) */ - -uint32 mem_rd (uint32 src) -{ -return M[MA]; -} - -t_stat mem_wr (uint32 dst, uint32 dat) -{ - -if (MEM_ADDR_OK (MA)) M[MA] = dat; -return SCPE_OK; -} - -/* Sequence counter (07) */ - -uint32 sc_rd (uint32 src) -{ -return SC; -} - -t_stat sc_wr (uint32 dst, uint32 dat) -{ -SCQ_ENTRY; -SC = dat & AMASK; -return SCPE_OK; -} - -/* Switch register (10) */ - -uint32 swr_rd (uint32 src) -{ -return SWR; -} - -/* Machine status register (17) */ - -uint32 msr_rd (uint32 src) -{ -return MSR; -} - -t_stat msr_wr (uint32 src, uint32 dat) -{ -MSR = dat; /* new MSR */ -ao_update (); /* update AOV */ -return SCPE_OK; -} - -/* Arithmetic operators (11:14) */ - -uint32 ao_update (void) -{ -int32 t; -int32 af = MSR_GET_FOA (MSR); - -switch (af) { -case AO_ADD: - t = (AX + AY) & DMASK; /* add */ - break; -case AO_AND: - t = AX & AY; /* and */ - break; -case AO_XOR: /* xor */ - t = AX ^ AY; - break; -case AO_IOR: - t = AX | AY; /* or */ - break; } -if ((AX + AY) & CBIT) MSR = MSR | MSR_AOV; /* always calc AOV */ -else MSR = MSR & ~MSR_AOV; -return t; -} - -uint32 ax_rd (uint32 src) -{ -return AX; -} - -t_stat ax_wr (uint32 dst, uint32 dat) -{ -AX = dat; -return SCPE_OK; -} - -uint32 ay_rd (uint32 src) -{ -return AY; -} - -t_stat ay_wr (uint32 dst, uint32 dat) -{ -AY = dat; -return SCPE_OK; -} - -uint32 ao_rd (uint32 src) -{ -AO = ao_update (); -return AO; -} - -t_stat ao_fo (uint32 op) -{ -uint32 t = OP_GET_FOA (op); /* get func */ -MSR = MSR_PUT_FOA (MSR, t); /* store in MSR */ -ao_update (); /* update AOV */ -return SCPE_OK; -} - -t_stat eao_fo (uint32 op) -{ -uint32 t; - -if (cpu_unit.flags & UNIT_NOEAO) return stop_opr; /* EAO installed? */ -if (op == EAO_MUL) { /* mul? */ - t = AX * AY; /* AX * AY */ - AX = (t >> 16) & DMASK; /* to AX'GR1 */ - 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 */ - } -return SCPE_OK; -} - -uint32 ao_sf (uint32 op) -{ -if (((op & 2) && (MSR & MSR_AOV)) || /* arith carry? */ - ((op & 4) && (SIGN & /* arith overflow? */ - ((AX ^ (AX + AY)) & (~AX ^ AY))))) return 1; -return 0; -} - -/* Byte swapper (24) */ - -uint32 bsw_rd (uint32 src) -{ -return BSW; -} - -t_stat bsw_wr (uint32 dst, uint32 val) -{ -BSW = ((val >> 8) & 0377) | ((val & 0377) << 8); -return SCPE_OK; -} - -/* Byte packer (25) */ - -uint32 bpk_rd (uint32 src) -{ -return BPK; -} - -t_stat bpk_wr (uint32 dst, uint32 val) -{ -BPK = ((BPK & 0377) << 8) | (val & 0377); -return SCPE_OK; -} - -/* General registers (30:35) */ - -uint32 gr_rd (uint32 src) -{ -return GR[src - U_GR]; -} - -t_stat gr_wr (uint32 dst, uint32 dat) -{ -GR[dst - U_GR] = dat; -return SCPE_OK; -} - -/* Reset routine */ - -t_stat cpu_reset (DEVICE *dptr) -{ -int32 i; - -AX = AY = AO = 0; -TRP = 0; -ISR = 0; -MSR = 0; -MA = IR = 0; -BSW = BPK = 0; -for (i = 0; i < 6; i++) GR[i] = 0; -dev_done = dev_done & ~INT_PENDING; -scq_r = find_reg ("SCQ", NULL, dptr); -if (scq_r) scq_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] & DMASK; -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 & DMASK; -return SCPE_OK; -} - -t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -int32 mc = 0; -uint32 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/GRI/gri_defs.h b/GRI/gri_defs.h deleted file mode 100644 index 2888bed1..00000000 --- a/GRI/gri_defs.h +++ /dev/null @@ -1,221 +0,0 @@ -/* gri_defs.h: GRI-909 simulator definitions - - 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. - - 25-Apr-03 RMS Revised for extended file support - 19-Sep-02 RMS Fixed declarations in gdev structure - - There are several discrepancies between the original GRI-909 Reference - Manual of 1969 and the only surviving code sample, the MIT Crystal Growing - System of 1972: - - 1. Ref Manual documents two GR's at codes 26-27; MITCS documents six GR's - at 30-35. - 2. Ref Manual documents only unsigned overflow (carry) for arithmetic - operator; MITCS uses both unsigned overflow (AOV) and signed overflow - (SOV). - 3. Ref Manual documents a ROM-subroutine multiply operator and mentions - but does not document a "fast multiply"; MITCS uses an extended - arithmetic operator with multiply, divide, and shifts. The behavior - of the extended arithmetic operator can only be inferred partially; - the shifts are never used, and there is no indication of how divide - overflow is handled. - - The simulator follows the code in these instances. - - Outstanding issues: - - 1. Is there any interaction between the byte swapper and the byte packer? - 2. Is SOV testable even if the FOA is not ADD? - 3. How does the EAO handle divide overflow? - 4. What are the other EAO functions beside multiply and divide? -*/ - -#include "sim_defs.h" /* simulator defns */ - -/* Simulator stop codes */ - -#define STOP_DEV 1 /* must be 1 */ -#define STOP_HALT 2 /* HALT */ -#define STOP_IBKPT 3 /* breakpoint */ -#define STOP_ILLINT 4 /* illegal intr */ - -/* Memory */ - -#define MAXMEMSIZE 32768 /* max memory size */ -#define AMASK 077777 /* logical addr mask */ -#define MEMSIZE (cpu_unit.capac) /* actual memory size */ -#define MEM_ADDR_OK(x) (((uint32) (x)) < MEMSIZE) - -/* Architectural constants */ - -#define SIGN 0100000 /* sign */ -#define DMASK 0177777 /* data mask */ -#define CBIT (DMASK + 1) /* carry bit */ - -/* Instruction format */ - -#define I_M_SRC 077 /* source */ -#define I_V_SRC 10 -#define I_GETSRC(x) (((x) >> I_V_SRC) & I_M_SRC) -#define I_M_OP 017 /* operator */ -#define I_V_OP 6 -#define I_GETOP(x) (((x) >> I_V_OP) & I_M_OP) -#define I_M_DST 077 /* destination */ -#define I_V_DST 0 -#define I_GETDST(x) (((x) >> I_V_DST) & I_M_DST) -#define SF_V_REASON 1 /* SF reason */ - -/* IO return */ - -#define IORETURN(f,v) ((f)? (v): SCPE_OK) /* stop on error */ - -/* Operators */ - -#define U_ZERO 000 /* zero */ -#define U_IR 001 /* instruction reg */ -#define U_FSK 002 /* func out/skip */ -#define U_TRP 003 /* trap */ -#define U_ISR 004 /* intr status */ -#define U_MA 005 /* mem addr */ -#define U_MEM 006 /* mem data */ -#define U_SC 007 /* seq counter */ -#define U_SWR 010 /* switch register */ -#define U_AX 011 /* arith in 1 */ -#define U_AY 012 /* arith in 2 */ -#define U_AO 013 /* arith out */ -#define U_EAO 014 /* ext arith */ -#define U_MSR 017 /* machine status */ -#define U_BSW 024 /* byte swap */ -#define U_BPK 025 /* byte pack */ -/* #define U_GR 026 /* dual general regs */ -#define U_GR 030 /* hex general regs */ -#define U_RTC 075 /* clock */ -#define U_HS 076 /* paper tape */ -#define U_TTY 077 /* console */ - -struct gdev { - uint32 (*Src)(uint32); /* source */ - t_stat (*Dst)(uint32, uint32); /* dest */ - t_stat (*FO)(uint32); /* func out */ - uint32 (*SF)(uint32); /* skip func */ -}; - -/* Trap (jump) */ - -#define TRP_DIR 00 /* direct */ -#define TRP_DEF 01 /* defer */ - -/* Interrupt status */ - -#define ISR_OFF 01 /* int off */ -#define ISR_ON 02 /* int on */ - -/* Bus modifiers */ - -#define BUS_COM 002 /* complement */ -#define BUS_FNC 014 /* function mask */ -#define BUS_P1 004 /* + 1 */ -#define BUS_L1 010 /* rotate left */ -#define BUS_R1 014 /* rotate right */ - -/* Memory address modes */ - -#define MEM_MOD 03 -#define MEM_DIR 00 /* direct */ -#define MEM_DEF 01 /* defer */ -#define MEM_IMM 02 /* immediate */ -#define MEM_IDF 03 /* immediate defer */ - -/* Arithmetic unit */ - -#define FO_V_FOA 8 /* arith func */ -#define FO_M_FOA 03 -#define OP_GET_FOA(x) (((x) >> (FO_V_FOA - I_V_OP)) & FO_M_FOA) -#define AO_ADD 00 /* add */ -#define AO_AND 01 /* and */ -#define AO_XOR 02 /* xor */ -#define AO_IOR 03 /* or */ -#define EAO_MUL 01 /* multiply */ -#define EAO_DIV 02 /* divide */ -#define EAO_ASR 03 /* arith rshft */ - -/* Machine status */ - -#define MSR_V_BOV 15 /* bus carry */ -#define MSR_BOV (1u << MSR_V_BOV) -#define MSR_V_L 14 /* bus link */ -#define MSR_L (1u << MSR_V_L) /* bus link */ -#define MSR_V_FOA 8 /* arith func */ -#define MSR_M_FOA 03 -#define MSR_V_AOV 0 /* arith carry */ -#define MSR_AOV (1u << MSR_V_AOV) -#define MSR_GET_FOA(x) (((x) >> MSR_V_FOA) & MSR_M_FOA) -#define MSR_PUT_FOA(x,n) (((x) & ~(MSR_M_FOA << MSR_V_FOA)) | \ - (((n) & MSR_M_FOA) << MSR_V_FOA)) - -/* Real time clock */ - -#define RTC_OFF 001 /* off */ -#define RTC_ON 002 /* clock on */ -#define RTC_OV 010 /* clock flag */ -#define RTC_CTR 0103 /* counter */ - -/* Terminal */ - -#define TTY_ORDY 002 /* output flag */ -#define TTY_IRDY 010 /* input flag */ - -/* Paper tape */ - -#define PT_STRT 001 /* start reader */ -#define PT_ORDY 002 /* output flag */ -#define PT_IRDY 010 /* input flag */ - -/* Interrupt masks (ISR) */ - -#define INT_V_TTO 0 /* console out */ -#define INT_V_TTI 1 /* console in */ -#define INT_V_HSP 2 /* paper tape punch */ -#define INT_V_HSR 3 /* paper tape reader */ -#define INT_V_RTC 11 /* clock */ -#define INT_V_NODEF 16 /* nodefer */ -#define INT_V_ON 17 /* enable */ -#define INT_TTO (1u << INT_V_TTO) -#define INT_TTI (1u << INT_V_TTI) -#define INT_HSP (1u << INT_V_HSP) -#define INT_HSR (1u << INT_V_HSR) -#define INT_RTC (1u << INT_V_RTC) -#define INT_NODEF (1u << INT_V_NODEF) -#define INT_ON (1u << INT_V_ON) -#define INT_PENDING (INT_ON | INT_NODEF) - -/* Vectors */ - -#define VEC_BKP 0000 /* breakpoint */ -#define VEC_TTO 0011 /* console out */ -#define VEC_TTI 0014 /* console in */ -#define VEC_HSP 0017 /* paper tape punch */ -#define VEC_HSR 0022 /* paper tape reader */ -#define VEC_RTC 0100 /* clock */ diff --git a/GRI/gri_doc.txt b/GRI/gri_doc.txt deleted file mode 100644 index aeab0072..00000000 --- a/GRI/gri_doc.txt +++ /dev/null @@ -1,321 +0,0 @@ -To: Users -From: Bob Supnik -Subj: GRI-909 Simulator Usage -Date: 20-Apr-2003 - - COPYRIGHT NOTICE - -The following copyright notice applies to both the SIMH source and binary: - - 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"), - 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 GRI-909 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/gri/ gri_defs.h - gri_cpu.c - gri_stddev.c - gri_sys.c - -2. GRI-909 Features - -The GRI-909 is configured as follows: - -device simulates -name(s) - -CPU GRI-909 CPU with up to 32KW of memory -HSR S42-004 high speed reader -HSP S42-004 high speed punch -TTI S42-001 Teletype input -TTO S42-002 Teletype output -RTC real-time clock - -The GRI-909 simulator implements the following unique stop conditions: - - - an unimplemented operator is referenced, and register - STOP_OPR is set - - an invalid interrupt request is made - -The LOAD commands has an optional argument to specify the load address: - - LOAD {} - -The LOAD command loads a paper-tape bootstrap format file at the specified -address. If no address is specified, loading starts at location 200. The -DUMP command is not supported. - -2.1 CPU - -The only CPU options are the presence of the extended arithmetic operator -and the size of main memory. - - SET CPU EAO enable extended arithmetic operator - SET CPU NOEAO disable extended arithmetic operator - 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 - -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 32K. - -CPU registers include the visible state of the processor as well as the -control registers for the interrupt system. - - name size comments - - SC 15 sequence counter - AX 16 arithmetic operator input register 1 - AY 16 arithmetic operator input register 2 - AO 16 arithmetic operator output register - TRP 16 TRP register - MSR 16 machine status register - ISR 16 interrupt status register - BSW 16 byte swapper buffer - BPK 16 byte packer buffer - GR1..GR6 16 general registers 1 to 6 - BOV 1 bus overflow (MSR<15>) - L 1 link (MSR<14>) - FOA 2 arithmetic operator function (MSR<9:8>) - AOV 1 arithmetic overflow (MSR<0>) - IR 16 instruction register (read only) - MA 16 memory address register (read only) - SWR 16 switch register - DR 16 display register - THW 6 thumbwheels (selects operator displayed in DR) - IREQ 16 interrupt requests - ION 1 interrupts enabled - INODEF 1 interrupts not deferred - BKP 1 breakpoint request - SCQ[0:63] 15 SC prior to last jump or interrupt; - most recent SC change first - STOP_OPR 1 stop on undefined operator - WRU 8 interrupt character - -2.2 Programmed I/O Devices - -2.2.1 S42-004 High Speed Reader (HSR) - -The paper tape reader (HSR) 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 implements these registers: - - name size comments - - BUF 8 last data item processed - IRDY 1 device ready flag - IENB 1 device interrupt enable 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 S42-006 High Speed Punch (HSP) - -The paper tape punch (HSP) 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 - ORDY 1 device ready flag - IENB 1 device interrupt enable 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 S42-001 Teletype Input (TTI) - -The Teletype interfaces (TTI, TTO) 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 interface changes both. The default mode is KSR. - -The Teletype input (TTI) polls the console keyboard for input. It -implements these registers: - - name size comments - - BUF 8 last data item processed - IRDY 1 device ready flag - IENB 1 device interrupt enable flag - POS 32 position in the output file - TIME 24 keyboard polling interval - -2.2.4 S42-002 Teletype Output (TTO) - -The Teletype output (TTO) writes to the simulator console window. It -implements these registers: - - name size comments - - BUF 8 last data item processed - ORDY 1 device ready flag - IENB 1 device interrupt enable flag - POS 32 number of characters output - TIME 24 time from I/O initiation to interrupt - -2.2.5 Real-Time Clock (RTC) - -The real-time clock (CLK) implements these registers: - - name size comments - - RDY 1 device ready flag - IENB 1 interrupt enable flag - TIME 24 clock interval - -The real-time clock autocalibrates; the clock interval is adjusted up or -down so that the clock tracks actual elapsed time. - -2.3 Symbolic Display and Input - -The GRI-909 simulator implements symbolic display and input. Display is -controlled by command line switches: - - -a display as ASCII character - -c display as packed ASCII characters - -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 packed ASCII characters - alphabetic instruction mnemonic - numeric octal number - -Instruction input uses modified GRI-909 basic assembler syntax. There are -thirteen different instruction formats. Operators, functions, and tests may -be octal or symbolic; jump conditions and bus operators are always symbolic. - -Function out, general - Syntax: FO function,operator - Function symbols: INP, IRDY, ORDY, STRT - Example: FO ORDY,TTO - -Function out, named - Syntax: FO{M|I|A} function - Function symbols: M: CLL, CML, STL, HLT; I: ICF, ICO; - A: ADD, AND, XOR, OR - Example: FOA XOR - -Sense function, general - Syntax: SF operator,{NOT} tests - Test symbols: IRDY, ORDY - Example: SF HSR,IRDY - -Sense function, named - Syntax: SF{M|A} {NOT} tests - Test symbols: M: POK BOV LNK; A: SOV AOV - Example: SFM NOT BOV - -Register to register - Syntax: RR{C} src,{bus op,}dst - Bus op symbols: P1, L1, R1 - Example: RRC AX,P1,AY - -Zero to register - Syntax: ZR{C} {bus op,}dst - Bus op symbols: P1, L1, R1 - Example: ZR P1,GR1 - -Register to self - Syntax: RS{C} dst{,bus op} - Bus op symbols: P1, L1, R1 - Example: RS AX,L1 - -Jump unconditional or named condition - Syntax: J{U|O|N}{D} address - Example: JUD 1400 - -Jump conditional - Syntax: JC{D} src,cond,address - Cond symbols: NEVER,ALWAYS,ETZ,NEZ,LTZ,GEZ,LEZ,GTZ - Example: JC AX,LEZ,200 - -Register to memory - syntax: RM{I|D|ID} src,{bus op,}address - Bus op symbols: P1, L1, R1 - Example: RMD AX,P1,1315 - -Zero to memory - Syntax: ZM{I|D|ID} {bus op,}address - Bus op symbols: P1, L1, R1 - Example: ZM P1,5502 - -Memory to register - Syntax: MR{I|D|ID} address,{bus op,}dst - Bus op symbols: P1, L1, R1 - Example: MRI 1405,GR6 - -Memory to self: - Syntax: MS{I|D|ID} address{,bus op} - Bus op symbols: P1, L1, R1 - Example: MS 3333,P1 diff --git a/GRI/gri_stddev.c b/GRI/gri_stddev.c deleted file mode 100644 index 425a8b7b..00000000 --- a/GRI/gri_stddev.c +++ /dev/null @@ -1,394 +0,0 @@ -/* gri_stddev.c: GRI-909 standard devices - - 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. - - tti S42-001 terminal input - tto S42-002 terminal output - hsr S42-004 high speed reader - hsp S42-006 high speed punch - rtc real time clock - - 25-Apr-03 RMS Revised for extended file support - 22-Dec-02 RMS Added break support - 01-Nov-02 RMS Added 7b/8B support to terminal -*/ - -#include "gri_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) - -uint32 hsr_stopioe = 1, hsp_stopioe = 1; - -extern uint16 M[]; -extern uint32 dev_done, ISR; - -t_stat tti_svc (UNIT *uhsr); -t_stat tto_svc (UNIT *uhsr); -t_stat tti_reset (DEVICE *dhsr); -t_stat tto_reset (DEVICE *dhsr); -t_stat tty_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat hsr_svc (UNIT *uhsr); -t_stat hsp_svc (UNIT *uhsr); -t_stat hsr_reset (DEVICE *dhsr); -t_stat hsp_reset (DEVICE *dhsr); -t_stat rtc_svc (UNIT *uhsr); -t_stat rtc_reset (DEVICE *dhsr); -int32 rtc_tps = 1000; - -/* TTI data structures - - tti_dev TTI device descriptor - tti_unit TTI unit descriptor - tti_reg TTI register list - tti_mod TTI modifiers list -*/ - -UNIT tti_unit = { UDATA (&tti_svc, UNIT_KSR, 0), KBD_POLL_WAIT }; - -REG tti_reg[] = { - { ORDATA (BUF, tti_unit.buf, 8) }, - { FLDATA (IRDY, dev_done, INT_V_TTI) }, - { FLDATA (IENB, ISR, INT_V_TTI) }, - { DRDATA (POS, tti_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, tti_unit.wait, 24), REG_NZ + PV_LEFT }, - { FLDATA (UC, tti_unit.flags, UNIT_V_KSR), REG_HRO }, - { NULL } }; - -MTAB tti_mod[] = { - { UNIT_KSR+UNIT_8B, UNIT_KSR, "KSR", "KSR", &tty_set_mode }, - { UNIT_KSR+UNIT_8B, 0 , "7b" , "7B" , &tty_set_mode }, - { UNIT_KSR+UNIT_8B, UNIT_8B , "8b" , "8B" , &tty_set_mode }, - { 0 } }; - -DEVICE tti_dev = { - "TTI", &tti_unit, tti_reg, tti_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &tti_reset, - NULL, NULL, NULL }; - -/* TTO data structures - - tto_dev TTO device descriptor - tto_unit TTO unit descriptor - tto_reg TTO register list -*/ - -UNIT tto_unit = { UDATA (&tto_svc, UNIT_KSR, 0), SERIAL_OUT_WAIT }; - -REG tto_reg[] = { - { ORDATA (BUF, tto_unit.buf, 8) }, - { FLDATA (ORDY, dev_done, INT_V_TTO) }, - { FLDATA (IENB, ISR, INT_V_TTO) }, - { DRDATA (POS, tto_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, tto_unit.wait, 24), PV_LEFT }, - { NULL } }; - -MTAB tto_mod[] = { - { UNIT_KSR+UNIT_8B, UNIT_KSR, "KSR", "KSR", &tty_set_mode }, - { UNIT_KSR+UNIT_8B, 0 , "7b" , "7B" , &tty_set_mode }, - { UNIT_KSR+UNIT_8B, UNIT_8B , "8b" , "8B" , &tty_set_mode }, - { 0 } }; - -DEVICE tto_dev = { - "TTO", &tto_unit, tto_reg, tto_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &tto_reset, - NULL, NULL, NULL }; - -/* HSR data structures - - hsr_dev HSR device descriptor - hsr_unit HSR unit descriptor - hsr_reg HSR register list - hsr_mod HSR modifiers list -*/ - -UNIT hsr_unit = { - UDATA (&hsr_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0), SERIAL_IN_WAIT }; - -REG hsr_reg[] = { - { ORDATA (BUF, hsr_unit.buf, 8) }, - { FLDATA (IRDY, dev_done, INT_V_HSR) }, - { FLDATA (IENB, ISR, INT_V_HSR) }, - { DRDATA (POS, hsr_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, hsr_unit.wait, 24), REG_NZ + PV_LEFT }, - { FLDATA (STOP_IOE, hsr_stopioe, 0) }, - { NULL } }; - -DEVICE hsr_dev = { - "HSR", &hsr_unit, hsr_reg, NULL, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &hsr_reset, - NULL, NULL, NULL }; - -/* HSP data structures - - hsp_dev HSP device descriptor - hsp_unit HSP unit descriptor - hsp_reg HSP register list -*/ - -UNIT hsp_unit = { - UDATA (&hsp_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT }; - -REG hsp_reg[] = { - { ORDATA (BUF, hsp_unit.buf, 8) }, - { FLDATA (ORDY, dev_done, INT_V_HSP) }, - { FLDATA (IENB, ISR, INT_V_HSP) }, - { DRDATA (POS, hsp_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, hsp_unit.wait, 24), PV_LEFT }, - { FLDATA (STOP_IOE, hsp_stopioe, 0) }, - { NULL } }; - -DEVICE hsp_dev = { - "HSP", &hsp_unit, hsp_reg, NULL, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &hsp_reset, - NULL, NULL, NULL }; - -/* RTC data structures - - rtc_dev RTC device descriptor - rtc_unit RTC unit descriptor - rtc_reg RTC register list -*/ - -UNIT rtc_unit = { UDATA (&rtc_svc, 0, 0), 16000 }; - -REG rtc_reg[] = { - { FLDATA (RDY, dev_done, INT_V_RTC) }, - { FLDATA (IENB, ISR, INT_V_RTC) }, - { DRDATA (TIME, rtc_unit.wait, 24), REG_NZ + PV_LEFT }, - { DRDATA (TPS, rtc_tps, 8), REG_NZ + PV_LEFT + REG_HIDDEN }, - { NULL } }; - -DEVICE rtc_dev = { - "RTC", &rtc_unit, rtc_reg, NULL, - 1, 0, 0, 0, 0, 0, - NULL, NULL, &rtc_reset, - NULL, NULL, NULL }; - -/* Console terminal function processors */ - -int32 tty_rd (int32 src, int32 ea) -{ -return tti_unit.buf; /* return data */ -} - -t_stat tty_wr (uint32 dst, uint32 val) -{ -tto_unit.buf = val & 0377; /* save char */ -dev_done = dev_done & ~INT_TTO; /* clear ready */ -sim_activate (&tto_unit, tto_unit.wait); /* activate unit */ -return SCPE_OK; -} - -t_stat tty_fo (uint32 op) -{ -if (op & TTY_IRDY) dev_done = dev_done & ~INT_TTI; -if (op & TTY_ORDY) dev_done = dev_done & ~INT_TTO; -return SCPE_OK; -} - -uint32 tty_sf (uint32 op) -{ -if (((op & TTY_IRDY) && (dev_done & INT_TTI)) || - ((op & TTY_ORDY) && (dev_done & INT_TTO))) return 1; -return 0; -} - -/* Service routines */ - -t_stat tti_svc (UNIT *uptr) -{ -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 (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 */ -else tti_unit.buf = c & ((tti_unit.flags & UNIT_8B)? 0377: 0177); -dev_done = dev_done | INT_TTI; /* set ready */ -tti_unit.pos = tti_unit.pos + 1; -return SCPE_OK; -} - -t_stat tto_svc (UNIT *uptr) -{ -int32 c; -t_stat r; - -dev_done = dev_done | INT_TTO; /* set ready */ -if (tto_unit.flags & UNIT_KSR) { /* KSR? */ - c = tto_unit.buf & 0177; /* force 7b */ - if (islower (c)) c = toupper (c); } /* cvt to UC */ -else c = tto_unit.buf & ((tto_unit.flags & UNIT_8B)? 0377: 0177); -if ((r = sim_putchar (c)) != SCPE_OK) return r; /* output */ -tto_unit.pos = tto_unit.pos + 1; -return SCPE_OK; -} - -/* Reset routines */ - -t_stat tti_reset (DEVICE *dptr) -{ -tti_unit.buf = 0; /* clear buffer */ -dev_done = dev_done & ~INT_TTI; /* clear ready */ -sim_activate (&tti_unit, tti_unit.wait); /* activate unit */ -return SCPE_OK; -} - -t_stat tto_reset (DEVICE *dptr) -{ -tto_unit.buf = 0; /* clear buffer */ -dev_done = dev_done | INT_TTO; /* set ready */ -sim_cancel (&tto_unit); /* deactivate unit */ -return SCPE_OK; -} - -t_stat tty_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -tti_unit.flags = (tti_unit.flags & ~(UNIT_KSR | UNIT_8B)) | val; -tto_unit.flags = (tto_unit.flags & ~(UNIT_KSR | UNIT_8B)) | val; -return SCPE_OK; -} - -/* High speed paper tape function processors */ - -int32 hsrp_rd (int32 src, int32 ea) -{ -return hsr_unit.buf; /* return data */ -} - -t_stat hsrp_wr (uint32 dst, uint32 val) -{ -hsp_unit.buf = val & 0377; /* save char */ -dev_done = dev_done & ~INT_HSP; /* clear ready */ -sim_activate (&hsp_unit, hsp_unit.wait); /* activate unit */ -return SCPE_OK; -} - -t_stat hsrp_fo (uint32 op) -{ -if (op & PT_IRDY) dev_done = dev_done & ~INT_HSR; -if (op & PT_ORDY) dev_done = dev_done & ~INT_HSP; -if (op & PT_STRT) sim_activate (&hsr_unit, hsr_unit.wait); -return SCPE_OK; -} - -uint32 hsrp_sf (uint32 op) -{ -if (((op & PT_IRDY) && (dev_done & INT_HSR)) || - ((op & PT_ORDY) && (dev_done & INT_HSP))) return 1; -return 0; -} - -t_stat hsr_svc (UNIT *uptr) -{ -int32 temp; - -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; } - else perror ("HSR I/O error"); - clearerr (hsr_unit.fileref); - return SCPE_IOERR; } -dev_done = dev_done | INT_HSR; /* set ready */ -hsr_unit.buf = temp & 0377; /* save char */ -hsr_unit.pos = hsr_unit.pos + 1; -return SCPE_OK; -} - -t_stat hsp_svc (UNIT *uptr) -{ -dev_done = dev_done | INT_HSP; /* set ready */ -if ((hsp_unit.flags & UNIT_ATT) == 0) /* attached? */ - return IORETURN (hsp_stopioe, SCPE_UNATT); -if (putc (hsp_unit.buf, hsp_unit.fileref) == EOF) { /* write char */ - perror ("HSP I/O error"); /* error? */ - clearerr (hsp_unit.fileref); - return SCPE_IOERR; } -hsp_unit.pos = hsp_unit.pos + 1; -return SCPE_OK; -} - -/* Reset routines */ - -t_stat hsr_reset (DEVICE *dptr) -{ -hsr_unit.buf = 0; /* clear buffer */ -dev_done = dev_done & ~INT_HSR; /* clear ready */ -sim_cancel (&hsr_unit); /* deactivate unit */ -return SCPE_OK; -} - -t_stat hsp_reset (DEVICE *dptr) -{ -hsp_unit.buf = 0; /* clear buffer */ -dev_done = dev_done | INT_HSP; /* set ready */ -sim_cancel (&hsp_unit); /* deactivate unit */ -return SCPE_OK; -} - -/* Clock function processors */ - -t_stat rtc_fo (int32 op) -{ -if (op & RTC_OFF) sim_cancel (&rtc_unit); /* clock off? */ -if ((op & RTC_ON) && !sim_is_active (&rtc_unit)) /* clock on? */ - sim_activate (&rtc_unit, sim_rtc_init (rtc_unit.wait)); -if (op & RTC_OV) dev_done = dev_done & ~INT_RTC; /* clr ovflo? */ -return SCPE_OK; -} - -int32 rtc_sf (int32 op) -{ -if ((op & RTC_OV) && (dev_done & INT_RTC)) return 1; -return 0; -} - -t_stat rtc_svc (UNIT *uptr) -{ -M[RTC_CTR] = (M[RTC_CTR] + 1) & DMASK; /* incr counter */ -if (M[RTC_CTR] == 0) dev_done = dev_done | INT_RTC; /* ovflo? set ready */ -sim_activate (&rtc_unit, sim_rtc_calb (rtc_tps)); /* reactivate */ -return SCPE_OK; -} - -t_stat rtc_reset (DEVICE *dptr) -{ -dev_done = dev_done & ~INT_RTC; /* clear ready */ -sim_cancel (&rtc_unit); /* stop clock */ -return SCPE_OK; -} diff --git a/GRI/gri_sys.c b/GRI/gri_sys.c deleted file mode 100644 index 6bde9909..00000000 --- a/GRI/gri_sys.c +++ /dev/null @@ -1,582 +0,0 @@ -/* gri_sys.c: GRI-909 simulator interface - - 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. - - 18-Oct-02 RMS Fixed bug in symbolic decode (found by Hans Pufal) -*/ - -#include "gri_defs.h" -#include - -extern DEVICE cpu_dev; -extern UNIT cpu_unit; -extern DEVICE tti_dev, tto_dev; -extern DEVICE hsr_dev, hsp_dev; -extern DEVICE rtc_dev; -extern REG cpu_reg[]; -extern uint16 M[]; -extern int32 sim_switches; - -/* SCP data structures and interface routines - - sim_name simulator name string - sim_PC pointer to saved PC register descriptor - sim_emax maximum number of words for examine/deposit - sim_devices array of pointers to simulated devices - sim_stop_messages array of pointers to stop messages - sim_load binary loader -*/ - -char sim_name[] = "GRI-909"; - -REG *sim_PC = &cpu_reg[0]; - -int32 sim_emax = 2; - -DEVICE *sim_devices[] = { - &cpu_dev, - &tti_dev, - &tto_dev, - &hsr_dev, - &hsp_dev, - &rtc_dev, - NULL }; - -const char *sim_stop_messages[] = { - "Unknown error", - "Unimplemented unit", - "HALT instruction", - "Breakpoint", - "Invalid interrupt request" }; - -/* Binary loader - - Bootstrap loader format consists of blocks separated by zeroes. Each - word in the block has three frames: a control frame (ignored) and two - data frames. The user must specify the load address. Switch -c means - continue and load all blocks until end of tape. -*/ - -t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag) -{ -int32 c; -uint32 org; -t_stat r; -char gbuf[CBUFSIZE]; - -if (*cptr != 0) { /* more input? */ - cptr = get_glyph (cptr, gbuf, 0); /* get origin */ - org = get_uint (gbuf, 8, AMASK, &r); - if (r != SCPE_OK) return r; - if (*cptr != 0) return SCPE_ARG; } /* no more */ -else org = 0200; /* default 200 */ - -for (;;) { /* until EOF */ - while ((c = getc (fileref)) == 0) ; /* skip starting 0's */ - 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 (!(sim_switches & SWMASK ('C'))) return SCPE_OK; - } /* end tape for */ -return SCPE_OK; -} - -/* Symbol tables */ - -#define F_V_FL 16 /* class flag */ -#define F_M_FL 017 -#define F_V_FO 000 /* function out */ -#define F_V_FOI 001 /* FO, impl reg */ -#define F_V_SF 002 /* skip function */ -#define F_V_SFI 003 /* SF, impl reg */ -#define F_V_RR 004 /* reg reg */ -#define F_V_ZR 005 /* zero reg */ -#define F_V_RS 006 /* reg self */ -#define F_V_JC 010 /* jump cond */ -#define F_V_JU 011 /* jump uncond */ -#define F_V_RM 012 /* reg mem */ -#define F_V_ZM 013 /* zero mem */ -#define F_V_MR 014 /* mem reg */ -#define F_V_MS 015 /* mem self */ -#define F_2WD 010 /* 2 words */ - -#define F_FO (F_V_FO << F_V_FL) -#define F_FOI (F_V_FOI << F_V_FL) -#define F_SF (F_V_SF << F_V_FL) -#define F_SFI (F_V_SFI << F_V_FL) -#define F_RR (F_V_RR << F_V_FL) -#define F_ZR (F_V_ZR << F_V_FL) -#define F_RS (F_V_RS << F_V_FL) -#define F_JC (F_V_JC << F_V_FL) -#define F_JU (F_V_JU << F_V_FL) -#define F_RM (F_V_RM << F_V_FL) -#define F_ZM (F_V_ZM << F_V_FL) -#define F_MR (F_V_MR << F_V_FL) -#define F_MS (F_V_MS << F_V_FL) - -struct fnc_op { - uint32 inst; /* instr prot */ - uint32 imask; /* instr mask */ - uint32 oper; /* operator */ - uint32 omask; }; /* oper mask */ - -static const int32 masks[] = { - 0176000, 0176077, 0000077, 0176077, - 0000300, 0176300, 0000300, 0177777, - 0000077, 0177777, 0000377, 0176377, - 0176300, 0176377 }; - -/* Instruction mnemonics - - Order is critical, as some instructions are more precise versions of - others. For example, JU must precede JC, otherwise, JU will be decoded - as JC 0,ETZ,dst. There are some ambiguities, eg, what is 02-xxxx-06? - Priority is as follows: - - FO (02-xxxx-rr) - SF (rr-xxxx-02) - MR (06-xxxx-rr) - RM (rr-xxxx-06) - JC (rr-xxxx-03) - RR -*/ - -static const char *opcode[] = { - "FOM", "FOA", "FOI", "FO", /* FOx before FO */ - "SFM", "SFA", "SFI", "SF", /* SFx before SF */ - "ZM", "ZMD", "ZMI", "ZMID", /* ZM before RM */ - "MS", "MSD", "MSI", "MSID", - "RM", "RMD", "RMI", "RMID", - "MR", "MRD", "MRI", "MRID", - "JO", "JOD", "JN", "JND", /* JU before JC */ - "JU", "JUD", "JC", "JCD", - "ZR", "ZRC", "RR", "RRC", /* ZR before RR */ - "RS", "RSC", - NULL }; - -static const uint32 opc_val[] = { - 0004000+F_FOI, 0004013+F_FOI, 0004004+F_FOI, 0004000+F_FO, - 0000002+F_SFI, 0026002+F_SFI, 0010002+F_SFI, 0000002+F_SF, - 0000006+F_ZM, 0000106+F_ZM, 0000206+F_ZM, 0000306+F_ZM, - 0014006+F_MS, 0014106+F_MS, 0014206+F_MS, 0014306+F_MS, - 0000006+F_RM, 0000106+F_RM, 0000206+F_RM, 0000306+F_RM, - 0014000+F_MR, 0014100+F_MR, 0014200+F_MR, 0014300+F_MR, - 0037003+F_JU, 0037103+F_JU, 0037203+F_JU, 0037303+F_JU, - 0000403+F_JU, 0000503+F_JU, 0000003+F_JC, 0000103+F_JC, - 0000000+F_ZR, 0000200+F_ZR, 0000000+F_RR, 0000200+F_RR, - 0000000+F_RS, 0000200+F_RS }; - -/* Unit mnemonics. All 64 units are decoded, most just to octal integers */ - -static const char *unsrc[64] = { - "0", "IR", "2", "TRP", "ISR", "MA", "MB", "SC", /* 00 - 07 */ - "SWR", "AX", "AY", "AO", "14", "15", "16", "MSR", /* 10 - 17 */ - "20", "21", "22", "23", "BSW", "BPK", "26", "27", /* 20 - 27 */ - "GR1", "GR2", "GR3", "GR4", "GR5", "GR6", "36", "37", /* 30 - 37 */ - "40", "41", "42", "43", "44", "45", "46", "47", - "50", "51", "52", "53", "54", "55", "56", "57", - "60", "61", "62", "63", "64", "65", "66", "67", - "70", "71", "72", "73", "74", "RTC", "HSR", "TTI" }; /* 70 - 77 */ - -static const char *undst[64] = { - "0", "IR", "2", "TRP", "ISR", "5", "MB", "SC", /* 00 - 07 */ - "SWR", "AX", "AY", "13", "EAO", "15", "16", "MSR", /* 10 - 17 */ - "20", "21", "22", "23", "BSW", "BPK", "26", "27", /* 20 - 27 */ - "GR1", "GR2", "GR3", "GR4", "GR5", "GR6", "36", "37", /* 30 - 37 */ - "40", "41", "42", "43", "44", "45", "46", "47", - "50", "51", "52", "53", "54", "55", "56", "57", - "60", "61", "62", "63", "64", "65", "66", "67", - "70", "71", "72", "73", "74", "RTC", "HSP", "TTO" }; /* 70 - 77 */ - - /* Operators */ - -static const char *opname[4] = { - NULL, "P1", "L1", "R1" }; - -/* Conditions */ - -static const char *cdname[8] = { - "NEVER", "ALWAYS", "ETZ", "NEZ", "LTZ", "GEZ", "LEZ", "GTZ" }; - -/* Function out/sense function */ - -static const char *fname[] = { - "NOT", /* any SF */ - "POK", "LNK", "BOV", /* SFM */ - "SOV", "AOV", /* SFA */ - "IRDY", "ORDY", /* any SF */ - "CLL", "STL", "CML", "HLT", /* FOM */ - "ICF", "ICO", /* FOI */ - "ADD", "AND", "XOR", "OR", /* FOA */ - "INP", "IRDY", "ORDY", "STRT", /* any FO */ - NULL }; - -static const struct fnc_op fop[] = { - { 0000002, 0000077, 001, 001 }, /* NOT */ - { 0000002, 0176077, 010, 010 }, /* POK */ - { 0000002, 0176077, 004, 004 }, /* LNK */ - { 0000002, 0176077, 002, 002 }, /* BOV */ - { 0026002, 0176077, 004, 004 }, /* SOV */ - { 0026002, 0176077, 002, 002 }, /* AOV */ - { 0000002, 0000077, 010, 010 }, /* IRDY */ - { 0000002, 0000077, 002, 002 }, /* ORDY */ - { 0004000, 0176077, 001, 003 }, /* CLL */ - { 0004000, 0176077, 002, 003 }, /* STL */ - { 0004000, 0176077, 003, 003 }, /* CML */ - { 0004000, 0176077, 004, 004 }, /* HLT */ - { 0004004, 0176077, 001, 001 }, /* ICF */ - { 0004004, 0176077, 002, 002 }, /* ICO */ - { 0004013, 0176077, 000, 014 }, /* ADD */ - { 0004013, 0176077, 004, 014 }, /* AND */ - { 0004013, 0176077, 010, 014 }, /* XOR */ - { 0004013, 0176077, 014, 014 }, /* OR */ - { 0004000, 0176000, 011, 011 }, /* INP */ - { 0004000, 0176000, 010, 010 }, /* IRDY */ - { 0004000, 0176000, 002, 002 }, /* ORDY */ - { 0004000, 0176000, 001, 001 } }; /* STRT */ - -/* Print opcode field for FO, SF */ - -void fprint_op (FILE *of, uint32 inst, uint32 op) -{ -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]); } - } -if (op) fprintf (of, " %o", op); -return; -} - -/* Symbolic decode - - Inputs: - *of = output stream - addr = current PC - *val = pointer to data - *uptr = pointer to unit - sw = switches - Outputs: - return = status code -*/ - -#define FMTASC(x) ((x) < 040)? "<%03o>": "%c", (x) - -t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, - UNIT *uptr, int32 sw) -{ -int32 i, j; -uint32 inst, src, dst, op, bop; - -inst = val[0]; -if (sw & SWMASK ('A')) { /* ASCII? */ - if (inst > 0377) return SCPE_ARG; - fprintf (of, FMTASC (inst & 0177)); - return SCPE_OK; } -if (sw & SWMASK ('C')) { /* characters? */ - fprintf (of, FMTASC ((inst >> 8) & 0177)); - fprintf (of, FMTASC (inst & 0177)); - return SCPE_OK; } -if (!(sw & SWMASK ('M'))) return SCPE_ARG; - -/* Instruction decode */ - -inst = val[0]; -src = I_GETSRC (inst); /* get fields */ -op = I_GETOP (inst); -dst = I_GETDST (inst); -bop = op >> 2; /* bus op */ -for (i = 0; opcode[i] != NULL; i++) { /* loop thru ops */ - j = (opc_val[i] >> F_V_FL) & F_M_FL; /* get class */ - if ((opc_val[i] & DMASK) == (inst & masks[j])) { /* match? */ - - 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; - case F_V_FOI: /* func out impl */ - 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; - case F_V_SFI: /* skip func impl */ - 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; - 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; - case F_V_JC: /* jump cond */ - 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; - 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; - 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; - 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; - 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 */ - return (j >= F_2WD)? -1: SCPE_OK; } /* end if */ - } /* end for */ -return SCPE_ARG; -} - -/* Field parse routines - - get_fnc get function field - get_ma get memory address - get_sd get source or dest - get_op get optional bus operator -*/ - -char *get_fnc (char *cptr, t_value *val) -{ -char gbuf[CBUFSIZE]; -int32 i; -t_value d; -t_stat r; -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; } } - if (fname[i] == NULL) return NULL; } /* end else */ - } /* end while */ -val[0] = val[0] | (fncv << I_V_OP); /* store fnc */ -return cptr; -} - -char *get_ma (char *cptr, t_value *val, char term) -{ -char gbuf[CBUFSIZE]; -t_value d; -t_stat r; - -cptr = get_glyph (cptr, gbuf, term); /* get glyph */ -d = get_uint (gbuf, 8, DMASK, &r); /* [0,177777] */ -if (r != SCPE_OK) return NULL; -val[1] = d; /* second wd */ -return cptr; -} - -char *get_sd (char *cptr, t_value *val, char term, t_bool src) -{ -char gbuf[CBUFSIZE]; -int32 d; -t_stat r; - -cptr = get_glyph (cptr, gbuf, term); /* get glyph */ -for (d = 0; d < 64; d++) { /* symbol match? */ - if ((strcmp (gbuf, unsrc[d]) == 0) || - (strcmp (gbuf, undst[d]) == 0)) break; } -if (d >= 64) { /* no, [0,63]? */ - d = get_uint (gbuf, 8, 077, &r); - if (r != SCPE_OK) return NULL; } -val[0] = val[0] | (d << (src? I_V_SRC: I_V_DST)); /* or to inst */ -return cptr; -} - -char *get_op (char *cptr, t_value *val, char term) -{ -char gbuf[CBUFSIZE], *tptr; -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; } } -return cptr; /* original ptr */ -} - -/* 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; -char *tptr, gbuf[CBUFSIZE]; - -while (isspace (*cptr)) cptr++; /* absorb spaces */ -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] & 0177; - return SCPE_OK; } -if ((sw & SWMASK ('C')) || ((*cptr == '"') && cptr++)) { /* char string? */ - if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */ - val[0] = (((t_value) cptr[0] & 0177) << 8) | - ((t_value) cptr[1] & 0177); - return SCPE_OK; } - -/* Instruction parse */ - -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] >> F_V_FL) & F_M_FL; /* get class */ - -switch (j) { /* case on class */ -case F_V_FO: /* func out */ - tptr = strchr (cptr, ','); /* find dst */ - if (!tptr) return SCPE_ARG; /* none? */ - *tptr = 0; /* split fields */ - cptr = get_fnc (cptr, val); /* fo # */ - if (!cptr) return SCPE_ARG; - cptr = get_sd (tptr + 1, val, 0, FALSE); /* dst */ - break; -case F_V_FOI: /* func out impl */ - cptr = get_fnc (cptr, val); /* fo # */ - break; -case F_V_SF: /* skip func */ - cptr = get_sd (cptr, val, ',', TRUE); /* src */ - if (!cptr) return SCPE_ARG; -case F_V_SFI: /* skip func impl */ - cptr = get_fnc (cptr, val); /* fo # */ - break; -case F_V_RR: /* reg-reg */ - cptr = get_sd (cptr, val, ',', TRUE); /* src */ - if (!cptr) return SCPE_ARG; - cptr = get_op (cptr, val, ','); /* op */ - if (!cptr) return SCPE_ARG; - cptr = get_sd (cptr, val, 0, FALSE); /* dst */ - break; -case F_V_ZR: /* zero-reg */ - cptr = get_op (cptr, val, ','); /* op */ - if (!cptr) return SCPE_ARG; - cptr = get_sd (cptr, val, 0, FALSE); /* dst */ - break; -case F_V_RS: /* reg self */ - cptr = get_sd (cptr, val, ',', TRUE); /* src */ - if (!cptr) return SCPE_ARG; - val[0] = val[0] | I_GETSRC (val[0]); /* duplicate */ - cptr = get_op (cptr, val, 0); /* op */ - break; -case F_V_JC: /* jump cond */ - cptr = get_sd (cptr, val, ',', TRUE); /* src */ - 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 (k >= 8) return SCPE_ARG; - val[0] = val[0] | (k << (I_V_OP + 1)); /* or to inst */ -case F_V_JU: /* jump uncond */ - cptr = get_ma (cptr, val, 0); /* addr */ - break; -case F_V_RM: /* reg mem */ - cptr = get_sd (cptr, val, ',', TRUE); /* src */ - if (!cptr) return SCPE_ARG; -case F_V_ZM: /* zero mem */ - cptr = get_op (cptr, val, ','); /* op */ - if (!cptr) return SCPE_ARG; - cptr = get_ma (cptr, val, 0); /* addr */ - break; -case F_V_MR: /* mem reg */ - cptr = get_ma (cptr, val, ','); /* addr */ - if (!cptr) return SCPE_ARG; - cptr = get_op (cptr, val, ','); /* op */ - if (!cptr) return SCPE_ARG; - cptr = get_sd (cptr, val, 0, FALSE); /* dst */ - break; -case F_V_MS: /* mem self */ - cptr = get_ma (cptr, val, ','); /* addr */ - if (!cptr) return SCPE_ARG; - cptr = get_op (cptr, val, 0); /* op */ - break; } -if (!cptr || (*cptr != 0)) return SCPE_ARG; /* junk at end? */ -return (j >= F_2WD)? -1: SCPE_OK; -} diff --git a/H316/h316_cpu.c b/H316/h316_cpu.c deleted file mode 100644 index 202f126b..00000000 --- a/H316/h316_cpu.c +++ /dev/null @@ -1,1088 +0,0 @@ -/* h316_cpu.c: Honeywell 316/516 CPU simulator - - Copyright (c) 1999-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. - - cpu H316/H516 CPU - - 30-Dec-01 RMS Added old PC queue - 03-Nov-01 RMS Fixed NOHSA modifier - 30-Nov-01 RMS Added extended SET/SHOW support - - The register state for the Honeywell 316/516 CPU is: - - AR<1:16> A register - BR<1:16> B register - XR<1:16> X register - PC<1:16> P register (program counter) - Y<1:16> memory address register - MB<1:16> memory data register - C overflow flag - EXT extend mode flag - DP double precision mode flag - SC<1:5> shift count - SR[1:4]<0> sense switches 1-4 - - The Honeywell 316/516 has six instruction formats: memory reference, - I/O, control, shift, skip, and operate. - - The memory reference format is: - - 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - |in|xr| op |sc| offset | memory reference - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - <13:10> mnemonic action - - 0000 (other) see control, shift, skip, operate instructions - 0001 JMP P = MA - 0010 LDA A = M[MA] - 0011 ANA A = A & M[MA] - 0100 STA M[MA] = A - 0101 ERA A = A ^ M[MA] - 0110 ADD A = A + M[MA] - 0111 SUB A = A - M[MA] - 1000 JST M[MA] = P, P = MA + 1 - 1001 CAS skip if A == M[MA], double skip if A < M[MA] - 1010 IRS M[MA] = M[MA] + 1, skip if M[MA] == 0 - 1011 IMA A <=> M[MA] - 1100 (I/O) see I/O instructions - 1101 LDX/STX X = M[MA] (xr = 1), M[MA] = x (xr = 0) - 1110 MPY multiply - 1111 DIV divide - - In non-extend mode, memory reference instructions can access an address - space of 16K words. Multiple levels of indirection are supported, and - each indirect word supplies its own indirect and index bits. - - <1,2,7> mode action - - 0,0,0 sector zero direct MA = IR<8:0> - 0,0,1 current direct MA = P<13:9>'IR<8:0> - 0,1,0 sector zero indexed MA = IR<8:0> + X - 0,1,1 current direct MA = P<13:9>'IR<8:0> + X - 1,0,0 sector zero indirect MA = M[IR<8:0>] - 1,0,1 current indirect MA = M[P<13:9>'IR<8:0>] - 1,1,0 sector zero indirect indexed MA = M[IR<8:0> + X] - 1,1,1 current indirect indexed MA = M[MA = P<13:9>'IR<8:0> + X] - - In extend mode, memory reference instructions can access an address - space of 32K words. Multiple levels of indirection are supported, but - only post-indexing, based on the original instruction word index flag, - is allowed. -*/ - -/* The control format is: - - 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | 0 0 0 0 0 0| opcode | control - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - The shift format is: - - 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | 0 1 0 0 0 0|dr|sz|type | shift count | shift - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | | \-+-/ - | | | - | | +--------------------- type - | +------------------------- long/A only - +---------------------------- right/left - - The skip format is: - - 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | 1 0 0 0 0 0|rv|po|pe|ev|ze|s1|s2|s3|s4|cz| skip - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | | | | | | | | | | - | | | | | | | | | +- skip if C = 0 - | | | | | | | | +---- skip if ssw 4 = 0 - | | | | | | | +------- skip if ssw 3 = 0 - | | | | | | +---------- skip if ssw 2 = 0 - | | | | | +------------- skip if ssw 1 = 0 - | | | | +---------------- skip if A == 0 - | | | +------------------- skip if A<0> == 0 - | | +---------------------- skip if mem par err - | +------------------------- skip if A<15> = 0 - +---------------------------- reverse skip sense - - The operate format is: - - 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | 1 1 0 0 0 0| opcode | operate - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - The I/O format is: - - 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | op | 1 1 0 0| function | device | I/O transfer - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - The IO transfer instruction controls the specified device. - Depending on the opcode, the instruction may set or clear - the device flag, start or stop I/O, or read or write data. -*/ - -/* This routine is the instruction decode routine for the Honeywell - 316/516. 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 - infinite indirection loop - unimplemented instruction and stop_inst flag set - unknown I/O device and stop_dev flag set - I/O error in I/O simulator - - 2. Interrupts. Interrupts are maintained by two parallel variables: - - dev_ready device ready flags - dev_enable device interrupt enable flags - - In addition, dev_ready contains the interrupt enable and interrupt no - defer flags. If interrupt enable and interrupt no defer are set, and - at least one interrupt request is pending, then an interrupt occurs. - The order of flags in these variables corresponds to the order - in the SMK instruction. - - 3. Non-existent memory. On the H316/516, 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: - - h316_defs.h add interrupt request definition - h316_cpu.c add device dispatch table entry - h316_sys.c add sim_devices table entry -*/ - -#include "h316_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 PCQ_TOP pcq[pcq_p] -#define UNIT_V_MSIZE (UNIT_V_UF) /* dummy mask */ -#define UNIT_MSIZE (1u << UNIT_V_MSIZE) -#define m7 0001000 /* for generics */ -#define m8 0000400 -#define m9 0000200 -#define m10 0000100 -#define m11 0000040 -#define m12 0000020 -#define m13 0000010 -#define m14 0000004 -#define m15 0000002 -#define m16 0000001 - -uint16 M[MAXMEMSIZE] = { 0 }; /* memory */ -int32 saved_AR = 0; /* A register */ -int32 saved_BR = 0; /* B register */ -int32 saved_XR = 0; /* X register */ -int32 PC = 0; /* P register */ -int32 C = 0; /* C register */ -int32 ext = 0; /* extend mode */ -int32 pme = 0; /* prev mode extend */ -int32 extoff_pending = 0; /* extend off pending */ -int32 dp = 0; /* double mode */ -int32 sc = 0; /* shift count */ -int32 ss[4]; /* sense switches */ -int32 dev_ready = 0; /* dev ready */ -int32 dev_enable = 0; /* dev enable */ -int32 ind_max = 8; /* iadr nest limit */ -int32 stop_inst = 1; /* stop on ill inst */ -int32 stop_dev = 2; /* stop on ill dev */ -uint16 pcq[PCQ_SIZE] = { 0 }; /* PC queue */ -int32 pcq_p = 0; /* PC queue ptr */ -REG *pcq_r = NULL; /* PC queue reg ptr */ -int32 dlog = 0; /* debug log */ -int32 turnoff = 0; - -extern int32 sim_int_char; -extern int32 sim_interval; -extern int32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */ -extern FILE *sim_log; - -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_noext (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); - -extern t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, - UNIT *uptr, int32 sw); - -/* 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 + UNIT_EXT, - MAXMEMSIZE) }; - -REG cpu_reg[] = { - { ORDATA (P, PC, 15) }, - { ORDATA (A, saved_AR, 16) }, - { ORDATA (B, saved_BR, 16) }, - { ORDATA (X, XR, 16) }, - { ORDATA (SC, sc, 16) }, - { FLDATA (C, C, 0) }, - { FLDATA (EXT, ext, 0) }, - { FLDATA (PME, pme, 0) }, - { FLDATA (EXT_OFF, extoff_pending, 0) }, - { FLDATA (DP, dp, 0) }, - { FLDATA (SS1, ss[0], 0) }, - { FLDATA (SS2, ss[1], 0) }, - { FLDATA (SS3, ss[2], 0) }, - { FLDATA (SS4, ss[3], 0) }, - { FLDATA (ION, dev_ready, INT_V_ON) }, - { FLDATA (INODEF, dev_ready, INT_V_NODEF) }, - { ORDATA (DEVRDY, dev_ready, 16), REG_RO }, - { ORDATA (DEVENB, dev_enable, 16), REG_RO }, - { FLDATA (MPERDY, dev_ready, INT_V_MPE) }, - { FLDATA (MPEENB, dev_enable, INT_V_MPE) }, - { FLDATA (STOP_INST, stop_inst, 0) }, - { FLDATA (STOP_DEV, stop_dev, 1) }, - { DRDATA (INDMAX, ind_max, 8), REG_NZ + PV_LEFT }, - { BRDATA (PCQ, pcq, 8, 15, PCQ_SIZE), REG_RO + REG_CIRC }, - { ORDATA (PCQP, pcq_p, 6), REG_HRO }, - { ORDATA (WRU, sim_int_char, 8) }, - { FLDATA (DLOG, dlog, 0), REG_HIDDEN }, - { NULL } }; - -MTAB cpu_mod[] = { - { UNIT_EXT, 0, "no extend", "NOEXTEND", &cpu_set_noext }, - { UNIT_EXT, UNIT_EXT, "extend", "EXTEND", NULL }, - { UNIT_HSA, 0, "no HSA", "NOHSA", NULL }, - { UNIT_HSA, UNIT_HSA, "HSA", "HSA", 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, 24576, NULL, "24K", &cpu_set_size }, - { UNIT_MSIZE, 32768, NULL, "32K", &cpu_set_size }, - { 0 } }; - -DEVICE cpu_dev = { - "CPU", &cpu_unit, cpu_reg, cpu_mod, - 1, 8, 15, 1, 8, 16, - &cpu_ex, &cpu_dep, &cpu_reset, - NULL, NULL, NULL }; - -/* I/O dispatch */ - -int32 undio (int32 op, int32 func, int32 AR); -extern int32 ptrio (int32 op, int32 func, int32 AR); -extern int32 ptpio (int32 op, int32 func, int32 AR); -extern int32 lptio (int32 op, int32 func, int32 AR); -extern int32 ttyio (int32 op, int32 func, int32 AR); -extern int32 clkio (int32 op, int32 func, int32 AR); - -int32 (*iotab[64])() = { - &undio, &ptrio, &ptpio, &lptio, &ttyio, &undio, &undio, &undio, - &undio, &undio, &undio, &undio, &undio, &undio, &undio, &undio, - &clkio, &undio, &undio, &undio, &undio, &undio, &undio, &undio, - &undio, &undio, &undio, &undio, &undio, &undio, &undio, &undio, - &undio, &undio, &undio, &undio, &undio, &undio, &undio, &undio, - &undio, &undio, &undio, &undio, &undio, &undio, &undio, &undio, - &undio, &undio, &undio, &undio, &undio, &undio, &undio, &undio, - &undio, &undio, &undio, &undio, &undio, &undio, &undio, &undio }; - - -t_stat sim_instr (void) -{ -extern UNIT clk_unit; -int32 AR, BR, MB, Y, t1, t2, t3, skip; -uint32 ut; -t_stat reason; -t_stat Ea (int32 inst, int32 *addr); -void Write (int32 val, int32 addr); -int32 Add16 (int32 val1, int32 val2); -int32 Add31 (int32 val1, int32 val2); -int32 Operate (int32 MB, int32 AR); - -#define Read(x) M[(x)] -#define GETDBL_S(h,l) (((h) << 15) | ((l) & MMASK)) -#define GETDBL_U(h,l) (((h) << 16) | (l)) -#define PUTDBL_S(x) AR = ((x) >> 15) & DMASK; \ - BR = (BR & SIGN) | ((x) & MMASK) -#define PUTDBL_U(x) AR = ((x) >> 16) & DMASK; \ - BR = (x) & DMASK -#define SEXT(x) (((x) & SIGN)? ((x) | ~DMASK): ((x) & DMASK)) -#define NEWA(c,n) (ext? (((c) & ~X_AMASK) | ((n) & X_AMASK)): \ - (((c) & ~NX_AMASK) | ((n) & NX_AMASK))) - -/* Restore register state */ - -AR = saved_AR & DMASK; /* restore reg */ -BR = saved_BR & DMASK; -XR = saved_XR & DMASK; -PC = PC & ((cpu_unit.flags & UNIT_EXT)? X_AMASK: NX_AMASK); /* mask PC */ -reason = 0; -turnoff = 0; -sim_rtc_init (clk_unit.wait); /* init calibration */ - -/* Main instruction fetch/decode loop */ - -while (reason == 0) { /* loop until halted */ -if (sim_interval <= 0) { /* check clock queue */ - if (reason = sim_process_event ()) break; } - -if ((dev_ready & (INT_PENDING | dev_enable)) > INT_PENDING) { /* int req? */ - pme = ext; /* save extend */ - if (cpu_unit.flags & UNIT_EXT) ext = 1; /* ext opt? extend on */ - dev_ready = dev_ready & ~INT_ON; /* intr off */ - turnoff = 0; - if (dlog && sim_log) fprintf (sim_log, "Interrupt\n"); - MB = 0120000 | M_INT; } /* inst = JST* 63 */ - -else { if (sim_brk_summ && - sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */ - reason = STOP_IBKPT; /* stop simulation */ - break; } - Y = PC; /* set mem addr */ - MB = Read (Y); /* fetch instr */ - PC = NEWA (Y, Y + 1); /* incr PC */ - dev_ready = dev_ready | INT_NODEF; } - -sim_interval = sim_interval - 1; -if (dlog && sim_log && !turnoff) { /* cycle log? */ - int32 op = I_GETOP (MB) & 017; /* core opcode */ - t_value val = MB; - fprintf (sim_log, "A= %06o C= %1o P= %05o (", AR, C, PC); - fprint_sym (sim_log, Y, &val, &cpu_unit, SWMASK ('M')); - fprintf (sim_log, ")"); - if ((op == 0) || (op == 014)) fprintf (sim_log, "\n"); } - -/* Memory reference instructions */ - -switch (I_GETOP (MB)) { /* case on <1:6> */ - -case 001: case 021: case 041: case 061: /* JMP */ - if (reason = Ea (MB, &Y)) break; /* eff addr */ - 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 */ - 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; } - else AR = Read (Y); /* no, get word */ - break; - -case 003: case 023: case 043: case 063: /* ANA */ - if (reason = Ea (MB, &Y)) break; /* eff addr */ - AR = AR & Read (Y); - break; - -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; } - else Write (AR, Y); /* no, store word */ - break; - -case 005: case 025: case 045: case 065: /* ERA */ - if (reason = Ea (MB, &Y)) break; /* eff addr */ - AR = AR ^ Read (Y); - break; - -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; } - 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; } - else AR = Add16 (AR, (-Read (Y)) & DMASK); /* no, 16b sub */ - break; - -/* Memory reference instructions */ - -case 010: case 030: case 050: case 070: /* JST */ - if (reason = Ea (MB, &Y)) break; /* eff addr */ - MB = NEWA (Read (Y), PC); /* merge old PC */ - Write (MB, Y); - PCQ_ENTRY; - PC = NEWA (PC, Y + 1); /* set new PC */ - break; - -case 011: case 031: case 051: case 071: /* CAS */ - if (reason = Ea (MB, &Y)) break; /* eff addr */ - MB = Read (Y); - if (AR == MB) PC = NEWA (PC, PC + 1); - else if (SEXT (AR) < SEXT (MB)) PC = NEWA (PC, PC + 2); - break; - -case 012: case 032: case 052: case 072: /* IRS */ - if (reason = Ea (MB, &Y)) break; /* eff addr */ - MB = (Read (Y) + 1) & DMASK; /* incr, rewrite */ - Write (MB, Y); - if (MB == 0) PC = NEWA (PC, PC + 1); /* skip if zero */ - break; - -case 013: case 033: case 053: case 073: /* IMA */ - if (reason = Ea (MB, &Y)) break; /* eff addr */ - MB = Read (Y); - Write (AR, Y); /* A to mem */ - AR = MB; /* mem to A */ - break; - -case 015: case 055: /* STX */ - if (reason = Ea (MB & ~IDX, &Y)) break; /* eff addr */ - Write (XR, Y); /* store XR */ - break; - -case 035: case 075: /* LDX */ - if (reason = Ea (MB & ~IDX, &Y)) break; /* eff addr */ - XR = Read (Y); /* load XR */ - 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; } - 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; } - else reason = stop_inst; - break; - -/* I/O instructions */ - -case 014: /* OCP */ - t2 = iotab[MB & DEVMASK] (ioOCP, I_GETFNC (MB), AR); - reason = t2 >> IOT_V_REASON; - turnoff = 0; - break; - -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; } - 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; } - 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; } - break; - -/* Control */ - -case 000: - if ((MB & 1) == 0) { /* HLT */ - 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 (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 (MB & m12) /* RMP */ - 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; } - 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; } - else if (MB & m9) { /* IAB */ - sc = BR; - BR = AR; - AR = sc; } - if (MB & m8) /* ENB */ - dev_ready = (dev_ready | INT_ON) & ~INT_NODEF; - if (MB & m7) /* INH */ - dev_ready = dev_ready & ~INT_ON; - break; - -/* Shift - - Shifts are microcoded as follows: - - op<7> = right/left - op<8> = long/short - op<9> = shift/rotate (rotate bits "or" into new position) - op<10> = logical/arithmetic - - If !op<7> && op<10> (right arithmetic), A<1> propagates rightward - If op<7> && op<10> (left arithmetic), C is set if A<1> changes state - If !op<8> && op<10> (long arithmetic), B<1> is skipped - - This microcoding "explains" how the 4 undefined opcodes actually work - 003 = long arith rotate right, skip B<1>, propagate A<1>, - bits rotated out "or" into A<1> - 007 = short arith rotate right, propagate A<1>, - bits rotated out "or" into A<1> - 013 = long arith rotate left, skip B<1>, C = overflow - 017 = short arith rotate left, C = overflow -*/ - -case 020: - C = 0; /* clear C */ - sc = 0; /* clear sc */ - 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; - - 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; - - 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; - - 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; - - 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; - - 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; - - case 006: /* ARR */ - 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; - -/* 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; - - 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; - - 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; - - 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; - - 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; - - 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; - - case 016: /* ALR */ - 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 */ - break; - -/* Skip */ - -case 040: - skip = 0; - if (((MB & 000001) && C) || /* SSC */ - ((MB & 000002) && ss[3]) || /* SS4 */ - ((MB & 000004) && ss[2]) || /* SS3 */ - ((MB & 000010) && ss[1]) || /* SS2 */ - ((MB & 000020) && ss[0]) || /* SS1 */ - ((MB & 000040) && AR) || /* SNZ */ - ((MB & 000100) && (AR & 1)) || /* SLN */ - ((MB & 000200) && (TST_INTREQ (INT_MPE))) || /* SPS */ - ((MB & 000400) && (AR & SIGN))) skip = 1; /* SMI */ - if ((MB & 001000) == 0) skip = skip ^ 1; /* reverse? */ - PC = NEWA (PC, PC + skip); - break; - -/* Operate */ - -case 060: - if (MB == 0140024) AR = AR ^ SIGN; /* CHS */ - else if (MB == 0140040) AR = 0; /* CRA */ - 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; } - else if (MB == 0140401) AR = AR ^ DMASK; /* CMA */ - else if (MB == 0140407) { /* TCA */ - 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 */ - else if (MB == 0141050) AR = AR & 0377; /* CAL */ - else if (MB == 0141140) AR = AR >> 8; /* ICL */ - else if (MB == 0141206) AR = Add16 (AR, 1); /* AOA */ - 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; - else if (reason = stop_inst) break; - else AR = Operate (MB, AR); /* undefined */ - break; - } /* end case op */ -} /* end while */ - -saved_AR = AR & DMASK; -saved_BR = BR & DMASK; -saved_XR = XR & DMASK; -pcq_r->qptr = pcq_p; /* update pc q ptr */ -return reason; -} - -/* Effective address - - The effective address calculation consists of three phases: - - base address calculation: 0/pagenumber'displacement - - (extend): indirect address resolution - (non-extend): pre-indexing - - (extend): post-indexing - (non-extend): indirect address/post-indexing resolution - - In extend mode, address calculations are carried out to 16b - and masked to 15b at exit. In non-extend mode, address bits - <1:2> are preserved by the NEWA macro; address bit <1> is - masked at exit. -*/ - -t_stat Ea (int32 IR, int32 *addr) -{ -int32 i; -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 */ - 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 */ - } /* end else */ -*addr = Y = Y & X_AMASK; /* return addr */ -if (dlog && sim_log && !turnoff) /* cycle log? */ - fprintf (sim_log, " EA= %06o [%06o]\n", Y, M[Y]); -if (i >= ind_max) return STOP_IND; /* too many ind? */ -return SCPE_OK; -} - -/* Write memory */ - -void Write (int32 val, int32 addr) -{ -if (((addr == 0) || (addr >= 020)) && MEM_ADDR_OK (addr)) - M[addr] = val; -return; -} - -/* Add */ - -int32 Add16 (int32 v1, int32 v2) -{ -int32 r = v1 + v2; - -C = 0; -if (((v1 ^ ~v2) & (v1 ^ r)) & SIGN) C = 1; -return (r & DMASK); -} - -int32 Add31 (int32 v1, int32 v2) -{ -int32 r = v1 + v2; - -C = 0; -if (((v1 ^ ~v2) & (v1 ^ r)) & (1u << 30)) C = 1; -return r; -} - -/* Unimplemented I/O device */ - -int32 undio (int32 op, int32 fnc, int32 val) -{ -return ((stop_dev << IOT_V_REASON) | val); -} - -/* Undefined operate instruction. This code is reached when the - opcode does not correspond to a standard operate instruction. - It simulates the behavior of the actual logic. - - An operate instruction executes in 4 or 6 phases. A 'normal' - instruction takes 4 phases: - - t1 t1 - t2/tlate t2/t2 extended into t3 - t3/tlate t3 - t4 t4 - - A '1.5 cycle' instruction takes 6 phases: - - t1 t1 - t2/tlate t2/t2 extended into t3 - t3/tlate t3 - t2/tlate 'special' t2/t2 extended into t3 - t3/tlate t3 - t4 t4 - - The key signals, by phase, are the following - - tlate EASTL enable A to sum leg 1 (else 0) - (((m12+m16)x!azzzz)+(m9+m11+azzzz) - EASBM enable 0 to sum leg 2 (else 177777) - (m9+m11+azzzz) - JAMKN jam carry network to 0 = force XOR - ((m12+m16)x!azzzz) - EIKI7 force carry into adder - ((m15x(C+!m13))x!JAMKN) - - t3 CLDTR set D to 177777 (always) - ESDTS enable adder sum to D (always) - SETAZ enable repeat cycle = set azzzz - (m8xm15) - - if azzzz { - t2 CLATR clear A register (due to azzzz) - EDAHS enable D high to A high register (due to azzzz) - EDALS enable D low to A low register (due to azzzz) - - tlate, t3 as above - } - - t4 CLATR clear A register - (m11+m15+m16) - CLA1R clear A1 register - (m10+m14) - EDAHS enable D high to A high register - ((m11xm14)+m15+m16) - EDALS enable D low to A low register - ((m11xm13)+m15+m16) - ETAHS enable D transposed to A high register - (m9xm11) - ETALS enable D transposed to A low register - (m10xm11) - EDA1R enable D1 to A1 register - ((m8xm10)+m14) - CBITL clear C, conditionally set C from adder output - (m9x!m11) - CBITG conditionally set C if D1 - (m10xm12xD1) - CBITE unconditionally set C - (m8xm9) -*/ - -int32 Operate (int32 MB, int32 AR) -{ -int32 D, jamkn, eiki7, easbm, eastl, setaz; -int32 clatr, cla1r, edahs, edals, etahs, etals, eda1r; -int32 cbitl, cbitg, cbite; -int32 aleg, bleg, ARx; - -/* Phase tlate */ - -ARx = AR; /* default */ -jamkn = (MB & (m12+m16)) != 0; /* m12+m16 */ -easbm = (MB & (m9+m11)) != 0; /* m9+m11 */ -eastl = jamkn || easbm; /* m9+m11+m12+m16 */ -setaz = (MB & (m8+m15)) == (m8+m15); /* m8xm15*/ -eiki7 = (MB & m15) && (C || !(MB & m13)); /* cin */ -aleg = eastl? AR: 0; /* a input */ -bleg = easbm? 0: DMASK; /* b input */ -if (jamkn) D = aleg ^ bleg; /* jammin? xor */ -else D = (aleg + bleg + eiki7) & DMASK; /* else add */ - -/* Possible repeat at end of tlate - special t2, repeat tlate */ - -if (setaz) { - ARx = D; /* forced: t2 */ - aleg = ARx; /* forced: tlate */ - bleg = 0; /* forced */ - jamkn = 0; /* forced */ - D = (aleg + bleg + eiki7) & DMASK; /* forced add */ - sc = 0; } /* ends repeat */ - -/* Phase t4 */ - -clatr = (MB & (m11+m15+m16)) != 0; /* m11+m15+m16 */ -cla1r = (MB & (m10+m14)) != 0; /* m10+m14 */ -edahs = ((MB & (m11+m14)) == (m11+m14)) || /* (m11xm14)+m15+m16 */ - (MB & (m15+m16)); -edals = ((MB & (m11+m13)) == (m11+m13)) || /* (m11xm13)+m15+m16 */ - (MB & (m15+m16)); -etahs = (MB & (m9+m11)) == (m9+m11); /* m9xm11 */ -etals = (MB & (m10+m11)) == (m10+m11); /* m10xm11 */ -eda1r = ((MB & (m8+m10)) == (m8+m10)) || (MB & m14); /* (m8xm10)+m14 */ -cbitl = (MB & (m9+m11)) == m9; /* m9x!m11 */ -cbite = (MB & (m8+m9)) == (m8+m9); /* m8xm9 */ -cbitg = (MB & (m10+m12)) == (m10+m12); /* m10xm12 */ - -if (clatr) ARx = 0; /* clear A */ -if (cla1r) ARx = ARx & ~SIGN; /* clear A1 */ -if (edahs) ARx = ARx | (D & 0177400); /* D hi to A hi */ -if (edals) ARx = ARx | (D & 0000377); /* D lo to A lo */ -if (etahs) ARx = ARx | ((D << 8) & 0177400); /* D lo to A hi */ -if (etals) ARx = ARx | ((D >> 8) & 0000377); /* D hi to A lo */ -if (eda1r) ARx = ARx | (D & SIGN); /* D1 to A1 */ -if (cbitl) { /* ovflo to C */ - -/* Overflow calculation. Cases: - - aleg bleg cin overflow - - 0 x x can't overflow - A 0 0 can't overflow - A -1 1 can't overflow - A 0 1 overflow if 77777->100000 - A -1 0 overflow if 100000->77777 -*/ - - if (!jamkn && - ((bleg && !eiki7 && (D == 0077777)) || - (!bleg && eiki7 && (D == 0100000)))) C = 1; - else C = 0; } -if (cbite || (cbitg && (D & SIGN))) C = 1; /* C = 1 */ -return ARx; -} - -/* Reset routines */ - -t_stat cpu_reset (DEVICE *dptr) -{ -saved_AR = saved_BR = saved_XR = 0; -C = 0; -dp = 0; -ext = pme = extoff_pending = 0; -dev_ready = dev_ready & ~INT_PENDING; -dev_enable = 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) -{ -int32 d; - -if (addr >= MEMSIZE) return SCPE_NXM; -if (addr == 0) d = saved_XR; -else d = M[addr]; -if (vptr != NULL) *vptr = d & DMASK; -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; -if (addr == 0) saved_XR = val & DMASK; -else M[addr] = val & DMASK; -return SCPE_OK; -} - -/* Option processors */ - -t_stat cpu_set_noext (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -if (MEMSIZE > (NX_AMASK + 1)) return SCPE_ARG; -return SCPE_OK; -} - -t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -int32 mc = 0; -uint32 i; - -if ((val <= 0) || (val > MAXMEMSIZE) || ((val & 07777) != 0) || - (((cpu_unit.flags & UNIT_EXT) == 0) && (val > (NX_AMASK + 1)))) - 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/H316/h316_defs.h b/H316/h316_defs.h deleted file mode 100644 index 240174c2..00000000 --- a/H316/h316_defs.h +++ /dev/null @@ -1,144 +0,0 @@ -/* h316_defs.h: Honeywell 316/516 simulator definitions - - Copyright (c) 1999-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. - - 25-Apr-03 RMS Revised for extended file support -*/ - -#include "sim_defs.h" /* simulator defns */ - -/* Simulator stop codes */ - -#define STOP_RSRV 1 /* must be 1 */ -#define STOP_IODV 2 /* must be 2 */ -#define STOP_HALT 3 /* HALT */ -#define STOP_IBKPT 4 /* breakpoint */ -#define STOP_IND 5 /* indirect loop */ - -/* Memory */ - -#define MAXMEMSIZE 32768 /* max memory size */ -#define MEMSIZE (cpu_unit.capac) /* actual memory size */ -#define X_AMASK (MAXMEMSIZE - 1) /* ext address mask */ -#define NX_AMASK ((MAXMEMSIZE / 2) - 1) /* nx address mask */ -#define MEM_ADDR_OK(x) (((uint32) (x)) < MEMSIZE) - -/* Architectural constants */ - -#define SIGN 0100000 /* sign */ -#define DMASK 0177777 /* data mask */ -#define MMASK (DMASK & ~SIGN) /* magnitude mask */ -#define XR M[0] -#define M_CLK 061 /* clock location */ -#define M_RSTINT 062 /* restrict int */ -#define M_INT 063 /* int location */ - -/* CPU options */ - -#define UNIT_V_EXT (UNIT_V_UF + 1) /* extended mem */ -#define UNIT_V_HSA (UNIT_V_UF + 2) /* high speed arith */ -#define UNIT_EXT (1u << UNIT_V_EXT) -#define UNIT_HSA (1u << UNIT_V_HSA) - -/* Instruction format */ - -#define I_M_OP 077 /* opcode */ -#define I_V_OP 10 -#define I_GETOP(x) (((x) >> I_V_OP) & I_M_OP) -#define I_M_FNC 017 /* function */ -#define I_V_FNC 6 -#define I_GETFNC(x) (((x) >> I_V_FNC) & I_M_FNC) -#define IA 0100000 /* indirect address */ -#define IDX 0040000 /* indexed */ -#define SC 0001000 /* sector */ -#define DISP 0000777 /* page displacement */ -#define PAGENO 0077000 /* page number */ -#define INCLRA (010 << I_V_FNC) /* INA clear A */ -#define DEVMASK 0000077 /* device mask */ -#define SHFMASK 0000077 /* shift mask */ - -/* I/O opcodes */ - -#define ioOCP 0 /* output control */ -#define ioSKS 1 /* skip if set */ -#define ioINA 2 /* input to A */ -#define ioOTA 3 /* output from A */ - -/* I/O devices */ - -#define PTR 001 /* paper tape reader */ -#define PTP 002 /* paper tape punch */ -#define LPT 003 /* line printer */ -#define TTY 004 /* console */ -#define CDR 005 /* card reader */ -#define MT 010 /* mag tape data */ -#define KEYS 020 /* keys (CPU) */ -#define FHD 022 /* fixed head disk */ -#define DMA 024 /* DMA control */ -#define DP 025 /* moving head disk */ -#define OPT 034 /* SKS/OCP option */ - -/* Interrupt flags, definitions correspond to SMK bits */ - -#define INT_V_CLK 0 /* clock */ -#define INT_V_MPE 1 /* parity error */ -#define INT_V_LPT 2 /* line printer */ -#define INT_V_CDR 4 /* card reader */ -#define INT_V_TTY 5 /* teletype */ -#define INT_V_PTP 6 /* paper tape punch */ -#define INT_V_PTR 7 /* paper tape reader */ -#define INT_V_FHD 8 /* fixed head disk */ -#define INT_V_DP 12 /* moving head disk */ -#define INT_V_MT 15 /* mag tape */ -#define INT_V_NODEF 16 /* int not deferred */ -#define INT_V_ON 17 /* int on */ - -/* I/O macros */ - -#define IOT_V_REASON 17 -#define IOT_V_SKIP 16 -#define IOT_SKIP (1u << IOT_V_SKIP) -#define IORETURN(f,v) ((f)? (v): SCPE_OK) /* stop on error */ -#define IOBADFNC(x) (((stop_inst) << IOT_V_REASON) | (x)) -#define IOSKIP(x) (IOT_SKIP | (x)) - -#define INT_CLK (1u << INT_V_CLK) -#define INT_MPE (1u << INT_V_MPE) -#define INT_LPT (1u << INT_V_LPT) -#define INT_CDR (1u << INT_V_CDR) -#define INT_TTY (1u << INT_V_TTY) -#define INT_PTP (1u << INT_V_PTP) -#define INT_PTR (1u << INT_V_PTR) -#define INT_FHD (1u << INT_V_FHD) -#define INT_DP (1u << INT_V_DP) -#define INT_MT (1u << INT_V_MT) -#define INT_NODEF (1u << INT_V_NODEF) -#define INT_ON (1u << INT_V_ON) -#define INT_PENDING (INT_ON | INT_NODEF) - -#define SET_READY(x) dev_ready = dev_ready | (x) -#define CLR_READY(x) dev_ready = dev_ready & ~(x) -#define TST_READY(x) ((dev_ready & (x)) != 0) -#define CLR_ENABLE(x) dev_enable = dev_enable & ~(x) -#define TST_INTREQ(x) ((dev_ready & dev_enable & (x)) != 0) diff --git a/H316/h316_doc.txt b/H316/h316_doc.txt deleted file mode 100644 index dc56fe0f..00000000 --- a/H316/h316_doc.txt +++ /dev/null @@ -1,320 +0,0 @@ -To: Users -From: Bob Supnik -Subj: H316 Simulator Usage -Date: 15-Jul-2003 - - COPYRIGHT NOTICE - -The following copyright notice applies to both the SIMH source and binary: - - 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"), - 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 Honeywell 316/516 simulator. - - -1. Simulator Files - -The H316 requires the following 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/h316/ h316_defs.h - h316_cpu.c - h316_lp.c - h316_stddev.c - h316_sys.c - -2. H316/H516 Features - -The Honeywell 316/516 simulator is configured as follows: - -device simulates -name(s) - -CPU H316/H516 CPU with 16/32KW memory -PTR 316/516-50 paper tape reader -PTP 316/516-52 paper tape punch -TTY 316/516-33 console terminal -CLK 316/516-12 real time clock -LPT 316/516 line printer - -The H316/H516 simulator implements several unique stop conditions: - - - decode of an undefined instruction, and STOP_INST is et - - reference to an undefined I/O device, and STOP_DEV is set - - more than INDMAX indirect references are detected during - memory reference address decoding - -The H316/H516 loader is not implemented. - -2.1 CPU - -CPU options include choice of instruction set and memory size. - - SET CPU HSA high speed arithmetic instructions - SET CPU NOHSA no high speed arithmetic instructions - 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 24K set memory size = 24K - SET CPU 32K set memory size = 32K - -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 32K. - -CPU registers include the visible state of the processor as well as the -control registers for the interrupt system. - - name size comments - - P 15 program counter - A 16 A register - B 16 B register - X 16 index register - SC 16 shift count - C 1 carry flag - EXT 1 extend flag - PME 1 previous mode extend flag - EXT_OFF 1 extend off pending flag - DP 1 double precision flag - SS1..4 1 sense switches 1..4 - ION 1 interrupts enabled - INODEF 1 interrupts not deferred - INTREQ 16 interrupt requests - DEVRDY 16 device ready flags (read only) - DEVENB 16 device interrupt enable flags (read only) - STOP_INST 1 stop on undefined instruction - STOP_DEV 1 stop on undefined device - INDMAX 1 indirect address limit - PCQ[0:63] 15 PC prior to last JMP, JSB, or interrupt; - most recent PC change first - WRU 8 interrupt character - -2.2 Programmed I/O Devices - -2.2.1 316/516-50 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 supports the BOOT command. BOOT PTR copies the -absolute binary loader into memory and starts it running. - -The paper tape reader implements these registers: - - name size comments - - BUF 8 last data item processed - INTREQ 1 device interrupt request - READY 1 device ready - ENABLE 1 device interrupts enabled - POS 32 position in the input or 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 - - end of file 1 report error and stop - 0 out of tape or paper - - OS I/O error x report error and stop - -2.2.2 316/516-52 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 - INTREQ 1 device interrupt request - READY 1 device ready - ENABLE 1 device interrupts enabled - POWER 1 device powered up - POS 32 position in the input or output file - TIME 24 time from I/O initiation to interrupt - PWRTIME 24 time from I/O request to power up - 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 316/516-33 Console Teletype (TTY) - -The Teletype units (TTY0, TTY1) 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 reads from the console keyboard and writes to the -simulator console window. It implements these registers: - - name size comments - - BUF 8 last data item processed - MODE 1 read/write mode - INTREQ 1 device interrupt request - READY 1 device ready - ENABLE 1 device interrupts enabled - KPOS 32 number of characters input - KTIME 24 keyboard polling interval - TPOS 32 number of characters output - TTIME 24 time from I/O initiation to interrupt - -2.2.4 316/516-12 Real Time Clock (CLK) - -The real time clock (CLK) frequency can be adjusted as follows: - - SET CLK 60HZ set frequency to 60Hz - SET CLK 50HZ set frequency to 50Hz - -The default is 60Hz. - -The clock implements these registers: - - name size comments - - INTREQ 1 device interrupt request - READY 1 device ready - ENABLE 1 device interrupts enabled - TIME 24 clock interval - -The real-time clock autocalibrates; the clock interval is adjusted up or -down so that the clock tracks actual elapsed time. - -2.2.5 316/516 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 - - WDPOS 6 word position in current scan - DRPOS 6 drum position - CRPOS 1 carriage position - XFER 1 transfer ready flag - PRDN 1 print done flag - INTREQ 1 device interrupt request - ENABLE 1 device interrupt enable - SVCST 2 service state - SVCCH 2 service channel - BUF 8 buffer - POS 32 number of characters output - XTIME 24 delay between transfers - ETIME 24 delay at end of scan - PTIME 24 delay for shuttle/line advance - 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.3 Symbolic Display and Input - -The H316/H516 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 - -Instruction input uses standard H316/H516 assembler syntax. There are six -instruction classes: memory reference, I/O, control, shift, skip, and -operate. - -Memory reference instructions have the format - - memref{*} {C/Z} address{,1} - -where * signifies indirect, C a current sector reference, Z a sector zero -reference, and 1 indexed. The address is an octal number in the range 0 - -077777; if C or Z is specified, the address is a page offset in the range -0 - 0777. Normally, C is not needed; the simulator figures out from the -address what mode to use. However, when referencing memory outside the CPU, -there is no valid PC, and C must be used to specify current sector addressing. - -I/O instructions have the format - - io pulse+device - -The pulse+device is an octal number in the range 0 - 01777. - -Control and operate instructions consist of a single opcode - - opcode - -Shift instructions have the format - - shift n - -where n is an octal number in the range 0-77. - -Skip instructions have the format - - sub-op sub-op sub-op... - -The simulator checks that the combination of sub-opcodes is legal. diff --git a/H316/h316_lp.c b/H316/h316_lp.c deleted file mode 100644 index 7c17b74e..00000000 --- a/H316/h316_lp.c +++ /dev/null @@ -1,261 +0,0 @@ -/* h316_lp.c: Honeywell 316/516 line printer - - Copyright (c) 1999-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. - - lpt line printer - - 25-Apr-03 RMS Revised for extended file support - 30-May-02 RMS Widened POS to 32b - - The Series 16 line printer is an unbuffered Analex shuttle printer. - Because it was unbuffered, the CPU had to scan out an entire line's - worth of characters (60 words) for every character on the print drum - (64 characters). Because it was a shuttle printer, the entire - process must be repeated first for the odd columns and then for the - even columns. After scanning the odd columns, the printer carriage - shuttled right by one column; after scanning the even columns, the - carriage shuttled left. This halved the number of hammers required, - reducing cost but increasing mechanical complexity. - - The real printer is very timing dependent. If the CPU misses a - scan, then the wrong characters are printed. If the printer protocol - is violated, then results are unpredictable. The simulated printer - is much more forgiving. Rather than simulating the fixed drum and - hammer timing of the real printer, the simulator is driven by the - program's OTA instructions. If the program misses a time slot, the - simulator will still print the "correct" result. A timing based - simulation would be very hard to do in the absense of accurate - instruction timing. - - Printer state is maintained in a set of position and state variables: - - lpt_wdpos word count within a line scan (0-59) - lpt_drpos drum position (0-63) - lpt_crpos carriage position (0-1) - lpt_svcst service state (shuttle, paper advance) - lpt_svcch channel for paper advance (0 = no adv) - lpt_xfer transfer ready flag - lpt_prdn printing done flag -*/ - -#include "h316_defs.h" - -#define LPT_WIDTH 120 /* width */ -#define LPT_SCAN (LPT_WIDTH / 2) /* words/scan */ -#define LPT_DRUM 64 /* drum rows */ -#define LPT_SVCSH 01 /* shuttle */ -#define LPT_SVCPA 02 /* paper advance */ - -extern int32 dev_ready, dev_enable; -extern int32 stop_inst; - -int32 lpt_wdpos = 0; /* word position */ -int32 lpt_drpos = 0; /* drum position */ -int32 lpt_crpos = 0; /* carriage position */ -int32 lpt_svcst = 0; /* service state */ -int32 lpt_svcch = 0; /* service channel */ -int32 lpt_xfer = 0; /* transfer flag */ -int32 lpt_prdn = 1; /* printing done */ -char lpt_buf[LPT_WIDTH + 1] = { 0 }; /* line buffer */ -int32 lpt_xtime = 5; /* transfer time */ -int32 lpt_etime = 50; /* end of scan time */ -int32 lpt_ptime = 5000; /* paper adv time */ -int32 lpt_stopioe = 0; /* stop on error */ - -t_stat lpt_svc (UNIT *uptr); -t_stat lpt_reset (DEVICE *dptr); - -/* LPT data structures - - lpt_dev LPT device descriptor - lpt_unit LPT unit descriptor - lpt_mod LPT modifiers - lpt_reg LPT register list -*/ - -UNIT lpt_unit = { UDATA (&lpt_svc, UNIT_SEQ+UNIT_ATTABLE, 0) }; - -REG lpt_reg[] = { - { DRDATA (WDPOS, lpt_wdpos, 6) }, - { DRDATA (DRPOS, lpt_drpos, 6) }, - { FLDATA (CRPOS, lpt_crpos, 0) }, - { FLDATA (XFER, lpt_xfer, 0) }, - { FLDATA (PRDN, lpt_prdn, 0) }, - { FLDATA (INTREQ, dev_ready, INT_V_LPT) }, - { FLDATA (ENABLE, dev_enable, INT_V_LPT) }, - { ORDATA (SVCST, lpt_svcst, 2) }, - { ORDATA (SVCCH, lpt_svcch, 2) }, - { BRDATA (BUF, lpt_buf, 8, 8, 120) }, - { DRDATA (POS, lpt_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (XTIME, lpt_xtime, 24), PV_LEFT }, - { DRDATA (ETIME, lpt_etime, 24), PV_LEFT }, - { DRDATA (PTIME, lpt_ptime, 24), PV_LEFT }, - { FLDATA (STOP_IOE, lpt_stopioe, 0) }, - { NULL } }; - -DEVICE lpt_dev = { - "LPT", &lpt_unit, lpt_reg, NULL, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &lpt_reset, - NULL, NULL, NULL }; - -/* IO routine */ - -int32 lptio (int32 inst, int32 fnc, int32 dat) -{ -int32 chr; - -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; - 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; - default: - return IOBADFNC (dat); } - break; - -case ioSKS: /* SKS */ - switch (fnc) { /* case on fnc */ - case 000: /* if xfer rdy */ - if (lpt_xfer) return IOSKIP (dat); - break; - case 002: /* if !alarm */ - if (lpt_unit.flags & UNIT_ATT) return IOSKIP (dat); - break; - case 003: /* if odd col */ - if (lpt_crpos) return IOSKIP (dat); - break; - case 004: /* if !interrupt */ - if (!TST_INTREQ (INT_LPT)) return IOSKIP (dat); - break; - case 011: /* if line printed */ - if (lpt_prdn) return IOSKIP (dat); - break; - case 012: /* if !shuttling */ - if (!(lpt_svcst & LPT_SVCSH)) return IOSKIP (dat); - break; - case 013: - if (lpt_prdn && !(lpt_svcst & LPT_SVCSH)) return IOSKIP (dat); - break; - case 014: /* if !advancing */ - if (!(lpt_svcst & LPT_SVCPA)) return IOSKIP (dat); - break; - case 015: - if (lpt_prdn && !(lpt_svcst & LPT_SVCPA)) return IOSKIP (dat); - break; - case 016: - 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; - default: - 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 */ - break; } /* end case op */ -return dat; -} - -/* Unit service */ - -t_stat lpt_svc (UNIT *uptr) -{ -int32 i; -static const char *lpt_cc[] = { - "\r", - "\n", - "\n\f", - "\n" }; - -if ((lpt_unit.flags & UNIT_ATT) == 0) /* attached? */ - return IORETURN (lpt_stopioe, SCPE_UNATT); -lpt_xfer = 1; -if (lpt_svcst & LPT_SVCSH) { /* shuttling */ - SET_READY (INT_LPT); /* interrupt */ - if (lpt_crpos == 0) lpt_prdn = 1; } -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; } - lpt_buf[i + 1] = 0; - fputs (lpt_buf, uptr->fileref); /* output buf */ - fputs (lpt_cc[lpt_svcch & 03], uptr->fileref); /* output eol */ - uptr->pos = ftell (uptr->fileref); /* update pos */ - for (i = 0; i < LPT_WIDTH; i++) lpt_buf[i] = ' '; /* clear buf */ - } -lpt_svcst = 0; -return SCPE_OK; -} - -/* Reset routine */ - -t_stat lpt_reset (DEVICE *dptr) -{ -int32 i; - -lpt_wdpos = lpt_drpos = lpt_crpos = 0; /* clear positions */ -lpt_svcst = lpt_svcch = 0; /* idle state */ -lpt_xfer = 0; /* not rdy to xfer */ -lpt_prdn = 1; /* printing done */ -for (i = 0; i < LPT_WIDTH; i++) lpt_buf[i] = ' '; /* clear buffer */ -lpt_buf[LPT_WIDTH] = 0; -CLR_READY (INT_LPT); /* clear int, enb */ -CLR_ENABLE (INT_LPT); -sim_cancel (&lpt_unit); /* deactivate unit */ -return SCPE_OK; -} diff --git a/H316/h316_stddev.c b/H316/h316_stddev.c deleted file mode 100644 index 2ff32fbe..00000000 --- a/H316/h316_stddev.c +++ /dev/null @@ -1,539 +0,0 @@ -/* h316_stddev.c: Honeywell 316/516 standard devices - - Copyright (c) 1999-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. - - ptr 316/516-50 paper tape reader - ptp 316/516-52 paper tape punch - tty 316/516-33 teleprinter - clk/options 316/516-12 real time clocks/internal options - - 25-Apr-03 RMS Revised for extended file support - 01-Mar-03 RMS Added SET/SHOW CLK FREQ support - 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 - 29-Nov-01 RMS Added read only unit support - 07-Sep-01 RMS Moved function prototypes -*/ - -#include "h316_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) - -extern uint16 M[]; -extern int32 PC; -extern int32 stop_inst; -extern int32 C, dp, ext, extoff_pending, sc; -extern int32 dev_ready, dev_enable; -extern UNIT cpu_unit; - -int32 ptr_stopioe = 0, ptp_stopioe = 0; /* stop on error */ -int32 ptp_power = 0, ptp_ptime; /* punch power, time */ -int32 tty_mode = 0, tty_buf = 0; /* tty mode, buf */ -int32 clk_tps = 60; /* ticks per second */ - -t_stat ptr_svc (UNIT *uptr); -t_stat ptr_reset (DEVICE *dptr); -t_stat ptr_boot (int32 unitno, DEVICE *dptr); -t_stat ptp_svc (UNIT *uptr); -t_stat ptp_reset (DEVICE *dptr); -t_stat tti_svc (UNIT *uptr); -t_stat tto_svc (UNIT *uptr); -t_stat tty_reset (DEVICE *dptr); -t_stat tty_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat clk_svc (UNIT *uptr); -t_stat clk_reset (DEVICE *dptr); -t_stat clk_set_freq (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat clk_show_freq (FILE *st, UNIT *uptr, int32 val, void *desc); - -/* PTR data structures - - ptr_dev PTR device descriptor - ptr_unit PTR unit descriptor - ptr_mod PTR modifiers - 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, 8) }, - { FLDATA (READY, dev_ready, INT_V_PTR) }, - { FLDATA (ENABLE, dev_enable, INT_V_PTR) }, - { DRDATA (POS, ptr_unit.pos, T_ADDR_W), 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 }; - -/* PTP data structures - - ptp_dev PTP device descriptor - ptp_unit PTP unit descriptor - ptp_mod PTP modifiers - 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 (READY, dev_ready, INT_V_PTP) }, - { FLDATA (ENABLE, dev_enable, INT_V_PTP) }, - { FLDATA (POWER, ptp_power, 0) }, - { DRDATA (POS, ptp_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, ptp_unit.wait, 24), PV_LEFT }, - { DRDATA (PWRTIME, ptp_ptime, 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 }; - -/* TTY data structures - - tty_dev TTY device descriptor - tty_unit TTY unit descriptor - tty_reg TTY register list - tty_mod TTy modifiers list -*/ - -#define TTI 0 -#define TTO 1 - -UNIT tty_unit[] = { - { UDATA (&tti_svc, UNIT_KSR, 0), KBD_POLL_WAIT }, - { UDATA (&tto_svc, UNIT_KSR, 0), SERIAL_OUT_WAIT } }; - -REG tty_reg[] = { - { ORDATA (BUF, tty_buf, 8) }, - { FLDATA (MODE, tty_mode, 0) }, - { FLDATA (READY, dev_ready, INT_V_TTY) }, - { FLDATA (ENABLE, dev_enable, INT_V_TTY) }, - { DRDATA (KPOS, tty_unit[TTI].pos, T_ADDR_W), PV_LEFT }, - { DRDATA (KTIME, tty_unit[TTI].wait, 24), REG_NZ + PV_LEFT }, - { DRDATA (TPOS, tty_unit[TTO].pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TTIME, tty_unit[TTO].wait, 24), REG_NZ + PV_LEFT }, - { NULL } }; - -MTAB tty_mod[] = { - { UNIT_KSR+UNIT_8B, UNIT_KSR, "KSR", "KSR", &tty_set_mode }, - { UNIT_KSR+UNIT_8B, 0 , "7b" , "7B" , &tty_set_mode }, - { UNIT_KSR+UNIT_8B, UNIT_8B , "8b" , "8B" , &tty_set_mode }, - { 0 } }; - -DEVICE tty_dev = { - "TTY", tty_unit, tty_reg, tty_mod, - 2, 10, 31, 1, 8, 8, - NULL, NULL, &tty_reset, - NULL, NULL, NULL }; - -/* CLK data structures - - clk_dev CLK device descriptor - clk_unit CLK unit descriptor - clk_mod CLK modifiers - clk_reg CLK register list -*/ - -UNIT clk_unit = { - UDATA (&clk_svc, 0, 0), 16000 }; - -REG clk_reg[] = { - { FLDATA (READY, dev_ready, INT_V_CLK) }, - { FLDATA (ENABLE, dev_enable, INT_V_CLK) }, - { DRDATA (TIME, clk_unit.wait, 24), REG_NZ + PV_LEFT }, - { DRDATA (TPS, clk_tps, 8), PV_LEFT + REG_HRO }, - { NULL } }; - -MTAB clk_mod[] = { - { MTAB_XTD|MTAB_VDV, 50, NULL, "50HZ", - &clk_set_freq, NULL, NULL }, - { MTAB_XTD|MTAB_VDV, 60, NULL, "60HZ", - &clk_set_freq, NULL, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "FREQUENCY", NULL, - NULL, &clk_show_freq, NULL }, - { 0 } }; - -DEVICE clk_dev = { - "CLK", &clk_unit, clk_reg, clk_mod, - 1, 0, 0, 0, 0, 0, - NULL, NULL, &clk_reset, - NULL, NULL, NULL }; - -/* Paper tape reader: IO routine */ - -int32 ptrio (int32 inst, int32 fnc, int32 dat) -{ -switch (inst) { /* case on opcode */ -case ioOCP: /* OCP */ - if (fnc & 016) return IOBADFNC (dat); /* only fnc 0,1 */ - if (fnc) sim_cancel (&ptr_unit); /* fnc 1? stop */ - else sim_activate (&ptr_unit, ptr_unit.wait); /* fnc 0? start */ - break; -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); - 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 */ - break; } /* end case op */ -return dat; -} - -/* 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) { /* read byte */ - 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; } -SET_READY (INT_PTR); /* set ready flag */ -ptr_unit.buf = temp & 0377; /* get byte */ -ptr_unit.pos = ftell (ptr_unit.fileref); /* update pos */ -sim_activate (&ptr_unit, ptr_unit.wait); /* reactivate */ -return SCPE_OK; -} - -/* Reset routine */ - -t_stat ptr_reset (DEVICE *dptr) -{ -CLR_READY (INT_PTR); /* clear ready, enb */ -CLR_ENABLE (INT_PTR); -ptr_unit.buf = 0; /* clear buffer */ -sim_cancel (&ptr_unit); /* deactivate unit */ -return SCPE_OK; -} - -/* Paper tape reader bootstrap routine */ - -#define PBOOT_START 1 -#define PBOOT_SIZE (sizeof (pboot) / sizeof (int32)) - -static const int32 pboot[] = { - 0010057, /* STA 57 */ - 0030001, /* OCP 1 */ - 0131001, /* READ, INA 1001 */ - 0002003, /* JMP READ */ - 0101040, /* SNZ */ - 0002003, /* JMP READ */ - 0010000, /* STA 0 */ - 0131001, /* READ1, INA 1001 */ - 0002010, /* JMP READ1 */ - 0041470, /* LGL 8 */ - 0130001, /* READ2, INA 1 */ - 0002013, /* JMP READ2 */ - 0110000, /* STA* 0 */ - 0024000, /* IRS 0 */ - 0100040 /* SZE */ -}; - -t_stat ptr_boot (int32 unitno, DEVICE *dptr) -{ -int32 i; - -for (i = 0; i < PBOOT_SIZE; i++) /* copy bootstrap */ - M[PBOOT_START + i] = pboot[i]; -PC = PBOOT_START; -return SCPE_OK; -} - -/* Paper tape punch: IO routine */ - -int32 ptpio (int32 inst, int32 fnc, int32 dat) -{ -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 */ - else if (ptp_power == 0) /* fnc 0? start */ - sim_activate (&ptp_unit, ptp_ptime); - break; -case ioSKS: /* SKS */ - if ((fnc & 012) || (fnc == 005)) /* only 0, 1, 4 */ - 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); - 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 */ - break; } -return dat; -} - -/* Unit service */ - -t_stat ptp_svc (UNIT *uptr) -{ - -SET_READY (INT_PTP); /* set flag */ -if (ptp_power == 0) { /* power on? */ - ptp_power = 1; /* ptp is ready */ - return SCPE_OK; } -if ((ptp_unit.flags & UNIT_ATT) == 0) /* attached? */ - return IORETURN (ptp_stopioe, SCPE_UNATT); -if (putc (ptp_unit.buf, ptp_unit.fileref) == EOF) { /* output byte */ - perror ("PTP I/O error"); - clearerr (ptp_unit.fileref); - return SCPE_IOERR; } -ptp_unit.pos = ftell (ptp_unit.fileref); /* update pos */ -return SCPE_OK; -} - -/* Reset routine */ - -t_stat ptp_reset (DEVICE *dptr) -{ -CLR_READY (INT_PTP); /* clear ready, enb */ -CLR_ENABLE (INT_PTP); -ptp_power = 0; /* power off */ -ptp_unit.buf = 0; /* clear buffer */ -sim_cancel (&ptp_unit); /* deactivate unit */ -return SCPE_OK; -} - -/* Terminal: IO routine */ - -int32 ttyio (int32 inst, int32 fnc, int32 dat) -{ -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 */ - 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 */ - break; -case ioSKS: /* SKS */ - if (fnc & 012) return IOBADFNC (dat); /* fnc 0,1,4,5 */ - if (((fnc == 0) && TST_READY (INT_TTY)) || /* fnc 0? skip rdy */ - ((fnc == 1) && /* fnc 1? skip !busy */ - tty_mode && !sim_is_active (&tty_unit[TTO])) || - ((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); - 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))); } - 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); } - break; } /* end case op */ -return dat; -} - -/* Unit service routines */ - -t_stat tti_svc (UNIT *uptr) -{ -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 (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); -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 */ - if (out) sim_putchar (out); } /* echo */ -return SCPE_OK; -} - -t_stat tto_svc (UNIT *uptr) -{ -int32 c; -t_stat r; - -SET_READY (INT_TTY); /* set done flag */ -if (tty_unit[TTO].flags & UNIT_KSR) { /* UC only? */ - c = tty_buf & 0177; /* mask to 7b */ - if (islower (c)) c = toupper (c); } /* cvt to UC */ -else c = tty_buf & ((tty_unit[TTO].flags & UNIT_8B)? 0377: 0177); -if ((r = sim_putchar (c)) != SCPE_OK) return r; /* output char */ -tty_unit[TTO].pos = tty_unit[TTO].pos + 1; -return SCPE_OK; -} - -/* Reset routine */ - -t_stat tty_reset (DEVICE *dptr) -{ -CLR_READY (INT_TTY); /* clear ready, enb */ -CLR_ENABLE (INT_TTY); -tty_mode = 0; /* mode = input */ -tty_buf = 0; -sim_activate (&tty_unit[TTI], tty_unit[TTI].wait); /* activate poll */ -sim_cancel (&tty_unit[TTO]); /* cancel output */ -return SCPE_OK; -} - -t_stat tty_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -tty_unit[TTI].flags = (tty_unit[TTI].flags & ~(UNIT_KSR | UNIT_8B)) | val; -tty_unit[TTO].flags = (tty_unit[TTO].flags & ~(UNIT_KSR | UNIT_8B)) | val; -return SCPE_OK; -} - -/* Clock/options: IO routine */ - -int32 clkio (int32 inst, int32 fnc, int32 dat) -{ -switch (inst) { /* case on opcode */ -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 { /* fnc = 0? */ - if (!sim_is_active (&clk_unit)) - sim_activate (&clk_unit, /* activate */ - 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); } - else if ((fnc & 007) == 002) { /* mem parity? */ - 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 */ - else return IOBADFNC (dat); - break; } -return dat; -} - -/* Unit service */ - -t_stat clk_svc (UNIT *uptr) -{ - -M[M_CLK] = M[M_CLK + 1] & DMASK; /* increment mem ctr */ -if (M[M_CLK] == 0) SET_READY (INT_CLK); /* = 0? set flag */ -sim_activate (&clk_unit, sim_rtc_calb (clk_tps)); /* reactivate */ -return SCPE_OK; -} - -/* Reset routine */ - -t_stat clk_reset (DEVICE *dptr) -{ -CLR_READY (INT_CLK); /* clear ready, enb */ -CLR_ENABLE (INT_CLK); -sim_cancel (&clk_unit); /* deactivate unit */ -return SCPE_OK; -} - -/* Set frequency */ - -t_stat clk_set_freq (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -if (cptr) return SCPE_ARG; -if ((val != 50) && (val != 60)) return SCPE_IERR; -clk_tps = val; -return SCPE_OK; -} - -/* Show frequency */ - -t_stat clk_show_freq (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -fprintf (st, (clk_tps == 50)? "50Hz": "60Hz"); -return SCPE_OK; -} diff --git a/H316/h316_sys.c b/H316/h316_sys.c deleted file mode 100644 index a280d4a1..00000000 --- a/H316/h316_sys.c +++ /dev/null @@ -1,346 +0,0 @@ -/* h316_sys.c: Honeywell 316/516 simulator interface - - Copyright (c) 1999-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. - - 17-Sep-01 RMS Removed multiconsole support -*/ - -#include "h316_defs.h" -#include - -extern DEVICE cpu_dev; -extern UNIT cpu_unit; -extern DEVICE ptr_dev, ptp_dev; -extern DEVICE tty_dev, lpt_dev; -extern DEVICE clk_dev; -extern REG cpu_reg[]; -extern uint16 M[]; -extern int32 sim_switches; - -/* SCP data structures and interface routines - - sim_name simulator name string - sim_PC pointer to saved PC register descriptor - sim_emax maximum number of words for examine/deposit - sim_devices array of pointers to simulated devices - sim_stop_messages array of pointers to stop messages - sim_load binary loader -*/ - -char sim_name[] = "H316"; - -REG *sim_PC = &cpu_reg[0]; - -int32 sim_emax = 1; - -DEVICE *sim_devices[] = { &cpu_dev, - &ptr_dev, &ptp_dev, - &tty_dev, &lpt_dev, - &clk_dev, - NULL }; - -const char *sim_stop_messages[] = { - "Unknown error", - "Unimplemented instruction", - "Unimplemented I/O device", - "HALT instruction", - "Breakpoint", - "Indirect address loop" }; - -/* Binary loader - - Tbs. -*/ - -t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag) -{ -return SCPE_FMT; -} - -/* Symbol tables */ - -#define I_V_FL 16 /* flag start */ -#define I_M_FL 07 /* flag mask */ -#define I_V_NPN 0 /* no operand */ -#define I_V_MRF 1 /* mem ref */ -#define I_V_MRX 2 /* mem ref, no idx */ -#define I_V_IOT 3 /* I/O */ -#define I_V_SHF 4 /* shift */ -#define I_V_SK0 5 /* skip 0 */ -#define I_V_SK1 6 /* skip 1 */ -#define I_NPN (I_V_NPN << I_V_FL) -#define I_MRF (I_V_MRF << I_V_FL) -#define I_MRX (I_V_MRX << I_V_FL) -#define I_IOT (I_V_IOT << I_V_FL) -#define I_SHF (I_V_SHF << I_V_FL) -#define I_SK0 (I_V_SK0 << I_V_FL) -#define I_SK1 (I_V_SK1 << I_V_FL) - -static const int32 masks[] = { - 0177777, 0136000, 0176000, 0176000, - 0177700, 0177000, 0177000 }; - -static const char *opcode[] = { - "HLT", "SGL", "DBL", - "DXA", "EXA", "RMP", - "SCA", "INK", "NRM", - "IAB", "ENB", "INH", "ERM", - "CHS", "CRA", "SSP", - "RCB", "CSA", "CMA", - "TCA", "SSM", "SCB", - "CAR", "CAL", "ICL", - "AOA", "ACA", "ICR", "ICA", - "NOP", "SKP", "SSR", "SSS", - "JMP", "JMP*", - "LDA", "LDA*", "ANA", "ANA*", - "STA", "STA*", "ERA", "ERA*", - "ADD", "ADD*", "SUB", "SUB*", - "JST", "JST*", "CAS", "CAS*", - "IRS", "IRS*", "IMA", "IMA*", - "MPY", "MPY*", "DIV", "DIV*", - "STX", "STX*", "LDX", "LDX*", - "LRL", "LRS", "LRR", - "LGR", "ARS", "ARR", - "LLL", "LLS", "LLR", - "LGL", "ALS", "ALR", - "OCP", "SKS", "INA", "OTA", - "SMK", - "SPL", "SPN", "SLZ", /* encode only */ - "SZE", "SR1", "SR2", - "SR3", "SR4", "SRC", - "SMI", "SPS", "SLN", - "SNZ", "SS1", "SS2", - "SS3", "SS4", "SSC", - NULL, NULL, /* decode only */ - NULL }; - -static const int32 opc_val[] = { - 0000000+I_NPN, 0000005+I_NPN, 0000007+I_NPN, - 0000011+I_NPN, 0000013+I_NPN, 0000021+I_NPN, - 0000041+I_NPN, 0000043+I_NPN, 0000101+I_NPN, - 0000201+I_NPN, 0000401+I_NPN, 0001001+I_NPN, 0001401+I_NPN, - 0140024+I_NPN, 0140040+I_NPN, 0140100+I_NPN, - 0140200+I_NPN, 0140320+I_NPN, 0140401+I_NPN, - 0140407+I_NPN, 0140500+I_NPN, 0140600+I_NPN, - 0141044+I_NPN, 0141050+I_NPN, 0141140+I_NPN, - 0141206+I_NPN, 0141216+I_NPN, 0141240+I_NPN, 0141340+I_NPN, - 0101000+I_NPN, 0100000+I_NPN, 0100036+I_NPN, 0101036+I_NPN, - 0002000+I_MRF, 0102000+I_MRF, - 0004000+I_MRF, 0104000+I_MRF, 0006000+I_MRF, 0106000+I_MRF, - 0010000+I_MRF, 0110000+I_MRF, 0012000+I_MRF, 0112000+I_MRF, - 0014000+I_MRF, 0114000+I_MRF, 0016000+I_MRF, 0116000+I_MRF, - 0020000+I_MRF, 0120000+I_MRF, 0022000+I_MRF, 0122000+I_MRF, - 0024000+I_MRF, 0124000+I_MRF, 0026000+I_MRF, 0126000+I_MRF, - 0034000+I_MRF, 0134000+I_MRF, 0036000+I_MRF, 0136000+I_MRF, - 0032000+I_MRX, 0132000+I_MRX, 0072000+I_MRX, 0172000+I_MRX, - 0040000+I_SHF, 0040100+I_SHF, 0040200+I_SHF, - 0040400+I_SHF, 0040500+I_SHF, 0040600+I_SHF, - 0041000+I_SHF, 0041100+I_SHF, 0041200+I_SHF, - 0041400+I_SHF, 0041500+I_SHF, 0041600+I_SHF, - 0030000+I_IOT, 0070000+I_IOT, 0130000+I_IOT, 0170000+I_IOT, - 0170000+I_IOT, - 0100400+I_SK0, 0100200+I_SK0, 0100100+I_SK0, /* encode only */ - 0100040+I_SK0, 0100020+I_SK0, 0100010+I_SK0, - 0100004+I_SK0, 0100002+I_SK0, 0100001+I_SK0, - 0101400+I_SK1, 0101200+I_SK1, 0101100+I_SK1, - 0101040+I_SK1, 0101020+I_SK1, 0101010+I_SK1, - 0101004+I_SK1, 0101002+I_SK1, 0101001+I_SK1, - 0100000+I_SK0, 0101000+I_SK1, /* decode only */ - -1 }; - -/* Operate 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 data - *uptr = pointer to unit - sw = switches - Outputs: - return = status code -*/ - -#define FMTASC(x) ((x) < 040)? "<%03o>": "%c", (x) - -t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, - UNIT *uptr, int32 sw) -{ -int32 cflag, i, j, inst, disp; - -cflag = (uptr == NULL) || (uptr == &cpu_unit); -inst = val[0]; -if (sw & SWMASK ('A')) { /* ASCII? */ - if (inst > 0377) return SCPE_ARG; - fprintf (of, FMTASC (inst & 0177)); - return SCPE_OK; } -if (sw & SWMASK ('C')) { /* characters? */ - fprintf (of, FMTASC ((inst >> 8) & 0177)); - fprintf (of, FMTASC (inst & 0177)); - 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 */ - 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; - case I_V_IOT: /* I/O */ - 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; - case I_V_SK0: case I_V_SK1: /* skips */ - fprint_opr (of, inst & 0777, j, 0); /* print skips */ - break; } /* end case */ - return SCPE_OK; } /* end if */ - } /* end for */ -return SCPE_ARG; -} - -/* 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; -t_stat r; -char gbuf[CBUFSIZE]; - -cflag = (uptr == NULL) || (uptr == &cpu_unit); -while (isspace (*cptr)) cptr++; /* absorb spaces */ -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] & 0177; - return SCPE_OK; } -if ((sw & SWMASK ('C')) || ((*cptr == '"') && cptr++)) { /* char string? */ - if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */ - val[0] = (((t_value) cptr[0] & 0177) << 8) | - ((t_value) cptr[1] & 0177); - return SCPE_OK; } - -/* Instruction parse */ - -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: /* no operand */ - break; -case I_V_IOT: /* IOT */ - cptr = get_glyph (cptr, gbuf, 0); /* get pulse+dev */ - d = get_uint (gbuf, 8, 01777, &r); - if (r != SCPE_OK) return SCPE_ARG; - val[0] = val[0] | d; - break; -case I_V_SHF: /* shift */ - cptr = get_glyph (cptr, gbuf, 0); /* get shift count */ - d = get_uint (gbuf, 8, SHFMASK, &r); - if (r != SCPE_OK) return SCPE_ARG; - val[0] = val[0] | (-d & SHFMASK); /* store 2's comp */ - break; -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); } - else if (k = (strcmp (gbuf, "Z") == 0)) { /* Z specified? */ - 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; - else return SCPE_ARG; - if ((j == I_V_MRX) || (*cptr == 0)) break; /* indexed? */ - cptr = get_glyph (cptr, gbuf, 0); - d = get_uint (gbuf, 8, 1, &r); /* get tag */ - if (r != SCPE_OK) return SCPE_ARG; - if (d) val[0] = val[0] | IDX; /* or in index */ - break; -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; } - 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 deleted file mode 100644 index b28972c4..00000000 --- a/HP2100/hp2100_cpu.c +++ /dev/null @@ -1,2602 +0,0 @@ -/* hp2100_cpu.c: HP 2100 CPU simulator - - 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. - - 12-Mar-03 RMS Added logical name support - 02-Feb-03 RMS Fixed last cycle bug in DMA output (found by Mike Gemeny) - 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 - 25-Sep-02 RMS Fixed bug in DMS decode (found by Robert Alan Byer) - 26-Jul-02 RMS Restructured extended instructions, added IOP support - 22-Mar-02 RMS Changed to allocate memory array dynamically - 11-Mar-02 RMS Cleaned up setjmp/auto variable interaction - 17-Feb-02 RMS Added DMS support - Fixed bugs in extended instructions - 03-Feb-02 RMS Added terminal multiplexor support - Changed PCQ macro to use unmodified PC - Fixed flop restore logic (found by Bill McDermith) - Fixed SZx,SLx,RSS bug (found by Bill McDermith) - Added floating point support - 16-Jan-02 RMS Added additional device support - 07-Jan-02 RMS Fixed DMA register tables (found by Bill McDermith) - 07-Dec-01 RMS Revised to use breakpoint package - 03-Dec-01 RMS Added extended SET/SHOW support - 10-Aug-01 RMS Removed register in declarations - 26-Nov-00 RMS Fixed bug in dual device number routine - 21-Nov-00 RMS Fixed bug in reset routine - 15-Oct-00 RMS Added dynamic device number support - - The register state for the HP 2116 CPU is: - - AR<15:0> A register - addressable as location 0 - BR<15:0> B register - addressable as location 1 - PC<14:0> P register (program counter) - SR<15:0> S register - E extend flag (carry out) - O overflow flag - - The 2100 adds memory protection logic: - - mp_fence<14:0> memory fence register - mp_viol<15:0> memory protection violation register (F register) - - The 21MX adds a pair of index registers and memory expansion logic: - - XR<15:0> X register - YR<15:0> Y register - dms_sr<15:0> dynamic memory system status register - dms_vr<15:0> dynamic memory system violation register - - The original HP 2116 has four instruction formats: memory reference, - shift, alter/skip, and I/O. The HP 2100 added extended memory reference - and extended arithmetic. The HP21MX added extended byte, bit, and word - instructions as well as extended memory. - - The memory reference format is: - - 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - |in| op |cp| offset | memory reference - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - <14:11> mnemonic action - - 0010 AND A = A & M[MA] - 0011 JSB M[MA] = P, P = MA + 1 - 0100 XOR A = A ^ M[MA] - 0101 JMP P = MA - 0110 IOR A = A | M[MA] - 0111 ISZ M[MA] = M[MA] + 1, skip if M[MA] == 0 - 1000 ADA A = A + M[MA] - 1001 ADB B = B + M[MA] - 1010 CPA skip if A != M[MA] - 1011 CPB skip if B != M[MA] - 1100 LDA A = M[MA] - 1101 LDB B = M[MA] - 1110 STA M[MA] = A - 1111 STB M[MA] = B - - <15,10> mode action - - 0,0 page zero direct MA = IR<9:0> - 0,1 current page direct MA = PC<14:0>'IR,9:0> - 1,0 page zero indirect MA = M[IR<9:0>] - 1,1 current page indirect MA = M[PC<14:10>'IR<9:0>] - - Memory reference instructions can access an address space of 32K words. - An instruction can directly reference the first 1024 words of memory - (called page zero), as well as 1024 words of the current page; it can - indirectly access all 32K. -*/ - -/* The shift format is: - - 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | 0 0 0 0|ab| 0|s1| op1 |ce|s2|sl| op2 | shift - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | | \---+---/ | | | \---+---/ - | | | | | | | - | | | | | | +---- shift 2 opcode - | | | | | +---------- skip if low bit == 0 - | | | | +------------- shift 2 enable - | | | +---------------- clear Extend - | | +---------------------- shift 1 opcode - | +---------------------------- shift 1 enable - +---------------------------------- A/B select - - The alter/skip format is: - - 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | 0 0 0 0|ab| 1|regop| e op|se|ss|sl|in|sz|rs| alter/skip - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | \-+-/ \-+-/ | | | | | | - | | | | | | | | +- reverse skip sense - | | | | | | | +---- skip if register == 0 - | | | | | | +------- increment register - | | | | | +---------- skip if low bit == 0 - | | | | +------------- skip if sign bit == 0 - | | | +---------------- skip if Extend == 0 - | | +--------------------- clr/com/set Extend - | +--------------------------- clr/com/set register - +---------------------------------- A/B select - - The I/O transfer format is: - - 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | 1 0 0 0|ab| 1|hc| opcode | device | I/O transfer - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | | \---+---/\-------+-------/ - | | | | - | | | +--------- device select - | | +---------------------- opcode - | +---------------------------- hold/clear flag - +---------------------------------- A/B select - - The IO transfer instruction controls the specified device. - Depending on the opcode, the instruction may set or clear - the device flag, start or stop I/O, or read or write data. -*/ - -/* The 2100 added an extended memory reference instruction; - the 21MX added extended arithmetic, operate, byte, word, - and bit instructions. Note that the HP 21xx is, despite - the right-to-left bit numbering, a big endian system. - Bits <15:8> are byte 0, and bits <7:0> are byte 1. - - - The extended memory reference format (HP 2100) is: - - 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | 1| 0 0 0|op| 0| opcode | extended mem ref - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - |in| operand address | - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - The extended arithmetic format (HP 2100) is: - - 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | 1| 0 0 0 0 0|dr| 0 0| opcode |shift count| extended arithmetic - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - The extended operate format (HP 21MX) is: - - 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | 1| 0 0 0|op| 0| 1 1 1 1 1| opcode | extended operate - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - The extended byte and word format (HP 21MX) is: - - 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | 1| 0 0 0 1 0 1 1 1 1 1 1| opcode | extended byte/word - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - |in| operand address | - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0| - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - The extended bit operate format (HP 21MX) is: - - 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | 1| 0 0 0 1 0 1 1 1 1 1 1 1| opcode | extended bit operate - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - |in| operand address | - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - |in| operand address | - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ -*/ - -/* This routine is the instruction decode routine for the HP 2100. - 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 - infinite indirection loop - unimplemented instruction and stop_inst flag set - unknown I/O device and stop_dev flag set - I/O error in I/O simulator - - 2. Interrupts. I/O devices are modelled as four parallel arrays: - - device commands as bit array dev_cmd[2][31..0] - device flags as bit array dev_flg[2][31..0] - device flag buffers as bit array dev_fbf[2][31..0] - device controls as bit array dev_ctl[2][31..0] - - The HP 2100 interrupt structure is based on flag, flag buffer,. - and control. If a device flag is set, the flag buffer is set, - the control bit is set, and the device is the highest priority - on the interrupt chain, it requests an interrupt. When the - interrupt is acknowledged, the flag buffer is cleared, preventing - further interrupt requests from that device. The combination of - flag and control set blocks interrupts from lower priority devices. - - Command plays no direct role in interrupts. The command flop - tells whether a device is active. It is set by STC and cleared - by CLC; it is also cleared when the device flag is set. Simple - devices don't need to track command separately from control. - - 3. Non-existent memory. On the HP 2100, 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: - - hp2100_defs.h add interrupt request definition - hp2100_sys.c add sim_devices table entry - - 5. Instruction interruptibility. The simulator is fast enough, compared - to the run-time of the longest instructions, for interruptibility not - to matter. But the HP diagnostics explicitly test interruptibility in - EIS and DMS instructions, and long indirect address chains. Accordingly, - the simulator does "just enough" to pass these tests. In particular, if - an interrupt is pending but deferred at the beginning of an interruptible - instruction, the interrupt is taken at the appropriate point; but there - is no testing for new interrupts during execution (that is, the event - timer is not called). -*/ - -#include "hp2100_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] = err_PC - -#define UNIT_V_2100 (UNIT_V_UF + 0) /* 2100 */ -#define UNIT_V_21MX (UNIT_V_UF + 1) /* 21MX */ -#define UNIT_V_EAU (UNIT_V_UF + 2) /* EAU */ -#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) /* 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) -#define UNIT_FP (1 << UNIT_V_FP) -#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 -#define MOD_2100 2 -#define MOD_21MX 4 - -#define ABORT(val) longjmp (save_env, (val)) - -#define DMAR0 1 -#define DMAR1 2 - -uint16 *M = NULL; /* memory */ -uint32 saved_AR = 0; /* A register */ -uint32 saved_BR = 0; /* B register */ -uint32 PC = 0; /* P register */ -uint32 SR = 0; /* S register */ -uint32 XR = 0; /* X register */ -uint32 YR = 0; /* Y register */ -uint32 E = 0; /* E register */ -uint32 O = 0; /* O register */ -uint32 dev_cmd[2] = { 0 }; /* device command */ -uint32 dev_ctl[2] = { 0 }; /* device control */ -uint32 dev_flg[2] = { 0 }; /* device flags */ -uint32 dev_fbf[2] = { 0 }; /* device flag bufs */ -struct DMA dmac[2] = { { 0 }, { 0 } }; /* DMA channels */ -uint32 ion = 0; /* interrupt enable */ -uint32 ion_defer = 0; /* interrupt defer */ -uint32 intaddr = 0; /* interrupt addr */ -uint32 mp_fence = 0; /* mem prot fence */ -uint32 mp_viol = 0; /* mem prot viol reg */ -uint32 mp_mevff = 0; /* mem exp (dms) viol */ -uint32 mp_evrff = 1; /* update mp_viol */ -uint32 err_PC = 0; /* error PC */ -uint32 dms_enb = 0; /* dms enable */ -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 */ -uint16 pcq[PCQ_SIZE] = { 0 }; /* PC queue */ -uint32 pcq_p = 0; /* PC queue ptr */ -REG *pcq_r = NULL; /* PC queue reg ptr */ -jmp_buf save_env; /* abort handler */ - -struct opt_table { /* options table */ - int32 optf; - int32 cpuf; }; - -static struct opt_table opt_val[] = { - { UNIT_EAU, MOD_2116 }, - { UNIT_FP, MOD_2100 }, - { UNIT_MPR, MOD_2100 | MOD_21MX }, - { UNIT_DMS, MOD_21MX }, - { UNIT_IOP, MOD_2100 | MOD_21MX }, - { 0, 0 } }; - -extern int32 sim_interval; -extern int32 sim_int_char; -extern int32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */ -extern FILE *sim_log; -extern DEVICE *sim_devices[]; - -t_stat Ea (uint32 IR, uint32 *addr, uint32 irq); -t_stat Ea1 (uint32 *addr, uint32 irq); -uint8 ReadB (uint32 addr); -uint8 ReadBA (uint32 addr); -uint16 ReadW (uint32 addr); -uint16 ReadWA (uint32 addr); -uint32 ReadF (uint32 addr); -uint16 ReadIO (uint32 addr, uint32 map); -void WriteB (uint32 addr, uint32 dat); -void WriteBA (uint32 addr, uint32 dat); -void WriteW (uint32 addr, uint32 dat); -void WriteWA (uint32 addr, uint32 dat); -void WriteIO (uint32 addr, uint32 dat, uint32 map); -t_stat iogrp (uint32 ir, uint32 iotrap); -uint32 dms (uint32 va, uint32 map, uint32 prot); -uint32 dms_io (uint32 va, uint32 map); -void mp_dms_jmp (uint32 va); -uint16 dms_rmap (uint32 mapi); -void dms_wmap (uint32 mapi, uint32 dat); -void dms_viol (uint32 va, uint32 st); -uint32 dms_upd_sr (void); -uint32 shift (uint32 inval, uint32 flag, uint32 oper); -uint32 calc_dma (void); -uint32 calc_int (void); -void dma_cycle (uint32 chan, uint32 map); -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 dma0_reset (DEVICE *dptr); -t_stat dma1_reset (DEVICE *dptr); -t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat cpu_set_opt (UNIT *uptr, int32 val, char *cptr, void *desc); -t_bool dev_conflict (void); - -extern uint32 f_as (uint32 op, t_bool sub); -extern uint32 f_mul (uint32 op); -extern uint32 f_div (uint32 op); -extern uint32 f_fix (void); -extern uint32 f_flt (void); -extern int32 clk_delay (int32 flg); - -/* 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, VASIZE) }; - -REG cpu_reg[] = { - { ORDATA (P, PC, 15) }, - { ORDATA (A, saved_AR, 16) }, - { ORDATA (B, saved_BR, 16) }, - { ORDATA (X, XR, 16) }, - { ORDATA (Y, YR, 16) }, - { ORDATA (S, SR, 16) }, - { ORDATA (F, mp_fence, 15) }, - { FLDATA (E, E, 0) }, - { FLDATA (O, O, 0) }, - { FLDATA (ION, ion, 0) }, - { FLDATA (ION_DEFER, ion_defer, 0) }, - { ORDATA (IADDR, intaddr, 6) }, - { FLDATA (MPCTL, dev_ctl[PRO/32], INT_V (PRO)) }, - { FLDATA (MPFLG, dev_flg[PRO/32], INT_V (PRO)) }, - { FLDATA (MPFBF, dev_fbf[PRO/32], INT_V (PRO)) }, - { ORDATA (MPVR, mp_viol, 16) }, - { FLDATA (MPMEV, mp_mevff, 0) }, - { FLDATA (MPEVR, mp_evrff, 0) }, - { FLDATA (DMSENB, dms_enb, 0) }, - { FLDATA (DMSCUR, dms_ump, VA_N_PAG) }, - { 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 }, - { BRDATA (PCQ, pcq, 8, 15, PCQ_SIZE), REG_RO+REG_CIRC }, - { ORDATA (PCQP, pcq_p, 6), REG_HRO }, - { ORDATA (WRU, sim_int_char, 8) }, - { ORDATA (HCMD, dev_cmd[0], 32), REG_HRO }, - { ORDATA (LCMD, dev_cmd[1], 32), REG_HRO }, - { ORDATA (HCTL, dev_ctl[0], 32), REG_HRO }, - { ORDATA (LCTL, dev_ctl[1], 32), REG_HRO }, - { ORDATA (HFLG, dev_flg[0], 32), REG_HRO }, - { ORDATA (LFLG, dev_flg[1], 32), REG_HRO }, - { ORDATA (HFBF, dev_fbf[0], 32), REG_HRO }, - { ORDATA (LFBF, dev_fbf[1], 32), REG_HRO }, - { NULL } }; - -MTAB cpu_mod[] = { - { 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_IOPX, - UNIT_2100+UNIT_EAU, NULL, "2100", NULL }, - { 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, "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, "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, "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, "no DMS", "NODMS", &cpu_set_opt, - NULL, (void *) UNIT_DMS }, - { UNIT_MSIZE, 2, NULL, "IOP", &cpu_set_opt, - NULL, (void *) UNIT_IOP }, - { 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 }, - { UNIT_MSIZE, 16384, NULL, "16K", &cpu_set_size }, - { UNIT_MSIZE, 32768, NULL, "32K", &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_MSIZE, 524288, NULL, "512K", &cpu_set_size }, - { UNIT_MSIZE, 1048576, NULL, "1024K", &cpu_set_size }, - { 0 } }; - -DEVICE cpu_dev = { - "CPU", &cpu_unit, cpu_reg, cpu_mod, - 1, 8, 15, 1, 8, 16, - &cpu_ex, &cpu_dep, &cpu_reset, - NULL, NULL, NULL }; - -/* DMA controller data structures - - dmax_dev DMAx device descriptor - dmax_reg DMAx register list -*/ - -UNIT dma0_unit = { UDATA (NULL, 0, 0) }; - -REG dma0_reg[] = { - { FLDATA (CMD, dev_cmd[DMA0/32], INT_V (DMA0)) }, - { FLDATA (CTL, dev_ctl[DMA0/32], INT_V (DMA0)) }, - { FLDATA (FLG, dev_flg[DMA0/32], INT_V (DMA0)) }, - { FLDATA (FBF, dev_fbf[DMA0/32], INT_V (DMA0)) }, - { ORDATA (CW1, dmac[0].cw1, 16) }, - { ORDATA (CW2, dmac[0].cw2, 16) }, - { ORDATA (CW3, dmac[0].cw3, 16) }, - { NULL } }; - -DEVICE dma0_dev = { - "DMA0", &dma0_unit, dma0_reg, NULL, - 1, 8, 1, 1, 8, 16, - NULL, NULL, &dma0_reset, - NULL, NULL, NULL }; - -UNIT dma1_unit = { UDATA (NULL, 0, 0) }; - -REG dma1_reg[] = { - { FLDATA (CMD, dev_cmd[DMA1/32], INT_V (DMA1)) }, - { FLDATA (CTL, dev_ctl[DMA1/32], INT_V (DMA1)) }, - { FLDATA (FLG, dev_flg[DMA1/32], INT_V (DMA1)) }, - { FLDATA (FBF, dev_fbf[DMA1/32], INT_V (DMA1)) }, - { ORDATA (CW1, dmac[1].cw1, 16) }, - { ORDATA (CW2, dmac[1].cw2, 16) }, - { ORDATA (CW3, dmac[1].cw3, 16) }, - { NULL } }; - -DEVICE dma1_dev = { - "DMA1", &dma1_unit, dma1_reg, NULL, - 1, 8, 1, 1, 8, 16, - NULL, NULL, &dma1_reset, - NULL, NULL, NULL }; - -/* Extended instruction decode tables */ - -#define E_V_FL 0 /* flags */ -#define E_M_FL 0xFF -#define E_FP (UNIT_FP >> (UNIT_V_UF - E_V_FL)) -#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 */ -#define E_CN 1 /* PC+1: count */ -#define E_AD 2 /* PC+1: addr */ -#define E_AA 3 /* PC+1,2: addr */ -#define E_AC 4 /* PC+1: addr, +2: count */ -#define E_AZ 5 /* PC+1: addr, +2: zero */ -#define ET_NO (E_NO << E_V_TY) -#define ET_AD (E_AD << E_V_TY) -#define ET_AA (E_AA << E_V_TY) -#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 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))? \ - E_V_TYI: E_V_TY)) & E_M_TY) -#define F_NO E_FP | ET_NO -#define F_MR E_FP | ET_AD -#define X_NO E_21MX | ET_NO -#define X_MR E_21MX | ET_AD -#define X_AA E_21MX | ET_AA -#define X_AZ E_21MX | ET_AZ -#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)) -#define I_AZ E_IOP | (ET_AZ << (E_V_TYI - E_V_TY)) - -static const uint32 e_inst[512] = { - F_MR | I_AC,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* FAD/ILIST */ - F_MR | I_NO,I_NO,I_NO,I_NO,I_NO,I_NO,I_NO,I_NO, /* FSB/LAI- */ - I_NO,I_NO,I_NO,I_NO,I_NO,I_NO,I_NO,I_NO, - F_MR | I_NO,I_NO,I_NO,I_NO,I_NO,I_NO,I_NO,I_NO, /* FMP/LAI+ */ - I_NO,I_NO,I_NO,I_NO,I_NO,I_NO,I_NO,I_NO, - F_MR | I_NO,I_NO,I_NO,I_NO,I_NO,I_NO,I_NO,I_NO, /* FDV/SAI- */ - I_NO,I_NO,I_NO,I_NO,I_NO,I_NO,I_NO,I_NO, - F_NO | I_NO,I_NO,I_NO,I_NO,I_NO,I_NO,I_NO,I_NO, /* FIX/SAI+ */ - I_NO,I_NO,I_NO,I_NO,I_NO,I_NO,I_NO,I_NO, - F_NO | I_AZ,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* FLT/MBYTE */ - 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,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 */ - 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 */ - 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 */ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0560 */ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0600 */ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0620 */ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0640 */ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0660 */ - D_NO,D_NO,D_NO,D_NO,D_NO,D_NO,D_NO,D_NO, /* XMM,test,MBI,MBF,MBW,MWI,MWF,MWW */ - D_NO,D_NO,D_NO,D_NO,D_MR,D_AA,D_NO,D_NO, /* SY*,US*,PA*,PB*,SSM,JRS,nop,nop */ - D_NO,D_NO,D_NO,D_NO,D_MR,D_MR,D_MR,D_NO, /* XMM,XMS,XM*,nop,XL*,XS*,XC*,LF* */ - D_NO,D_NO,D_MR,D_MR,D_MR,D_MR,D_MR,D_MR, /* RS*,RV*,DJP,DJS,SJP,SJS,UJP,UJS */ - X_MR,X_NO,X_MR,X_MR,X_NO,X_MR,X_MR,X_NO, /* S*X,C*X,L*X,STX,CX*,LDX,ADX,X*X */ - X_MR,X_NO,X_MR,X_MR,X_NO,X_MR,X_MR,X_NO, /* S*Y,C*Y,L*Y,STY,CY*,LDY,ADY,X*Y */ - X_NO,X_NO,X_MR,X_NO,X_NO,X_AZ,X_AZ,X_NO, /* ISX,DSX,JLY,LBT,SBT,MBT,CBT,SFB */ - X_NO,X_NO,X_MR,X_AA,X_AA,X_AA,X_AZ,X_AZ }; /* ISY,DSY,JPY,SBS,CBS,TBS,CMW,MVW */ - -/* Interrupt defer table */ - -static const int32 defer_tab[] = { 0, 1, 1, 1, 0, 0, 0, 1 }; - -/* Device dispatch table */ - -uint32 devdisp (uint32 devno, uint32 inst, uint32 IR, uint32 outdat); -int32 cpuio (int32 op, int32 IR, int32 outdat); -int32 ovfio (int32 op, int32 IR, int32 outdat); -int32 pwrio (int32 op, int32 IR, int32 outdat); -int32 proio (int32 op, int32 IR, int32 outdat); -int32 dmsio (int32 op, int32 IR, int32 outdat); -int32 dmpio (int32 op, int32 IR, int32 outdat); -int32 nulio (int32 op, int32 IR, int32 outdat); - -int32 (*dtab[64])() = { - &cpuio, &ovfio, &dmsio, &dmsio, &pwrio, &proio, &dmpio, &dmpio, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; - -t_stat sim_instr (void) -{ -uint32 intrq, dmarq; /* set after setjmp */ -t_stat reason; /* set after setjmp */ -int32 i, dev; /* temp */ -DEVICE *dptr; /* temp */ -DIB *dibp; /* temp */ -int abortval; - -/* Restore register state */ - -if (dev_conflict ()) return SCPE_STOP; /* check consistency */ -AR = saved_AR & DMASK; /* restore reg */ -BR = saved_BR & DMASK; -err_PC = PC = PC & VAMASK; /* load local PC */ -reason = 0; - -/* Restore I/O state */ - -for (i = VARDEV; i <= I_DEVMASK; i++) dtab[i] = NULL; /* clr disp table */ -dev_cmd[0] = dev_cmd[0] & M_FXDEV; /* clear dynamic info */ -dev_ctl[0] = dev_ctl[0] & M_FXDEV; -dev_flg[0] = dev_flg[0] & M_FXDEV; -dev_fbf[0] = dev_fbf[0] & M_FXDEV; -dev_cmd[1] = dev_ctl[1] = dev_flg[1] = dev_fbf[1] = 0; -for (i = 0; dptr = sim_devices[i]; i++) { /* loop thru dev */ - dibp = (DIB *) dptr->ctxt; /* get DIB */ - if (dibp && !(dptr->flags & DEV_DIS)) { /* exist, enabled? */ - dev = dibp->devno; /* get dev # */ - if (dibp->cmd) { setCMD (dev); } /* restore cmd */ - if (dibp->ctl) { setCTL (dev); } /* restore ctl */ - if (dibp->flg) { setFLG (dev); } /* restore flg */ - clrFBF (dev); /* also sets fbf */ - if (dibp->fbf) { setFBF (dev); } /* restore fbf */ - dtab[dev] = dibp->iot; } } /* set I/O dispatch */ -sim_rtc_init (clk_delay (0)); /* recalibrate clock */ - -/* 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 - HP 2100. All referenced variables must be globals, and all sim_instr - scoped automatics must be set after the setjmp. -*/ - -abortval = setjmp (save_env); /* set abort hdlr */ -if (abortval != 0) { /* mem mgt abort? */ - setFLG (PRO); /* req interrupt */ - mp_evrff = 0; } /* block mp_viol upd */ -dmarq = calc_dma (); /* recalc DMA masks */ -intrq = calc_int (); /* recalc interrupts */ - -/* Main instruction fetch/decode loop */ - -while (reason == 0) { /* loop until halted */ -uint32 IR, MA, M1, absel, v1, v2, t; -uint32 fop, eop, etype, eflag; -uint32 skip, mapi, mapj, qs, rs; -uint32 awc, sc, wc, hp, tp, iotrap; -int32 sop1, sop2; - -if (sim_interval <= 0) { /* check clock queue */ - if (reason = sim_process_event ()) break; - dmarq = calc_dma (); /* recalc DMA reqs */ - intrq = calc_int (); } /* recalc interrupts */ - -if (dmarq) { - if (dmarq & DMAR0) dma_cycle (0, PAMAP); /* DMA1 cycle? */ - if (dmarq & DMAR1) dma_cycle (1, PBMAP); /* DMA2 cycle? */ - dmarq = calc_dma (); /* recalc DMA reqs */ - intrq = calc_int (); } /* recalc interrupts */ - -if (intrq && ((intrq <= PRO) || !ion_defer)) { /* interrupt request? */ - iotrap = 1; /* I/O trap cell instr */ - clrFBF (intrq); /* clear flag buffer */ - intaddr = intrq; /* save int addr */ - if (dms_enb) dms_sr = dms_sr | MST_ENBI; /* dms enabled? */ - else dms_sr = dms_sr & ~MST_ENBI; - if (dms_ump) { /* user map? */ - dms_sr = dms_sr | MST_UMPI; - dms_ump = SMAP; } /* switch to system */ - else dms_sr = dms_sr & ~MST_UMPI; - IR = ReadW (intrq); /* get dispatch instr */ - ion_defer = 1; /* defer interrupts */ - intrq = 0; /* clear request */ - if (((IR & I_NMRMASK) != I_IO) || /* if not I/O or */ - (I_GETIOOP (IR) == ioHLT)) /* if halt, */ - clrCTL (PRO); } /* protection off */ - -else { iotrap = 0; /* normal instruction */ - err_PC = PC; /* save PC for error */ - if (sim_brk_summ && - sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */ - reason = STOP_IBKPT; /* stop simulation */ - break; } - if (mp_evrff) mp_viol = PC; /* if ok, upd mp_viol */ - IR = ReadW (PC); /* fetch instr */ - PC = (PC + 1) & VAMASK; - sim_interval = sim_interval - 1; - ion_defer = 0; } - -/* Instruction decode. The 21MX does a 256-way decode on IR<15:8> - - 15 14 13 12 11 10 09 08 instruction - - x <-!= 0-> x x x x memory reference - 0 0 0 0 x 0 x x shift - 0 0 0 0 x 0 x x alter-skip - 1 0 0 0 x 1 x x IO - 1 0 0 0 0 0 x 0 extended arithmetic - 1 0 0 0 0 0 0 1 divide (decoded as 100400) - 1 0 0 0 1 0 0 0 double load (decoded as 104000) - 1 0 0 0 1 0 0 1 double store (decoded as 104400) - 1 0 0 0 1 0 1 0 extended instr group 0 (A/B must be set) - 1 0 0 0 x 0 1 1 extended instr group 1 (A/B ignored) */ - -absel = (IR & I_AB)? 1: 0; /* get A/B select */ -switch ((IR >> 8) & 0377) { /* decode IR<15:8> */ - -/* Memory reference instructions */ - -case 0020:case 0021:case 0022:case 0023: -case 0024:case 0025:case 0026:case 0027: -case 0220:case 0221:case 0222:case 0223: -case 0224:case 0225:case 0226:case 0227: - if (reason = Ea (IR, &MA, intrq)) break; /* AND */ - AR = AR & ReadW (MA); - break; -case 0030:case 0031:case 0032:case 0033: -case 0034:case 0035:case 0036:case 0037: -case 0230:case 0231:case 0232:case 0233: -case 0234:case 0235:case 0236:case 0237: - if (reason = Ea (IR, &MA, intrq)) break; /* JSB */ - WriteW (MA, PC); /* store PC */ - PCQ_ENTRY; - PC = (MA + 1) & VAMASK; /* jump */ - if (IR & I_IA) ion_defer = 1; /* ind? defer intr */ - break; -case 0040:case 0041:case 0042:case 0043: -case 0044:case 0045:case 0046:case 0047: -case 0240:case 0241:case 0242:case 0243: -case 0244:case 0245:case 0246:case 0247: - if (reason = Ea (IR, &MA, intrq)) break; /* XOR */ - AR = AR ^ ReadW (MA); - break; -case 0050:case 0051:case 0052:case 0053: -case 0054:case 0055:case 0056:case 0057: -case 0250:case 0251:case 0252:case 0253: -case 0254:case 0255:case 0256:case 0257: - if (reason = Ea (IR, &MA, intrq)) break; /* JMP */ - mp_dms_jmp (MA); /* validate jump addr */ - PCQ_ENTRY; - PC = MA; /* jump */ - if (IR & I_IA) ion_defer = 1; /* ind? defer int */ - break; -case 0060:case 0061:case 0062:case 0063: -case 0064:case 0065:case 0066:case 0067: -case 0260:case 0261:case 0262:case 0263: -case 0264:case 0265:case 0266:case 0267: - if (reason = Ea (IR, &MA, intrq)) break; /* IOR */ - AR = AR | ReadW (MA); - break; -case 0070:case 0071:case 0072:case 0073: -case 0074:case 0075:case 0076:case 0077: -case 0270:case 0271:case 0272:case 0273: -case 0274:case 0275:case 0276:case 0277: - if (reason = Ea (IR, &MA, intrq)) break; /* ISZ */ - t = (ReadW (MA) + 1) & DMASK; - WriteW (MA, t); - if (t == 0) PC = (PC + 1) & VAMASK; - break; - -/* Memory reference instructions, continued */ - -case 0100:case 0101:case 0102:case 0103: -case 0104:case 0105:case 0106:case 0107: -case 0300:case 0301:case 0302:case 0303: -case 0304:case 0305:case 0306:case 0307: - if (reason = Ea (IR, &MA, intrq)) break; /* ADA */ - v1 = ReadW (MA); - t = AR + v1; - if (t > DMASK) E = 1; - if (((~AR ^ v1) & (AR ^ t)) & SIGN) O = 1; - AR = t & DMASK; - break; -case 0110:case 0111:case 0112:case 0113: -case 0114:case 0115:case 0116:case 0117: -case 0310:case 0311:case 0312:case 0313: -case 0314:case 0315:case 0316:case 0317: - if (reason = Ea (IR, &MA, intrq)) break; /* ADB */ - v1 = ReadW (MA); - t = BR + v1; - if (t > DMASK) E = 1; - if (((~BR ^ v1) & (BR ^ t)) & SIGN) O = 1; - BR = t & DMASK; - break; -case 0120:case 0121:case 0122:case 0123: -case 0124:case 0125:case 0126:case 0127: -case 0320:case 0321:case 0322:case 0323: -case 0324:case 0325:case 0326:case 0327: - if (reason = Ea (IR, &MA, intrq)) break; /* CPA */ - if (AR != ReadW (MA)) PC = (PC + 1) & VAMASK; - break; -case 0130:case 0131:case 0132:case 0133: -case 0134:case 0135:case 0136:case 0137: -case 0330:case 0331:case 0332:case 0333: -case 0334:case 0335:case 0336:case 0337: - if (reason = Ea (IR, &MA, intrq)) break; /* CPB */ - if (BR != ReadW (MA)) PC = (PC + 1) & VAMASK; - break; -case 0140:case 0141:case 0142:case 0143: -case 0144:case 0145:case 0146:case 0147: -case 0340:case 0341:case 0342:case 0343: -case 0344:case 0345:case 0346:case 0347: - if (reason = Ea (IR, &MA, intrq)) break; /* LDA */ - AR = ReadW (MA); - break; -case 0150:case 0151:case 0152:case 0153: -case 0154:case 0155:case 0156:case 0157: -case 0350:case 0351:case 0352:case 0353: -case 0354:case 0355:case 0356:case 0357: - if (reason = Ea (IR, &MA, intrq)) break; /* LDB */ - BR = ReadW (MA); - break; -case 0160:case 0161:case 0162:case 0163: -case 0164:case 0165:case 0166:case 0167: -case 0360:case 0361:case 0362:case 0363: -case 0364:case 0365:case 0366:case 0367: - if (reason = Ea (IR, &MA, intrq)) break; /* STA */ - WriteW (MA, AR); - break; -case 0170:case 0171:case 0172:case 0173: -case 0174:case 0175:case 0176:case 0177: -case 0370:case 0371:case 0372:case 0373: -case 0374:case 0375:case 0376:case 0377: - if (reason = Ea (IR, &MA, intrq)) break; /* STB */ - WriteW (MA, BR); - break; - -/* Alter/skip instructions */ - -case 0004:case 0005:case 0006:case 0007: -case 0014:case 0015:case 0016:case 0017: - skip = 0; /* no skip */ - if (IR & 000400) t = 0; /* CLx */ - else t = ABREG[absel]; - if (IR & 001000) t = t ^ DMASK; /* CMx */ - if (IR & 000001) { /* RSS? */ - if ((IR & 000040) && (E != 0)) skip = 1; /* SEZ,RSS */ - if (IR & 000100) E = 0; /* CLE */ - if (IR & 000200) E = E ^ 1; /* CME */ - if (((IR & 000030) == 000030) && /* SSx,SLx,RSS */ - ((t & 0100001) == 0100001)) skip = 1; - if (((IR & 000030) == 000020) && /* SSx,RSS */ - ((t & SIGN) != 0)) skip = 1; - if (((IR & 000030) == 000010) && /* SLx,RSS */ - ((t & 1) != 0)) skip = 1; - if (IR & 000004) { /* INx */ - t = (t + 1) & DMASK; - if (t == 0) E = 1; - if (t == SIGN) O = 1; } - if ((IR & 000002) && (t != 0)) skip = 1; /* SZx,RSS */ - if ((IR & 000072) == 0) skip = 1; /* RSS */ - } /* end if RSS */ - else { - if ((IR & 000040) && (E == 0)) skip = 1; /* SEZ */ - if (IR & 000100) E = 0; /* CLE */ - if (IR & 000200) E = E ^ 1; /* CME */ - if ((IR & 000020) && /* SSx */ - ((t & SIGN) == 0)) skip = 1; - if ((IR & 000010) && /* SLx */ - ((t & 1) == 0)) skip = 1; - if (IR & 000004) { /* INx */ - 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 */ - ABREG[absel] = t; /* store result */ - PC = (PC + skip) & VAMASK; /* add in skip */ - break; /* end if alter/skip */ - -/* Shift instructions */ - -case 0000:case 0001:case 0002:case 0003: -case 0010:case 0011:case 0012:case 0013: - t = shift (ABREG[absel], IR & 01000, IR >> 6); /* do first shift */ - if (IR & 000040) E = 0; /* CLE */ - if ((IR & 000010) && ((t & 1) == 0)) /* SLx */ - PC = (PC + 1) & VAMASK; - ABREG[absel] = shift (t, IR & 00020, IR); /* do second shift */ - break; /* end if shift */ - -/* I/O instructions */ - -case 0204:case 0205:case 0206:case 0207: -case 0214:case 0215:case 0216:case 0217: - reason = iogrp (IR, iotrap); /* execute instr */ - dmarq = calc_dma (); /* recalc DMA */ - intrq = calc_int (); /* recalc interrupts */ - break; /* end if I/O */ - -/* Extended arithmetic */ - -case 0200: /* EAU group 0 */ - if ((cpu_unit.flags & UNIT_EAU) == 0) { /* implemented? */ - reason = stop_inst; - break; } - switch ((IR >> 4) & 017) { /* decode IR<7:4> */ - case 000: /* diagnostic */ - break; - case 001: /* ASL */ - sc = (IR & 017)? (IR & 017): 16; /* get sc */ - O = 0; /* clear ovflo */ - while (sc-- != 0) { /* bit by bit */ - t = BR << 1; /* shift B */ - BR = (BR & SIGN) | (t & 077777) | (AR >> 15); - AR = (AR << 1) & DMASK; - if ((BR ^ t) & SIGN) O = 1; } - break; - case 002: /* LSL */ - sc = (IR & 017)? (IR & 017): 16; /* get sc */ - BR = ((BR << sc) | (AR >> (16 - sc))) & DMASK; - AR = (AR << sc) & DMASK; /* BR'AR lsh left */ - break; - case 003: /* TIMER */ - BR = (BR + 1) & DMASK; /* increment B */ - if (BR) PC = err_PC; /* if !=0, repeat */ - break; - case 004: /* RRL */ - sc = (IR & 017)? (IR & 017): 16; /* get sc */ - t = BR; /* BR'AR rot left */ - BR = ((BR << sc) | (AR >> (16 - sc))) & DMASK; - AR = ((AR << sc) | (t >> (16 - sc))) & DMASK; - break; - case 010: /* MPY */ - if (reason = Ea1 (&MA, intrq)) break; /* get opnd addr */ - sop1 = SEXT (AR); /* sext AR */ - sop2 = SEXT (ReadW (MA)); /* sext mem */ - sop1 = sop1 * sop2; /* signed mpy */ - BR = (sop1 >> 16) & DMASK; /* to BR'AR */ - AR = sop1 & DMASK; - O = 0; /* no overflow */ - break; - default: - reason = stop_inst; - break; } - break; -case 0201: /* divide */ - if ((cpu_unit.flags & UNIT_EAU) == 0) { /* implemented? */ - reason = stop_inst; - break; } - if (reason = Ea1 (&MA, intrq)) break; /* get opnd addr */ - if (rs = qs = BR & SIGN) { /* save divd sign, neg? */ - AR = (~AR + 1) & DMASK; /* make B'A pos */ - BR = (~BR + (AR == 0)) & DMASK; } /* make divd pos */ - v2 = ReadW (MA); /* divr = mem */ - if (v2 & SIGN) { /* neg? */ - v2 = (~v2 + 1) & DMASK; /* make divr pos */ - qs = qs ^ SIGN; } /* sign of quotient */ - if (BR >= v2) O = 1; /* divide work? */ - else { /* maybe... */ - O = 0; /* assume ok */ - v1 = (BR << 16) | AR; /* 32b divd */ - AR = (v1 / v2) & DMASK; /* quotient */ - BR = (v1 % v2) & DMASK; /* remainder */ - if (AR) { /* quotient > 0? */ - if (qs) AR = (~AR + 1) & DMASK; /* apply quo sign */ - if ((AR ^ qs) & SIGN) O = 1; } /* still wrong? ovflo */ - if (rs) BR = (~BR + 1) & DMASK; } /* apply rem sign */ - break; -case 0202: /* EAU group 2 */ - if ((cpu_unit.flags & UNIT_EAU) == 0) { /* implemented? */ - reason = stop_inst; - break; } - switch ((IR >> 4) & 017) { /* decode IR<7:4> */ - case 001: /* ASR */ - sc = (IR & 017)? (IR & 017): 16; /* get sc */ - AR = ((BR << (16 - sc)) | (AR >> sc)) & DMASK; - BR = (SEXT (BR) >> sc) & DMASK; /* BR'AR ash right */ - O = 0; - break; - case 002: /* LSR */ - sc = (IR & 017)? (IR & 017): 16; /* get sc */ - AR = ((BR << (16 - sc)) | (AR >> sc)) & DMASK; - BR = BR >> sc; /* BR'AR log right */ - break; - case 004: /* RRR */ - sc = (IR & 017)? (IR & 017): 16; /* get sc */ - t = AR; /* BR'AR rot right */ - AR = ((AR >> sc) | (BR << (16 - sc))) & DMASK; - BR = ((BR >> sc) | (t << (16 - sc))) & DMASK; - break; - default: - reason = stop_inst; - break; } - break; -case 0210: /* DLD */ - if ((cpu_unit.flags & UNIT_EAU) == 0) { /* implemented? */ - reason = stop_inst; - break; } - if (reason = Ea1 (&MA, intrq)) break; /* get opnd addr */ - AR = ReadW (MA); /* load AR */ - MA = (MA + 1) & VAMASK; - BR = ReadW (MA); /* load BR */ - break; -case 0211: /* DST */ - if ((cpu_unit.flags & UNIT_EAU) == 0) { /* get opnd addr */ - reason = stop_inst; - break; } - if (reason = Ea1 (&MA, intrq)) break; /* get opnd addr */ - WriteW (MA, AR); /* store AR */ - MA = (MA + 1) & VAMASK; - WriteW (MA, BR); /* store BR */ - break; - -/* Extended instructions */ - -case 0212: /* MAC0 ext */ -case 0203:case 0213: /* MAC1 ext */ - eop = IR & 0777; /* extended opcode */ - eflag = E_GETFL (e_inst[eop]); /* get flags */ - if ((eflag & (cpu_unit.flags >> UNIT_V_UF)) == 0) { - reason = stop_inst; /* invalid? error */ - break; } - etype = E_GETTY (eflag, e_inst[eop]); /* get format */ - if (etype > E_CN) { /* at least 1 addr? */ - if (reason = Ea1 (&MA, intrq)) break; } /* get first address */ - if ((etype == E_AC) || (etype == E_CN)) { /* addr + cnt, cnt */ - wc = ReadW (PC); /* get count */ - awc = PC; /* addr of count */ - PC = (PC + 1) & VAMASK; } - else if (etype == E_AZ) { /* addr + zero */ - wc = ReadW (MA); /* get wc */ - awc = PC; /* addr of interim */ - if (wc) { /* wc > 0? */ - if (t = ReadW (PC)) wc = t; } /* use interim if nz */ - WriteW (awc, 0); /* clear interim */ - PC = (PC + 1) & VAMASK; } - else if (etype == E_AA) { /* second addr */ - if (reason = Ea1 (&M1, intrq)) break; } /* get second address */ - - switch (eop) { /* decode IR<8:0> */ - -/* Floating point instructions */ - - case 0000: /* IOP ILIST/FAD */ - 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) */ - 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) */ - 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) */ - 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) */ - goto IOP_SAIP; - O = f_fix (); /* FIX (E_NO) */ - break; - case 0120: /* IOP MBYTE/FLT */ - if (cpu_unit.flags & UNIT_IOP) /* MBYTE (I_AZ) */ - goto IOP_MBYTE; - O = f_flt (); /* FLT (E_NO) */ - break; - -/* 2100 (and 21MX) IOP instructions */ - - 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; - 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; - 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; - 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: - MA = ((IR & 017) + BR) & VAMASK; /* IR<3:0> = +offset */ - 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 */ - if (t & SIGN) t = t ^ 020001; } /* old t<0>? xor */ - 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; - t = ReadB (MA); /* xlate */ - WriteB (BR, t); /* store char */ - BR = (BR + 1) & DMASK; /* incr ptr */ - wc = (wc - 1) & DMASK; /* decr cnt */ - WriteW (awc, wc); - if (wc && intrq) { /* more and intr? */ - PC = err_PC; /* stop for now */ - break; } } - break; - case 0220: /* IOP READF (I_NO) */ - 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 PRFEI (I_NO) */ - case 0471: /* IOPX PFREI (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 */ - /* 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 */ - WriteW ((tp - 1) & VAMASK, BR); /* tail link */ - WriteW ((AR + 1) & VAMASK, BR); /* queue tail */ - if (hp != 0) PC = (PC + 1) & VAMASK; /* q not empty? skip */ - break; - 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 */ - if (hp == 0) /* q empty? */ - WriteW ((AR + 1) & VAMASK, BR); /* queue tail */ - 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 */ - WriteW (AR & VAMASK, hp); /* becomes queue head */ - if (hp == 0) /* q now empty? */ - WriteW ((AR + 1) & VAMASK, (AR + 1) & DMASK); - PC = (PC + 1) & VAMASK; } /* skip */ - break; - case 0300: /* IOP SBYTE (I_NO) */ - WriteB (BR, AR); /* store byte */ - BR = (BR + 1) & DMASK; /* incr ptr */ - break; - case 0320: /* IOP LBYTE (I_NO) */ - AR = ReadB (BR); /* load byte */ - BR = (BR + 1) & DMASK; /* incr ptr */ - break; - case 0340: /* IOP REST (I_NO) */ - 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; - 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) */ - 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 (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 - - DMS privilege violation rules are - - load map and CTL set (XMM, XMS, XM*, SY*, US*, PA*, PB*) - - load state or fence and UMAP set (JRS, DJP, DJS, SJP, SJS, UJP, UJS, LF*) - - The 21MX manual is incorrect in stating that M*I, M*W, XS* are privileged */ - - case 0701: /* self test */ - ABREG[absel] = ABREG[absel] ^ DMASK; /* CMA or CMB */ - break; - case 0702: /* MBI (E_NO) */ - AR = AR & ~1; /* force A, B even */ - BR = BR & ~1; - while (XR != 0) { /* loop */ - t = ReadB (AR); /* read curr */ - WriteBA (BR, t); /* write alt */ - AR = (AR + 1) & DMASK; /* incr ptrs */ - BR = (BR + 1) & DMASK; - XR = (XR - 1) & DMASK; - if (XR && intrq && !(AR & 1)) { /* more, int, even? */ - PC = err_PC; /* stop for now */ - break; } } - break; - case 0703: /* MBF (E_NO) */ - AR = AR & ~1; /* force A, B even */ - BR = BR & ~1; - while (XR != 0) { /* loop */ - t = ReadBA (AR); /* read alt */ - WriteB (BR, t); /* write curr */ - AR = (AR + 1) & DMASK; /* incr ptrs */ - BR = (BR + 1) & DMASK; - XR = (XR - 1) & DMASK; - if (XR && intrq && !(AR & 1)) { /* more, int, even? */ - PC = err_PC; /* stop for now */ - break; } } - break; - case 0704: /* MBW (E_NO) */ - AR = AR & ~1; /* force A, B even */ - BR = BR & ~1; - while (XR != 0) { /* loop */ - t = ReadBA (AR); /* read alt */ - WriteBA (BR, t); /* write alt */ - AR = (AR + 1) & DMASK; /* incr ptrs */ - BR = (BR + 1) & DMASK; - XR = (XR - 1) & DMASK; - if (XR && intrq && !(AR & 1)) { /* more, int, even? */ - PC = err_PC; /* stop for now */ - break; } } - break; - case 0705: /* MWI (E_NO) */ - while (XR != 0) { /* loop */ - t = ReadW (AR & VAMASK); /* read curr */ - WriteWA (BR & VAMASK, t); /* write alt */ - AR = (AR + 1) & DMASK; /* incr ptrs */ - BR = (BR + 1) & DMASK; - XR = (XR - 1) & DMASK; - if (XR && intrq) { /* more and intr? */ - PC = err_PC; /* stop for now */ - break; } } - break; - case 0706: /* MWF (E_NO) */ - while (XR != 0) { /* loop */ - t = ReadWA (AR & VAMASK); /* read alt */ - WriteW (BR & VAMASK, t); /* write curr */ - AR = (AR + 1) & DMASK; /* incr ptrs */ - BR = (BR + 1) & DMASK; - XR = (XR - 1) & DMASK; - if (XR && intrq) { /* more and intr? */ - PC = err_PC; /* stop for now */ - break; } } - break; - case 0707: /* MWW (E_NO) */ - while (XR != 0) { /* loop */ - t = ReadWA (AR & VAMASK); /* read alt */ - WriteWA (BR & VAMASK, t); /* write alt */ - AR = (AR + 1) & DMASK; /* incr ptrs */ - BR = (BR + 1) & DMASK; - XR = (XR - 1) & DMASK; - if (XR && intrq) { /* more and intr? */ - PC = err_PC; /* stop for now */ - break; } } - break; - -/* DMS, continued */ - - case 0710: /* SYA, SYB (E_NO) */ - case 0711: /* USA, USB (E_NO) */ - case 0712: /* PAA, PAB (E_NO) */ - case 0713: /* PBA, PBB (E_NO) */ - mapi = (IR & 03) << VA_N_PAG; /* map base */ - if (ABREG[absel] & SIGN) { /* store? */ - for (i = 0; i < MAP_LNT; i++) { - t = dms_rmap (mapi + i); /* map to memory */ - WriteW ((ABREG[absel] + i) & VAMASK, t); } } - else { /* load */ - dms_viol (err_PC, MVI_PRV); /* priv if PRO */ - for (i = 0; i < MAP_LNT; i++) { - t = ReadW ((ABREG[absel] + i) & VAMASK); - dms_wmap (mapi + i, t); } } /* mem to map */ - ABREG[absel] = (ABREG[absel] + MAP_LNT) & DMASK; - break; - case 0714: /* SSM (E_AD) */ - WriteW (MA, dms_upd_sr ()); /* store stat */ - break; - case 0715: /* JRS (E_AA) */ - if (dms_ump) dms_viol (err_PC, MVI_PRV); - t = ReadW (MA); /* get status */ - dms_enb = 0; /* assume off */ - dms_ump = SMAP; - if (t & 0100000) { /* set enable? */ - dms_enb = 1; - if (t & 0040000) dms_ump = UMAP; } /* set/clr usr */ - PCQ_ENTRY; /* save old PC */ - PC = M1; /* jump */ - ion_defer = 1; /* defer intr */ - break; - -/* DMS, continued */ - - case 0700: case 0720: /* XMM (E_NO) */ - if (XR == 0) break; /* nop? */ - while (XR != 0) { /* loop */ - if (XR & SIGN) { /* store? */ - t = dms_rmap (AR); /* map to mem */ - WriteW (BR & VAMASK, t); - XR = (XR + 1) & DMASK; } - else { /* load */ - dms_viol (err_PC, MVI_PRV); /* priv if PRO */ - t = ReadW (BR & VAMASK); /* mem to map */ - dms_wmap (AR, t); - XR = (XR - 1) & DMASK; } - AR = (AR + 1) & DMASK; - BR = (BR + 1) & DMASK; - if (intrq && ((XR & 0xF) == 0xF)) { /* intr, cnt4 = F? */ - PC = err_PC; /* stop for now */ - break; } } - break; - case 0721: /* XMS (E_NO) */ - if ((XR & SIGN) || (XR == 0)) break; /* nop? */ - dms_viol (err_PC, MVI_PRV); /* priv if PRO */ - while (XR != 0) { - dms_wmap (AR, BR); /* AR to map */ - XR = (XR - 1) & DMASK; - AR = (AR + 1) & DMASK; - BR = (BR + 1) & DMASK; - if (intrq && ((XR & 0xF) == 0xF)) { /* intr, cnt4 = F? */ - PC = err_PC; - break; } } - break; - case 0722: /* XMA, XMB (E_NO) */ - dms_viol (err_PC, MVI_PRV); /* priv if PRO */ - if (ABREG[absel] & 0100000) mapi = UMAP; - else mapi = SMAP; - if (ABREG[absel] & 0000001) mapj = PBMAP; - else mapj = PAMAP; - for (i = 0; i < MAP_LNT; i++) { - t = dms_rmap (mapi + i); /* read map */ - dms_wmap (mapj + i, t); } /* write map */ - break; - case 0724: /* XLA, XLB (E_AD) */ - ABREG[absel] = ReadWA (MA); /* load alt */ - break; - case 0725: /* XSA, XSB (E_AD) */ - WriteWA (MA, ABREG[absel]); /* store alt */ - break; - case 0726: /* XCA, XCB (E_AD) */ - if (ABREG[absel] != ReadWA (MA)) /* compare alt */ - PC = (PC + 1) & VAMASK; - break; - case 0727: /* LFA, LFB (E_NO) */ - if (dms_ump) dms_viol (err_PC, MVI_PRV); - dms_sr = (dms_sr & ~(MST_FLT | MST_FENCE)) | - (ABREG[absel] & (MST_FLT | MST_FENCE)); - break; - -/* DMS, continued */ - - case 0730: /* RSA, RSB (E_NO) */ - ABREG[absel] = dms_upd_sr (); /* save stat */ - break; - case 0731: /* RVA, RVB (E_NO) */ - ABREG[absel] = dms_vr; /* save viol */ - break; - case 0732: /* DJP (E_AD) */ - if (dms_ump) dms_viol (err_PC, MVI_PRV); - mp_dms_jmp (MA); /* validate jump addr */ - PCQ_ENTRY; /* save curr PC */ - PC = MA; /* new PC */ - dms_enb = 0; /* disable map */ - dms_ump = SMAP; - ion_defer = 1; - break; - case 0733: /* DJS (E_AD) */ - if (dms_ump) dms_viol (err_PC, MVI_PRV); - WriteW (MA, PC); /* store ret addr */ - PCQ_ENTRY; /* save curr PC */ - PC = (MA + 1) & VAMASK; /* new PC */ - dms_enb = 0; /* disable map */ - dms_ump = SMAP; - ion_defer = 1; /* defer intr */ - break; - case 0734: /* SJP (E_AD) */ - if (dms_ump) dms_viol (err_PC, MVI_PRV); - mp_dms_jmp (MA); /* validate jump addr */ - PCQ_ENTRY; /* save curr PC */ - PC = MA; /* jump */ - dms_enb = 1; /* enable system */ - dms_ump = SMAP; - ion_defer = 1; /* defer intr */ - break; - case 0735: /* SJS (E_AD) */ - if (dms_ump) dms_viol (err_PC, MVI_PRV); - t = PC; /* save retn addr */ - PCQ_ENTRY; /* save curr PC */ - PC = (MA + 1) & VAMASK; /* new PC */ - dms_enb = 1; /* enable system */ - dms_ump = SMAP; - WriteW (MA, t); /* store ret addr */ - ion_defer = 1; /* defer intr */ - break; - case 0736: /* UJP (E_AD) */ - if (dms_ump) dms_viol (err_PC, MVI_PRV); - mp_dms_jmp (MA); /* validate jump addr */ - PCQ_ENTRY; /* save curr PC */ - PC = MA; /* jump */ - dms_enb = 1; /* enable user */ - dms_ump = UMAP; - ion_defer = 1; /* defer intr */ - break; - case 0737: /* UJS (E_AD) */ - if (dms_ump) dms_viol (err_PC, MVI_PRV); - t = PC; /* save retn addr */ - PCQ_ENTRY; /* save curr PC */ - PC = (MA + 1) & VAMASK; /* new PC */ - dms_enb = 1; /* enable user */ - dms_ump = UMAP; - WriteW (MA, t); /* store ret addr */ - ion_defer = 1; /* defer intr */ - break; - -/* Index register instructions */ - - case 0740: /* SAX, SBX (E_AD) */ - MA = (MA + XR) & VAMASK; /* indexed addr */ - WriteW (MA, ABREG[absel]); /* store */ - break; - case 0741: /* CAX, CBX (E_NO) */ - XR = ABREG[absel]; /* copy to XR */ - break; - case 0742: /* LAX, LBX (E_AD) */ - MA = (MA + XR) & VAMASK; /* indexed addr */ - ABREG[absel] = ReadW (MA); /* load */ - break; - case 0743: /* STX (E_AD) */ - WriteW (MA, XR); /* store XR */ - break; - case 0744: /* CXA, CXB (E_NO) */ - ABREG[absel] = XR; /* copy from XR */ - break; - case 0745: /* LDX (E_AD)*/ - XR = ReadW (MA); /* load XR */ - break; - case 0746: /* ADX (E_AD) */ - v1 = ReadW (MA); /* add to XR */ - t = XR + v1; - if (t > DMASK) E = 1; /* set E, O */ - if (((~XR ^ v1) & (XR ^ t)) & SIGN) O = 1; - XR = t & DMASK; - break; - case 0747: /* XAX, XBX (E_NO) */ - t = XR; /* exchange XR */ - XR = ABREG[absel]; - ABREG[absel] = t; - break; - case 0750: /* SAY, SBY (E_AD) */ - MA = (MA + YR) & VAMASK; /* indexed addr */ - WriteW (MA, ABREG[absel]); /* store */ - break; - case 0751: /* CAY, CBY (E_NO) */ - YR = ABREG[absel]; /* copy to YR */ - break; - case 0752: /* LAY, LBY (E_AD) */ - MA = (MA + YR) & VAMASK; /* indexed addr */ - ABREG[absel] = ReadW (MA); /* load */ - break; - case 0753: /* STY (E_AD) */ - WriteW (MA, YR); /* store YR */ - break; - case 0754: /* CYA, CYB (E_NO) */ - ABREG[absel] = YR; /* copy from YR */ - break; - case 0755: /* LDY (E_AD) */ - YR = ReadW (MA); /* load YR */ - break; - case 0756: /* ADY (E_AD) */ - v1 = ReadW (MA); /* add to YR */ - t = YR + v1; - if (t > DMASK) E = 1; /* set E, O */ - if (((~YR ^ v1) & (YR ^ t)) & SIGN) O = 1; - YR = t & DMASK; - break; - case 0757: /* XAY, XBY (E_NO) */ - t = YR; /* exchange YR */ - YR = ABREG[absel]; - ABREG[absel] = t; - break; - case 0760: /* ISX (E_NO) */ - XR = (XR + 1) & DMASK; /* incr XR */ - if (XR == 0) PC = (PC + 1) & VAMASK; /* skip if zero */ - break; - case 0761: /* DSX (E_NO) */ - XR = (XR - 1) & DMASK; /* decr XR */ - if (XR == 0) PC = (PC + 1) & VAMASK; /* skip if zero */ - break; - case 0762: /* JLY (E_AD) */ - mp_dms_jmp (MA); /* validate jump addr */ - PCQ_ENTRY; - YR = PC; /* ret addr to YR */ - PC = MA; /* jump */ - break; - case 0770: /* ISY (E_NO) */ - YR = (YR + 1) & DMASK; /* incr YR */ - if (YR == 0) PC = (PC + 1) & VAMASK; /* skip if zero */ - break; - case 0771: /* DSY (E_NO) */ - YR = (YR - 1) & DMASK; /* decr YR */ - if (YR == 0) PC = (PC + 1) & VAMASK; /* skip if zero */ - break; - case 0772: /* JPY (E_NO) */ - MA = (ReadW (PC) + YR) & VAMASK; /* index, no indir */ - PC = (PC + 1) & VAMASK; - mp_dms_jmp (MA); /* validate jump addr */ - PCQ_ENTRY; - PC = MA; /* jump */ - break; - -/* Byte instructions */ - - case 0763: /* LBT (E_NO) */ - AR = ReadB (BR); /* load byte */ - BR = (BR + 1) & DMASK; /* incr ptr */ - break; - case 0764: /* SBT (E_NO) */ - WriteB (BR, AR); /* store byte */ - break; - IOP_MBYTE: /* IOP MBYTE (I_AZ) */ - if (wc & SIGN) break; /* must be positive */ - case 0765: /* MBT (E_AZ) */ - while (wc != 0) { /* while count */ - WriteW (awc, wc); /* for abort */ - t = ReadB (AR); /* move byte */ - WriteB (BR, t); - AR = (AR + 1) & DMASK; /* incr src */ - BR = (BR + 1) & DMASK; /* incr dst */ - wc = (wc - 1) & DMASK; /* decr cnt */ - if (intrq && wc) { /* intr, more to do? */ - PC = err_PC; /* back up PC */ - break; } } /* take intr */ - WriteW (awc, wc); /* clean up inline */ - break; - case 0766: /* CBT (E_AZ) */ - while (wc != 0) { /* while count */ - WriteW (awc, wc); /* for abort */ - v1 = ReadB (AR); /* get src1 */ - v2 = ReadB (BR); /* get src2 */ - if (v1 != v2) { /* compare */ - PC = (PC + 1 + (v1 > v2)) & VAMASK; - BR = (BR + wc) & DMASK; /* update BR */ - wc = 0; /* clr interim */ - break; } - AR = (AR + 1) & DMASK; /* incr src1 */ - BR = (BR + 1) & DMASK; /* incr src2 */ - wc = (wc - 1) & DMASK; /* decr cnt */ - if (intrq && wc) { /* intr, more to do? */ - PC = err_PC; /* back up PC */ - break; } } /* take intr */ - WriteW (awc, wc); /* clean up inline */ - break; - case 0767: /* SFB (E_NO) */ - v1 = AR & 0377; /* test byte */ - v2 = (AR >> 8) & 0377; /* term byte */ - for (;;) { /* scan */ - t = ReadB (BR); /* read byte */ - if (t == v1) break; /* test match? */ - BR = (BR + 1) & DMASK; - if (t == v2) { /* term match? */ - PC = (PC + 1) & VAMASK; - break; } - if (intrq) { /* int pending? */ - PC = err_PC; /* back up PC */ - break; } } /* take intr */ - break; - -/* Bit, word instructions */ - - case 0773: /* SBS (E_AA) */ - WriteW (M1, M[M1] | M [MA]); /* set bit */ - break; - case 0774: /* CBS (E_AA) */ - WriteW (M1, M[M1] & ~M[MA]); /* clear bit */ - break; - case 0775: /* TBS (E_AA) */ - if ((M[MA] & M[M1]) != M[MA]) /* test bit */ - PC = (PC + 1) & VAMASK; - break; - case 0776: /* CMW (E_AZ) */ - while (wc != 0) { /* while count */ - WriteW (awc, wc); /* for abort */ - v1 = ReadW (AR & VAMASK); /* first op */ - v2 = ReadW (BR & VAMASK); /* second op */ - sop1 = (int32) SEXT (v1); /* signed */ - sop2 = (int32) SEXT (v2); - if (sop1 != sop2) { /* compare */ - PC = (PC + 1 + (sop1 > sop2)) & VAMASK; - BR = (BR + wc) & DMASK; /* update BR */ - wc = 0; /* clr interim */ - break; } - AR = (AR + 1) & DMASK; /* incr src1 */ - BR = (BR + 1) & DMASK; /* incr src2 */ - wc = (wc - 1) & DMASK; /* decr cnt */ - if (intrq && wc) { /* intr, more to do? */ - PC = err_PC; /* back up PC */ - break; } } /* take intr */ - WriteW (awc, wc); /* clean up inline */ - break; - case 0200: /* IOP WMOVE (I_AZ) */ - if (wc & SIGN) break; /* must be positive */ - case 0777: /* MVW (E_AZ) */ - while (wc != 0) { /* while count */ - WriteW (awc, wc); /* for abort */ - t = ReadW (AR & VAMASK); /* move word */ - WriteW (BR & VAMASK, t); - AR = (AR + 1) & DMASK; /* incr src */ - BR = (BR + 1) & DMASK; /* incr dst */ - wc = (wc - 1) & DMASK; /* decr cnt */ - if (intrq && wc) { /* intr, more to do? */ - PC = err_PC; /* back up PC */ - break; } } /* take intr */ - WriteW (awc, wc); /* clean up inline */ - break; - default: /* all others NOP */ - break; } /* end case ext */ - break; } /* end case IR */ - -if (reason == STOP_INDINT) { /* indirect intr? */ - PC = err_PC; /* back out of inst */ - ion_defer = 0; /* clear defer */ - reason = 0; } /* continue */ -} /* end while */ - -/* Simulation halted */ - -saved_AR = AR & DMASK; -saved_BR = BR & DMASK; -for (i = 0; dptr = sim_devices[i]; i++) { /* loop thru dev */ - dibp = (DIB *) dptr->ctxt; /* get DIB */ - if (dibp) { /* exist? */ - dev = dibp->devno; - dibp->cmd = CMD (dev); - dibp->ctl = CTL (dev); - dibp->flg = FLG (dev); - dibp->fbf = FBF (dev); } } -pcq_r->qptr = pcq_p; /* update pc q ptr */ -return reason; -} - -/* Effective address calculation */ - -t_stat Ea (uint32 IR, uint32 *addr, uint32 irq) -{ -uint32 i, MA; - -MA = IR & (I_IA | I_DISP); /* ind + disp */ -if (IR & I_CP) MA = ((PC - 1) & I_PAGENO) | MA; /* current page? */ -for (i = 0; (i < ind_max) && (MA & I_IA); i++) { /* resolve multilevel */ - if ((i >= 2) && irq && /* >3 levels, int req, */ - (cpu_unit.flags & UNIT_MPR)) /* mprot installed? */ - return STOP_INDINT; /* break out */ - MA = ReadW (MA & VAMASK); } -if (i >= ind_max) return STOP_IND; /* indirect loop? */ -*addr = MA; -return SCPE_OK; -} - -/* Effective address, two words */ - -t_stat Ea1 (uint32 *addr, uint32 irq) -{ -uint32 i, MA; - -MA = ReadW (PC); /* get next address */ -PC = (PC + 1) & VAMASK; -for (i = 0; (i < ind_max) && (MA & I_IA); i++) { /* resolve multilevel */ - if ((i >= 2) && irq && /* >3 levels, int req, */ - (cpu_unit.flags & UNIT_MPR)) /* mprot installed? */ - return STOP_INDINT; /* break out */ - MA = ReadW (MA & VAMASK); } -if (i >= ind_max) return STOP_IND; /* indirect loop? */ -*addr = MA; -return SCPE_OK; -} - -/* Shift micro operation */ - -uint32 shift (uint32 t, uint32 flag, uint32 op) -{ -uint32 oldE; - -op = op & 07; /* get shift op */ -if (flag) { /* enabled? */ - switch (op) { /* case on operation */ - case 00: /* signed left shift */ - return ((t & SIGN) | ((t << 1) & 077777)); - case 01: /* signed right shift */ - return ((t & SIGN) | (t >> 1)); - case 02: /* rotate left */ - return (((t << 1) | (t >> 15)) & DMASK); - case 03: /* rotate right */ - return (((t >> 1) | (t << 15)) & DMASK); - case 04: /* left shift, 0 sign */ - return ((t << 1) & 077777); - case 05: /* ext right rotate */ - oldE = E; - E = t & 1; - return ((t >> 1) | (oldE << 15)); - case 06: /* ext left rotate */ - oldE = E; - E = (t >> 15) & 1; - return (((t << 1) | oldE) & DMASK); - case 07: /* rotate left four */ - return (((t << 4) | (t >> 12)) & DMASK); - } /* end case */ - } /* end if */ -if (op == 05) E = t & 1; /* disabled ext rgt rot */ -if (op == 06) E = (t >> 15) & 1; /* disabled ext lft rot */ -return t; /* input unchanged */ -} - -/* IO instruction decode */ - -t_stat iogrp (uint32 ir, uint32 iotrap) -{ -uint32 dev, sop, iodata, ab; - -ab = (ir & I_AB)? 1: 0; /* get A/B select */ -dev = ir & I_DEVMASK; /* get device */ -sop = I_GETIOOP (ir); /* get subopcode */ -if (!iotrap && CTL (PRO) && ((sop == ioHLT) || (dev != OVF))) { /* protected? */ - if (sop == ioLIX) ABREG[ab] = 0; /* A/B writes anyway */ - ABORT (ABORT_PRO); } -iodata = devdisp (dev, sop, ir, ABREG[ab]); /* process I/O */ -ion_defer = defer_tab[sop]; /* set defer */ -if ((sop == ioMIX) || (sop == ioLIX)) /* store ret data */ - ABREG[ab] = iodata & DMASK; -if (sop == ioHLT) return STOP_HALT; /* halt? */ -return (iodata >> IOT_V_REASON); /* return status */ -} - -/* Device dispatch */ - -uint32 devdisp (uint32 devno, uint32 inst, uint32 IR, uint32 dat) -{ -if (dtab[devno]) return dtab[devno] (inst, IR, dat); -else return nulio (inst, IR, dat); -} - -/* Calculate DMA requests */ - -uint32 calc_dma (void) -{ -uint32 r = 0; - -if (CMD (DMA0) && FLG (dmac[0].cw1 & I_DEVMASK)) /* check DMA0 cycle */ - r = r | DMAR0; -if (CMD (DMA1) && FLG (dmac[1].cw1 & I_DEVMASK)) /* check DMA1 cycle */ - r = r | DMAR1; -return r; -} - -/* Calculate interrupt requests - - This routine takes into account all the relevant state of the - interrupt system: ion, dev_flg, dev_fbf, and dev_ctl. - - 1. dev_flg & dev_ctl determines the end of the priority grant. - The break in the chain will occur at the first device for - which dev_flg & dev_ctl is true. This is determined by - AND'ing the set bits with their 2's complement; only the low - order (highest priority) bit will differ. 1 less than - that, or'd with the single set bit itself, is the mask of - possible interrupting devices. If ION is clear, only devices - 4 and 5 are eligible to interrupt. - 2. dev_flg & dev_ctl & dev_fbf determines the outstanding - interrupt requests. All three bits must be on for a device - to request an interrupt. This is the masked under the - result from #1 to determine the highest priority interrupt, - if any. - */ - -uint32 calc_int (void) -{ -int32 j, lomask, mask[2], req[2]; - -lomask = dev_flg[0] & dev_ctl[0] & ~M_NXDEV; /* start chain calc */ -req[0] = lomask & dev_fbf[0]; /* calc requests */ -lomask = lomask & (-lomask); /* chain & -chain */ -mask[0] = lomask | (lomask - 1); /* enabled devices */ -req[0] = req[0] & mask[0]; /* highest request */ -if (ion) { /* ion? */ - if (lomask == 0) { /* no break in chn? */ - mask[1] = dev_flg[1] & dev_ctl[1]; /* do all devices */ - req[1] = mask[1] & dev_fbf[1]; - mask[1] = mask[1] & (-mask[1]); - mask[1] = mask[1] | (mask[1] - 1); - req[1] = req[1] & mask[1]; } - else req[1] = 0; } -else { req[0] = req[0] & (INT_M (PWR) | INT_M (PRO)); - req[1] = 0; } -if (req[0]) { /* if low request */ - for (j = 0; j < 32; j++) { /* find dev # */ - if (req[0] & INT_M (j)) return j; } } -if (req[1]) { /* if hi request */ - for (j = 0; j < 32; j++) { /* find dev # */ - if (req[1] & INT_M (j)) return (32 + j); } } -return 0; -} - -/* Memory access routines */ - -uint8 ReadB (uint32 va) -{ -int32 pa; - -if (dms_enb) pa = dms (va >> 1, dms_ump, RD); -else pa = va >> 1; -if (va & 1) return (M[pa] & 0377); -else return ((M[pa] >> 8) & 0377); -} - -uint8 ReadBA (uint32 va) -{ -uint32 pa; - -if (dms_enb) pa = dms (va >> 1, dms_ump ^ MAP_LNT, RD); -else pa = va >> 1; -if (va & 1) return (M[pa] & 0377); -else return ((M[pa] >> 8) & 0377); -} - -uint16 ReadW (uint32 va) -{ -uint32 pa; - -if (dms_enb) pa = dms (va, dms_ump, RD); -else pa = va; -return M[pa]; -} - -uint16 ReadWA (uint32 va) -{ -uint32 pa; - -if (dms_enb) pa = dms (va, dms_ump ^ MAP_LNT, RD); -else pa = va; -return M[pa]; -} - -uint32 ReadF (uint32 va) -{ -uint32 t = ReadW (va); -uint32 t1 = ReadW ((va + 1) & VAMASK); -return (t << 16) | t1; -} - -uint16 ReadIO (uint32 va, uint32 map) -{ -uint32 pa; - -if (dms_enb) pa = dms_io (va, map); -else pa = va; -return M[pa]; -} - -/* Memory protection test for writes */ - -#define MP_TEST(x) (CTL (PRO) && ((x) > 1) && ((x) < mp_fence)) - -void WriteB (uint32 va, uint32 dat) -{ -uint32 pa; - -if (dms_enb) pa = dms (va >> 1, dms_ump, WR); -else { if (MP_TEST (va >> 1)) ABORT (ABORT_PRO); - pa = va >> 1; } -if (MEM_ADDR_OK (pa)) { - if (va & 1) M[pa] = (M[pa] & 0177400) | (dat & 0377); - else M[pa] = (M[pa] & 0377) | ((dat & 0377) << 8); } -return; -} - -void WriteBA (uint32 va, uint32 dat) -{ -uint32 pa; - -if (dms_enb) { - dms_viol (va >> 1, MVI_WPR); /* viol if prot */ - pa = dms (va >> 1, dms_ump ^ MAP_LNT, WR); } -else { if (MP_TEST (va >> 1)) ABORT (ABORT_PRO); - pa = va >> 1; } -if (MEM_ADDR_OK (pa)) { - if (va & 1) M[pa] = (M[pa] & 0177400) | (dat & 0377); - else M[pa] = (M[pa] & 0377) | ((dat & 0377) << 8); } -return; -} - -void WriteW (uint32 va, uint32 dat) -{ -uint32 pa; - -if (dms_enb) pa = dms (va, dms_ump, WR); -else { if (MP_TEST (va)) ABORT (ABORT_PRO); - pa = va; } -if (MEM_ADDR_OK (pa)) M[pa] = dat; -return; -} - -void WriteWA (uint32 va, uint32 dat) -{ -int32 pa; - -if (dms_enb) { - dms_viol (va, MVI_WPR); /* viol if prot */ - pa = dms (va, dms_ump ^ MAP_LNT, WR); } -else { if (MP_TEST (va)) ABORT (ABORT_PRO); - pa = va; } -if (MEM_ADDR_OK (pa)) M[pa] = dat; -return; -} - -void WriteIO (uint32 va, uint32 dat, uint32 map) -{ -uint32 pa; - -if (dms_enb) pa = dms_io (va, map); -else pa = va; -if (MEM_ADDR_OK (pa)) M[pa] = dat; -return; -} - -/* DMS relocation for CPU access */ - -uint32 dms (uint32 va, uint32 map, uint32 prot) -{ -uint32 pgn, mpr; - -if (va <= 1) return va; /* A, B */ -pgn = VA_GETPAG (va); /* get page num */ -if (pgn == 0) { /* base page? */ - uint32 dms_fence = dms_sr & MST_FENCE; /* get fence value */ - if ((dms_sr & MST_FLT)? /* check unmapped */ - (va >= dms_fence): /* 1B10: >= fence */ - (va < dms_fence)) { /* 0B10: < fence */ - if (prot == WR) dms_viol (va, MVI_BPG); /* if W, viol */ - return va; } } /* no mapping */ -mpr = dms_map[map + pgn]; /* get map reg */ -if (mpr & prot) dms_viol (va, prot << (MVI_V_WPR - MAPA_V_WPR)); -return (PA_GETPAG (mpr) | VA_GETOFF (va)); -} - -/* DMS relocation for IO access */ - -uint32 dms_io (uint32 va, uint32 map) -{ -uint32 pgn, mpr; - -if (va <= 1) return va; /* A, B */ -pgn = VA_GETPAG (va); /* get page num */ -if (pgn == 0) { /* base page? */ - uint32 dms_fence = dms_sr & MST_FENCE; /* get fence value */ - if ((dms_sr & MST_FLT)? /* check unmapped */ - (va >= dms_fence): /* 1B10: >= fence */ - (va < dms_fence)) { /* 0B10: < fence */ - return va; } } /* no mapping */ -mpr = dms_map[map + pgn]; /* get map reg */ -return (PA_GETPAG (mpr) | VA_GETOFF (va)); -} - -/* DMS relocation for console access */ - -uint32 dms_cons (uint32 va, int32 sw) -{ -if (sw & SWMASK ("V")) return dms_io (va, dms_ump); -if (sw & SWMASK ("S")) return dms_io (va, SMAP); -if (sw & SWMASK ("U")) return dms_io (va, UMAP); -if (sw & SWMASK ("P")) return dms_io (va, PAMAP); -if (sw & SWMASK ("Q")) return dms_io (va, PBMAP); -return va; -} - -/* Mem protect and DMS validation for jumps */ - -void mp_dms_jmp (uint32 va) -{ -uint32 pgn = VA_GETPAG (va); /* get page num */ - -if ((pgn == 0) && (va > 1)) { /* base page? */ - uint32 dms_fence = dms_sr & MST_FENCE; /* get fence value */ - if ((dms_sr & MST_FLT)? /* check unmapped */ - (va >= dms_fence): /* 1B10: >= fence */ - (va < dms_fence)) { /* 0B10: < fence */ - dms_viol (va, MVI_BPG); /* if W, viol */ - return; } } /* PRO not set */ -if (CTL (PRO) && (va < mp_fence)) ABORT (ABORT_PRO); /* base page MPR */ -return; -} - -/* DMS read and write maps */ - -uint16 dms_rmap (uint32 mapi) -{ -int32 t; - -mapi = mapi & MAP_MASK; -t = (((dms_map[mapi] >> VA_N_OFF) & PA_M_PAG) | - ((dms_map[mapi] & (RD | WR)) << (MAPM_V_WPR - MAPA_V_WPR))); -return (uint16) t; -} - -void dms_wmap (uint32 mapi, uint32 dat) -{ -mapi = mapi & MAP_MASK; -dms_map[mapi] = ((dat & PA_M_PAG) << VA_N_OFF) | - ((dat >> (MAPM_V_WPR - MAPA_V_WPR)) & (RD | WR)); -return; -} - -/* DMS violation */ - -void dms_viol (uint32 va, uint32 st) -{ -dms_vr = st | VA_GETPAG (va) | - ((st & (MVI_RPR | MVI_WPR))? MVI_MEB: 0) | /* set MEB */ - (dms_enb? MVI_MEM: 0) | /* set MEM */ - (dms_ump? MVI_UMP: 0); /* set UMAP */ -if (CTL (PRO)) { /* protected? */ - mp_mevff = 1; /* signal dms */ - ABORT (ABORT_PRO); } /* abort */ -return; -} - -/* DMS update status */ - -uint32 dms_upd_sr (void) -{ -dms_sr = dms_sr & ~(MST_ENB | MST_UMP | MST_PRO); -if (dms_enb) dms_sr = dms_sr | MST_ENB; -if (dms_ump) dms_sr = dms_sr | MST_UMP; -if (CTL (PRO)) dms_sr = dms_sr | MST_PRO; -return dms_sr; -} - -/* Device 0 (CPU) I/O routine */ - -int32 cpuio (int32 inst, int32 IR, int32 dat) -{ -int i; - -switch (inst) { /* case on opcode */ -case ioFLG: /* flag */ - ion = (IR & I_HC)? 0: 1; /* interrupts off/on */ - return dat; -case ioSFC: /* skip flag clear */ - if (!ion) PC = (PC + 1) & VAMASK; - return dat; -case ioSFS: /* skip flag set */ - if (ion) PC = (PC + 1) & VAMASK; - return dat; -case ioLIX: /* load */ - dat = 0; /* returns 0 */ - break; -case ioCTL: /* control */ - if (IR & I_CTL) { /* =CLC 02,03,06..77 */ - devdisp (DMALT0, inst, I_CTL + DMALT0, 0); - devdisp (DMALT1, inst, I_CTL + DMALT1, 0); - for (i = 6; i <= I_DEVMASK; i++) - devdisp (i, inst, I_CTL + i, 0); } - break; -default: - break; } -if (IR & I_HC) ion = 0; /* HC option */ -return dat; -} - -/* Device 1 (overflow) I/O routine */ - -int32 ovfio (int32 inst, int32 IR, int32 dat) -{ -switch (inst) { /* case on opcode */ -case ioFLG: /* flag */ - O = (IR & I_HC)? 0: 1; /* clear/set overflow */ - return dat; -case ioSFC: /* skip flag clear */ - if (!O) PC = (PC + 1) & VAMASK; - break; /* can clear flag */ -case ioSFS: /* skip flag set */ - if (O) PC = (PC + 1) & VAMASK; - break; /* can clear flag */ -case ioMIX: /* merge */ - dat = dat | SR; - break; -case ioLIX: /* load */ - dat = SR; - break; -case ioOTX: /* output */ - SR = dat; - break; -default: - break; } -if (IR & I_HC) O = 0; /* HC option */ -return dat; -} - -/* Device 4 (power fail) I/O routine */ - -int32 pwrio (int32 inst, int32 IR, int32 dat) -{ -switch (inst) { /* case on opcode */ -case ioMIX: /* merge */ - dat = dat | intaddr; - break; -case ioLIX: /* load */ - dat = intaddr; - break; -default: - break; } -return dat; -} - -/* Device 5 (memory protect) I/O routine */ - -int32 proio (int32 inst, int32 IR, int32 dat) -{ -if ((cpu_unit.flags & UNIT_MPR) == 0) /* not installed? */ - return nulio (inst, IR, dat); /* non-existent dev */ -switch (inst) { /* case on opcode */ -case ioSFC: /* skip flag clear */ - if (FLG (PRO) && !mp_mevff) /* skip if mem prot */ - PC = (PC + 1) & VAMASK; - return dat; -case ioSFS: /* skip flag set */ - if (FLG (PRO) && mp_mevff) /* skip if DMS */ - PC = (PC + 1) & VAMASK; - return dat; -case ioMIX: /* merge */ - dat = dat | mp_viol; - break; -case ioLIX: /* load */ - dat = mp_viol; - 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 */ - setCTL (PRO); - dms_vr = 0; - mp_evrff = 1; /* allow mp_viol upd */ - mp_mevff = 0; } /* clear DMS flag */ - break; -default: - break; } -if (IR & I_HC) { clrFLG (PRO); } /* HC option */ -return dat; -} - -/* Devices 2,3 (secondary DMA) I/O routine */ - -int32 dmsio (int32 inst, int32 IR, int32 dat) -{ -int32 ch; - -ch = IR & 1; /* get channel num */ -switch (inst) { /* case on opcode */ -case ioMIX: /* merge */ - dat = dat | dmac[ch].cw3; - break; -case ioLIX: /* load */ - dat = dmac[ch].cw3; - break; -case ioOTX: /* output */ - if (CTL (DMALT0 + ch)) dmac[ch].cw3 = dat; - else dmac[ch].cw2 = dat; - break; -case ioCTL: /* control clear/set */ - if (IR & I_CTL) { clrCTL (DMALT0 + ch); } /* CLC */ - else { setCTL (DMALT0 + ch); } /* STC */ - break; -default: - break; } -return dat; -} - -/* Devices 6,7 (primary DMA) I/O routine */ - -int32 dmpio (int32 inst, int32 IR, int32 dat) -{ -int32 ch; - -ch = IR & 1; /* get channel number */ -switch (inst) { /* case on opcode */ -case ioFLG: /* flag */ - if ((IR & I_HC) == 0) { /* set->abort */ - setFLG (DMA0 + ch); /* set flag */ - clrCMD (DMA0 + ch); } /* clr cmd */ - break; -case ioSFC: /* skip flag clear */ - if (FLG (DMA0 + ch) == 0) PC = (PC + 1) & VAMASK; - return dat; -case ioSFS: /* skip flag set */ - if (FLG (DMA0 + ch) != 0) PC = (PC + 1) & VAMASK; - return dat; -case ioMIX: case ioLIX: /* load, merge */ - dat = DMASK; - break; -case ioOTX: /* output */ - dmac[ch].cw1 = dat; - break; -case ioCTL: /* control */ - if (IR & I_CTL) { clrCTL (DMA0 + ch); } /* CLC: cmd unchgd */ - else { /* STC */ - setCTL (DMA0 + ch); /* set ctl, cmd */ - setCMD (DMA0 + ch); } - break; -default: - break; } -if (IR & I_HC) { clrFLG (DMA0 + ch); } /* HC option */ -return dat; -} - -/* DMA cycle routine - - The last cycle (word count reaches 0) logic is quite tricky. - Input cases: - - CLC requested: issue CLC - Output cases: - - neither STC nor CLC requested: issue CLF - - CLC requested but not STC: issue CLC,C - - STC requested but not CLC: issue STC,C - - STC and CLC both requested: issue STC,C and CLC,C -*/ - -void dma_cycle (uint32 ch, uint32 map) -{ -int32 temp, dev, MA; -int32 inp = dmac[ch].cw2 & DMA2_OI; /* input flag */ - -dev = dmac[ch].cw1 & I_DEVMASK; /* get device */ -MA = dmac[ch].cw2 & VAMASK; /* get mem addr */ -if (inp) { /* input? */ - temp = devdisp (dev, ioLIX, dev, 0); /* do LIA dev */ - WriteIO (MA, temp, map); } /* store data */ -else { temp = ReadIO (MA, map); /* read data */ - devdisp (dev, ioOTX, dev, temp); } /* do OTA dev */ -dmac[ch].cw2 = (dmac[ch].cw2 & DMA2_OI) | ((dmac[ch].cw2 + 1) & VAMASK); -dmac[ch].cw3 = (dmac[ch].cw3 + 1) & DMASK; /* incr wcount */ -if (dmac[ch].cw3) { /* more to do? */ - if (dmac[ch].cw1 & DMA1_STC) /* if STC flag, */ - devdisp (dev, ioCTL, I_HC + dev, 0); /* do STC,C dev */ - else devdisp (dev, ioFLG, I_HC + dev, 0); } /* else CLF dev */ -else { if (inp) { /* last cycle, input? */ - if (dmac[ch].cw1 & DMA1_CLC) /* CLC at end? */ - devdisp (dev, ioCTL, I_CTL + dev, 0); /* yes */ - } /* end input */ - else { /* output */ - devdisp (dev, ioFLG, I_HC + dev, 0); /* clear flag */ - if (dmac[ch].cw1 & DMA1_STC) /* if STC flag, */ - devdisp (dev, ioCTL, dev, 0); /* do STC dev */ - if (dmac[ch].cw1 & DMA1_CLC) /* CLC at end? */ - devdisp (dev, ioCTL, I_CTL + dev, 0); /* yes */ - } /* end output */ - setFLG (DMA0 + ch); /* set DMA flg */ - clrCMD (DMA0 + ch); } /* clr DMA cmd */ -return; -} - -/* Unimplemented device routine */ - -int32 nulio (int32 inst, int32 IR, int32 dat) -{ -switch (inst) { /* case on opcode */ -case ioSFC: /* skip flag clear */ - PC = (PC + 1) & VAMASK; - return (stop_dev << IOT_V_REASON) | dat; -case ioSFS: /* skip flag set */ - return (stop_dev << IOT_V_REASON) | dat; -default: - break; } -if (IR & I_HC) { clrFLG (IR & I_DEVMASK); } /* HC option */ -return (stop_dev << IOT_V_REASON) | dat; -} - -/* Reset routines */ - -t_stat cpu_reset (DEVICE *dptr) -{ -E = 0; -O = 0; -ion = ion_defer = 0; -clrCMD (PWR); -clrCTL (PWR); -clrFLG (PWR); -clrFBF (PWR); -clrCMD (PRO); -clrCTL (PRO); -clrFLG (PRO); -clrFBF (PRO); -mp_fence = 0; /* init mprot */ -mp_viol = 0; -mp_mevff = 0; -mp_evrff = 1; -dms_enb = dms_ump = 0; /* init DMS */ -dms_sr = 0; -dms_vr = 0; -pcq_r = find_reg ("PCQ", NULL, dptr); -sim_brk_types = sim_brk_dflt = SWMASK ('E'); -if (M == NULL) M = calloc (PASIZE, sizeof (unsigned int16)); -if (M == NULL) return SCPE_MEM; -if (pcq_r) pcq_r->qptr = 0; -else return SCPE_IERR; -return SCPE_OK; -} - -t_stat dma0_reset (DEVICE *tptr) -{ -clrCMD (DMA0); -clrCTL (DMA0); -setFLG (DMA0); -dmac[0].cw1 = dmac[0].cw2 = dmac[0].cw3 = 0; -return SCPE_OK; -} - -t_stat dma1_reset (DEVICE *tptr) -{ -clrCMD (DMA1); -clrCTL (DMA1); -setFLG (DMA1); -dmac[1].cw1 = dmac[1].cw2 = dmac[1].cw3 = 0; -return SCPE_OK; -} - -/* Memory examine */ - -t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) -{ -int32 d; - -if (addr >= MEMSIZE) return SCPE_NXM; -addr = dms_cons (addr, sw); -if (addr == 0) d = saved_AR; -else if (addr == 1) d = saved_BR; -else d = M[addr]; -if (vptr != NULL) *vptr = d & DMASK; -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; -addr = dms_cons (addr, sw); -if (addr == 0) saved_AR = val & DMASK; -else if (addr == 1) saved_BR = val & DMASK; -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; -uint32 i; - -if ((val <= 0) || (val > PASIZE) || ((val & 07777) != 0) || - (!(uptr->flags & UNIT_21MX) && (val > 32768))) - 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 < PASIZE; i++) M[i] = 0; -return SCPE_OK; -} - -/* Set device number */ - -t_stat hp_setdev (UNIT *uptr, int32 num, char *cptr, void *desc) -{ -DEVICE *dptr = (DEVICE *) desc; -DIB *dibp; -int32 i, newdev; -t_stat r; - -if (cptr == NULL) return SCPE_ARG; -if ((desc == NULL) || (num > 1)) return SCPE_IERR; -dibp = (DIB *) dptr->ctxt; -if (dibp == NULL) return SCPE_IERR; -newdev = get_uint (cptr, 8, I_DEVMASK - num, &r); -if (r != SCPE_OK) return r; -if (newdev < VARDEV) return SCPE_ARG; -for (i = 0; i <= num; i++, dibp++) dibp->devno = newdev + i; -return SCPE_OK; -} - -/* Show device number */ - -t_stat hp_showdev (FILE *st, UNIT *uptr, int32 num, void *desc) -{ -DEVICE *dptr = (DEVICE *) desc; -DIB *dibp; -int32 i; - -if ((desc == NULL) || (num > 1)) return SCPE_IERR; -dibp = (DIB *) dptr->ctxt; -if (dibp == NULL) return SCPE_IERR; -fprintf (st, "devno=%o", dibp->devno); -for (i = 1; i <= num; i++) fprintf (st, "/%o", dibp->devno + i); -return SCPE_OK; -} - -/* Make a pair of devices consistent */ - -void hp_enbdis_pair (DEVICE *ccp, DEVICE *dcp) -{ -if (ccp->flags & DEV_DIS) dcp->flags = dcp->flags | DEV_DIS; -else dcp->flags = dcp->flags & ~DEV_DIS; -return; -} - -/* Test for device conflict */ - -t_bool dev_conflict (void) -{ -DEVICE *dptr, *cdptr; -DIB *dibp, *chkp; -int32 i, j, dno; - -for (i = 0; cdptr = sim_devices[i]; i++) { - chkp = (DIB *) cdptr->ctxt; - if (chkp && !(cdptr->flags & DEV_DIS)) { - dno = chkp->devno; - for (j = 0; dptr = sim_devices[j]; j++) { - dibp = (DIB *) dptr->ctxt; - if (dibp && !(dptr->flags & DEV_DIS) && - (chkp != dibp) && (dno == dibp->devno)) { - printf ("%s device number conflict, devno = %d\n", - sim_dname (dptr), dno); - if (sim_log) fprintf (sim_log, - "%s device number conflict, devno = %d\n", - sim_dname (dptr), dno); - return TRUE; } } } } -return FALSE; -} - -/* Configuration validation */ - -t_bool cpu_set_opt (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -int32 opt = (int32) desc; -int32 mod, i; - -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 ((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 deleted file mode 100644 index 3c7940df..00000000 --- a/HP2100/hp2100_defs.h +++ /dev/null @@ -1,269 +0,0 @@ -/* hp2100_defs.h: HP 2100 simulator definitions - - 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. - - 25-Apr-03 RMS Revised for extended file support - 24-Oct-02 RMS Added indirect address interrupt - 08-Feb-02 RMS Added DMS definitions - 01-Feb-02 RMS Added terminal multiplexor support - 16-Jan-02 RMS Added additional device support - 30-Nov-01 RMS Added extended SET/SHOW support - 15-Oct-00 RMS Added dynamic device numbers - 14-Apr-99 RMS Changed t_addr to unsigned - - The author gratefully acknowledges the help of Jeff Moffat in answering - questions about the HP2100. -*/ - -#include "sim_defs.h" /* simulator defns */ - -/* Simulator stop codes */ - -#define STOP_RSRV 1 /* must be 1 */ -#define STOP_IODV 2 /* must be 2 */ -#define STOP_HALT 3 /* HALT */ -#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 */ - -/* Memory */ - -#define MEMSIZE (cpu_unit.capac) /* actual memory size */ -#define MEM_ADDR_OK(x) (((uint32) (x)) < MEMSIZE) -#define VA_N_SIZE 15 /* virtual addr size */ -#define VASIZE (1 << VA_N_SIZE) -#define VAMASK (VASIZE - 1) /* virt addr mask */ -#define PA_N_SIZE 20 /* phys addr size */ -#define PASIZE (1 << PA_N_SIZE) -#define PAMASK (PASIZE - 1) /* phys addr mask */ - -/* Architectural constants */ - -#define SIGN32 020000000000 /* 32b sign */ -#define SIGN 0100000 /* 16b sign */ -#define DMASK 0177777 /* 16b data mask */ -#define AR M[0] /* A = location 0 */ -#define BR M[1] /* B = location 1 */ -#define ABREG M /* register array */ -#define SEXT(x) ((int32) (((x) & SIGN)? ((x) | ~DMASK): ((x) & DMASK))) - -/* Memory reference instructions */ - -#define I_IA 0100000 /* indirect address */ -#define I_AB 0004000 /* A/B select */ -#define I_CP 0002000 /* current page */ -#define I_DISP 0001777 /* page displacement */ -#define I_PAGENO 0076000 /* page number */ - -/* Other instructions */ - -#define I_NMRMASK 0102000 /* non-mrf opcode */ -#define I_SRG 0000000 /* shift */ -#define I_ASKP 0002000 /* alter/skip */ -#define I_EXTD 0100000 /* extend */ -#define I_IO 0102000 /* I/O */ -#define I_CTL 0004000 /* CTL on/off */ -#define I_HC 0001000 /* hold/clear */ -#define I_DEVMASK 0000077 /* device mask */ -#define I_GETIOOP(x) (((x) >> 6) & 07) /* I/O sub op */ - -/* DMA channels */ - -#define DMA1_STC 0100000 /* DMA - issue STC */ -#define DMA1_CLC 0020000 /* DMA - issue CLC */ -#define DMA2_OI 0100000 /* DMA - output/input */ - -struct DMA { /* DMA channel */ - int32 cw1; /* device select */ - int32 cw2; /* direction, address */ - int32 cw3; /* word count */ -}; - -/* Memory management */ - -#define VA_N_OFF 10 /* offset width */ -#define VA_M_OFF ((1 << VA_N_OFF) - 1) /* offset mask */ -#define VA_GETOFF(x) ((x) & VA_M_OFF) -#define VA_N_PAG (VA_N_SIZE - VA_N_OFF) /* page width */ -#define VA_V_PAG (VA_N_OFF) -#define VA_M_PAG ((1 << VA_N_PAG) - 1) -#define VA_GETPAG(x) (((x) >> VA_V_PAG) & VA_M_PAG) - -/* Maps */ - -#define MAP_NUM 4 /* num maps */ -#define MAP_LNT (1 << VA_N_PAG) /* map length */ -#define MAP_MASK ((MAP_NUM * MAP_LNT) - 1) -#define SMAP 0 /* system map */ -#define UMAP (SMAP + MAP_LNT) /* user map */ -#define PAMAP (UMAP + MAP_LNT) /* port A map */ -#define PBMAP (PAMAP + MAP_LNT) /* port B map */ - -/* Map entries are left shifted by VA_N_OFF, flags in lower 2b */ - -#define PA_N_PAG (PA_N_SIZE - VA_N_OFF) /* page width */ -#define PA_V_PAG (VA_N_OFF) -#define PA_M_PAG ((1 << PA_N_PAG) - 1) -#define MAPM_V_RPR 15 /* in mem: read prot */ -#define MAPM_V_WPR 14 /* write prot */ -#define MAPA_V_RPR 1 /* in array: */ -#define MAPA_V_WPR 0 -#define PA_GETPAG(x) ((x) & (PA_M_PAG << VA_V_PAG)) -#define RD (1 << MAPA_V_RPR) -#define WR (1 << MAPA_V_WPR) - -/* Map status register */ - -#define MST_ENBI 0100000 /* mem enb @ int */ -#define MST_UMPI 0040000 /* usr map @ int */ -#define MST_ENB 0020000 /* mem enb */ -#define MST_UMP 0010000 /* usr map */ -#define MST_PRO 0004000 /* protection */ -#define MST_FLT 0002000 /* fence comp */ -#define MST_FENCE 0001777 /* base page fence */ - -/* Map violation register */ - -#define MVI_V_RPR 15 -#define MVI_V_WPR 14 -#define MVI_RPR (1 << MVI_V_RPR) /* rd viol */ -#define MVI_WPR (1 << MVI_V_WPR) /* wr viol */ -#define MVI_BPG 0020000 /* base page viol */ -#define MVI_PRV 0010000 /* priv viol */ -#define MVI_MEB 0000200 /* me bus enb @ viol */ -#define MVI_MEM 0000100 /* mem enb @ viol */ -#define MVI_UMP 0000040 /* usr map @ viol */ -#define MVI_PAG 0000037 /* pag sel */ - -/* Timers */ - -#define TMR_CLK 0 /* clock */ -#define TMR_MUX 1 /* multiplexor */ - -/* I/O sub-opcodes */ - -#define ioHLT 0 /* halt */ -#define ioFLG 1 /* set/clear flag */ -#define ioSFC 2 /* skip on flag clear */ -#define ioSFS 3 /* skip on flag set */ -#define ioMIX 4 /* merge into A/B */ -#define ioLIX 5 /* load into A/B */ -#define ioOTX 6 /* output from A/B */ -#define ioCTL 7 /* set/clear control */ - -/* I/O devices - fixed assignments */ - -#define CPU 000 /* interrupt control */ -#define OVF 001 /* overflow */ -#define DMALT0 002 /* DMA 0 alternate */ -#define DMALT1 003 /* DMA 1 alternate */ -#define PWR 004 /* power fail */ -#define PRO 005 /* parity/mem protect */ -#define DMA0 006 /* DMA channel 0 */ -#define DMA1 007 /* DMA channel 1 */ -#define VARDEV (DMA1 + 1) /* start of var assign */ -#define M_NXDEV (INT_M (CPU) | INT_M (OVF) | \ - INT_M (DMALT0) | INT_M (DMALT1)) -#define M_FXDEV (M_NXDEV | INT_M (PWR) | INT_M (PRO) | \ - INT_M (DMA0) | INT_M (DMA1)) - -/* I/O devices - variable assignment defaults */ - -#define PTR 010 /* paper tape reader */ -#define TTY 011 /* console */ -#define PTP 012 /* paper tape punch */ -#define CLK 013 /* clock */ -#define LPS 014 /* 12653 line printer */ -#define LPT 015 /* 12845 line printer */ -#define MTD 020 /* 12559A data */ -#define MTC 021 /* 12559A control */ -#define DPD 022 /* 12557A data */ -#define DPC 023 /* 12557A control */ -#define DQD 024 /* 12565A data */ -#define DQC 025 /* 12565A control */ -#define DRD 026 /* 12610A data */ -#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 */ - -/* IBL assignments */ - -#define IBL_PTR 0000000 /* PTR */ -#define IBL_DP 0040000 /* DP */ -#define IBL_DQ 0060000 /* DQ */ -#define IBL_MS 0100000 /* MS */ -#define IBL_TBD 0140000 /* tbd */ -#define IBL_V_DEV 6 /* dev in <11:6> */ -#define IBL_FIX 0000001 /* DP fixed */ -#define IBL_LNT 64 /* boot length */ -#define IBL_MASK (IBL_LNT - 1) /* boot length mask */ - -/* Dynamic device information table */ - -struct hp_dib { - int32 devno; /* device number */ - int32 cmd; /* saved command */ - int32 ctl; /* saved control */ - int32 flg; /* saved flag */ - int32 fbf; /* saved flag buf */ - int32 (*iot)(); /* I/O routine */ -}; - -typedef struct hp_dib DIB; - -/* I/O macros */ - -#define INT_V(x) ((x) & 037) /* device bit pos */ -#define INT_M(x) (1u << INT_V (x)) /* device bit mask */ -#define setCMD(D) dev_cmd[(D)/32] = dev_cmd[(D)/32] | INT_M ((D)) -#define clrCMD(D) dev_cmd[(D)/32] = dev_cmd[(D)/32] & ~INT_M (D) -#define setCTL(D) dev_ctl[(D)/32] = dev_ctl[(D)/32] | INT_M ((D)) -#define clrCTL(D) dev_ctl[(D)/32] = dev_ctl[(D)/32] & ~INT_M (D) -#define setFBF(D) dev_fbf[(D)/32] = dev_fbf[(D)/32] | INT_M (D) -#define clrFBF(D) dev_fbf[(D)/32] = dev_fbf[(D)/32] & ~INT_M (D) -#define setFLG(D) dev_flg[(D)/32] = dev_flg[(D)/32] | INT_M (D); \ - setFBF(D) -#define clrFLG(D) dev_flg[(D)/32] = dev_flg[(D)/32] & ~INT_M (D); \ - clrFBF(D) -#define CMD(D) ((dev_cmd[(D)/32] >> INT_V (D)) & 1) -#define CTL(D) ((dev_ctl[(D)/32] >> INT_V (D)) & 1) -#define FLG(D) ((dev_flg[(D)/32] >> INT_V (D)) & 1) -#define FBF(D) ((dev_fbf[(D)/32] >> INT_V (D)) & 1) - -#define IOT_V_REASON 16 -#define IORETURN(f,v) ((f)? (v): SCPE_OK) /* stop on error */ - -/* Function prototypes */ - -t_stat hp_setdev (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat hp_showdev (FILE *st, UNIT *uptr, int32 val, void *desc); -void hp_enbdis_pair (DEVICE *ccp, DEVICE *dcp); diff --git a/HP2100/hp2100_diag.txt b/HP2100/hp2100_diag.txt deleted file mode 100644 index 263c10f8..00000000 --- a/HP2100/hp2100_diag.txt +++ /dev/null @@ -1,171 +0,0 @@ -HP2100 Diagnostics - -CPU status writeup sources - -24315 Memory reference group passed in 21MX CE no - - LOAD diagnostic - - RUN 100 - - HLT 77, PC = 3353 - -24316 Alter/skip group passed in 21MX CE no - - LOAD diagnostic - - RUN 100 - - HLT 77, PC = 633 - -24317 Shift/rotate group passed in 21MX CE no - - LOAD diagnostic - - RUN 100 - - HLT 77, PC = 1726 - -24296 Diagnostic configurator passed in 21MX CE no - - LOAD configurator - - SET CPU 21MX - - ATTACH PTR binary image of - diagnostic to be configured - - D S XXYY, where XX = device number - of PTR, YY = device number of TTY - - RUN 2 - - HLT 77, PC = 77237 (for 32K mem) - -24319 Extended arithmetic group passed in 21MX CE no - - load diagnostic via configurator - - D S 0 - - RUN 100 - - prints diagnostic name - - prints END OF PASS 1 and halts - -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 - - D S 0 - - RUN 100 - - prints diagnostic name - - prints PASS 000001 and halts - -12943-1 Extended instruction group, part 1 passed 12943 manual no - - load diagnostic via configurator - - D S 0 - - RUN 100 - - prints diagnostic name - - prints PASS 000001 and halts - -12943-2 Extended instruction group, part 2 passed 12943 manual no - - load diagnostic via configurator - - D S XX, where XX = device number - of TTY - - RUN 100 - - HLT 74, PC = 2406 - - D S 0 - - CONTINUE - - prints diagnostic name - - prints PASS 000001 and halts - -24322 Dual channel port controller passed in 21MX CE no - - load diagnostic via configurator - - SET LPS ENA - - SET LPS DIAG - - D S XX, where XX = device number - of LPS - - RUN 100 - - HALT 74, PC = 1541 - - D S 0 - - CONTINUE - - prints diagnostic name - - prints H324 PRESS PRESET AND RUN - - HLT 24, PC = 2312 - - RESET ALL - - CONTINUE - - prints PASS 000001 and halts - -12892 Memory protect-parity error passed in 21MX CE no - - load diagnostic via configurator - - disable all I/O devices except - PTR, TTY, clock - - D S 1400XX, where XX = device number - of PTR - - RUN 100 - - HLT 74, PC = 2444 - - D S 1000 (test select mode) - - CONTINUE - - prints diagnostic name - - HLT 75, PC = 2026 - - D S 0 - - D A 31777 (tests 10-11 can't be run) - - Rings bell and prints - H314 PRESS HALT,PRESET AND RUN WITHIN 30 SECONDS - - WRU (CTRL+E) to interrupt simulation - - RESET ALL - - CONTINUE - - prints PASS 000001 and halts - -12929 Memory expansion unit (DMS) passed in 21MX CE no - - load diagnostic via configurator - - SET CPU 64K - - SET LPS ENA - - SET LPS DIAG - - D S XX, where XX = device number - of LPS - - RUN 100 - - HLT 74, PC = 2435 - - D S 0 - - CONTINUE - - Prints H115 PRESS HALT-PRESET-RUN IN LESS THAN 10 SECONDS - - WRU (CTRL+E) to interrupt simulation - - RESET ALL - - CONTINUE - - Prints H117 PRESET TEST COMPLETE - - Prints PASS 000001 and halts - - Test 23 won't run at >256K mem - (real 21MX limited to 304K) - -Peripherals - -12531 TTY test passed in 21MX CE no - - set TTY TTIME to 100 - - run with test select = 173 - - remaining tests can't be run -12539 time base generator passed in 21MX CE no - - runs with CLK in diag mode -12597 reader/punch passed in 21MX CE no - - set PTP TIME to 100 - - run with test select a=4017 - - remaining tests can't be run -12984 2767 line printer passed in 21MX CE no - - set LPS PTIME, CTIME to 100 - - run with test select a = 15 - - remaining tests can't be run -12960 7900/7901 disk passed in 21MX CE no -12965 2883/2884 disk passed 12965 manual no -12559 3030 magtape not run no documentation -13181 7970B magtape partial in 21MX CE no - - initial s = 102030 - - set MSC CTIME to 180000 - - do not change MSC XTIME - - attach scratch tapes to units 0,1 - - set s = 1201 (suppress CRC/LRC) - - run with test select a = 37757, b = 7767 - - tests 4, 14, 15 are timing dependent - - test 19 uses non-supported read rev -13183 7970E magtape not run in 21MX CE no -12920 multiplexor not run in 21MX CE no diff --git a/HP2100/hp2100_doc.txt b/HP2100/hp2100_doc.txt deleted file mode 100644 index b6440a10..00000000 --- a/HP2100/hp2100_doc.txt +++ /dev/null @@ -1,945 +0,0 @@ -To: Users -From: Bob Supnik -Subj: HP2100 Simulator Usage -Date: 15-Jul-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 HP 2100 simulator. - - -1. Simulator Files - -sim/ sim_defs.h - sim_rev.h - sim_sock.h - sim_tape.h - sim_tmxr.h - scp.c - scp_tty.c - sim_sock.c - sim_tape.c - sim_tmxr.c - -sim/hp2100/ hp2100_defs.h - hp2100_cpu.c - hp2100_fp.c - hp2100_dp.c - hp2100_dq.c - hp2100_dr.c - hp2100_ipl.c - hp2100_lps.c - hp2100_lpt.c - hp2100_mt.c - hp2100_ms.c - hp2100_mux.c - hp2100_stddev.c - hp2100_sys.c - -2. HP2100 Features - -The HP2100 simulator is configured as follows: - -device simulates -name(s) - -CPU 2116 CPU with 32KW memory - 2100 CPU with 32KW memory, FP or IOP instructions - 21MX CPU with 1024KW memory, FP or DMS instructions -DMA0, DMA1 dual channel DMA controller -PTR,PTP 12597A paper tape reader/punch -TTY 12631C buffered terminal controller -LPS 12653A printer controller with 2767 printer - 12566B microcircuit interface for diagnostics -LPT 12845A printer controller with 2607 printer -CLK 12539A/B/C time base generator -MUXL,MUXU,MUXC 12920A terminal multiplexor -DP 12557A disk controller with four 2871 drives - 13210A disk controller with four 7900 drives -DQ 12565A disk controller with two 2883 drives -DR 12606B fixed head disk controller with 2770/2771 disks - 12610B drum controller with 2773/2774/2775 drums -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: - - - decode of an undefined instruction, and STOP_INST is et - - reference to an undefined I/O device, and STOP_DEV is set - - more than INDMAX indirect references are detected during - memory reference address decoding - -The HP2100 loader supports standard absolute binary format. The DUMP -command is not implemented. - -2.1 CPU - -CPU options include choice of instruction set and memory size. - - SET CPU 2116 2116 CPU - SET CPU 2100 2100 CPU - SET CPU 21MX 21MX CPU - SET CPU EAU EAU instructions (2116 only) - 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, 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 - SET CPU 8K set memory size = 8K - SET CPU 16K set memory size = 16K - SET CPU 32K set memory size = 32K - SET CPU 64K set memory size = 64K (21MX only) - SET CPU 128K set memory size = 128K (21MX only) - SET CPU 256K set memory size = 256K (21MX only) - SET CPU 512K set memory size = 512K (21MX only) - SET CPU 1024K set memory size = 1024K (21MX only) - -On the 2100, EAU is standard, and the FP and IOP options are mutually -exclusive. On the 21MX, EAU and FP are standard. The 2100 and 21MX -include memory protection as standard; the 21MX optionally includes -DMS (dynamic memory system). - -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 32K. - -These switches are recognized when examining or depositing in CPU memory: - - -v if DMS enabled, interpret address as virtual - -s if DMS enabled, force system map - -u if DMS enabled, force user map - -p if DMS enabled, force port A map - -q if DMS enabled, force port B map - -CPU registers include the visible state of the processor as well as the -control registers for the interrupt system. - - name models size comments - - P all 15 program counter - A all 16 A register - B all 16 B register - X 21MX 16 X index register - Y 21MX 16 Y index register - S all 16 switch/display register - F 2100,21MX 15 memory protection fence - E all 1 extend flag - O all 1 overflow flag - ION all 1 interrupt enable flag - ION_DEFER all 1 interrupt defer flag - IADDR all 6 most recent interrupting device - MPCTL 2100,21MX 1 memory protection enable - MPFLG 2100,21MX 1 memory protection flag - MPFBF 2100,21MX 1 memory protection flag buffer - MPVR 2100,21MX 16 memory protection violation reg - MPEVR 2100,21MX 1 memory protection freeze flag - MPMEV 2100,21MX 1 memory protection DMS error flag - DMSENB 21MX 1 DMS enable - DMSCUR 21MX 1 DMS current mode - DMSSR 21MX 16 DMS status register - DMSVR 21MX 16 DMS violation register - DMSMAP[4][32] 21MX 20 DMS maps - STOP_INST all 1 stop on undefined instruction - STOP_DEV all 1 stop on undefined device - INDMAX all 16 indirect address limit - PCQ[0:63] all 15 P of last JMP, JSB, or interrupt; - most recent P change first - WRU all 8 interrupt character - -2.2 DMA Controllers - -The HP2100 includes two DMA channel controllers (DMA0 and DMA1). Each -DMA channel has the following visible state: - - name size comments - - CMD 1 channel enabled - CTL 1 interrupt enabled - FLG 1 channel ready - FBF 1 channel ready buffer - CW1 16 command word 1 - CW2 16 command word 2 - CW3 16 command word 3 - -2.3 Variable Device Assignments - -On the HP2100, I/O device take their device numbers from the backplane -slot they are plugged into. Thus, device number assignments vary -considerably from system to system, and software package to software -package. The HP2100 simulator supports dynamic device number assignment. -To show the current device number, use the SHOW DEVNO command: - - sim> SHOW PTR DEV - device=10 - -To change the device number, use the SET DEVNO= command: - - sim> SET PTR DEV=30 - sim> SHOW PTR DEV - device=30 - -The new device number must be in the range 010..077 (octal). For devices -with two device numbers, only the lower numbered device number can be -changed; the higher is automatically set to the lower + 1. If a -device number conflict occurs, the simulator will return an error -when started. - -In addition, most devices can be enabled or disabled. To enable a -device, use the SET ENABLED command: - - sim> SET DP ENABLED - -To disable a device, use the SET DISABLED command: - - sim> SET DP DISABLED - -For devices with more than one device number, disabling or enabling any -device in the set disables all the devices. - -2.4 Programmed I/O Devices - -2.4.1 12597A-002 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 supports the BOOT command. BOOT PTR copies the -absolute binary loader into memory and starts it running. - -The paper tape reader implements these registers: - - name size comments - - BUF 8 last data item processed - CMD 1 reader enable - CTL 1 device/interrupt enable - FLG 1 device ready - FBF 1 device ready buffer - 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 or paper - - OS I/O error x report error and stop - -2.4.2 12597A-005 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 - CMD 1 punch enable - CTL 1 device/interrupt enable - FLG 1 device ready - FBF 1 device ready buffer - 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.4.3 12631C Buffered Terminal (TTY) - -The console terminal has three units: keyboard (unit 0), printer -(unit 1), and punch (unit 2). The keyboard reads from the console -keyboard; the printer writes to the simulator console window. The -punch writes to a disk file. The keyboard and printer units (TTY0, -TTY1) 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. - -The console teleprinter implements these registers: - - name size comments - - BUF 8 last data item processed - MODE 16 mode - CTL 1 device/interrupt enable - FLG 1 device ready - FBF 1 device ready buffer - KPOS 32 number of characters input - KTIME 24 keyboard polling interval - TPOS 32 number of characters printed - TTIME 24 time from I/O initiation to interrupt - PPOS 32 position in the punch output file - STOP_IOE 1 punch stop on I/O error - -Error handling for the punch 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.4.4 12653A Printer Controller (LPS) with 2767 Printer - 12566B Microcircuit Interface - -The 12653A line printer uses the 12566B microcircuit interface as -its controller. As a line printer, LPS 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. - -As a microcircuit interface, LPS provides the DMA test device for -running the dual channel port controller and DMS diagnostics. Printer -mode verus diagnostic mode is controlled by the commands: - - SET LPS PRINTER configure as line printer - SET LPS DIAG configure for diagnostic tests - -The 12653A is disabled by default. - -The 12653A implements these registers: - - name size comments - - BUF 16 output buffer - STA 16 input buffer or status - CMD 1 printer enable - CTL 1 device/interrupt enable - FLG 1 device ready - FBF 1 device ready buffer - POS 32 position in the output file - CTIME 24 time between characters - PTIME 24 time for a print operation - STOP_IOE 1 stop on I/O error - -In printer mode, 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 - -In diagnostic mode, there are no errors; data sent to the output -buffer is looped back to the status register with a fixed delay of 1. - -2.4.5 12845A Printer Controller (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 8 last data item processed - CMD 1 printer enable - CTL 1 device/interrupt enable - FLG 1 device ready - FBF 1 device ready buffer - LCNT 7 line count within page - POS 32 position in the output file - CTIME 24 time between characters - PTIME 24 time for a print operation - 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 or paper - - OS I/O error x report error and stop - -2.4.6 12539A/B/C Time Base Generator (CLK) - -The time base generator (CLK) implements these registers: - - name size comments - - SEL 3 time base select - CTR 14 repeat counter for < 1Hz operation - CTL 1 device/interrupt enable - FLG 1 device ready - FBF 1 device ready buffer - ERR 1 error flag - TIME[0:7] 31 clock intervals, select = 0..7 - DEVNO 6 current device number (read only) - -The time base generator autocalibrates; the clock interval is adjusted -up or down so that the clock tracks actual elapsed time. Operation at -the fastest rates (100 usec, 1 msec) is not recommended. - -2.4.7 12920A Terminal Multiplexor (MUXL, MUXU, MUXC) - -The 12920A is a 16-line terminal multiplexor, with five additional -receive-only diagnostic lines. It consists of three devices: - - MUX scanning logic (corresponding more or less - to the upper data card) - MUXL individual lines (corresponding more or - less to the lower data card) - MUXC modem control and status logic (corresponding - to the control card) - -The MUX performs input and output through Telnet sessions connected to a -user-specified port. The ATTACH command to the scanning logic 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) 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. In addition, each line supports the DATASET option. -DATASET, when set, enables modem control. The default settings are UC -mode and DATASET disabled. - -The modem controls model a simplified Bell 103A dataset with just four -lines: data terminal ready and request to send from the computer to the -data set, and carrier detect and data set ready from the data set to -the computer. There is no ring detection. If data terminal ready is -set when a Telnet connection starts up, then carrier detect and data -set ready are also set. The connection is established whether data -terminal ready is set or not. - -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 MUXL 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 scanner (MUX) implements these registers: - - name size comments - - IBUF 16 input buffer, holds line status - OBUF 16 output buffer, holds channel select - -The lines (MUXL) implements these registers: - - name size comments - - CTL 1 device/interrupt enable - FLG 1 device ready - FBF 1 device ready buffer - STA[0:20] 16 line status, lines 0-20 - RPAR[0:20] 16 receive parameters, lines 0-20 - XPAR[0:15] 16 transmit parameters, lines 0-15 - RBUF[0:20] 8 receive buffer, lines 0-20 - XBUF[0:15] 8 transmit buffer, lines 0-15 - RCHP[0:20] 1 receive character present, lines 0-20 - XDON[0:15] 1 transmit done, lines 0-15 - TIME[0:15] 24 transmit time, lines 0-15 - -The modem control (MUXM) implements these registers: - - name size comments - - CTL 1 device/interrupt enable - FLG 1 device ready - FBF 1 device ready buffer - SCAN 1 scan enabled - CHAN 4 current line - DSO[0:15] 6 C2,C1,ES2,ES1,SS2,SS1, lines 0-15 - DSI[0:15] 2 S2,S1, lines 0-15 - - -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 - -The 12557A/13210A disk controller can be configured as either a -12557A, supporting 2.5MB drives, or a 13210A, supporting 5MB drives, -with the commands: - - SET DP 12557A 2.5MB drives - SET DP 13210A 5.0MB drives - -Drive types cannot be intermixed; the controller is configured for -one type or the other. The 13210A (for 7900/7901 disks) is selected -by default. - -The simulated controller has two separate devices, a data channel and -a device controller. The data channel includes a 128-word (one sector) -buffer for reads and writes. The device controller includes the four -disk drives. Disk drives can be set ONLINE or OFFLINE. - -The 12557A/13210A supports the BOOT command. BOOT DP loads the IBL -for 7900 class disks into memory and starts it running. BOOT -F DP -boots from the fixed platter (head 2). The switch register (S) is -set automatically to the value expected by the IBL loader: - - <15:14> = 01 - <13:12> = 00 - <11:6> = data channel device code - <5:1> = 00000 - <0> = 1 if booting from the fixed platter - -The data channel implements these registers: - - name size comments - - IBUF 16 input buffer - OBUF 16 output buffer - DBUF[0:127] 16 sector buffer - BPTR 7 sector buffer pointer - CMD 1 channel enable - CTL 1 interrupt enable - FLG 1 channel ready - FBF 1 channel ready buffer - XFER 1 transfer in progress flag - WVAL 1 write data valid flag - -The device controller implements these registers: - - name size comments - - OBUF 16 output buffer - BUSY 3 busy (unit #, + 1, of active unit) - CNT 5 check record count - CMD 1 controller enable - CTL 1 interrupt enable - FLG 1 controller ready - FBF 1 controller ready buffer - EOC 1 end of cylinder pending - RARC[0:3] 8 record address register cylinder, drives 0-3 - RARH[0:3] 2 record address register head, drives 0-3 - RARS[0:3] 4 record address register sector, drives 0-3 - STA[0:3] 16 drive status, drives 0-3 - CTIME 24 data transfer command delay time - DTIME 24 data channel command delay time - STIME 24 seek delay time, per cylinder - XTIME 24 interword transfer time - -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 12565A Disk Controller (DQC, DRC) with 2883 Drives - -The 12565A disk controller has two separate devices, a data channel and -a device controller. The data channel includes a 128-word (one sector) -buffer for reads and writes. The device controller includes the two -disk drives. Disk drives can be set ONLINE or OFFLINE. - -The 12565A supports the BOOT command. BOOT DQ loads the IBL for 2883 -class disks into memory and starts it running. The switch register (S) -is set automatically to the value expected by the IBL loader: - - <15:14> = 01 - <13:12> = 10 - <11:6> = data channel device code - <5:0> = 00000 - -The data channel implements these registers: - - name size comments - - IBUF 16 input buffer - OBUF 16 output buffer - DBUF[0:127] 16 sector buffer - BPTR 7 sector buffer pointer - CMD 1 channel enable - CTL 1 interrupt enable - FLG 1 channel ready - FBF 1 channel ready buffer - XFER 1 transfer in progress flag - WVAL 1 write data valid flag - -The device controller implements these registers: - - name size comments - - OBUF 16 output buffer - BUSY 2 busy (unit #, + 1, of active unit) - CNT 9 check record count - CMD 1 controller enable - CTL 1 interrupt enable - FLG 1 controller ready - FBF 1 controller ready buffer - RARC[0:1] 8 record address register cylinder, drives 0-1 - RARH[0:1] 5 record address register head, drives 0-1 - RARS[0:1] 5 record address register sector, drives 0-1 - STA[0:1] 16 drive status, drives 0-3 - CTIME 24 data transfer command delay time - DTIME 24 data channel command delay time - STIME 24 seek delay time, per cylinder - XTIME 24 interword transfer time - -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 12606B Fixed Head Disk Controller (DRC, DRD) with 2770/2771 Disk - 12610B Drum Controller (DRC, DRD) with 2773/2774/2775 Drum - -The 12606B/12610B fixed head disk/drum controller has two separate devices, -a data channel and a device controller. The device controller includes the -actual drive. Ten different models are supported: - - SET DRC 180K 12606B, 180K words - SET DRC 360K 12606B, 360K words - SET DRC 720K 12606B, 720K words - SET DRC 384K 12610B, 84K words - SET DRC 512K 12610B, 512K words - SET DRC 640K 12610B, 640K words - SET DRC 768K 12610B, 768K words - SET DRC 896K 12610B, 896K words - SET DRC 1024K 12610B, 1024K words - SET DRC 1536K 12610B, 1536K words - -The 12606B/12610B support the BOOT command. The BOOT command loads the -first sector from the disk or drum into locations 0-77 and then jumps to 77. -This is very different from the IBL loader protocol used by the 12565A and -the 12557A/13210A. - -The data channel implements these registers: - - name size comments - - IBUF 16 input buffer - OBUF 16 output buffer - CMD 1 channel enable - CTL 1 interrupt enable - FLG 1 channel ready - FBF 1 channel ready buffer - BPTR 6 sector buffer pointer - -The device controller implements these registers: - - name size comments - - CW 16 command word - STA 16 status - CMD 1 controller enable - CTL 1 interrupt enable - FLG 1 controller ready - FBF 1 controller ready buffer - TIME 24 interword transfer time - STOP_IOE 1 stop on I/O error - -Error handling is as follows: - - error processed as - - not attached disk not ready - -12606B/12610B data files are buffered in memory; therefore, end of file -and OS I/O errors cannot occur. - -2.8 12559C Magnetic Tape Controller (MTC, MTD) with 3030 Drive - -Magnetic tape options include the ability to make the unit write enabled -or write locked. - - SET MTC LOCKED set unit write locked - SET MTC WRITEENABLED set unit write enabled - -The 12559C mag tape drive has two separate devices, a data channel and -a device controller. The data channel includes a maximum record sized -buffer for reads and writes. The device controller includes the tape -unit. - -The BOOT command is not supported. The 12559C was HP's earliest tape -drive and is not supported by most of its operating systems. It is -disabled by default. - -The data channel implements these registers: - - name size comments - - FLG 1 channel ready - DBUF[0:65535] 8 transfer buffer - BPTR 16 buffer pointer (reads and writes) - BMAX 16 buffer size (writes) - -The device controller implements these registers: - - name size comments - - FNC 8 current function - STA 9 tape status - BUF 8 buffer - CTL 1 interrupt enabled - FLG 1 controller ready - FBF 1 controller ready buffer - DTF 1 data transfer flop - FSVC 1 first service flop - POS 32 magtape position - CTIME 24 command delay time - XTIME 24 interword transfer delay time - 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 parity error - - OS I/O error parity error; if STOP_IOE, stop - -2.9 13181A Magnetic Tape Controller (MSC, MSD) with 7970B Drives - 18183A Magnetic Tape Controller (MSC, MSD) with 7970E Drives - -Magnetic tape options include the ability to make the unit write enabled -or write locked, and the ability to select the 13181A (800 bpi) controller -or the 13183A (1600 bpi) controller. - - SET MTn LOCKED set unit n write locked - SET MTn WRITEENABLED set unit n write enabled - SET MT 13181A set controller to 13181A - SET MT 13183A set controller to 13183A - -The 13181A/13183A mag tape drive has two separate devices, a data channel -and a device controller. The data channel includes a maximum record -sized buffer for reads and writes. The device controller includes the -tape units. - -The 13181A/13183A supports the BOOT command. BOOT MS loads the IBL for -7970B/E magnetic tape drives into memory and starts it running. BOOT -S -MS causes the loader to space forward the number of files specified in -the A register before starting to load data. The switch register (S) is -set automatically to the value expected by the IBL loader: - - <15:14> = 10 - <13:12> = 00 - <11:6> = data channel device code - <5:1> = 00000 - <0> = 1 if space forward before loading - -The data channel implements these registers: - - name size comments - - BUF 16 data buffer - CTL 1 interrupt enabled - FLG 1 channel ready - FBF 1 channel ready buffer - DBUF[0:65535] 8 transfer buffer - BPTR 17 buffer pointer (reads and writes) - BMAX 17 buffer size (writes) - -The device controller implements these registers: - - name size comments - - STA 12 tape status - BUF 16 buffer - USEL 2 currently selected unit - FSVC 1 first service flop - CTL 1 interrupt enabled - FLG 1 controller ready - FBF 1 controller ready buffer - POS[0:3] 32 magtape position - CTIME 24 command delay time - XTIME 24 interword transfer delay time - 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 parity error - - OS I/O error parity error; if STOP_IOE, stop - -2.10 Symbolic Display and Input - -The HP2100 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 - -Instruction input uses standard HP2100 assembler syntax. There are seven -instruction classes: memory reference, I/O, shift, alter skip, extended -shift, extended memory reference, extended two address reference. - -Memory reference instructions have the format - - memref {C/Z} address{,I} - -where I signifies indirect, C a current page reference, and Z a zero page -reference. The address is an octal number in the range 0 - 077777; if C or -Z is specified, the address is a page offset in the range 0 - 01777. Normally, -C is not needed; the simulator figures out from the address what mode to use. -However, when referencing memory outside the CPU (eg, disks), there is no -valid PC, and C must be used to specify current page addressing. - -IOT instructions have the format - - io device{,C} - -where C signifies that the device flag is to be cleared. The device is an -octal number in the range 0 - 77. - -Shift and alter/skip instructions have the format - - sub-op sub-op sub-op... - -The simulator checks that the combination of sub-opcodes is legal. - -Extended shift instructions have the format - - extshift count - -where count is an octal number in the range 1 - 020. - -Extended memory reference instructions have the format - - extmemref address{,I} - -where I signifies indirect addressing. The address is an octal number in -the range 0 - 077777. - -Extended two address instructions have the format - - ext2addr addr1{,I},addr2{,I} - -where I signifies indirect addressing. Both address 1 and address 2 are -octal numbers in the range 0 - 077777. diff --git a/HP2100/hp2100_dp.c b/HP2100/hp2100_dp.c deleted file mode 100644 index 64a7ad0b..00000000 --- a/HP2100/hp2100_dp.c +++ /dev/null @@ -1,796 +0,0 @@ -/* hp2100_dp.c: HP 2100 12557A/13210A disk simulator - - 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. - - dp 12557A 2871 disk subsystem - 13210A 7900 disk subsystem - - 25-Apr-03 RMS Revised for extended file support - Fixed bug(s) in boot (found by Terry Newton) - 10-Nov-02 RMS Added BOOT command, fixed numerous bugs - 15-Jan-02 RMS Fixed INIT handling (found by Bill McDermith) - 10-Jan-02 RMS Fixed f(x)write call (found by Bill McDermith) - 03-Dec-01 RMS Changed DEVNO to use extended SET/SHOW - 24-Nov-01 RMS Changed STA to be an array - 07-Sep-01 RMS Moved function prototypes - 29-Nov-00 RMS Made variable names unique - 21-Nov-00 RMS Fixed flag, buffer power up state -*/ - -#include "hp2100_defs.h" - -#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */ -#define UNIT_WLK (1 << UNIT_V_WLK) -#define FNC u3 /* saved function */ -#define CYL u4 /* cylinder */ -#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write prot */ - -#define DP_N_NUMWD 7 -#define DP_NUMWD (1 << DP_N_NUMWD) /* words/sector */ -#define DP_NUMSC2 12 /* sectors/srf 12557 */ -#define DP_NUMSC3 24 /* sectors/srf 13210 */ -#define DP_NUMSC (dp_ctype? DP_NUMSC3: DP_NUMSC2) -#define DP_NUMSF 4 /* surfaces/cylinder */ -#define DP_NUMCY 203 /* cylinders/disk */ -#define DP_SIZE2 (DP_NUMSF * DP_NUMCY * DP_NUMSC2 * DP_NUMWD) -#define DP_SIZE3 (DP_NUMSF * DP_NUMCY * DP_NUMSC3 * DP_NUMWD) -#define DP_NUMDRV 4 /* # drives */ - -/* Command word */ - -#define CW_V_FNC 12 /* function */ -#define CW_M_FNC 017 -#define CW_GETFNC(x) (((x) >> CW_V_FNC) & CW_M_FNC) -#define FNC_STA 000 /* status check */ -#define FNC_WD 001 /* write */ -#define FNC_RD 002 /* read */ -#define FNC_SEEK 003 /* seek */ -#define FNC_REF 005 /* refine */ -#define FNC_CHK 006 /* check */ -#define FNC_INIT 011 /* init */ -#define FNC_AR 013 /* address */ -#define FNC_SEEK1 020 /* fake - seek1 */ -#define FNC_SEEK2 021 /* fake - seek2 */ -#define FNC_SEEK3 022 /* fake - seek3 */ -#define FNC_CHK1 023 /* fake - check1 */ -#define FNC_AR1 024 /* fake - arec1 */ -#define CW_V_DRV 0 /* drive */ -#define CW_M_DRV 03 -#define CW_GETDRV(x) (((x) >> CW_V_DRV) & CW_M_DRV) - -/* Disk address words */ - -#define DA_V_CYL 0 /* cylinder */ -#define DA_M_CYL 0377 -#define DA_GETCYL(x) (((x) >> DA_V_CYL) & DA_M_CYL) -#define DA_V_HD 8 /* head */ -#define DA_M_HD 03 -#define DA_GETHD(x) (((x) >> DA_V_HD) & DA_M_HD) -#define DA_V_SC 0 /* sector */ -#define DA_M_SC2 017 -#define DA_M_SC3 037 -#define DA_M_SC (dp_ctype? DA_M_SC3: DA_M_SC2) -#define DA_GETSC(x) (((x) >> DA_V_SC) & DA_M_SC) -#define DA_CKMASK2 037 /* check mask */ -#define DA_CKMASK3 077 -#define DA_CKMASK (dp_ctype? DA_CKMASK3: DA_CKMASK2) - -/* Status in dpc_sta[drv], (u) = unused in 13210, (d) = dynamic */ - -#define STA_ATN 0100000 /* attention (u) */ -#define STA_1ST 0040000 /* first status */ -#define STA_OVR 0020000 /* overrun */ -#define STA_RWU 0010000 /* rw unsafe NI (u) */ -#define STA_ACU 0004000 /* access unsafe NI */ -#define STA_HUNT 0002000 /* hunting NI (12557) */ -#define STA_PROT 0002000 /* protected (13210) */ -#define STA_SKI 0001000 /* incomplete NI (u) */ -#define STA_SKE 0000400 /* seek error */ -/* 0000200 /* unused */ -#define STA_NRDY 0000100 /* not ready (d) */ -#define STA_EOC 0000040 /* end of cylinder */ -#define STA_AER 0000020 /* addr error */ -#define STA_FLG 0000010 /* flagged */ -#define STA_BSY 0000004 /* seeking */ -#define STA_DTE 0000002 /* data error */ -#define STA_ERR 0000001 /* any error (d) */ -#define STA_ALLERR (STA_ATN + STA_1ST + STA_OVR + STA_RWU + STA_ACU + \ - STA_SKI + STA_SKE + STA_NRDY + STA_EOC + STA_AER + \ - STA_FLG + STA_BSY + STA_DTE) -#define STA_MBZ13 (STA_ATN + STA_RWU + STA_SKI) /* zero in 13210 */ - -extern uint16 *M; -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; - -int32 dp_ctype = 1; /* ctrl type */ -int32 dpc_busy = 0; /* cch unit */ -int32 dpc_cnt = 0; /* check count */ -int32 dpc_eoc = 0; /* end of cyl */ -int32 dpc_stime = 100; /* seek time */ -int32 dpc_ctime = 100; /* command time */ -int32 dpc_xtime = 5; /* xfer time */ -int32 dpc_dtime = 2; /* dch time */ -int32 dpd_obuf = 0, dpd_ibuf = 0; /* dch buffers */ -int32 dpc_obuf = 0; /* cch buffers */ -int32 dpd_xfer = 0; /* xfer in prog */ -int32 dpd_wval = 0; /* write data valid */ -int32 dp_ptr = 0; /* buffer ptr */ -uint8 dpc_rarc[DP_NUMDRV] = { 0 }; /* cylinder */ -uint8 dpc_rarh[DP_NUMDRV] = { 0 }; /* head */ -uint8 dpc_rars[DP_NUMDRV] = { 0 }; /* sector */ -uint16 dpc_sta[DP_NUMDRV] = { 0 }; /* status regs */ -uint16 dpxb[DP_NUMWD]; /* sector buffer */ - -DEVICE dpd_dev, dpc_dev; -int32 dpdio (int32 inst, int32 IR, int32 dat); -int32 dpcio (int32 inst, int32 IR, int32 dat); -t_stat dpc_svc (UNIT *uptr); -t_stat dpd_svc (UNIT *uptr); -t_stat dpc_reset (DEVICE *dptr); -t_stat dpc_vlock (UNIT *uptr, int32 val); -t_stat dpc_attach (UNIT *uptr, char *cptr); -t_stat dpc_boot (int32 unitno, DEVICE *dptr); -void dp_god (int32 fnc, int32 drv, int32 time); -void dp_goc (int32 fnc, int32 drv, int32 time); -t_stat dp_settype (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat dp_showtype (FILE *st, UNIT *uptr, int32 val, void *desc); - -/* DPD data structures - - dpd_dev DPD device descriptor - dpd_unit DPD unit list - dpd_reg DPD register list -*/ - -DIB dp_dib[] = { - { DPD, 0, 0, 0, 0, &dpdio }, - { DPC, 0, 0, 0, 0, &dpcio } }; - -#define dpd_dib dp_dib[0] -#define dpc_dib dp_dib[1] - -UNIT dpd_unit = { UDATA (&dpd_svc, 0, 0) }; - -REG dpd_reg[] = { - { ORDATA (IBUF, dpd_ibuf, 16) }, - { ORDATA (OBUF, dpd_obuf, 16) }, - { FLDATA (CMD, dpd_dib.cmd, 0) }, - { FLDATA (CTL, dpd_dib.ctl, 0) }, - { FLDATA (FLG, dpd_dib.flg, 0) }, - { FLDATA (FBF, dpd_dib.fbf, 0) }, - { FLDATA (XFER, dpd_xfer, 0) }, - { FLDATA (WVAL, dpd_wval, 0) }, - { BRDATA (DBUF, dpxb, 8, 16, DP_NUMWD) }, - { DRDATA (BPTR, dp_ptr, DP_N_NUMWD) }, - { ORDATA (DEVNO, dpd_dib.devno, 6), REG_HRO }, - { NULL } }; - -MTAB dpd_mod[] = { - { MTAB_XTD | MTAB_VDV, 1, "DEVNO", "DEVNO", - &hp_setdev, &hp_showdev, &dpd_dev }, - { 0 } }; - -DEVICE dpd_dev = { - "DPD", &dpd_unit, dpd_reg, dpd_mod, - 1, 10, DP_N_NUMWD, 1, 8, 16, - NULL, NULL, &dpc_reset, - NULL, NULL, NULL, - &dpd_dib, 0 }; - -/* DPC data structures - - dpc_dev DPC device descriptor - dpc_unit DPC unit list - dpc_reg DPC register list - dpc_mod DPC modifier list -*/ - -UNIT dpc_unit[] = { - { UDATA (&dpc_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE, DP_SIZE3) }, - { UDATA (&dpc_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE, DP_SIZE3) }, - { UDATA (&dpc_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE, DP_SIZE3) }, - { UDATA (&dpc_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE, DP_SIZE3) } }; - -REG dpc_reg[] = { - { ORDATA (OBUF, dpc_obuf, 16) }, - { ORDATA (BUSY, dpc_busy, 3), REG_RO }, - { ORDATA (CNT, dpc_cnt, 5) }, - { FLDATA (CMD, dpc_dib.cmd, 0) }, - { FLDATA (CTL, dpc_dib.ctl, 0) }, - { FLDATA (FLG, dpc_dib.flg, 0) }, - { FLDATA (FBF, dpc_dib.fbf, 0) }, - { FLDATA (EOC, dpc_eoc, 0) }, - { BRDATA (RARC, dpc_rarc, 8, 8, DP_NUMDRV) }, - { BRDATA (RARH, dpc_rarh, 8, 2, DP_NUMDRV) }, - { BRDATA (RARS, dpc_rars, 8, 4, DP_NUMDRV) }, - { BRDATA (STA, dpc_sta, 8, 16, DP_NUMDRV) }, - { DRDATA (CTIME, dpc_ctime, 24), PV_LEFT }, - { DRDATA (DTIME, dpc_dtime, 24), PV_LEFT }, - { DRDATA (STIME, dpc_stime, 24), PV_LEFT }, - { DRDATA (XTIME, dpc_xtime, 24), REG_NZ + PV_LEFT }, - { FLDATA (CTYPE, dp_ctype, 0), REG_HRO }, - { URDATA (UCYL, dpc_unit[0].CYL, 10, 8, 0, - DP_NUMDRV, PV_LEFT | REG_HRO) }, - { URDATA (UFNC, dpc_unit[0].FNC, 8, 8, 0, - DP_NUMDRV, REG_HRO) }, - { URDATA (CAPAC, dpc_unit[0].capac, 10, T_ADDR_W, 0, - DP_NUMDRV, PV_LEFT | REG_HRO) }, - { ORDATA (DEVNO, dpc_dib.devno, 6), REG_HRO }, - { NULL } }; - -MTAB dpc_mod[] = { - { UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL }, - { UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL }, - { MTAB_XTD | MTAB_VDV, 1, NULL, "13210A", - &dp_settype, NULL, NULL }, - { MTAB_XTD | MTAB_VDV, 0, NULL, "12557A", - &dp_settype, NULL, NULL }, - { MTAB_XTD | MTAB_VDV, 0, "TYPE", NULL, - NULL, &dp_showtype, NULL }, - { MTAB_XTD | MTAB_VDV, 1, "DEVNO", "DEVNO", - &hp_setdev, &hp_showdev, &dpd_dev }, - { 0 } }; - -DEVICE dpc_dev = { - "DPC", dpc_unit, dpc_reg, dpc_mod, - DP_NUMDRV, 8, 24, 1, 8, 16, - NULL, NULL, &dpc_reset, - &dpc_boot, &dpc_attach, NULL, - &dpc_dib, DEV_DISABLE }; - -/* IOT routines */ - -int32 dpdio (int32 inst, int32 IR, int32 dat) -{ -int32 devd; - -devd = IR & I_DEVMASK; /* get device no */ -switch (inst) { /* case on opcode */ -case ioFLG: /* flag clear/set */ - if ((IR & I_HC) == 0) { setFLG (devd); } /* STF */ - break; -case ioSFC: /* skip flag clear */ - if (FLG (devd) == 0) PC = (PC + 1) & VAMASK; - return dat; -case ioSFS: /* skip flag set */ - if (FLG (devd) != 0) PC = (PC + 1) & VAMASK; - return dat; -case ioOTX: /* output */ - dpd_obuf = dat; - if (!dpc_busy || dpd_xfer) dpd_wval = 1; /* if !overrun, valid */ - break; -case ioMIX: /* merge */ - dat = dat | dpd_ibuf; - break; -case ioLIX: /* load */ - dat = dpd_ibuf; - break; -case ioCTL: /* control clear/set */ - if (IR & I_CTL) { /* CLC */ - clrCTL (devd); /* clr ctl, cmd */ - clrCMD (devd); - dpd_xfer = 0; } /* clr xfer */ - else { /* STC */ - if (!dp_ctype) setCTL (devd); /* 12557: set ctl */ - setCMD (devd); /* set cmd */ - if (dpc_busy && !dpd_xfer) /* overrun? */ - dpc_sta[dpc_busy - 1] |= STA_OVR; } - break; -default: - break; } -if (IR & I_HC) { clrFLG (devd); } /* H/C option */ -return dat; -} - -int32 dpcio (int32 inst, int32 IR, int32 dat) -{ -int32 i, devc, fnc, drv; -int32 devd = dpd_dib.devno; - -devc = IR & I_DEVMASK; /* get device no */ -switch (inst) { /* case on opcode */ -case ioFLG: /* flag clear/set */ - if ((IR & I_HC) == 0) { setFLG (devc); } /* STF */ - break; -case ioSFC: /* skip flag clear */ - if (FLG (devc) == 0) PC = (PC + 1) & VAMASK; - return dat; -case ioSFS: /* skip flag set */ - if (FLG (devc) != 0) PC = (PC + 1) & VAMASK; - return dat; -case ioOTX: /* output */ - dpc_obuf = dat; - break; -case ioLIX: /* load */ - dat = 0; -case ioMIX: /* merge */ - for (i = 0; i < DP_NUMDRV; i++) - if (dpc_sta[i] & STA_ATN) dat = dat | (1 << i); - break; -case ioCTL: /* control clear/set */ - if (IR & I_CTL) { /* CLC? */ - clrCTL (devc); /* clr cmd, ctl */ - clrCMD (devc); /* cancel non-seek */ - if (dpc_busy) sim_cancel (&dpc_unit[dpc_busy - 1]); - sim_cancel (&dpd_unit); /* cancel dch */ - dpd_xfer = 0; /* clr dch xfer */ - dpc_busy = 0; } /* clr cch busy */ - else { /* STC */ - setCTL (devc); /* set ctl */ - if (!CMD (devc)) { /* is cmd clr? */ - setCMD (devc); /* set cmd */ - drv = CW_GETDRV (dpc_obuf); /* get fnc, drv */ - fnc = CW_GETFNC (dpc_obuf); /* from cmd word */ - switch (fnc) { /* case on fnc */ - case FNC_STA: /* rd sta */ - if (dp_ctype) { clrFLG (devd); } /* 13210? clr dch flag */ - case FNC_SEEK: case FNC_CHK: /* seek, check */ - case FNC_AR: /* addr rec */ - dp_god (fnc, drv, dpc_dtime); /* sched dch xfr */ - break; - case FNC_RD: case FNC_WD: /* read, write */ - case FNC_REF: case FNC_INIT: /* refine, init */ - dp_goc (fnc, drv, dpc_ctime); /* sched drive */ - break; } /* end case */ - } - } /* end else */ - break; -default: - break; } -if (IR & I_HC) { clrFLG (devc); } /* H/C option */ -return dat; -} - -/* Start data channel operation */ - -void dp_god (int32 fnc, int32 drv, int32 time) -{ -dpd_unit.CYL = drv; /* save unit */ -dpd_unit.FNC = fnc; /* save function */ -sim_activate (&dpd_unit, time); -return; -} - -/* Start controller operation */ - -void dp_goc (int32 fnc, int32 drv, int32 time) -{ -if (sim_is_active (&dpc_unit[drv])) { /* still seeking? */ - sim_cancel (&dpc_unit[drv]); /* stop seek */ - dpc_sta[drv] = dpc_sta[drv] & ~STA_BSY; /* clear busy */ - time = time + dpc_stime; } /* take longer */ -dp_ptr = 0; /* init buf ptr */ -dpc_eoc = 0; /* clear end cyl */ -dpc_busy = drv + 1; /* set busy */ -dpd_xfer = 1; /* xfer in prog */ -dpc_unit[drv].FNC = fnc; /* save function */ -sim_activate (&dpc_unit[drv], time); /* activate unit */ -return; -} - -/* Data channel unit service - - This routine handles the data channel transfers. It also handles - data transfers that are blocked by seek in progress. - - uptr->CYL = target drive - uptr->FNC = target function - - Seek substates - seek - transfer cylinder - seek1 - transfer head/surface - Address record - ar - transfer cylinder - ar1 - transfer head/surface, finish operation - Status check - transfer status, finish operation - Check data - chk - transfer sector count -*/ - -t_stat dpd_svc (UNIT *uptr) -{ -int32 drv, devc, devd, st; - -drv = uptr->CYL; /* get drive no */ -devc = dpc_dib.devno; /* get cch devno */ -devd = dpd_dib.devno; /* get dch devno */ -switch (uptr->FNC) { /* case function */ - -case FNC_SEEK: /* seek, need cyl */ - if (CMD (devd)) { /* dch active? */ - dpc_rarc[drv] = DA_GETCYL (dpd_obuf); /* take cyl word */ - dpd_wval = 0; /* clr data valid */ - setFLG (devd); /* set dch flg */ - clrCMD (devd); /* clr dch cmd */ - uptr->FNC = FNC_SEEK1; } /* advance state */ - sim_activate (uptr, dpc_xtime); /* no, wait more */ - break; -case FNC_SEEK1: /* seek, need hd/sec */ - if (CMD (devd)) { /* dch active? */ - dpc_rarh[drv] = DA_GETHD (dpd_obuf); /* get head */ - dpc_rars[drv] = DA_GETSC (dpd_obuf); /* get sector */ - dpd_wval = 0; /* clr data valid */ - setFLG (devd); /* set dch flg */ - clrCMD (devd); /* clr dch cmd */ - if (sim_is_active (&dpc_unit[drv])) { /* if busy, */ - dpc_sta[drv] = dpc_sta[drv] | STA_SKE; - break; } /* error, ignore */ - st = abs (dpc_rarc[drv] - dpc_unit[drv].CYL) * dpc_stime; - if (st == 0) st = dpc_stime; /* min time */ - sim_activate (&dpc_unit[drv], st); /* schedule drive */ - dpc_sta[drv] = (dpc_sta[drv] | STA_BSY) & - ~(STA_SKE | STA_SKI | STA_HUNT); - dpc_unit[drv].CYL = dpc_rarc[drv]; /* on cylinder */ - dpc_unit[drv].FNC = FNC_SEEK2; } /* set operation */ - else sim_activate (uptr, dpc_xtime); /* no, wait more */ - break; - -case FNC_AR: /* arec, need cyl */ - if (CMD (devd)) { /* dch active? */ - dpc_rarc[drv] = DA_GETCYL (dpd_obuf); /* take cyl word */ - dpd_wval = 0; /* clr data valid */ - setFLG (devd); /* set dch flg */ - clrCMD (devd); /* clr dch cmd */ - uptr->FNC = FNC_AR1; } /* advance state */ - sim_activate (uptr, dpc_xtime); /* no, wait more */ - break; -case FNC_AR1: /* arec, need hd/sec */ - if (CMD (devd)) { /* dch active? */ - dpc_rarh[drv] = DA_GETHD (dpd_obuf); /* get head */ - dpc_rars[drv] = DA_GETSC (dpd_obuf); /* get sector */ - dpd_wval = 0; /* clr data valid */ - setFLG (devc); /* set cch flg */ - clrCMD (devc); /* clr cch cmd */ - setFLG (devd); /* set dch flg */ - clrCMD (devd); } /* clr dch cmd */ - else sim_activate (uptr, dpc_xtime); /* no, wait more */ - break; - -case FNC_STA: /* read status */ - if (CMD (devd) || dp_ctype) { /* dch act or 13210? */ - if (dpc_unit[drv].flags & UNIT_ATT) { /* attached? */ - dpd_ibuf = dpc_sta[drv] & ~STA_ERR; /* clear err */ - if (dp_ctype) dpd_ibuf = /* 13210? */ - (dpd_ibuf & ~(STA_MBZ13 | STA_PROT)) | - (uptr->flags & UNIT_WPRT? STA_PROT: 0); } - else dpd_ibuf = STA_NRDY; /* not ready */ - if (dpd_ibuf & STA_ALLERR) /* errors? set flg */ - dpd_ibuf = dpd_ibuf | STA_ERR; - setFLG (devd); /* set dch flg */ - clrCMD (devd); /* clr dch cmd */ - clrCMD (devc); /* clr cch cmd */ - dpc_sta[drv] = dpc_sta[drv] & /* clr sta flags */ - ~(STA_ATN | STA_1ST | STA_OVR | - STA_RWU | STA_ACU | STA_EOC | - STA_AER | STA_FLG | STA_DTE); } - else sim_activate (uptr, dpc_xtime); /* wait more */ - break; - -case FNC_CHK: /* check, need cnt */ - if (CMD (devd)) { /* dch active? */ - dpc_cnt = dpd_obuf & DA_CKMASK; /* get count */ - dpd_wval = 0; /* clr data valid */ -/* setFLG (devd); /* set dch flg */ -/* clrCMD (devd); /* clr dch cmd */ - dp_goc (FNC_CHK1, drv, dpc_xtime); } /* sched drv */ - else sim_activate (uptr, dpc_xtime); /* wait more */ - break; - -default: - return SCPE_IERR; } - -return SCPE_OK; -} - -/* Drive unit service - - This routine handles the data transfers. - - Seek substates - seek2 - done - Refine sector - erase sector, finish operation - Check data - chk1 - finish operation - Read - Write -*/ - -#define GETDA(x,y,z) \ - (((((x) * DP_NUMSF) + (y)) * DP_NUMSC) + (z)) * DP_NUMWD - -t_stat dpc_svc (UNIT *uptr) -{ -int32 da, drv, devc, devd, err; - -err = 0; /* assume no err */ -drv = uptr - dpc_dev.units; /* get drive no */ -devc = dpc_dib.devno; /* get cch devno */ -devd = dpd_dib.devno; /* get dch devno */ -if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */ - setFLG (devc); /* set cch flg */ - clrCMD (devc); /* clr cch cmd */ - dpc_sta[drv] = 0; /* clr status */ - dpc_busy = 0; /* ctlr is free */ - dpd_xfer = dpd_wval = 0; - return SCPE_OK; } -switch (uptr->FNC) { /* case function */ - -case FNC_SEEK2: /* seek done */ - dpc_sta[drv] = (dpc_sta[drv] | STA_ATN) & ~STA_BSY; - if (uptr->CYL >= DP_NUMCY) { /* invalid cyl? */ - dpc_sta[drv] = dpc_sta[drv] | STA_SKE; - uptr->CYL = DP_NUMCY - 1; } -case FNC_SEEK3: /* waiting for flag */ - if (dpc_busy || FLG (devc)) { /* ctrl busy? wait */ - uptr->FNC = FNC_SEEK3; /* next state */ - sim_activate (uptr, dpc_xtime); } - else { - setFLG (devc); /* set cch flg */ - clrCMD (devc); } /* clear cmd */ - return SCPE_OK; - -case FNC_REF: /* refine sector */ - break; /* just a NOP */ - -case FNC_RD: /* read */ -case FNC_CHK1: /* check */ - if (dp_ptr == 0) { /* new sector? */ - if (!CMD (devd) && (uptr->FNC != FNC_CHK1)) break; - if (uptr->CYL != dpc_rarc[drv]) /* wrong cyl? */ - dpc_sta[drv] = dpc_sta[drv] | STA_AER; /* set flag, read */ - if (dpc_rars[drv] >= DP_NUMSC) { /* bad sector? */ - dpc_sta[drv] = dpc_sta[drv] | STA_AER; /* set flag, stop */ - break; } - if (dpc_eoc) { /* end of cyl? */ - dpc_sta[drv] = dpc_sta[drv] | STA_EOC; - break; } - da = GETDA (dpc_rarc[drv], dpc_rarh[drv], dpc_rars[drv]); - dpc_rars[drv] = dpc_rars[drv] + 1; /* incr address */ - if (dpc_rars[drv] >= DP_NUMSC) { /* end of surf? */ - dpc_rars[drv] = 0; /* wrap to */ - dpc_rarh[drv] = dpc_rarh[drv] ^ 1; /* next head */ - dpc_eoc = ((dpc_rarh[drv] & 1) == 0); }/* calc eoc */ - if (err = fseek (uptr->fileref, da * sizeof (int16), - SEEK_SET)) break; - fxread (dpxb, sizeof (int16), DP_NUMWD, uptr->fileref); - if (err = ferror (uptr->fileref)) break; } - dpd_ibuf = dpxb[dp_ptr++]; /* get word */ - if (dp_ptr >= DP_NUMWD) { /* end of sector? */ - if (uptr->FNC == FNC_CHK1) { /* check? */ - dpc_cnt = (dpc_cnt - 1) & DA_CKMASK; /* decr count */ - if (dpc_cnt == 0) break; } /* stop at zero */ - dp_ptr = 0; } /* wrap buf ptr */ - if (CMD (devd) && dpd_xfer) { /* dch on, xfer? */ - setFLG (devd); } /* set flag */ - clrCMD (devd); /* clr dch cmd */ - sim_activate (uptr, dpc_xtime); /* sched next word */ - return SCPE_OK; - -case FNC_INIT: /* init */ -case FNC_WD: /* write */ - if (dp_ptr == 0) { /* start sector? */ - if (!CMD (devd) && !dpd_wval) break; /* xfer done? */ - if (uptr->flags & UNIT_WPRT) { /* wr prot? */ - dpc_sta[drv] = dpc_sta[drv] | STA_FLG; /* set status */ - break; } /* done */ - if ((uptr->CYL != dpc_rarc[drv]) || /* wrong cyl or */ - (dpc_rars[drv] >= DP_NUMSC)) { /* bad sector? */ - dpc_sta[drv] = dpc_sta[drv] | STA_AER; /* set flag, stop */ - break; } - if (dpc_eoc) { /* end of cyl? */ - dpc_sta[drv] = dpc_sta[drv] | STA_EOC; /* set status */ - break; } } /* done */ - dpxb[dp_ptr++] = dpd_wval? dpd_obuf: 0; /* store word/fill */ - dpd_wval = 0; /* clr data valid */ - if (dp_ptr >= DP_NUMWD) { /* buffer full? */ - da = GETDA (dpc_rarc[drv], dpc_rarh[drv], dpc_rars[drv]); - dpc_rars[drv] = dpc_rars[drv] + 1; /* incr address */ - if (dpc_rars[drv] >= DP_NUMSC) { /* end of surf? */ - dpc_rars[drv] = 0; /* wrap to */ - dpc_rarh[drv] = dpc_rarh[drv] ^ 1; /* next head */ - dpc_eoc = ((dpc_rarh[drv] & 1) == 0); }/* calc eoc */ - if (err = fseek (uptr->fileref, da * sizeof (int16), - SEEK_SET)) break; - fxwrite (dpxb, sizeof (int16), DP_NUMWD, uptr->fileref); - if (err = ferror (uptr->fileref)) break; /* error? */ - dp_ptr = 0; } /* next sector */ - if (CMD (devd) && dpd_xfer) { /* dch on, xfer? */ - setFLG (devd); } /* set flag */ - clrCMD (devd); /* clr dch cmd */ - sim_activate (uptr, dpc_xtime); /* sched next word */ - return SCPE_OK; - -default: - return SCPE_IERR; } /* end case fnc */ - -if (!dp_ctype) dpc_sta[drv] = dpc_sta[drv] | STA_ATN; /* 12559 sets ATN */ -setFLG (devc); /* set cch flg */ -clrCMD (devc); /* clr cch cmd */ -dpc_busy = 0; /* ctlr is free */ -dpd_xfer = dpd_wval = 0; -if (err != 0) { /* error? */ - perror ("DP I/O error"); - clearerr (uptr->fileref); - return SCPE_IOERR; } -return SCPE_OK; -} - -/* Reset routine */ - -t_stat dpc_reset (DEVICE *dptr) -{ -int32 i; - -hp_enbdis_pair (&dpc_dev, &dpd_dev); /* make pair cons */ -dpd_ibuf = dpd_obuf = 0; /* clear buffers */ -dpc_busy = dpc_obuf = 0; -dpc_eoc = 0; -dpd_xfer = dpd_wval = 0; -dp_ptr = 0; -dpc_dib.cmd = dpd_dib.cmd = 0; /* clear cmd */ -dpc_dib.ctl = dpd_dib.ctl = 0; /* clear ctl */ -dpc_dib.fbf = dpd_dib.fbf = 1; /* set fbf */ -dpc_dib.flg = dpd_dib.flg = 1; /* set flg */ -sim_cancel (&dpd_unit); /* cancel dch */ -for (i = 0; i < DP_NUMDRV; i++) { /* loop thru drives */ - sim_cancel (&dpc_unit[i]); /* cancel activity */ - dpc_unit[i].FNC = 0; /* clear function */ - dpc_unit[i].CYL = 0; - dpc_rarc[i] = dpc_rarh[i] = dpc_rars[i] = 0; - if (dpc_unit[i].flags & UNIT_ATT) - dpc_sta[i] = dpc_sta[i] & STA_1ST; - else dpc_sta[i] = 0; } -return SCPE_OK; -} - -/* Attach routine */ - -t_stat dpc_attach (UNIT *uptr, char *cptr) -{ -int32 drv; -t_stat r; - -drv = uptr - dpc_dev.units; /* get drive no */ -r = attach_unit (uptr, cptr); /* attach unit */ -if (r != SCPE_OK) return r; -dpc_sta[drv] = dpc_sta[drv] | STA_1ST; /* update status */ -return r; -} - -/* Set controller type */ - -t_stat dp_settype (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -int32 i; - -if ((val < 0) || (val > 1) || (cptr != NULL)) return SCPE_ARG; -for (i = 0; i < DP_NUMDRV; i++) { - if (dpc_unit[i].flags & UNIT_ATT) return SCPE_ALATT; } -for (i = 0; i < DP_NUMDRV; i++) - dpc_unit[i].capac = (val? DP_SIZE3: DP_SIZE2); -dp_ctype = val; -return SCPE_OK; -} - -/* Show controller type */ - -t_stat dp_showtype (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -if (dp_ctype) fprintf (st, "13210A"); -else fprintf (st, "12557A"); -return SCPE_OK; -} - -/* 7900/7901 bootstrap routine (HP 12992F ROM) */ - -#define LDR_BASE 077 -#define CHANGE_DEV (1 << 24) - -static const int32 dboot[IBL_LNT] = { - 0106700+CHANGE_DEV, /*ST CLC DC ; clr dch */ - 0106701+CHANGE_DEV, /* CLC CC ; clr cch */ - 0017757, /* JSB STAT ; get status */ - 0067746, /*SK LDB SKCMD ; seek cmd */ - 0106600+CHANGE_DEV, /* OTB DC ; cyl # */ - 0103700+CHANGE_DEV, /* STC DC,C ; to dch */ - 0106601+CHANGE_DEV, /* OTB CC ; seek cmd */ - 0103701+CHANGE_DEV, /* STC CC,C ; to cch */ - 0102300+CHANGE_DEV, /* SFS DC ; addr wd ok? */ - 0027710, /* JMP *-1 ; no, wait */ - 0006400, /* CLB */ - 0102501, /* LIA 1 ; read switches */ - 0002011, /* SLA,RSS ; <0> set? */ - 0047747, /* ADB BIT9 ; head 2 = fixed */ - 0106600+CHANGE_DEV, /* OTB DC ; head/sector */ - 0103700+CHANGE_DEV, /* STC DC,C ; to dch */ - 0102301+CHANGE_DEV, /* SFS CC ; seek done? */ - 0027720, /* JMP *-1 ; no, wait */ - 0017757, /* JSB STAT ; get status */ - 0067776, /* LDB DMACW ; DMA control */ - 0106606, /* OTB 6 */ - 0067750, /* LDB ADDR1 ; memory addr */ - 0106602, /* OTB 2 */ - 0102702, /* STC 2 ; flip DMA ctrl */ - 0067752, /* LDB CNT ; word count */ - 0106602, /* OTB 2 */ - 0063745, /* LDB RDCMD ; read cmd */ - 0102601+CHANGE_DEV, /* OTA CC ; to cch */ - 0103700+CHANGE_DEV, /* STC DC,C ; start dch */ - 0103606, /* STC 6,C ; start DMA */ - 0103701+CHANGE_DEV, /* STC CC,C ; start cch */ - 0102301+CHANGE_DEV, /* SFS CC ; done? */ - 0027737, /* JMP *-1 ; no, wait */ - 0017757, /* JSB STAT ; get status */ - 0027775, /* JMP XT ; done */ - 0037766, /*FSMSK 037766 ; status mask */ - 0004000, /*STMSK 004000 ; unsafe mask */ - 0020000, /*RDCMD 020000 ; read cmd */ - 0030000, /*SKCMD 030000 ; seek cmd */ - 0001000, /*BIT9 001000 ; head 2 select */ - 0102011, /*ADDR1 102011 */ - 0102055, /*ADDR2 102055 */ - 0164000, /*CNT -6144. */ - 0, 0, 0, 0, /* unused */ - 0000000, /*STAT 0 */ - 0002400, /* CLA ; status request */ - 0102601+CHANGE_DEV, /* OTC CC ; to cch */ - 0103701+CHANGE_DEV, /* STC CC,C ; start cch */ - 0102300+CHANGE_DEV, /* SFS DC ; done? */ - 0027763, /* JMP *-1 */ - 0102500+CHANGE_DEV, /* LIA DC ; get status */ - 0013743, /* AND FSMSK ; mask 15,14,3,0 */ - 0002003, /* SZA,RSS ; drive ready? */ - 0127757, /* JMP STAT,I ; yes */ - 0013744, /* AND STMSK ; fault? */ - 0002002, /* SZA */ - 0102030, /* HLT 30 ; yes */ - 0027700, /* JMP ST ; no, retry */ - 0117751, /*XT JSB ADDR2,I ; start program */ - 0120000+CHANGE_DEV, /*DMACW 120000+DC */ - 0000000 }; /* -ST */ - -t_stat dpc_boot (int32 unitno, DEVICE *dptr) -{ -int32 i, dev; - -if (unitno != 0) return SCPE_NOFNC; /* only unit 0 */ -dev = dpd_dib.devno; /* get data chan dev */ -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_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_dq.c b/HP2100/hp2100_dq.c deleted file mode 100644 index 47edee33..00000000 --- a/HP2100/hp2100_dq.c +++ /dev/null @@ -1,720 +0,0 @@ -/* hp2100_dq.c: HP 2100 12565A disk simulator - - Copyright (c) 1993-2003, Bill McDermith - - 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 the author shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from the author. - - dq 12565A 2883 disk system - - 25-Apr-03 RMS Fixed bug in status check - 10-Nov-02 RMS Added boot command, rebuilt like 12559/13210 - 09-Jan-02 WOM Copied dp driver and mods for 2883 - - Differences between 12559/13210 and 12565 controllers - - 12565 stops transfers on address miscompares; 12559/13210 only stops writes - - 12565 does not set error on positioner busy - - 12565 does not set positioner busy if already on cylinder - - 12565 does not need eoc logic, it will hit an invalid head number -*/ - -#include "hp2100_defs.h" - -#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */ -#define UNIT_WLK (1 << UNIT_V_WLK) -#define FNC u3 /* saved function */ -#define CYL u4 /* cylinder */ -#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write prot */ - -#define DQ_N_NUMWD 7 -#define DQ_NUMWD (1 << DQ_N_NUMWD) /* words/sector */ -#define DQ_NUMSC 23 /* sectors/track */ -#define DQ_NUMSF 20 /* tracks/cylinder */ -#define DQ_NUMCY 203 /* cylinders/disk */ -#define DQ_SIZE (DQ_NUMSF * DQ_NUMCY * DQ_NUMSC * DQ_NUMWD) -#define DQ_NUMDRV 2 /* # drives */ - -/* Command word */ - -#define CW_V_FNC 12 /* function */ -#define CW_M_FNC 017 -#define CW_GETFNC(x) (((x) >> CW_V_FNC) & CW_M_FNC) -/* 000 /* unused */ -#define FNC_STA 001 /* status check */ -#define FNC_RCL 002 /* recalibrate */ -#define FNC_SEEK 003 /* seek */ -#define FNC_RD 004 /* read */ -#define FNC_WD 005 /* write */ -#define FNC_RA 006 /* read address */ -#define FNC_WA 007 /* write address */ -#define FNC_CHK 010 /* check */ -#define FNC_LA 013 /* load address */ -#define FNC_AS 014 /* address skip */ - -#define FNC_SEEK1 020 /* fake - seek1 */ -#define FNC_SEEK2 021 /* fake - seek2 */ -#define FNC_SEEK3 022 /* fake - seek3 */ -#define FNC_CHK1 023 /* fake - check1 */ -#define FNC_LA1 024 /* fake - ldaddr1 */ - -#define CW_V_DRV 0 /* drive */ -#define CW_M_DRV 01 -#define CW_GETDRV(x) (((x) >> CW_V_DRV) & CW_M_DRV) - -/* Disk address words */ - -#define DA_V_CYL 0 /* cylinder */ -#define DA_M_CYL 0377 -#define DA_GETCYL(x) (((x) >> DA_V_CYL) & DA_M_CYL) -#define DA_V_HD 8 /* head */ -#define DA_M_HD 037 -#define DA_GETHD(x) (((x) >> DA_V_HD) & DA_M_HD) -#define DA_V_SC 0 /* sector */ -#define DA_M_SC 037 -#define DA_GETSC(x) (((x) >> DA_V_SC) & DA_M_SC) -#define DA_CKMASK 0777 /* check mask */ - -/* Status in dqc_sta[drv] - (d) = dynamic */ - -#define STA_DID 0000200 /* drive ID (d) */ -#define STA_NRDY 0000100 /* not ready (d) */ -#define STA_EOC 0000040 /* end of cylinder */ -#define STA_AER 0000020 /* addr error */ -#define STA_FLG 0000010 /* flagged */ -#define STA_BSY 0000004 /* seeking */ -#define STA_DTE 0000002 /* data error */ -#define STA_ERR 0000001 /* any error */ -#define STA_ALLERR (STA_NRDY + STA_EOC + STA_AER + STA_FLG + STA_DTE) - -extern uint16 *M; -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; - -int32 dqc_busy = 0; /* cch xfer */ -int32 dqc_cnt = 0; /* check count */ -int32 dqc_stime = 100; /* seek time */ -int32 dqc_ctime = 100; /* command time */ -int32 dqc_xtime = 5; /* xfer time */ -int32 dqc_dtime = 2; /* dch time */ -int32 dqd_obuf = 0, dqd_ibuf = 0; /* dch buffers */ -int32 dqc_obuf = 0; /* cch buffers */ -int32 dqd_xfer = 0; /* xfer in prog */ -int32 dqd_wval = 0; /* write data valid */ -int32 dq_ptr = 0; /* buffer ptr */ -uint8 dqc_rarc[DQ_NUMDRV] = { 0 }; /* cylinder */ -uint8 dqc_rarh[DQ_NUMDRV] = { 0 }; /* head */ -uint8 dqc_rars[DQ_NUMDRV] = { 0 }; /* sector */ -uint16 dqc_sta[DQ_NUMDRV] = { 0 }; /* status regs */ -uint16 dqxb[DQ_NUMWD]; /* sector buffer */ - -DEVICE dqd_dev, dqc_dev; -int32 dqdio (int32 inst, int32 IR, int32 dat); -int32 dqcio (int32 inst, int32 IR, int32 dat); -t_stat dqc_svc (UNIT *uptr); -t_stat dqd_svc (UNIT *uptr); -t_stat dqc_reset (DEVICE *dptr); -t_stat dqc_boot (int32 unitno, DEVICE *dptr); -void dq_god (int32 fnc, int32 drv, int32 time); -void dq_goc (int32 fnc, int32 drv, int32 time); - -/* DQD data structures - - dqd_dev DQD device descriptor - dqd_unit DQD unit list - dqd_reg DQD register list -*/ - -DIB dq_dib[] = { - { DQD, 0, 0, 0, 0, &dqdio }, - { DQC, 0, 0, 0, 0, &dqcio } }; - -#define dqd_dib dq_dib[0] -#define dqc_dib dq_dib[1] - -UNIT dqd_unit = { UDATA (&dqd_svc, 0, 0) }; - -REG dqd_reg[] = { - { ORDATA (IBUF, dqd_ibuf, 16) }, - { ORDATA (OBUF, dqd_obuf, 16) }, - { FLDATA (CMD, dqd_dib.cmd, 0) }, - { FLDATA (CTL, dqd_dib.ctl, 0) }, - { FLDATA (FLG, dqd_dib.flg, 0) }, - { FLDATA (FBF, dqd_dib.fbf, 0) }, - { FLDATA (XFER, dqd_xfer, 0) }, - { FLDATA (WVAL, dqd_wval, 0) }, - { BRDATA (DBUF, dqxb, 8, 16, DQ_NUMWD) }, - { DRDATA (BPTR, dq_ptr, DQ_N_NUMWD) }, - { ORDATA (DEVNO, dqd_dib.devno, 6), REG_HRO }, - { NULL } }; - -MTAB dqd_mod[] = { - { MTAB_XTD | MTAB_VDV, 1, "DEVNO", "DEVNO", - &hp_setdev, &hp_showdev, &dqd_dev }, - { 0 } }; - -DEVICE dqd_dev = { - "DQD", &dqd_unit, dqd_reg, dqd_mod, - 1, 10, DQ_N_NUMWD, 1, 8, 16, - NULL, NULL, &dqc_reset, - NULL, NULL, NULL, - &dqd_dib, 0 }; - -/* DQC data structures - - dqc_dev DQC device descriptor - dqc_unit DQC unit list - dqc_reg DQC register list - dqc_mod DQC modifier list -*/ - -UNIT dqc_unit[] = { - { UDATA (&dqc_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE, DQ_SIZE) }, - { UDATA (&dqc_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE, DQ_SIZE) } }; - -REG dqc_reg[] = { - { ORDATA (OBUF, dqc_obuf, 16) }, - { ORDATA (BUSY, dqc_busy, 2), REG_RO }, - { ORDATA (CNT, dqc_cnt, 9) }, - { FLDATA (CMD, dqc_dib.cmd, 0) }, - { FLDATA (CTL, dqc_dib.ctl, 0) }, - { FLDATA (FLG, dqc_dib.flg, 0) }, - { FLDATA (FBF, dqc_dib.fbf, 0) }, - { BRDATA (RARC, dqc_rarc, 8, 8, DQ_NUMDRV) }, - { BRDATA (RARH, dqc_rarh, 8, 5, DQ_NUMDRV) }, - { BRDATA (RARS, dqc_rars, 8, 5, DQ_NUMDRV) }, - { BRDATA (STA, dqc_sta, 8, 16, DQ_NUMDRV) }, - { DRDATA (CTIME, dqc_ctime, 24), PV_LEFT }, - { DRDATA (DTIME, dqc_dtime, 24), PV_LEFT }, - { DRDATA (STIME, dqc_stime, 24), PV_LEFT }, - { DRDATA (XTIME, dqc_xtime, 24), REG_NZ + PV_LEFT }, - { URDATA (UCYL, dqc_unit[0].CYL, 10, 8, 0, - DQ_NUMDRV, PV_LEFT | REG_HRO) }, - { URDATA (UFNC, dqc_unit[0].FNC, 8, 8, 0, - DQ_NUMDRV, REG_HRO) }, - { ORDATA (DEVNO, dqc_dib.devno, 6), REG_HRO }, - { NULL } }; - -MTAB dqc_mod[] = { - { UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL }, - { UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL }, - { MTAB_XTD | MTAB_VDV, 1, "DEVNO", "DEVNO", - &hp_setdev, &hp_showdev, &dqd_dev }, - { 0 } }; - -DEVICE dqc_dev = { - "DQC", dqc_unit, dqc_reg, dqc_mod, - DQ_NUMDRV, 8, 24, 1, 8, 16, - NULL, NULL, &dqc_reset, - &dqc_boot, NULL, NULL, - &dqc_dib, DEV_DISABLE }; - -/* IOT routines */ - -int32 dqdio (int32 inst, int32 IR, int32 dat) -{ -int32 devd; - -devd = IR & I_DEVMASK; /* get device no */ -switch (inst) { /* case on opcode */ -case ioFLG: /* flag clear/set */ - if ((IR & I_HC) == 0) { setFLG (devd); } /* STF */ - break; -case ioSFC: /* skip flag clear */ - if (FLG (devd) == 0) PC = (PC + 1) & VAMASK; - return dat; -case ioSFS: /* skip flag set */ - if (FLG (devd) != 0) PC = (PC + 1) & VAMASK; - return dat; -case ioOTX: /* output */ - dqd_obuf = dat; - if (!dqc_busy || dqd_xfer) dqd_wval = 1; /* if !overrun, valid */ - break; -case ioMIX: /* merge */ - dat = dat | dqd_ibuf; - break; -case ioLIX: /* load */ - dat = dqd_ibuf; - break; -case ioCTL: /* control clear/set */ - if (IR & I_CTL) { /* CLC */ - clrCTL (devd); /* clr ctl, cmd */ - clrCMD (devd); - dqd_xfer = 0; } /* clr xfer */ - else { /* STC */ - setCTL (devd); /* set ctl, cmd */ - setCMD (devd); - if (dqc_busy && !dqd_xfer) /* overrun? */ - dqc_sta[dqc_busy - 1] |= STA_DTE | STA_ERR; } - break; -default: - break; } -if (IR & I_HC) { clrFLG (devd); } /* H/C option */ -return dat; -} - -int32 dqcio (int32 inst, int32 IR, int32 dat) -{ -int32 devc, fnc, drv; - -devc = IR & I_DEVMASK; /* get device no */ -switch (inst) { /* case on opcode */ -case ioFLG: /* flag clear/set */ - if ((IR & I_HC) == 0) { setFLG (devc); } /* STF */ - break; -case ioSFC: /* skip flag clear */ - if (FLG (devc) == 0) PC = (PC + 1) & VAMASK; - return dat; -case ioSFS: /* skip flag set */ - if (FLG (devc) != 0) PC = (PC + 1) & VAMASK; - return dat; -case ioOTX: /* output */ - dqc_obuf = dat; - break; -case ioLIX: /* load */ - dat = 0; -case ioMIX: /* merge */ - break; /* no data */ -case ioCTL: /* control clear/set */ - if (IR & I_CTL) { /* CLC? */ - clrCMD (devc); /* clr cmd, ctl */ - clrCTL (devc); /* cancel non-seek */ - if (dqc_busy) sim_cancel (&dqc_unit[dqc_busy - 1]); - sim_cancel (&dqd_unit); /* cancel dch */ - dqd_xfer = 0; /* clr dch xfer */ - dqc_busy = 0; } /* clr busy */ - else { /* STC */ - setCTL (devc); /* set ctl */ - if (!CMD (devc)) { /* cmd clr? */ - setCMD (devc); /* set cmd, ctl */ - drv = CW_GETDRV (dqc_obuf); /* get fnc, drv */ - fnc = CW_GETFNC (dqc_obuf); /* from cmd word */ - switch (fnc) { /* case on fnc */ - case FNC_SEEK: case FNC_RCL: /* seek, recal */ - case FNC_CHK: /* check */ - dqc_sta[drv] = 0; /* clear status */ - case FNC_STA: case FNC_LA: /* rd sta, load addr */ - dq_god (fnc, drv, dqc_dtime); /* sched dch xfer */ - break; - case FNC_RD: case FNC_WD: /* read, write */ - case FNC_RA: case FNC_WA: /* rd addr, wr addr */ - case FNC_AS: /* address skip */ - dq_goc (fnc, drv, dqc_ctime); /* sched drive */ - break; } /* end case */ - } /* end if !CMD */ - } /* end else */ - break; -default: - break; } -if (IR & I_HC) { clrFLG (devc); } /* H/C option */ -return dat; -} - -/* Start data channel operation */ - -void dq_god (int32 fnc, int32 drv, int32 time) -{ -dqd_unit.CYL = drv; /* save unit */ -dqd_unit.FNC = fnc; /* save function */ -sim_activate (&dqd_unit, time); -return; -} - -/* Start controller operation */ - -void dq_goc (int32 fnc, int32 drv, int32 time) -{ -if (sim_is_active (&dqc_unit[drv])) { /* still seeking? */ - sim_cancel (&dqc_unit[drv]); /* cancel */ - time = time + dqc_stime; } /* take longer */ -dqc_sta[drv] = 0; /* clear status */ -dq_ptr = 0; /* init buf ptr */ -dqc_busy = drv + 1; /* set busy */ -dqd_xfer = 1; /* xfer in prog */ -dqc_unit[drv].FNC = fnc; /* save function */ -sim_activate (&dqc_unit[drv], time); /* activate unit */ -return; -} - -/* Data channel unit service - - This routine handles the data channel transfers. It also handles - data transfers that are blocked by seek in progress. - - uptr->CYL = target drive - uptr->FNC = target function - - Seek substates - seek - transfer cylinder - seek1 - transfer head/surface, sched drive - Recalibrate substates - rcl - clear cyl/head/surface, sched drive - Load address - la - transfer cylinder - la1 - transfer head/surface, finish operation - Status check - transfer status, finish operation - Check data - chk - transfer sector count, sched drive -*/ - -t_stat dqd_svc (UNIT *uptr) -{ -int32 drv, devc, devd, st; - -drv = uptr->CYL; /* get drive no */ -devc = dqc_dib.devno; /* get cch devno */ -devd = dqd_dib.devno; /* get dch devno */ -switch (uptr->FNC) { /* case function */ - -case FNC_SEEK: /* seek, need cyl */ - if (CMD (devd)) { /* dch active? */ - dqc_rarc[drv] = DA_GETCYL (dqd_obuf); /* take cyl word */ - dqd_wval = 0; /* clr data valid */ - setFLG (devd); /* set dch flg */ - clrCMD (devd); /* clr dch cmd */ - uptr->FNC = FNC_SEEK1; } /* advance state */ - sim_activate (uptr, dqc_xtime); /* no, wait more */ - break; -case FNC_SEEK1: /* seek, need hd/sec */ - if (CMD (devd)) { /* dch active? */ - dqc_rarh[drv] = DA_GETHD (dqd_obuf); /* get head */ - dqc_rars[drv] = DA_GETSC (dqd_obuf); /* get sector */ - dqd_wval = 0; /* clr data valid */ - setFLG (devd); /* set dch flg */ - clrCMD (devd); /* clr dch cmd */ - if (sim_is_active (&dqc_unit[drv])) break; /* if busy */ - st = abs (dqc_rarc[drv] - dqc_unit[drv].CYL) * dqc_stime; - if (st == 0) st = dqc_xtime; /* if on cyl, min time */ - else dqc_sta[drv] = dqc_sta[drv] | STA_BSY; /* set busy */ - sim_activate (&dqc_unit[drv], st); /* schedule op */ - dqc_unit[drv].CYL = dqc_rarc[drv]; /* on cylinder */ - dqc_unit[drv].FNC = FNC_SEEK2; } /* advance state */ - else sim_activate (uptr, dqc_xtime); /* no, wait more */ - break; - -case FNC_RCL: /* recalibrate */ - dqc_rarc[drv] = dqc_rarh[drv] = dqc_rars[drv] = 0; /* clear RAR */ - if (sim_is_active (&dqc_unit[drv])) break; /* ignore if busy */ - st = dqc_unit[drv].CYL * dqc_stime; /* calc diff */ - if (st == 0) st = dqc_xtime; /* if on cyl, min time */ - else dqc_sta[drv] = dqc_sta[drv] | STA_BSY; /* set busy */ - sim_activate (&dqc_unit[drv], st); /* schedule drive */ - dqc_unit[drv].CYL = 0; /* on cylinder */ - dqc_unit[drv].FNC = FNC_SEEK2; /* advance state */ - break; - -case FNC_LA: /* arec, need cyl */ - if (CMD (devd)) { /* dch active? */ - dqc_rarc[drv] = DA_GETCYL (dqd_obuf); /* take cyl word */ - dqd_wval = 0; /* clr data valid */ - setFLG (devd); /* set dch flg */ - clrCMD (devd); /* clr dch cmd */ - uptr->FNC = FNC_LA1; } /* advance state */ - sim_activate (uptr, dqc_xtime); /* no, wait more */ - break; -case FNC_LA1: /* arec, need hd/sec */ - if (CMD (devd)) { /* dch active? */ - dqc_rarh[drv] = DA_GETHD (dqd_obuf); /* get head */ - dqc_rars[drv] = DA_GETSC (dqd_obuf); /* get sector */ - dqd_wval = 0; /* clr data valid */ - setFLG (devc); /* set cch flg */ - clrCMD (devc); /* clr cch cmd */ - setFLG (devd); /* set dch flg */ - clrCMD (devd); } /* clr dch cmd */ - else sim_activate (uptr, dqc_xtime); /* no, wait more */ - break; - -case FNC_STA: /* read status */ - if (CMD (devd)) { /* dch active? */ - if (dqc_unit[drv].flags & UNIT_ATT) /* attached? */ - dqd_ibuf = dqc_sta[drv] & ~STA_DID; - else dqd_ibuf = STA_NRDY; - if (drv) dqd_ibuf = dqd_ibuf | STA_DID; - setFLG (devd); /* set dch flg */ - clrCMD (devd); /* clr dch cmd */ - clrCMD (devc); /* clr cch cmd */ - dqc_sta[drv] = dqc_sta[drv] & /* clr sta flags */ - ~(STA_DTE | STA_FLG | STA_AER | STA_EOC | STA_ERR); - } - else sim_activate (uptr, dqc_xtime); /* wait more */ - break; - -case FNC_CHK: /* check, need cnt */ - if (CMD (devd)) { /* dch active? */ - dqc_cnt = dqd_obuf & DA_CKMASK; /* get count */ - dqd_wval = 0; /* clr data valid */ -/* setFLG (devd); /* set dch flg */ -/* clrCMD (devd); /* clr dch cmd */ - dq_goc (FNC_CHK1, drv, dqc_ctime); } /* sched drv */ - else sim_activate (uptr, dqc_xtime); /* wait more */ - break; - -default: - return SCPE_IERR; } -return SCPE_OK; -} - -/* Drive unit service - - This routine handles the data transfers. - - Seek substates - seek2 - done - Recalibrate substate - rcl1 - done - Check data substates - chk1 - finish operation - Read - Read address - Address skip (read without header check) - Write - Write address -*/ - -#define GETDA(x,y,z) \ - (((((x) * DQ_NUMSF) + (y)) * DQ_NUMSC) + (z)) * DQ_NUMWD - -t_stat dqc_svc (UNIT *uptr) -{ -int32 da, drv, devc, devd, err; - -err = 0; /* assume no err */ -drv = uptr - dqc_dev.units; /* get drive no */ -devc = dqc_dib.devno; /* get cch devno */ -devd = dqd_dib.devno; /* get dch devno */ -if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */ - setFLG (devc); /* set cch flg */ - clrCMD (devc); /* clr cch cmd */ - dqc_sta[drv] = 0; /* clr status */ - dqc_busy = 0; /* ctlr is free */ - dqd_xfer = dqd_wval = 0; - return SCPE_OK; } -switch (uptr->FNC) { /* case function */ - -case FNC_SEEK2: /* seek done */ - if (uptr->CYL >= DQ_NUMCY) { /* out of range? */ - dqc_sta[drv] = dqc_sta[drv] | STA_BSY | STA_ERR; - dqc_unit[drv].CYL = 0; } - else dqc_sta[drv] = dqc_sta[drv] & ~STA_BSY; /* drive not busy */ -case FNC_SEEK3: - if (dqc_busy || FLG (devc)) { /* ctrl busy? */ - uptr->FNC = FNC_SEEK3; /* next state */ - sim_activate (uptr, dqc_xtime); } /* ctrl busy? wait */ - else { - setFLG (devc); /* set cch flg */ - clrCMD (devc); } /* clr cch cmd */ - return SCPE_OK; - -case FNC_RA: /* read addr */ - if (!CMD (devd)) break; /* dch clr? done */ - if (dq_ptr == 0) dqd_ibuf = uptr->CYL; /* 1st word? */ - else if (dq_ptr == 1) { /* second word? */ - dqd_ibuf = (dqc_rarh[drv] << DA_V_HD) | - (dqc_rars[drv] << DA_V_SC); - dqc_rars[drv] = dqc_rars[drv] + 1; /* incr address */ - if (dqc_rars[drv] >= DQ_NUMSC) /* end of surf? */ - dqc_rars[drv] = 0; } - else break; - dq_ptr = dq_ptr + 1; - setFLG (devd); /* set dch flg */ - clrCMD (devd); /* clr dch cmd */ - sim_activate (uptr, dqc_xtime); /* sched next word */ - return SCPE_OK; - -case FNC_AS: /* address skip */ -case FNC_RD: /* read */ -case FNC_CHK1: /* check */ - if (dq_ptr == 0) { /* new sector? */ - if (!CMD (devd) && (uptr->FNC != FNC_CHK1)) break; - if ((uptr->CYL != dqc_rarc[drv]) || /* wrong cyl or */ - (dqc_rars[drv] >= DQ_NUMSC)) { /* bad sector? */ - dqc_sta[drv] = dqc_sta[drv] | STA_AER | STA_ERR; - break; } - if (dqc_rarh[drv] >= DQ_NUMSF) { /* bad head? */ - dqc_sta[drv] = dqc_sta[drv] | STA_EOC | STA_ERR; - break; } - da = GETDA (dqc_rarc[drv], dqc_rarh[drv], dqc_rars[drv]); - dqc_rars[drv] = dqc_rars[drv] + 1; /* incr address */ - if (dqc_rars[drv] >= DQ_NUMSC) { /* end of surf? */ - dqc_rars[drv] = 0; /* wrap to */ - dqc_rarh[drv] = dqc_rarh[drv] + 1; } /* next head */ - if (err = fseek (uptr->fileref, da * sizeof (int16), - SEEK_SET)) break; - fxread (dqxb, sizeof (int16), DQ_NUMWD, uptr->fileref); - if (err = ferror (uptr->fileref)) break; } - dqd_ibuf = dqxb[dq_ptr++]; /* get word */ - if (dq_ptr >= DQ_NUMWD) { /* end of sector? */ - if (uptr->FNC == FNC_CHK1) { /* check? */ - dqc_cnt = (dqc_cnt - 1) & DA_CKMASK; /* decr count */ - if (dqc_cnt == 0) break; } /* if zero, done */ - dq_ptr = 0; } /* wrap buf ptr */ - if (CMD (devd) && dqd_xfer) { /* dch on, xfer? */ - setFLG (devd); } /* set flag */ - clrCMD (devd); /* clr dch cmd */ - sim_activate (uptr, dqc_xtime); /* sched next word */ - return SCPE_OK; - -case FNC_WA: /* write address */ -case FNC_WD: /* write */ - if (dq_ptr == 0) { /* sector start? */ - if (!CMD (devd) && !dqd_wval) break; /* xfer done? */ - if(uptr->flags & UNIT_WPRT) { /* write protect? */ - dqc_sta[drv] = dqc_sta[drv] | STA_FLG | STA_ERR; - break; } /* done */ - if ((uptr->CYL != dqc_rarc[drv]) || /* wrong cyl or */ - (dqc_rars[drv] >= DQ_NUMSC)) { /* bad sector? */ - dqc_sta[drv] = dqc_sta[drv] | STA_AER | STA_ERR; - break; } - if (dqc_rarh[drv] >= DQ_NUMSF) { /* bad head? */ - dqc_sta[drv] = dqc_sta[drv] | STA_EOC | STA_ERR; - break; } } /* done */ - dqxb[dq_ptr++] = dqd_wval? dqd_obuf: 0; /* store word/fill */ - dqd_wval = 0; /* clr data valid */ - if (dq_ptr >= DQ_NUMWD) { /* buffer full? */ - da = GETDA (dqc_rarc[drv], dqc_rarh[drv], dqc_rars[drv]); - dqc_rars[drv] = dqc_rars[drv] + 1; /* incr address */ - if (dqc_rars[drv] >= DQ_NUMSC) { /* end of surf? */ - dqc_rars[drv] = 0; /* wrap to */ - dqc_rarh[drv] = dqc_rarh[drv] + 1; } /* next head */ - if (err = fseek (uptr->fileref, da * sizeof (int16), - SEEK_SET)) return TRUE; - fxwrite (dqxb, sizeof (int16), DQ_NUMWD, uptr->fileref); - if (err = ferror (uptr->fileref)) break; - dq_ptr = 0; } - if (CMD (devd) && dqd_xfer) { /* dch on, xfer? */ - setFLG (devd); } /* set flag */ - clrCMD (devd); /* clr dch cmd */ - sim_activate (uptr, dqc_xtime); /* sched next word */ - return SCPE_OK; - -default: - return SCPE_IERR; } /* end case fnc */ - -setFLG (devc); /* set cch flg */ -clrCMD (devc); /* clr cch cmd */ -dqc_busy = 0; /* ctlr is free */ -dqd_xfer = dqd_wval = 0; -if (err != 0) { /* error? */ - perror ("DQ I/O error"); - clearerr (uptr->fileref); - return SCPE_IOERR; } -return SCPE_OK; -} - -/* Reset routine */ - -t_stat dqc_reset (DEVICE *dptr) -{ -int32 i; - -hp_enbdis_pair (&dqc_dev, &dqd_dev); /* make pair cons */ -dqd_ibuf = dqd_obuf = 0; /* clear buffers */ -dqc_busy = dqc_obuf = 0; -dqd_xfer = dqd_wval = 0; -dq_ptr = 0; -dqc_dib.cmd = dqd_dib.cmd = 0; /* clear cmd */ -dqc_dib.ctl = dqd_dib.ctl = 0; /* clear ctl */ -dqc_dib.fbf = dqd_dib.fbf = 1; /* set fbf */ -dqc_dib.flg = dqd_dib.flg = 1; /* set flg */ -sim_cancel (&dqd_unit); /* cancel dch */ -for (i = 0; i < DQ_NUMDRV; i++) { /* loop thru drives */ - sim_cancel (&dqc_unit[i]); /* cancel activity */ - dqc_unit[i].FNC = 0; /* clear function */ - dqc_unit[i].CYL = 0; - dqc_rarc[i] = dqc_rarh[i] = dqc_rars[i] = 0; /* clear rar */ - dqc_sta[i] = 0; } -return SCPE_OK; -} - -/* Write lock/enable routine */ - -t_stat dqc_vlock (UNIT *uptr, int32 val) -{ -if (uptr->flags & UNIT_ATT) return SCPE_ARG; -return SCPE_OK; -} - -/* 2883/2884 bootstrap routine (subset HP 12992A ROM) */ - -#define LDR_BASE 077 -#define CHANGE_DEV (1 << 24) - -static const int32 dboot[IBL_LNT] = { - 0106700+CHANGE_DEV, /*ST CLC DC ; clr dch */ - 0106701+CHANGE_DEV, /* CLC CC ; clr cch */ - 0067771, /* LDA SKCMD ; seek cmd */ - 0106600+CHANGE_DEV, /* OTB DC ; cyl # */ - 0103700+CHANGE_DEV, /* STC DC,C ; to dch */ - 0106601+CHANGE_DEV, /* OTB CC ; seek cmd */ - 0103701+CHANGE_DEV, /* STC CC,C ; to cch */ - 0102300+CHANGE_DEV, /* SFS DC ; addr wd ok? */ - 0027707, /* JMP *-1 ; no, wait */ - 0006400, /* CLB */ - 0106600+CHANGE_DEV, /* OTB DC ; head/sector */ - 0103700+CHANGE_DEV, /* STC DC,C ; to dch */ - 0102301+CHANGE_DEV, /* SFS CC ; seek done? */ - 0027714, /* JMP *-1 ; no, wait */ - 0063770, /* LDA RDCMD ; get read read */ - 0067776, /* LDB DMACW ; DMA control */ - 0106606, /* OTB 6 */ - 0067772, /* LDB ADDR1 ; memory addr */ - 0106602, /* OTB 2 */ - 0102702, /* STC 2 ; flip DMA ctrl */ - 0067774, /* LDB CNT ; word count */ - 0106602, /* OTB 2 */ - 0102601+CHANGE_DEV, /* OTA CC ; to cch */ - 0103700+CHANGE_DEV, /* STC DC,C ; start dch */ - 0103606, /* STC 6,C ; start DMA */ - 0103701+CHANGE_DEV, /* STC CC,C ; start cch */ - 0102301+CHANGE_DEV, /* SFS CC ; done? */ - 0027732, /* JMP *-1 ; no, wait */ - 0027775, /* JMP XT ; done */ - 0, 0, 0, /* unused */ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0020000, /*RDCMD 020000 ; read cmd */ - 0030000, /*SKCMD 030000 ; seek cmd */ - 0102011, /*ADDR1 102011 */ - 0102055, /*ADDR2 102055 */ - 0164000, /*CNT -6144. */ - 0117773, /*XT JSB ADDR2,I ; start program */ - 0120000+CHANGE_DEV, /*DMACW 120000+DC */ - 0000000 }; /* -ST */ - -t_stat dqc_boot (int32 unitno, DEVICE *dptr) -{ -int32 i, dev; - -if (unitno != 0) return SCPE_NOFNC; /* only unit 0 */ -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_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 deleted file mode 100644 index 9a02a638..00000000 --- a/HP2100/hp2100_dr.c +++ /dev/null @@ -1,422 +0,0 @@ -/* hp2100_dr.c: HP 2100 12606B/12610B fixed head disk/drum simulator - - 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. - - fhd 12606B 2770/2771 fixed head disk - 12610B 2773/2774/2775 drum - - These head-per-track devices are buffered in memory, to minimize overhead. - - The drum data channel does not have a command flip-flop. Its control - flip-flop is not wired into the interrupt chain; accordingly, the - simulator uses command rather than control for the data channel. Its - flag does not respond to SFS, SFC, or STF. - - The drum control channel does not have any of the traditional flip-flops. - - 27-Jul-03 RMS Fixed drum sizes - Fixed variable capacity interaction with SAVE/RESTORE - 10-Nov-02 RMS Added BOOT command -*/ - -#include "hp2100_defs.h" -#include - -/* Constants */ - -#define DR_NUMWD 64 /* words/sector */ -#define DR_FNUMSC 90 /* fhd sec/track */ -#define DR_DNUMSC 32 /* drum sec/track */ -#define DR_NUMSC ((drc_unit.flags & UNIT_DR)? DR_DNUMSC: DR_FNUMSC) -#define DR_SIZE (512 * DR_DNUMSC * DR_NUMWD) /* initial size */ -#define UNIT_V_SZ (UNIT_V_UF) /* disk vs drum */ -#define UNIT_M_SZ 017 /* size */ -#define UNIT_SZ (UNIT_M_SZ << UNIT_V_SZ) -#define UNIT_DR (1 << UNIT_V_SZ) /* low order bit */ -#define SZ_180K 000 /* disks */ -#define SZ_360K 002 -#define SZ_720K 004 -#define SZ_1024K 001 /* drums: default size */ -#define SZ_1536K 003 -#define SZ_384K 005 -#define SZ_512K 007 -#define SZ_640K 011 -#define SZ_768K 013 -#define SZ_896K 015 -#define DR_GETSZ(x) (((x) >> UNIT_V_SZ) & UNIT_M_SZ) - -/* Command word */ - -#define CW_WR 0100000 /* write vs read */ -#define CW_V_FTRK 7 /* fhd track */ -#define CW_M_FTRK 0177 -#define CW_V_DTRK 5 /* drum track */ -#define CW_M_DTRK 01777 -#define MAX_TRK (((drc_unit.flags & UNIT_DR)? CW_M_DTRK: CW_M_FTRK) + 1) -#define CW_GETTRK(x) ((drc_unit.flags & UNIT_DR)? \ - (((x) >> CW_V_DTRK) & CW_M_DTRK): \ - (((x) >> CW_V_FTRK) & CW_M_FTRK)) -#define CW_PUTTRK(x) ((drc_unit.flags & UNIT_DR)? \ - (((x) & CW_M_DTRK) << CW_V_DTRK): \ - (((x) & CW_M_FTRK) << CW_V_FTRK)) -#define CW_V_FSEC 0 /* fhd sector */ -#define CW_M_FSEC 0177 -#define CW_V_DSEC 0 /* drum sector */ -#define CW_M_DSEC 037 -#define CW_GETSEC(x) ((drc_unit.flags & UNIT_DR)? \ - (((x) >> CW_V_DSEC) & CW_M_DSEC): \ - (((x) >> CW_V_FSEC) & CW_M_FSEC)) -#define CW_PUTSEC(x) ((drc_unit.flags & UNIT_DR)? \ - (((x) & CW_M_DSEC) << CW_V_DSEC): \ - (((x) & CW_M_FSEC) << CW_V_FSEC)) - -/* Status register */ - -#define DRS_V_NS 8 /* next sector */ -#define DRS_M_NS 0177 -#define DRS_SEC 0100000 /* sector flag */ -#define DRS_RDY 0000200 /* ready */ -#define DRS_RIF 0000100 /* read inhibit */ -#define DRS_SAC 0000040 /* sector coincidence */ -#define DRS_ABO 0000010 /* abort */ -#define DRS_WEN 0000004 /* write enabled */ -#define DRS_PER 0000002 /* parity error */ -#define DRS_BSY 0000001 /* busy */ - -#define GET_CURSEC(x) ((int32) fmod (sim_gtime() / ((double) (x)), \ - ((double) ((drc_unit.flags & UNIT_DR)? DR_DNUMSC: DR_FNUMSC)))) - -extern UNIT cpu_unit; -extern uint16 *M; -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 */ -int32 drd_ibuf = 0; /* input buffer */ -int32 drd_obuf = 0; /* output buffer */ -int32 drd_ptr = 0; /* sector pointer */ -int32 dr_stopioe = 1; /* stop on error */ -int32 dr_time = 10; /* time per word */ - -static int32 sz_tab[16] = { - 184320, 1048576, 368640, 1572864, 737280, 393216, 0, 524288, - 0, 655360, 0, 786432, 0, 917504, 0, 0 }; - -DEVICE drd_dev, drc_dev; -int32 drdio (int32 inst, int32 IR, int32 dat); -int32 drcio (int32 inst, int32 IR, int32 dat); -t_stat drc_svc (UNIT *uptr); -t_stat drc_reset (DEVICE *dptr); -t_stat drc_attach (UNIT *uptr, char *cptr); -t_stat drc_boot (int32 unitno, DEVICE *dptr); -int32 dr_incda (int32 trk, int32 sec, int32 ptr); -t_stat dr_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); - -/* DRD data structures - - drd_dev device descriptor - drd_unit unit descriptor - drd_reg register list -*/ - -DIB dr_dib[] = { - { DRD, 0, 0, 0, 0, &drdio }, - { DRC, 0, 0, 0, 0, &drcio } }; - -#define drd_dib dr_dib[0] -#define drc_dib dr_dib[1] - -UNIT drd_unit = { UDATA (NULL, 0, 0) }; - -REG drd_reg[] = { - { ORDATA (IBUF, drd_ibuf, 16) }, - { ORDATA (OBUF, drd_obuf, 16) }, - { FLDATA (CMD, drd_dib.cmd, 0) }, - { FLDATA (CTL, drd_dib.ctl, 0) }, - { FLDATA (FLG, drd_dib.flg, 0) }, - { FLDATA (FBF, drd_dib.fbf, 0) }, - { ORDATA (BPTR, drd_ptr, 6) }, - { ORDATA (DEVNO, drd_dib.devno, 6), REG_HRO }, - { NULL } }; - -MTAB drd_mod[] = { - { MTAB_XTD | MTAB_VDV, 1, "DEVNO", "DEVNO", - &hp_setdev, &hp_showdev, &drd_dev }, - { 0 } }; - -DEVICE drd_dev = { - "DRD", &drd_unit, drd_reg, drd_mod, - 1, 0, 0, 0, 0, 0, - NULL, NULL, NULL, - NULL, NULL, NULL, - &drd_dib, DEV_DISABLE }; - -/* DRC data structures - - drc_dev device descriptor - drc_unit unit descriptor - drc_mod unit modifiers - drc_reg register list -*/ - -UNIT drc_unit = - { UDATA (&drc_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+ - UNIT_MUSTBUF+UNIT_DR+UNIT_BINK, DR_SIZE) }; - -REG drc_reg[] = { - { ORDATA (CW, drc_cw, 16) }, - { ORDATA (STA, drc_sta, 16) }, - { FLDATA (CMD, drc_dib.cmd, 0) }, - { FLDATA (CTL, drc_dib.ctl, 0) }, - { FLDATA (FLG, drc_dib.flg, 0) }, - { FLDATA (FBF, drc_dib.fbf, 0) }, - { DRDATA (TIME, dr_time, 24), REG_NZ + PV_LEFT }, - { FLDATA (STOP_IOE, dr_stopioe, 0) }, - { ORDATA (DEVNO, drc_dib.devno, 6), REG_HRO }, - { DRDATA (CAPAC, drc_unit.capac, 24), REG_HRO }, - { NULL } }; - -MTAB drc_mod[] = { - { UNIT_DR, 0, "disk", NULL, NULL }, - { UNIT_DR, UNIT_DR, "drum", NULL, NULL }, - { UNIT_SZ, (SZ_180K << UNIT_V_SZ), NULL, "180K", &dr_set_size }, - { UNIT_SZ, (SZ_360K << UNIT_V_SZ), NULL, "360K", &dr_set_size }, - { UNIT_SZ, (SZ_720K << UNIT_V_SZ), NULL, "720K", &dr_set_size }, - { UNIT_SZ, (SZ_384K << UNIT_V_SZ), NULL, "384K", &dr_set_size }, - { UNIT_SZ, (SZ_512K << UNIT_V_SZ), NULL, "512K", &dr_set_size }, - { UNIT_SZ, (SZ_640K << UNIT_V_SZ), NULL, "640K", &dr_set_size }, - { UNIT_SZ, (SZ_768K << UNIT_V_SZ), NULL, "768K", &dr_set_size }, - { UNIT_SZ, (SZ_896K << UNIT_V_SZ), NULL, "896K", &dr_set_size }, - { UNIT_SZ, (SZ_1024K << UNIT_V_SZ), NULL, "1024K", &dr_set_size }, - { UNIT_SZ, (SZ_1536K << UNIT_V_SZ), NULL, "1536K", &dr_set_size }, - { MTAB_XTD | MTAB_VDV, 1, "DEVNO", "DEVNO", - &hp_setdev, &hp_showdev, &drd_dev }, - { 0 } }; - -DEVICE drc_dev = { - "DRC", &drc_unit, drc_reg, drc_mod, - 1, 8, 21, 1, 8, 16, - NULL, NULL, &drc_reset, - &drc_boot, &drc_attach, NULL, - &drc_dib, DEV_DISABLE }; - -/* IOT routines */ - -int32 drdio (int32 inst, int32 IR, int32 dat) -{ -int32 devd, t; - -devd = IR & I_DEVMASK; /* get device no */ -switch (inst) { /* case on opcode */ -case ioOTX: /* output */ - drd_obuf = dat; - break; -case ioMIX: /* merge */ - dat = dat | drd_ibuf; - break; -case ioLIX: /* load */ - dat = drd_ibuf; - break; -case ioCTL: /* control clear/set */ - if (IR & I_AB) { /* CLC */ - clrCMD (devd); /* clr "ctl" */ - clrFLG (devd); /* clr flg */ - drc_sta = drc_sta & ~DRS_SAC; } /* clear SAC flag */ - else if (!CMD (devd)) { /* STC, not set? */ - setCMD (devd); /* set "ctl" */ - if (drc_cw & CW_WR) { setFLG (devd); } /* prime DMA */ - drc_sta = 0; /* clear errors */ - drd_ptr = 0; /* clear sec ptr */ - sim_cancel (&drc_unit); /* cancel curr op */ - t = CW_GETSEC (drc_cw) - GET_CURSEC (dr_time * DR_NUMWD); - if (t <= 0) t = t + DR_NUMSC; - sim_activate (&drc_unit, t * DR_NUMWD * dr_time); } - break; -default: - break; } -if (IR & I_HC) { clrFLG (devd); } /* H/C option */ -return dat; -} - -int32 drcio (int32 inst, int32 IR, int32 dat) -{ -int32 st; - -switch (inst) { /* case on opcode */ -case ioSFC: /* skip flag clear */ - PC = (PC + 1) & VAMASK; - return dat; -case ioOTX: /* output */ - drc_cw = dat; - break; -case ioLIX: /* load */ - dat = 0; -case ioMIX: /* merge */ - if (drc_unit.flags & UNIT_ATT) /* attached? */ - st = GET_CURSEC (dr_time) | DRS_RDY | drc_sta | - (sim_is_active (&drc_unit)? DRS_BSY: 0); - else st = drc_sta; - dat = dat | st; /* merge status */ - break; -default: - break; } -return dat; -} - -/* Unit service */ - -t_stat drc_svc (UNIT *uptr) -{ -int32 devd, trk, sec; -uint32 da; - -if ((uptr->flags & UNIT_ATT) == 0) { - drc_sta = DRS_ABO; - return IORETURN (dr_stopioe, SCPE_UNATT); } - -drc_sta = drc_sta | DRS_SAC; -devd = drd_dib.devno; /* get dch devno */ -trk = CW_GETTRK (drc_cw); -sec = CW_GETSEC (drc_cw); -da = ((trk * DR_NUMSC) + sec) * DR_NUMWD; - -if (drc_cw & CW_WR) { /* write? */ - if ((da < uptr->capac) && (sec < DR_NUMSC)) { - *(((uint16 *) uptr->filebuf) + da + drd_ptr) = drd_obuf; - if (((uint32) (da + drd_ptr)) >= uptr->hwmark) - uptr->hwmark = da + drd_ptr + 1; } - drd_ptr = dr_incda (trk, sec, drd_ptr); /* inc disk addr */ - if (CMD (devd)) { /* dch active? */ - setFLG (devd); /* set dch flg */ - sim_activate (uptr, dr_time); } /* sched next word */ - else if (drd_ptr) { /* done, need to fill? */ - for ( ; drd_ptr < DR_NUMWD; drd_ptr++) - *(((uint16 *) uptr->filebuf) + da + drd_ptr) = 0; } - } /* end write */ -else { /* read */ - if (CMD (devd)) { /* dch active? */ - if ((da >= uptr->capac) || (sec >= DR_NUMSC)) drd_ibuf = 0; - else drd_ibuf = *(((uint16 *) uptr->filebuf) + da + drd_ptr); - drd_ptr = dr_incda (trk, sec, drd_ptr); - setFLG (devd); /* set dch flg */ - sim_activate (uptr, dr_time); } /* sched next word */ - } -return SCPE_OK; -} - -/* Increment current disk address */ - -int32 dr_incda (int32 trk, int32 sec, int32 ptr) -{ -ptr = ptr + 1; /* inc pointer */ -if (ptr >= DR_NUMWD) { /* end sector? */ - ptr = 0; /* new sector */ - sec = sec + 1; /* adv sector */ - if (sec >= DR_NUMSC) { /* end track? */ - sec = 0; /* new track */ - trk = trk + 1; /* adv track */ - if (trk >= MAX_TRK) trk = 0; } /* wraps at max */ - drc_cw = (drc_cw & CW_WR) | CW_PUTTRK (trk) | CW_PUTSEC (sec); - } -return ptr; -} - -/* Reset routine */ - -t_stat drc_reset (DEVICE *dptr) -{ -hp_enbdis_pair (&drc_dev, &drd_dev); /* make pair cons */ -drc_sta = drc_cw = drd_ptr = 0; -drc_dib.cmd = drd_dib.cmd = 0; /* clear cmd */ -drc_dib.ctl = drd_dib.ctl = 0; /* clear ctl */ -drc_dib.fbf = drd_dib.fbf = 0; /* clear fbf */ -drc_dib.flg = drd_dib.flg = 0; /* clear flg */ -sim_cancel (&drc_unit); -return SCPE_OK; -} - -/* Attach routine */ - -t_stat drc_attach (UNIT *uptr, char *cptr) -{ -int32 sz = sz_tab[DR_GETSZ (uptr->flags)]; - -if (sz == 0) return SCPE_IERR; -uptr->capac = sz; -return attach_unit (uptr, cptr); -} -/* Set size routine */ - -t_stat dr_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -int32 sz; - -if (val < 0) return SCPE_IERR; -if ((sz = sz_tab[DR_GETSZ (val)]) == 0) return SCPE_IERR; -if (uptr->flags & UNIT_ATT) return SCPE_ALATT; -uptr->capac = sz; -return SCPE_OK; -} - -/* Fixed head disk/drum bootstrap routine (disc subset of disc/paper tape loader) */ - -#define CHANGE_DEV (1 << 24) -#define BOOT_BASE 056 -#define BOOT_START 060 - -static const int32 dboot[IBL_LNT - BOOT_BASE] = { - 0020000+CHANGE_DEV, /*DMA 20000+DC */ - 0000000, /* 0 */ - 0107700, /* CLC 0,C */ - 0063756, /* LDA DMA ; DMA ctrl */ - 0102606, /* OTA 6 */ - 0002700, /* CLA,CCE */ - 0102601+CHANGE_DEV, /* OTA CC ; trk = sec = 0 */ - 0001500, /* ERA ; A = 100000 */ - 0102602, /* OTA 2 ; DMA in, addr */ - 0063777, /* LDA M64 */ - 0102702, /* STC 2 */ - 0102602, /* OTA 2 ; DMA wc = -64 */ - 0103706, /* STC 6,C ; start DMA */ - 0067776, /* LDB JSF ; get JMP . */ - 0074077, /* STB 77 ; in base page */ - 0102700+CHANGE_DEV, /* STC DC ; start disc */ - 0024077, /*JSF JMP 77 ; go wait */ - 0177700 }; /*M64 -100 */ - -t_stat drc_boot (int32 unitno, DEVICE *dptr) -{ -int32 i, dev, ad; - -if (unitno != 0) return SCPE_NOFNC; /* only unit 0 */ -dev = drd_dib.devno; /* get data chan dev */ -ad = ((MEMSIZE - 1) & ~IBL_MASK) & VAMASK; /* start at mem top */ -for (i = 0; i < (IBL_LNT - BOOT_BASE); i++) { /* copy bootstrap */ - if (dboot[i] & CHANGE_DEV) /* IO instr? */ - M[ad + BOOT_BASE + i] = (dboot[i] + dev) & DMASK; - else M[ad + BOOT_BASE + i] = dboot[i]; } -PC = ad + BOOT_START; -return SCPE_OK; -} diff --git a/HP2100/hp2100_fp.c b/HP2100/hp2100_fp.c deleted file mode 100644 index 365413b8..00000000 --- a/HP2100/hp2100_fp.c +++ /dev/null @@ -1,312 +0,0 @@ -/* hp2100_fp.c: HP 2100 floating point instructions - - 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"), - 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. - - 15-Jul-03 RMS Fixed signed/unsigned warning - 21-Oct-02 RMS Recoded for compatibility with 21MX microcode algorithms - - The HP2100 uses a unique binary floating point format: - - 15 14 0 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - |S | fraction high | : A - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | fraction low | exponent |XS| : A + 1 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - 15 8 7 1 0 - - where S = 0 for plus fraction, 1 for minus fraction - fraction = s.bbbbb..., 24 binary digits - exponent = 2**+/-n - XS = 0 for plus exponent, 1 for minus exponent - - Numbers can be normalized or unnormalized but are always normalized - when loaded. - - Unpacked floating point numbers are stored in structure ufp - - exp = exponent, 2's complement - h'l = fraction, 2's comp, left justified - - This routine tries to reproduce the algorithms of the 2100/21MX - microcode in order to achieve 'bug-for-bug' compatibility. In - particular, - - - The FIX code produces various results in B. - - The fraction multiply code uses 16b x 16b multiplies to produce - a 31b result. It always loses the low order bit of the product. - - The fraction divide code is an approximation that may produce - an error of 1 LSB. - - Signs are tracked implicitly as part of the fraction. Unnormalized - inputs may cause the packup code to produce the wrong sign. - - "Unclean" zeros (zero fraction, non-zero exponent) are processed - like normal operands. -*/ - -#include "hp2100_defs.h" - -struct ufp { /* unpacked fp */ - int32 exp; /* exp */ - uint32 fr; }; /* frac */ - -#define FP_V_SIGN 31 /* sign */ -#define FP_M_SIGN 01 -#define FP_V_FR 8 /* fraction */ -#define FP_M_FR 077777777 -#define FP_V_EXP 1 /* exponent */ -#define FP_M_EXP 0177 -#define FP_V_EXPS 0 /* exp sign */ -#define FP_M_EXPS 01 -#define FP_SIGN (FP_M_SIGN << FP_V_SIGN) -#define FP_FR (FP_M_FR << FP_V_FR) -#define FP_EXP (FP_M_EXP << FP_V_EXP) -#define FP_EXPS (FP_M_EXPS << FP_V_EXPS) -#define FP_GETSIGN(x) (((x) >> FP_V_SIGN) & FP_M_SIGN) -#define FP_GETEXP(x) (((x) >> FP_V_EXP) & FP_M_EXP) -#define FP_GETEXPS(x) (((x) >> FP_V_EXPS) & FP_M_EXPS) - -#define FP_NORM (1 << (FP_V_SIGN - 1)) /* normalized */ -#define FP_LOW (1 << FP_V_FR) -#define FP_RNDP (1 << (FP_V_FR - 1)) /* round for plus */ -#define FP_RNDM (FP_RNDP - 1) /* round for minus */ - -#define FPAB ((((uint32) AR) << 16) | ((uint32) BR)) - -#define DMASK32 0xFFFFFFFF - -/* Fraction shift; 0 < shift < 32 */ - -#define FR_ARS(v,s) (((v) >> (s)) | (((v) & FP_SIGN)? \ - (DMASK32 << (32 - (s))): 0)) & DMASK32 - -#define FR_NEG(v) ((~(v) + 1) & DMASK32) - -extern uint16 *M; -uint32 UnpackFP (struct ufp *fop, uint32 opnd); -void NegFP (struct ufp *fop); -void NormFP (struct ufp *fop); -uint32 StoreFP (struct ufp *fop); - -/* Floating to integer conversion */ - -uint32 f_fix (void) -{ -struct ufp fop; -uint32 res = 0; - -UnpackFP (&fop, FPAB); /* unpack op */ -if (fop.exp < 0) { /* exp < 0? */ - AR = 0; /* result = 0 */ - return 0; } /* B unchanged */ -if (fop.exp > 15) { /* exp > 15? */ - BR = AR; /* B has high bits */ - AR = 077777; /* result = 77777 */ - return 1; } /* overflow */ -if (fop.exp < 15) { /* if not aligned */ - res = FR_ARS (fop.fr, 15 - fop.exp); /* shift right */ - AR = (res >> 16) & DMASK; } /* AR gets result */ -BR = AR; -if ((AR & SIGN) && ((fop.fr | res) & DMASK)) /* any low bits lost? */ - AR = (AR + 1) & DMASK; /* round up */ -return 0; -} - -/* Integer to floating conversion */ - -uint32 f_flt (void) -{ -struct ufp res = { 15, 0 }; /* +, 2**15 */ - -res.fr = ((uint32) AR) << 16; /* left justify */ -StoreFP (&res); /* store result */ -return 0; /* clr overflow */ -} - -/* Floating point add/subtract */ - -uint32 f_as (uint32 opnd, t_bool sub) -{ -struct ufp fop1, fop2, t; -int32 ediff; - -UnpackFP (&fop1, FPAB); /* unpack A-B */ -UnpackFP (&fop2, opnd); /* get op */ -if (sub) { /* subtract? */ - fop2.fr = FR_NEG (fop2.fr); /* negate frac */ - if (fop2.fr == ((uint32) FP_SIGN)) { /* -1/2? */ - fop2.fr = fop2.fr >> 1; /* special case */ - fop2.exp = fop2.exp + 1; } } -if (fop1.fr == 0) fop1 = fop2; /* op1 = 0? res = op2 */ -else if (fop2.fr != 0) { /* op2 = 0? no add */ - if (fop1.exp < fop2.exp) { /* |op1| < |op2|? */ - t = fop2; /* swap operands */ - fop2 = fop1; - fop1 = t; } - ediff = fop1.exp - fop2.exp; /* get exp diff */ - if (ediff <= 24) { - if (ediff) fop2.fr = FR_ARS (fop2.fr, ediff); /* denorm, signed */ - if ((fop1.fr ^ fop2.fr) & FP_SIGN) /* unlike signs? */ - fop1.fr = fop1.fr + fop2.fr; /* eff subtract */ - else { /* like signs */ - fop1.fr = fop1.fr + fop2.fr; /* eff add */ - if (fop2.fr & FP_SIGN) { /* both -? */ - if ((fop1.fr & FP_SIGN) == 0) { /* overflow? */ - fop1.fr = FP_SIGN | (fop1.fr >> 1); /* renormalize */ - fop1.exp = fop1.exp + 1; } } /* incr exp */ - else if (fop1.fr & FP_SIGN) { /* both +, cry out? */ - fop1.fr = fop1.fr >> 1; /* renormalize */ - fop1.exp = fop1.exp + 1; } /* incr exp */ - } /* end else like */ - } /* end if ediff */ - } /* end if fop2 */ -return StoreFP (&fop1); /* store result */ -} - -/* Floating point multiply - passes diagnostic */ - -uint32 f_mul (uint32 opnd) -{ -struct ufp fop1, fop2; -struct ufp res = { 0, 0 }; -int32 shi1, shi2, t1, t2, t3, t4, t5; - -UnpackFP (&fop1, FPAB); /* unpack A-B */ -UnpackFP (&fop2, opnd); /* unpack op */ -if (fop1.fr && fop2.fr) { /* if both != 0 */ - res.exp = fop1.exp + fop2.exp + 1; /* exp = sum */ - shi1 = SEXT (fop1.fr >> 16); /* mpy hi */ - shi2 = SEXT (fop2.fr >> 16); /* mpc hi */ - t1 = shi2 * ((int32) ((fop1.fr >> 1) & 077600));/* mpc hi * (mpy lo/2) */ - t2 = shi1 * ((int32) ((fop2.fr >> 1) & 077600));/* mpc lo * (mpy hi/2) */ - t3 = t1 + t2; /* cross product */ - t4 = (shi1 * shi2) & ~1; /* mpy hi * mpc hi */ - t5 = (SEXT (t3 >> 16)) << 1; /* add in cross */ - res.fr = (t4 + t5) & DMASK32; } /* bit<0> is lost */ -return StoreFP (&res); /* store */ -} - -/* Floating point divide - reverse engineered from diagnostic */ - -uint32 divx (uint32 ba, uint32 dvr, uint32 *rem) -{ -int32 sdvd = 0, sdvr = 0; -uint32 q, r; - -if (ba & FP_SIGN) sdvd = 1; /* 32b/16b signed dvd */ -if (dvr & SIGN) sdvr = 1; /* use old-fashioned */ -if (sdvd) ba = (~ba + 1) & DMASK32; /* unsigned divides, */ -if (sdvr) dvr = (~dvr + 1) & DMASK; /* as results may ovflo */ -q = ba / dvr; -r = ba % dvr; -if (sdvd ^ sdvr) q = (~q + 1) & DMASK; -if (sdvd) r = (~r + 1) & DMASK; -if (rem) *rem = r; -return q; -} - -uint32 f_div (uint32 opnd) -{ -struct ufp fop1, fop2; -struct ufp quo = { 0, 0 }; -uint32 ba, q0, q1, q2, dvrh; - -UnpackFP (&fop1, FPAB); /* unpack A-B */ -UnpackFP (&fop2, opnd); /* unpack op */ -dvrh = (fop2.fr >> 16) & DMASK; /* high divisor */ -if (dvrh == 0) { /* div by zero? */ - AR = 0077777; /* return most pos */ - BR = 0177776; - return 1; } -if (fop1.fr) { /* dvd != 0? */ - quo.exp = fop1.exp - fop2.exp + 1; /* exp = diff */ - ba = FR_ARS (fop1.fr, 2); /* prevent ovflo */ - q0 = divx (ba, dvrh, &ba); /* Q0 = dvd / dvrh */ - ba = (ba & ~1) << 16; /* remainder */ - ba = FR_ARS (ba, 1); /* prevent ovflo */ - q1 = divx (ba, dvrh, NULL); /* Q1 = rem / dvrh */ - ba = (fop2.fr & 0xFF00) << 13; /* dvrl / 8 */ - q2 = divx (ba, dvrh, NULL); /* dvrl / dvrh */ - ba = -(SEXT (q2)) * (SEXT (q0)); /* -Q0 * Q2 */ - ba = (ba >> 16) & 0xFFFF; /* save ms half */ - if (q1 & SIGN) quo.fr = quo.fr - 0x00010000; /* Q1 < 0? -1 */ - if (ba & SIGN) quo.fr = quo.fr - 0x00010000; /* -Q0*Q2 < 0? */ - quo.fr = quo.fr + ((ba << 2) & 0xFFFF) + q1; /* rest prod, add Q1 */ - quo.fr = quo.fr << 1; /* shift result */ - quo.fr = quo.fr + (q0 << 16); /* add Q0 */ - } /* end if fop1.h */ -return StoreFP (&quo); /* store result */ -} - -/* Utility routines */ - -/* Unpack operand */ - -uint32 UnpackFP (struct ufp *fop, uint32 opnd) -{ -fop->fr = opnd & FP_FR; /* get frac */ -fop->exp = FP_GETEXP (opnd); /* get exp */ -if (FP_GETEXPS (opnd)) fop->exp = fop->exp | ~FP_M_EXP; /* < 0? sext */ -return FP_GETSIGN (opnd); /* return sign */ -} - -/* Normalize unpacked floating point number */ - -void NormFP (struct ufp *fop) -{ -if (fop->fr) { /* any fraction? */ - uint32 test = (fop->fr >> 1) & FP_NORM; - while ((fop->fr & FP_NORM) == test) { /* until norm */ - fop->exp = fop->exp - 1; - fop->fr = (fop->fr << 1); } } -else fop->exp = 0; /* clean 0 */ -return; -} - -/* Round fp number, store, generate overflow */ - -uint32 StoreFP (struct ufp *fop) -{ -uint32 sign, svfr, hi, ov = 0; - -NormFP (fop); /* normalize */ -svfr = fop->fr; /* save fraction */ -sign = FP_GETSIGN (fop->fr); /* save sign */ -fop->fr = (fop->fr + (sign? FP_RNDM: FP_RNDP)) & FP_FR; /* round */ -if ((fop->fr ^ svfr) & FP_SIGN) { /* sign change? */ - fop->fr = (fop->fr >> 1) | (sign? FP_SIGN: 0); /* renormalize */ - fop->exp = fop->exp + 1; } -if (fop->fr == 0) hi = 0; /* result 0? */ -else if (fop->exp < -(FP_M_EXP + 1)) { /* underflow? */ - hi = 0; /* store clean 0 */ - ov = 1; } -else if (fop->exp > FP_M_EXP) { /* overflow? */ - hi = 0x7FFFFFFE; /* all 1's */ - ov = 1; } -else hi = (fop->fr & FP_FR) | /* merge frac */ - ((fop->exp & FP_M_EXP) << FP_V_EXP) | /* and exp */ - ((fop->exp < 0)? (1 << FP_V_EXPS): 0); /* add exp sign */ -AR = (hi >> 16) & DMASK; -BR = hi & DMASK; -return ov; -} diff --git a/HP2100/hp2100_ipl.c b/HP2100/hp2100_ipl.c deleted file mode 100644 index ede40ccf..00000000 --- a/HP2100/hp2100_ipl.c +++ /dev/null @@ -1,476 +0,0 @@ -/* hp2100_ipl.c: HP 2000 interprocessor link simulator - - 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"), - 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 - - 09-May-03 RMS Added network device flag - 31-Jan-03 RMS Links are full duplex (found by Mike Gemeny) -*/ - -#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_V_HOLD (UNIT_V_UF + 3) /* character holding */ -#define UNIT_DIAG (1 << UNIT_V_DIAG) -#define UNIT_ACTV (1 << UNIT_V_ACTV) -#define UNIT_ESTB (1 << UNIT_V_ESTB) -#define UNIT_HOLD (1 << UNIT_V_HOLD) -#define IBUF buf /* input buffer */ -#define OBUF wait /* output buffer */ -#define DSOCKET u3 /* data socket */ -#define LSOCKET u4 /* listening socket */ - -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 */ -int32 ipl_hold[2] = { 0 }; /* holding character */ - -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 (IBUF, ipli_unit.IBUF, 16) }, - { ORDATA (OBUF, ipli_unit.OBUF, 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, ipl_hold[0], 8) }, - { 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_NET | 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 (IBUF, iplo_unit.IBUF, 16) }, - { ORDATA (OBUF, iplo_unit.OBUF, 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, ipl_hold[1], 8) }, - { 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_NET | 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->OBUF = dat; - break; -case ioLIX: /* load */ - dat = uptr->IBUF; /* return val */ - break; -case ioMIX: /* merge */ - dat = dat | uptr->IBUF; /* 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->OBUF >> 8) & 0377; - msg[1] = uptr->OBUF & 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].IBUF = uptr->OBUF; /* 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]; - -u = uptr - ipl_unit; /* get link number */ -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->flags & UNIT_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->flags & UNIT_HOLD) { /* holdover byte? */ - uptr->IBUF = (ipl_hold[u] << 8) | (((int32) msg[0]) & 0377); - uptr->flags = uptr->flags & ~UNIT_HOLD; } -else if (nb == 1) { - ipl_hold[u] = ((int32) msg[0]) & 0377; - uptr->flags = uptr->flags | UNIT_HOLD; } -else uptr->IBUF = ((((int32) msg[0]) & 0377) << 8) | - (((int32) msg[1]) & 0377); -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->IBUF = uptr->OBUF = 0; /* clr buffers */ -if (uptr->flags & UNIT_ATT) sim_activate (uptr, ipl_ptime); -else sim_cancel (uptr); /* deactivate unit */ -uptr->flags = uptr->flags & ~UNIT_HOLD; -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->IBUF = uptr->OBUF = 0; -uptr->flags = (uptr->flags | UNIT_ATT) & ~(UNIT_ESTB | UNIT_HOLD); -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 deleted file mode 100644 index cca3e6ed..00000000 --- a/HP2100/hp2100_lps.c +++ /dev/null @@ -1,176 +0,0 @@ -/* hp2100_lps.c: HP 2100 12653A line printer simulator - - 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. - - lps 12653A 2767 line printer - (based on 12556B microcircuit interface) - - 25-Apr-03 RMS Revised for extended file support - 24-Oct-02 RMS Added microcircuit test features - 30-May-02 RMS Widened POS to 32b - 03-Dec-01 RMS Changed DEVNO to use extended SET/SHOW - 07-Sep-01 RMS Moved function prototypes - 21-Nov-00 RMS Fixed flag, fbf power up state - Added command flop - 15-Oct-00 RMS Added variable device number support -*/ - -#include "hp2100_defs.h" - -#define LPS_BUSY 0000001 /* busy */ -#define LPS_NRDY 0100000 /* not ready */ -#define UNIT_V_DIAG (UNIT_V_UF + 0) /* diagnostic mode */ -#define UNIT_DIAG (1 << UNIT_V_DIAG) - -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; - -DEVICE lps_dev; -int32 lpsio (int32 inst, int32 IR, int32 dat); -t_stat lps_svc (UNIT *uptr); -t_stat lps_reset (DEVICE *dptr); - -/* LPS data structures - - lps_dev LPS device descriptor - lps_unit LPS unit descriptor - lps_reg LPS register list -*/ - -DIB lps_dib = { LPS, 0, 0, 0, 0, &lpsio }; - -UNIT lps_unit = { - UDATA (&lps_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT }; - -REG lps_reg[] = { - { ORDATA (BUF, lps_unit.buf, 16) }, - { ORDATA (STA, lps_sta, 16) }, - { FLDATA (CMD, lps_dib.cmd, 0) }, - { FLDATA (CTL, lps_dib.ctl, 0) }, - { FLDATA (FLG, lps_dib.flg, 0) }, - { FLDATA (FBF, lps_dib.fbf, 0) }, - { DRDATA (POS, lps_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (CTIME, lps_ctime, 31), PV_LEFT }, - { DRDATA (PTIME, lps_unit.wait, 24), PV_LEFT }, - { FLDATA (STOP_IOE, lps_stopioe, 0) }, - { ORDATA (DEVNO, lps_dib.devno, 6), REG_HRO }, - { NULL } }; - -MTAB lps_mod[] = { - { 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 } }; - -DEVICE lps_dev = { - "LPS", &lps_unit, lps_reg, lps_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &lps_reset, - NULL, NULL, NULL, - &lps_dib, DEV_DISABLE | DEV_DIS }; - -/* Line printer IOT routine */ - -int32 lpsio (int32 inst, int32 IR, int32 dat) -{ -int32 dev; - -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 */ - lps_unit.buf = dat; - break; -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; } - 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 { /* 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; } -if (IR & I_HC) { clrFLG (dev); } /* H/C option */ -return dat; -} - -t_stat lps_svc (UNIT *uptr) -{ -int32 dev; -int32 c = lps_unit.buf & 0177; - -dev = lps_dib.devno; /* get dev no */ -clrCMD (dev); /* clear cmd */ -setFLG (dev); /* set flag, fbf */ -if (lps_unit.flags & UNIT_DIAG) { /* diagnostic? */ - lps_sta = lps_unit.buf; /* loop back */ - return SCPE_OK; } /* done */ -if ((lps_unit.flags & UNIT_ATT) == 0) /* real lpt, att? */ - return IORETURN (lps_stopioe, SCPE_UNATT); -if (fputc (c, lps_unit.fileref) == EOF) { - perror ("LPS I/O error"); - clearerr (lps_unit.fileref); - return SCPE_IOERR; } -lps_unit.pos = lps_unit.pos + 1; /* update pos */ -return SCPE_OK; -} - -/* Reset routine - called from SCP, flags in DIB */ - -t_stat lps_reset (DEVICE *dptr) -{ -lps_dib.cmd = lps_dib.ctl = 0; /* clear cmd, ctl */ -lps_dib.flg = lps_dib.fbf = 1; /* set flg, fbf */ -lps_sta = lps_unit.buf = 0; -sim_cancel (&lps_unit); /* deactivate unit */ -return SCPE_OK; -} diff --git a/HP2100/hp2100_lpt.c b/HP2100/hp2100_lpt.c deleted file mode 100644 index bd7bba70..00000000 --- a/HP2100/hp2100_lpt.c +++ /dev/null @@ -1,194 +0,0 @@ -/* hp2100_lpt.c: HP 2100 12845A line printer simulator - - 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. - - lpt 12845A line printer - - 25-Apr-03 RMS Revised for extended file support - 24-Oct-02 RMS Cloned from 12653A -*/ - -#include "hp2100_defs.h" - -#define LPT_PAGELNT 60 /* page length */ - -#define LPT_NBSY 0000001 /* not busy */ -#define LPT_PAPO 0040000 /* paper out */ -#define LPT_RDY 0100000 /* ready */ - -#define LPT_CTL 0100000 /* control output */ -#define LPT_CHAN 0000100 /* skip to chan */ -#define LPT_SKIPM 0000077 /* line count mask */ -#define LPT_CHANM 0000007 /* channel mask */ - -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 */ -static int32 lpt_cct[8] = { - 1, 1, 1, 2, 3, LPT_PAGELNT/2, LPT_PAGELNT/4, LPT_PAGELNT/6 }; - -DEVICE lpt_dev; -int32 lptio (int32 inst, int32 IR, int32 dat); -t_stat lpt_svc (UNIT *uptr); -t_stat lpt_reset (DEVICE *dptr); -t_stat lpt_attach (UNIT *uptr, char *cptr); - -/* LPT data structures - - lpt_dev LPT device descriptor - lpt_unit LPT unit descriptor - lpt_reg LPT register list -*/ - -DIB lpt_dib = { LPT, 0, 0, 0, 0, &lptio }; - -UNIT lpt_unit = { - UDATA (&lpt_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT }; - -REG lpt_reg[] = { - { ORDATA (BUF, lpt_unit.buf, 7) }, - { FLDATA (CMD, lpt_dib.cmd, 0) }, - { FLDATA (CTL, lpt_dib.ctl, 0) }, - { FLDATA (FLG, lpt_dib.flg, 0) }, - { FLDATA (FBF, lpt_dib.fbf, 0) }, - { DRDATA (LCNT, lpt_lcnt, 7) }, - { DRDATA (POS, lpt_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (CTIME, lpt_ctime, 31), PV_LEFT }, - { DRDATA (PTIME, lpt_unit.wait, 24), PV_LEFT }, - { FLDATA (STOP_IOE, lpt_stopioe, 0) }, - { ORDATA (DEVNO, lpt_dib.devno, 6), REG_HRO }, - { NULL } }; - -MTAB lpt_mod[] = { - { MTAB_XTD | MTAB_VDV, 0, "DEVNO", "DEVNO", - &hp_setdev, &hp_showdev, &lpt_dev }, - { 0 } }; - -DEVICE lpt_dev = { - "LPT", &lpt_unit, lpt_reg, lpt_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &lpt_reset, - NULL, &lpt_attach, NULL, - &lpt_dib, DEV_DISABLE }; - -/* Line printer IOT routine */ - -int32 lptio (int32 inst, int32 IR, int32 dat) -{ -int32 dev; - -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 */ - lpt_unit.buf = dat & (LPT_CTL | 0177); - break; -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; } - else dat = dat | LPT_PAPO; - 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); - sim_activate (&lpt_unit, /* schedule op */ - (lpt_unit.buf & LPT_CTL)? lpt_unit.wait: lpt_ctime); } - break; -default: - break; } -if (IR & I_HC) { clrFLG (dev); } /* H/C option */ -return dat; -} - -t_stat lpt_svc (UNIT *uptr) -{ -int32 i, skip, chan, dev; - -dev = lpt_dib.devno; /* get dev no */ -clrCMD (dev); /* clear cmd */ -if ((uptr->flags & UNIT_ATT) == 0) /* attached? */ - return IORETURN (lpt_stopioe, SCPE_UNATT); -setFLG (dev); /* set flag, fbf */ -if (uptr->buf & LPT_CTL) { /* control word? */ - if (uptr->buf & LPT_CHAN) { - chan = uptr->buf & LPT_CHANM; - if (chan == 0) { /* top of form? */ - fputc ('\f', uptr->fileref); /* ffeed */ - lpt_lcnt = 0; /* reset line cnt */ - skip = 1; } - else if (chan == 1) skip = LPT_PAGELNT - lpt_lcnt - 1; - else skip = lpt_cct[chan] - (lpt_lcnt % lpt_cct[chan]); - } - else { - skip = uptr->buf & LPT_SKIPM; - if (skip == 0) fputc ('\r', uptr->fileref); - } - for (i = 0; i < skip; i++) fputc ('\n', uptr->fileref); - lpt_lcnt = (lpt_lcnt + skip) % LPT_PAGELNT; - } -else fputc (uptr->buf & 0177, uptr->fileref); /* no, just add char */ -if (ferror (uptr->fileref)) { - perror ("LPT I/O error"); - clearerr (uptr->fileref); - return SCPE_IOERR; } -lpt_unit.pos = ftell (uptr->fileref); /* update pos */ -return SCPE_OK; -} - -/* Reset routine - called from SCP, flags in DIB */ - -t_stat lpt_reset (DEVICE *dptr) -{ -lpt_dib.cmd = lpt_dib.ctl = 0; /* clear cmd, ctl */ -lpt_dib.flg = lpt_dib.fbf = 1; /* set flg, fbf */ -lpt_unit.buf = 0; -sim_cancel (&lpt_unit); /* deactivate unit */ -return SCPE_OK; -} - -/* Attach routine */ - -t_stat lpt_attach (UNIT *uptr, char *cptr) -{ -lpt_lcnt = 0; /* top of form */ -return attach_unit (uptr, cptr); -} diff --git a/HP2100/hp2100_ms.c b/HP2100/hp2100_ms.c deleted file mode 100644 index e607cc88..00000000 --- a/HP2100/hp2100_ms.c +++ /dev/null @@ -1,672 +0,0 @@ -/* hp2100_ms.c: HP 2100 13181A/13183A magnetic tape simulator - - 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. - - ms 13181A 7970B 800bpi nine track magnetic tape - 13183A 7970E 1600bpi nine track magnetic tape - - 25-Apr-03 RMS Revised for extended file support - 28-Mar-03 RMS Added multiformat support - 28-Feb-03 RMS Revised for magtape library - 18-Oct-02 RMS Added BOOT command, added 13183A support - 30-Sep-02 RMS Revamped error handling - 29-Aug-02 RMS Added end of medium support - 30-May-02 RMS Widened POS to 32b - 22-Apr-02 RMS Added maximum record length test - - Magnetic tapes are represented as a series of variable records - of the form: - - 32b byte count - byte 0 - byte 1 - : - byte n-2 - byte n-1 - 32b byte count - - If the byte count is odd, the record is padded with an extra byte - of junk. File marks are represented by a byte count of 0. - - Unusually among HP peripherals, the 12559 does not have a command flop, - and its flag and flag buffer power up as clear rather than set. -*/ - -#include "hp2100_defs.h" -#include "sim_tape.h" - -#define MS_NUMDR 4 /* number of drives */ -#define DB_N_SIZE 16 /* max data buf */ -#define DBSIZE (1 << DB_N_SIZE) /* max data cmd */ -#define FNC u3 /* function */ -#define UST u4 /* unit status */ - -/* Command - msc_fnc */ - -#define FNC_CLR 00110 /* clear */ -#define FNC_GAP 00015 /* write gap */ -#define FNC_GFM 00215 /* gap+file mark */ -#define FNC_RC 00023 /* read */ -#define FNC_WC 00031 /* write */ -#define FNC_FSR 00003 /* forward space */ -#define FNC_BSR 00041 /* backward space */ -#define FNC_FSF 00203 /* forward file */ -#define FNC_BSF 00241 /* backward file */ -#define FNC_REW 00101 /* rewind */ -#define FNC_RWS 00105 /* rewind and offline */ -#define FNC_WFM 00211 /* write file mark */ -#define FNC_RFF 00223 /* "read file fwd" */ -#define FNC_V_SEL 9 /* select */ -#define FNC_M_SEL 017 -#define FNC_GETSEL(x) (((x) >> FNC_V_SEL) & FNC_M_SEL) - -#define FNF_MOT 00001 /* motion */ -#define FNF_OFL 00004 -#define FNF_WRT 00010 /* write */ -#define FNF_REV 00040 /* reverse */ -#define FNF_RWD 00100 /* rewind */ -#define FNF_CHS 00400 /* change select */ - -/* Status - stored in msc_sta, unit.UST (u), or dynamic (d) */ - -#define STA_PE 0100000 /* 1600 bpi (d) */ -#define STA_V_SEL 13 /* unit sel (d) */ -#define STA_M_SEL 03 -#define STA_SEL (STA_M_SEL << STA_V_SEL) -#define STA_ODD 0004000 /* odd bytes */ -#define STA_REW 0002000 /* rewinding (u) */ -#define STA_TBSY 0001000 /* transport busy (d) */ -#define STA_BUSY 0000400 /* ctrl busy */ -#define STA_EOF 0000200 /* end of file */ -#define STA_BOT 0000100 /* beg of tape (u) */ -#define STA_EOT 0000040 /* end of tape (u) */ -#define STA_TIM 0000020 /* timing error */ -#define STA_REJ 0000010 /* programming error */ -#define STA_WLK 0000004 /* write locked (d) */ -#define STA_PAR 0000002 /* parity error */ -#define STA_LOCAL 0000001 /* local (d) */ -#define STA_DYN (STA_PE|STA_SEL|STA_TBSY|STA_WLK|STA_LOCAL) - -extern uint16 *M; -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; - -int32 ms_ctype = 0; /* ctrl type */ -int32 msc_sta = 0; /* status */ -int32 msc_buf = 0; /* buffer */ -int32 msc_usl = 0; /* unit select */ -int32 msc_1st = 0; -int32 msc_ctime = 1000; /* command wait */ -int32 msc_gtime = 1000; /* gap stop time */ -int32 msc_rtime = 1000; /* rewind wait */ -int32 msc_xtime = 15; /* data xfer time */ -int32 msc_stopioe = 1; /* stop on error */ -int32 msd_buf = 0; /* data buffer */ -uint8 msxb[DBSIZE] = { 0 }; /* data buffer */ -t_mtrlnt ms_ptr = 0, ms_max = 0; /* buffer ptrs */ - -DEVICE msd_dev, msc_dev; -int32 msdio (int32 inst, int32 IR, int32 dat); -int32 mscio (int32 inst, int32 IR, int32 dat); -t_stat msc_svc (UNIT *uptr); -t_stat msc_reset (DEVICE *dptr); -t_stat msc_attach (UNIT *uptr, char *cptr); -t_stat msc_detach (UNIT *uptr); -t_stat msc_boot (int32 unitno, DEVICE *dptr); -t_stat ms_map_err (UNIT *uptr, t_stat st); -t_stat ms_settype (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat ms_showtype (FILE *st, UNIT *uptr, int32 val, void *desc); - -/* MSD data structures - - msd_dev MSD device descriptor - msd_unit MSD unit list - msd_reg MSD register list -*/ - -DIB ms_dib[] = { - { MSD, 0, 0, 0, 0, &msdio }, - { MSC, 0, 0, 0, 0, &mscio } }; - -#define msd_dib ms_dib[0] -#define msc_dib ms_dib[1] - -UNIT msd_unit = { UDATA (NULL, 0, 0) }; - -REG msd_reg[] = { - { ORDATA (BUF, msd_buf, 16) }, - { FLDATA (CMD, msd_dib.cmd, 0), REG_HRO }, - { FLDATA (CTL, msd_dib.ctl, 0) }, - { FLDATA (FLG, msd_dib.flg, 0) }, - { FLDATA (FBF, msd_dib.fbf, 0) }, - { BRDATA (DBUF, msxb, 8, 8, DBSIZE) }, - { DRDATA (BPTR, ms_ptr, DB_N_SIZE + 1) }, - { DRDATA (BMAX, ms_max, DB_N_SIZE + 1) }, - { ORDATA (DEVNO, msd_dib.devno, 6), REG_HRO }, - { NULL } }; - -MTAB msd_mod[] = { - { MTAB_XTD | MTAB_VDV, 1, "DEVNO", "DEVNO", - &hp_setdev, &hp_showdev, &msd_dev }, - { 0 } }; - -DEVICE msd_dev = { - "MSD", &msd_unit, msd_reg, msd_mod, - 1, 10, DB_N_SIZE, 1, 8, 8, - NULL, NULL, &msc_reset, - NULL, NULL, NULL, - &msd_dib, 0 }; - -/* MSC data structures - - msc_dev MSC device descriptor - msc_unit MSC unit list - msc_reg MSC register list - msc_mod MSC modifier list -*/ - -UNIT msc_unit[] = { - { UDATA (&msc_svc, UNIT_ATTABLE + UNIT_ROABLE + UNIT_DISABLE, 0) }, - { UDATA (&msc_svc, UNIT_ATTABLE + UNIT_ROABLE + UNIT_DISABLE, 0) }, - { UDATA (&msc_svc, UNIT_ATTABLE + UNIT_ROABLE + UNIT_DISABLE, 0) }, - { UDATA (&msc_svc, UNIT_ATTABLE + UNIT_ROABLE + UNIT_DISABLE, 0) } }; - -REG msc_reg[] = { - { ORDATA (STA, msc_sta, 12) }, - { ORDATA (BUF, msc_buf, 16) }, - { ORDATA (USEL, msc_usl, 2) }, - { FLDATA (FSVC, msc_1st, 0) }, - { FLDATA (CMD, msc_dib.cmd, 0), REG_HRO }, - { FLDATA (CTL, msc_dib.ctl, 0) }, - { FLDATA (FLG, msc_dib.flg, 0) }, - { FLDATA (FBF, msc_dib.fbf, 0) }, - { URDATA (POS, msc_unit[0].pos, 10, T_ADDR_W, 0, MS_NUMDR, PV_LEFT) }, - { URDATA (FNC, msc_unit[0].FNC, 8, 8, 0, MS_NUMDR, REG_HRO) }, - { URDATA (UST, msc_unit[0].UST, 8, 12, 0, MS_NUMDR, REG_HRO) }, - { DRDATA (CTIME, msc_ctime, 24), REG_NZ + PV_LEFT }, - { DRDATA (GTIME, msc_gtime, 24), REG_NZ + PV_LEFT }, - { DRDATA (RTIME, msc_rtime, 24), REG_NZ + PV_LEFT }, - { DRDATA (XTIME, msc_xtime, 24), REG_NZ + PV_LEFT }, - { FLDATA (STOP_IOE, msc_stopioe, 0) }, - { FLDATA (CTYPE, ms_ctype, 0), REG_HRO }, - { ORDATA (DEVNO, msc_dib.devno, 6), REG_HRO }, - { NULL } }; - -MTAB msc_mod[] = { - { MTUF_WLK, 0, "write enabled", "WRITEENABLED", NULL }, - { MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL }, - { MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT", - &sim_tape_set_fmt, &sim_tape_show_fmt, NULL }, - { MTAB_XTD | MTAB_VDV, 0, NULL, "13181A", - &ms_settype, NULL, NULL }, - { MTAB_XTD | MTAB_VDV, 1, NULL, "13183A", - &ms_settype, NULL, NULL }, - { MTAB_XTD | MTAB_VDV, 0, "TYPE", NULL, - NULL, &ms_showtype, NULL }, - { MTAB_XTD | MTAB_VDV, 1, "DEVNO", "DEVNO", - &hp_setdev, &hp_showdev, &msd_dev }, - { 0 } }; - -DEVICE msc_dev = { - "MSC", msc_unit, msc_reg, msc_mod, - MS_NUMDR, 10, 31, 1, 8, 8, - NULL, NULL, &msc_reset, - &msc_boot, &msc_attach, &msc_detach, - &msc_dib, DEV_DISABLE }; - -/* IOT routines */ - -int32 msdio (int32 inst, int32 IR, int32 dat) -{ -int32 devd; - -devd = IR & I_DEVMASK; /* get device no */ -switch (inst) { /* case on opcode */ -case ioFLG: /* flag clear/set */ - if ((IR & I_HC) == 0) { setFLG (devd); } /* STF */ - break; -case ioSFC: /* skip flag clear */ - if (FLG (devd) == 0) PC = (PC + 1) & VAMASK; - return dat; -case ioSFS: /* skip flag set */ - if (FLG (devd) != 0) PC = (PC + 1) & VAMASK; - return dat; -case ioOTX: /* output */ - msd_buf = dat; /* store data */ - break; -case ioMIX: /* merge */ - dat = dat | msd_buf; - break; -case ioLIX: /* load */ - dat = msd_buf; - break; -case ioCTL: /* control clear/set */ - if (IR & I_CTL) { /* CLC */ - clrCTL (devd); /* clr ctl, cmd */ - clrCMD (devd); } - else { /* STC */ - setCTL (devd); /* set ctl, cmd */ - setCMD (devd); } - break; -default: - break; } -if (IR & I_HC) { clrFLG (devd); } /* H/C option */ -return dat; -} - -int32 mscio (int32 inst, int32 IR, int32 dat) -{ -int32 i, devc, devd; -t_stat st; -UNIT *uptr = msc_dev.units + msc_usl; -static const uint8 map_sel[16] = { - 0, 0, 1, 1, 2, 2, 2, 2, - 3, 3, 3, 3, 3, 3, 3, 3 }; - -devc = IR & I_DEVMASK; /* get device no */ -devd = devc - 1; -switch (inst) { /* case on opcode */ -case ioFLG: /* flag clear/set */ - if ((IR & I_HC) == 0) { setFLG (devc); } /* STF */ - break; -case ioSFC: /* skip flag clear */ - if (FLG (devc) == 0) PC = (PC + 1) & VAMASK; - return dat; -case ioSFS: /* skip flag set */ - if (FLG (devc) != 0) PC = (PC + 1) & VAMASK; - return dat; -case ioOTX: /* output */ - msc_buf = dat; - msc_sta = msc_sta & ~STA_REJ; /* clear reject */ - if ((dat & 0377) == FNC_CLR) break; /* clear always ok */ - if (msc_sta & STA_BUSY) { /* busy? reject */ - msc_sta = msc_sta | STA_REJ; /* dont chg select */ - break; } - if (dat & FNF_CHS) { /* select change */ - msc_usl = map_sel[FNC_GETSEL (dat)]; /* is immediate */ - uptr = msc_dev.units + msc_usl; } - if (((dat & FNF_MOT) && sim_is_active (uptr)) || - ((dat & FNF_REV) && (uptr->UST & STA_BOT)) || - ((dat & FNF_WRT) && sim_tape_wrp (uptr))) - msc_sta = msc_sta | STA_REJ; /* reject? */ - break; -case ioLIX: /* load */ - dat = 0; -case ioMIX: /* merge */ - dat = dat | ((msc_sta | uptr->UST) & ~STA_DYN); - if (uptr->flags & UNIT_ATT) { /* online? */ - if (sim_is_active (uptr)) /* busy */ - dat = dat | STA_TBSY; - if (sim_tape_wrp (uptr)) /* write prot? */ - dat = dat | STA_WLK; } - else dat = dat | STA_TBSY | STA_LOCAL; - if (ms_ctype) dat = dat | STA_PE | /* 13183A? */ - (msc_usl << STA_V_SEL); - break; -case ioCTL: /* control clear/set */ - if (IR & I_CTL) { clrCTL (devc); } /* CLC */ - else { /* STC */ - if ((msc_buf & 0377) == FNC_CLR) { /* clear? */ - for (i = 0; i < MS_NUMDR; i++) { /* loop thru units */ - if (sim_is_active (&msc_unit[i]) && /* write in prog? */ - (msc_unit[i].FNC == FNC_WC) && (ms_ptr > 0)) { - if (st = sim_tape_wrrecf (uptr, msxb, ms_ptr | MTR_ERF)) - ms_map_err (uptr, st); } - if ((msc_unit[i].UST & STA_REW) == 0) - sim_cancel (&msc_unit[i]); } /* stop if now rew */ - clrCTL (devc); /* init device */ - setFLG (devc); - clrCTL (devd); - setFLG (devd); - msc_sta = msd_buf = msc_buf = msc_1st = 0; - return SCPE_OK; } - uptr->FNC = msc_buf & 0377; /* save function */ - if (uptr->FNC & FNF_RWD) /* rewind? */ - sim_activate (uptr, msc_rtime); /* fast response */ - else sim_activate (uptr, msc_ctime); /* schedule op */ - uptr->UST = 0; /* clear status */ - msc_sta = STA_BUSY; /* ctrl is busy */ - msc_1st = 1; - setCTL (devc); } /* go */ - break; -default: - break; } -if (IR & I_HC) { clrFLG (devc); } /* H/C option */ -return dat; -} - -/* Unit service - - If rewind done, reposition to start of tape, set status - else, do operation, set done, interrupt - - Can't be write locked, can only write lock detached unit -*/ - -t_stat msc_svc (UNIT *uptr) -{ -int32 devc, devd; -t_mtrlnt tbc; -t_stat st, r = SCPE_OK; - -devc = msc_dib.devno; /* get device nos */ -devd = msd_dib.devno; - -if ((uptr->flags & UNIT_ATT) == 0) { /* offline? */ - msc_sta = (msc_sta | STA_REJ) & ~STA_BUSY; /* reject */ - setFLG (devc); /* set cch flg */ - return IORETURN (msc_stopioe, SCPE_UNATT); } - -switch (uptr->FNC) { /* case on function */ -case FNC_REW: /* rewind */ -case FNC_RWS: /* rewind offline */ - if (uptr->UST & STA_REW) { /* rewind in prog? */ - sim_tape_rewind (uptr); /* done */ - uptr->UST = STA_BOT; /* set BOT status */ - if (uptr->FNC & FNF_OFL) detach_unit (uptr); - return SCPE_OK; } - uptr->UST = STA_REW; /* set rewinding */ - sim_activate (uptr, msc_ctime); /* sched completion */ - break; /* "done" */ - -case FNC_GFM: /* gap file mark */ -case FNC_WFM: /* write file mark */ - if (st = sim_tape_wrtmk (uptr)) /* write tmk, err? */ - r = ms_map_err (uptr, st); /* map error */ - msc_sta = STA_EOF; /* set EOF status */ - break; - -case FNC_GAP: /* erase gap */ - break; - -case FNC_FSR: /* space forward */ - if (st = sim_tape_sprecf (uptr, &tbc)) /* space rec fwd, err? */ - r = ms_map_err (uptr, st); /* map error */ - if (tbc & 1) msc_sta = msc_sta | STA_ODD; - else msc_sta = msc_sta & ~STA_ODD; - break; - -case FNC_BSR: - if (st = sim_tape_sprecr (uptr, &tbc)) /* space rec rev, err? */ - r = ms_map_err (uptr, st); /* map error */ - if (tbc & 1) msc_sta = msc_sta | STA_ODD; - else msc_sta = msc_sta & ~STA_ODD; - break; - -case FNC_FSF: - while ((st = sim_tape_sprecf (uptr, &tbc)) == MTSE_OK) ; - if (st == MTSE_TMK) /* stopped by tmk? */ - msc_sta = msc_sta | STA_EOF | STA_ODD; /* normal status */ - else r = ms_map_err (uptr, st); /* map error */ - break; - -case FNC_BSF: - while ((st = sim_tape_sprecr (uptr, &tbc)) == MTSE_OK) ; - if (st == MTSE_TMK) /* stopped by tmk? */ - msc_sta = msc_sta | STA_EOF | STA_ODD; /* normal status */ - else r = ms_map_err (uptr, st); /* map error */ - break; - -/* Unit service, continued */ - -case FNC_RFF: /* diagnostic read */ -case FNC_RC: /* read */ - if (msc_1st) { /* first svc? */ - msc_1st = ms_ptr = 0; /* clr 1st flop */ - st = sim_tape_rdrecf (uptr, msxb, &ms_max, DBSIZE); /* read rec */ - if (st == MTSE_RECE) msc_sta = msc_sta | STA_PAR; /* rec in err? */ - else if (st != MTSE_OK) { /* other error? */ - r = ms_map_err (uptr, st); /* map error */ - if (r == SCPE_OK) { /* recoverable? */ - sim_activate (uptr, msc_gtime); /* sched IRG */ - uptr->FNC = 0; /* NOP func */ - return SCPE_OK; } - break; } /* err, done */ - } - if (ms_ptr < ms_max) { /* more chars? */ - if (FLG (devd)) msc_sta = msc_sta | STA_TIM | STA_PAR; - msd_buf = ((uint16) msxb[ms_ptr] << 8) | msxb[ms_ptr + 1]; - ms_ptr = ms_ptr + 2; - setFLG (devd); /* set dch flg */ - sim_activate (uptr, msc_xtime); /* re-activate */ - return SCPE_OK; } - sim_activate (uptr, msc_gtime); /* sched IRG */ - if (uptr->FNC == FNC_RFF) msc_1st = 1; /* diagnostic? */ - else uptr->FNC = 0; /* NOP func */ - return SCPE_OK; - -case FNC_WC: /* write */ - if (msc_1st) msc_1st = ms_ptr = 0; /* no xfer on first */ - else { /* not 1st, next char */ - if (ms_ptr < DBSIZE) { /* room in buffer? */ - msxb[ms_ptr] = msd_buf >> 8; /* store 2 char */ - msxb[ms_ptr + 1] = msd_buf & 0377; - ms_ptr = ms_ptr + 2; - uptr->UST = 0; } - else msc_sta = msc_sta | STA_PAR; } - if (CTL (devd)) { /* xfer flop set? */ - setFLG (devd); /* set dch flag */ - sim_activate (uptr, msc_xtime); /* re-activate */ - return SCPE_OK; } - if (ms_ptr) { /* any data? write */ - if (st = sim_tape_wrrecf (uptr, msxb, ms_ptr)) { /* write, err? */ - r = ms_map_err (uptr, st); /* map error */ - break; } } - sim_activate (uptr, msc_gtime); /* sched IRG */ - uptr->FNC = 0; /* NOP func */ - return SCPE_OK; - -default: /* unknown */ - break; } - -setFLG (devc); /* set cch flg */ -msc_sta = msc_sta & ~STA_BUSY; /* update status */ -return SCPE_OK; -} - -/* Map tape error status */ - -t_stat ms_map_err (UNIT *uptr, t_stat st) -{ -switch (st) { -case MTSE_FMT: /* illegal fmt */ -case MTSE_UNATT: /* unattached */ - msc_sta = msc_sta | STA_REJ; /* reject */ -case MTSE_OK: /* no error */ - return SCPE_IERR; /* never get here! */ -case MTSE_TMK: /* end of file */ - msc_sta = msc_sta | STA_EOF | STA_ODD; /* eof (also sets odd) */ - break; -case MTSE_INVRL: /* invalid rec lnt */ - msc_sta = msc_sta | STA_PAR; - return SCPE_MTRLNT; -case MTSE_IOERR: /* IO error */ - msc_sta = msc_sta | STA_PAR; /* error */ - if (msc_stopioe) return SCPE_IOERR; - break; -case MTSE_RECE: /* record in error */ -case MTSE_EOM: /* end of medium */ - msc_sta = msc_sta | STA_PAR; /* error */ - break; -case MTSE_BOT: /* reverse into BOT */ - uptr->UST = STA_BOT; /* set status */ - break; -case MTSE_WRP: /* write protect */ - msc_sta = msc_sta | STA_REJ; /* reject */ - break; } -return SCPE_OK; -} - -/* Reset routine */ - -t_stat msc_reset (DEVICE *dptr) -{ -int32 i; -UNIT *uptr; - -hp_enbdis_pair (&msc_dev, &msd_dev); /* make pair cons */ -msc_buf = msd_buf = 0; -msc_sta = msc_usl = 0; -msc_1st = 0; -msc_dib.cmd = msd_dib.cmd = 0; /* clear cmd */ -msc_dib.ctl = msd_dib.ctl = 0; /* clear ctl */ -msc_dib.flg = msd_dib.flg = 1; /* set flg */ -msc_dib.fbf = msd_dib.fbf = 1; /* set fbf */ -for (i = 0; i < MS_NUMDR; i++) { - uptr = msc_dev.units + i; - sim_tape_reset (uptr); - sim_cancel (uptr); - uptr->UST = 0; } -return SCPE_OK; -} - -/* Attach routine */ - -t_stat msc_attach (UNIT *uptr, char *cptr) -{ -t_stat r; - -r = sim_tape_attach (uptr, cptr); /* attach unit */ -if (r != SCPE_OK) return r; /* update status */ -uptr->UST = STA_BOT; -return r; -} - -/* Detach routine */ - -t_stat msc_detach (UNIT* uptr) -{ -uptr->UST = 0; /* update status */ -return sim_tape_detach (uptr); /* detach unit */ -} - -/* Set controller type */ - -t_stat ms_settype (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -int32 i; - -if ((val < 0) || (val > 1) || (cptr != NULL)) return SCPE_ARG; -for (i = 0; i < MS_NUMDR; i++) { - if (msc_unit[i].flags & UNIT_ATT) return SCPE_ALATT; } -ms_ctype = val; -return SCPE_OK; -} - -/* Show controller type */ - -t_stat ms_showtype (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -if (ms_ctype) fprintf (st, "13183A"); -else fprintf (st, "13181A"); -return SCPE_OK; -} - -/* 7970B/7970E bootstrap routine (HP 12992D ROM) */ - -#define CHANGE_DEV (1 << 24) - -static const int32 mboot[IBL_LNT] = { - 0106501, /*ST LIB 1 ; read sw */ - 0006011, /* SLB,RSS ; bit 0 set? */ - 0027714, /* JMP RD ; no read */ - 0003004, /* CMA,INA ; A is ctr */ - 0073775, /* STA WC ; save */ - 0067772, /* LDA SL0RW ; sel 0, rew */ - 0017762, /*FF JSB CMD ; do cmd */ - 0102301+CHANGE_DEV, /* SFS CC ; done? */ - 0027707, /* JMP *-1 ; wait */ - 0067774, /* LDB FFC ; get file fwd */ - 0037775, /* ISZ WC ; done files? */ - 0027706, /* JMP FF ; no */ - 0067773, /*RD LDB RDCMD ; read cmd */ - 0017762, /* JSB CMD ; do cmd */ - 0103700+CHANGE_DEV, /* STC DC,C ; start dch */ - 0102201+CHANGE_DEV, /* SFC CC ; read done? */ - 0027752, /* JMP STAT ; no, get stat */ - 0102300+CHANGE_DEV, /* SFS DC ; any data? */ - 0027717, /* JMP *-3 ; wait */ - 0107500+CHANGE_DEV, /* LIB DC,C ; get rec cnt */ - 0005727, /* BLF,BLF ; move to lower */ - 0007000, /* CMB ; make neg */ - 0077775, /* STA WC ; save */ - 0102201+CHANGE_DEV, /* SFC CC ; read done? */ - 0027752, /* JMP STAT ; no, get stat */ - 0102300+CHANGE_DEV, /* SFS DC ; any data? */ - 0027727, /* JMP *-3 ; wait */ - 0107500+CHANGE_DEV, /* LIB DC,C ; get load addr */ - 0074000, /* STB 0 ; start csum */ - 0077762, /* STA CMD ; save address */ - 0027742, /* JMP *+4 */ - 0177762, /*NW STB CMD,I ; store data */ - 0040001, /* ADA 1 ; add to csum */ - 0037762, /* ISZ CMD ; adv addr ptr */ - 0102300+CHANGE_DEV, /* SFS DC ; any data? */ - 0027742, /* JMP *-1 ; wait */ - 0107500+CHANGE_DEV, /* LIB DC,C ; get word */ - 0037775, /* ISZ WC ; done? */ - 0027737, /* JMP NW ; no */ - 0054000, /* CPB 0 ; csum ok? */ - 0027717, /* JMP RD+3 ; yes, cont */ - 0102011, /* HLT 11 ; no, halt */ - 0102501+CHANGE_DEV, /*ST LIA CC ; get status */ - 0001727, /* ALF,ALF ; get eof bit */ - 0002020, /* SSA ; set? */ - 0102077, /* HLT 77 ; done */ - 0001727, /* ALF,ALF ; put status back */ - 0001310, /* RAR,SLA ; read ok? */ - 0102000, /* HLT 0 ; no */ - 0027714, /* JMP RD ; read next */ - 0000000, /*CMD 0 */ - 0106601+CHANGE_DEV, /* OTB CC ; output cmd */ - 0102501+CHANGE_DEV, /* LIA CC ; check for reject */ - 0001323, /* RAR,RAR */ - 0001310, /* RAR,SLA */ - 0027763, /* JMP CMD+1 ; try again */ - 0103701+CHANGE_DEV, /* STC CC,C ; start command */ - 0127762, /* JMP CMD,I ; exit */ - 0001501, /*SL0RW 001501 ; select 0, rewind */ - 0001423, /*RDCMD 001423 ; read record */ - 0000203, /*FFC 000203 ; space forward file */ - 0000000, /*WC 000000 */ - 0000000, - 0000000 }; - -t_stat msc_boot (int32 unitno, DEVICE *dptr) -{ -int32 i, dev; - -if (unitno != 0) return SCPE_NOFNC; /* only unit 0 */ -dev = msd_dib.devno; /* get data chan dev */ -PC = ((MEMSIZE - 1) & ~IBL_MASK) & VAMASK; /* start at mem top */ -SR = IBL_MS + (dev << IBL_V_DEV); /* set SR */ -if ((sim_switches & SWMASK ('S')) && AR) SR = SR | 1; /* skip? */ -for (i = 0; i < IBL_LNT; i++) { /* copy bootstrap */ - if (mboot[i] & CHANGE_DEV) /* IO instr? */ - M[PC + i] = (mboot[i] + dev) & DMASK; - else M[PC + i] = mboot[i]; } -return SCPE_OK; -} diff --git a/HP2100/hp2100_mt.c b/HP2100/hp2100_mt.c deleted file mode 100644 index 320dc7ee..00000000 --- a/HP2100/hp2100_mt.c +++ /dev/null @@ -1,478 +0,0 @@ -/* hp2100_mt.c: HP 2100 12559A magnetic tape simulator - - 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. - - mt 12559A 3030 nine track magnetic tape - - 25-Apr-03 RMS Revised for extended file support - 28-Mar-03 RMS Added multiformat support - 28-Feb-03 RMS Revised for magtape library - 30-Sep-02 RMS Revamped error handling - 28-Aug-02 RMS Added end of medium support - 30-May-02 RMS Widened POS to 32b - 22-Apr-02 RMS Added maximum record length test - 20-Jan-02 RMS Fixed bug on last character write - 03-Dec-01 RMS Added read only unit, extended SET/SHOW support - 07-Sep-01 RMS Moved function prototypes - 30-Nov-00 RMS Made variable names unique - 04-Oct-98 RMS V2.4 magtape format - - Magnetic tapes are represented as a series of variable records - of the form: - - 32b byte count - byte 0 - byte 1 - : - byte n-2 - byte n-1 - 32b byte count - - If the byte count is odd, the record is padded with an extra byte - of junk. File marks are represented by a byte count of 0. - - Unusually among HP peripherals, the 12559 does not have a command flop, - and its flag and flag buffer power up as clear rather than set. -*/ - -#include "hp2100_defs.h" -#include "sim_tape.h" - -#define DB_V_SIZE 16 /* max data buf */ -#define DBSIZE (1 << DB_V_SIZE) /* max data cmd */ - -/* Command - mtc_fnc */ - -#define FNC_CLR 0300 /* clear */ -#define FNC_WC 0031 /* write */ -#define FNC_RC 0023 /* read */ -#define FNC_GAP 0011 /* write gap */ -#define FNC_FSR 0003 /* forward space */ -#define FNC_BSR 0041 /* backward space */ -#define FNC_REW 0201 /* rewind */ -#define FNC_RWS 0101 /* rewind and offline */ -#define FNC_WFM 0035 /* write file mark */ - -/* Status - stored in mtc_sta, (d) = dynamic */ - -#define STA_LOCAL 0400 /* local (d) */ -#define STA_EOF 0200 /* end of file */ -#define STA_BOT 0100 /* beginning of tape */ -#define STA_EOT 0040 /* end of tape */ -#define STA_TIM 0020 /* timing error */ -#define STA_REJ 0010 /* programming error */ -#define STA_WLK 0004 /* write locked (d) */ -#define STA_PAR 0002 /* parity error */ -#define STA_BUSY 0001 /* busy (d) */ - -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 */ -int32 mtc_1st = 0; /* first svc flop */ -int32 mtc_ctime = 1000; /* command wait */ -int32 mtc_gtime = 1000; /* gap stop time */ -int32 mtc_xtime = 15; /* data xfer time */ -int32 mtc_stopioe = 1; /* stop on error */ -uint8 mtxb[DBSIZE] = { 0 }; /* data buffer */ -t_mtrlnt mt_ptr = 0, mt_max = 0; /* buffer ptrs */ -static const int32 mtc_cmd[] = { - FNC_WC, FNC_RC, FNC_GAP, FNC_FSR, FNC_BSR, FNC_REW, FNC_RWS, FNC_WFM }; - -DEVICE mtd_dev, mtc_dev; -int32 mtdio (int32 inst, int32 IR, int32 dat); -int32 mtcio (int32 inst, int32 IR, int32 dat); -t_stat mtc_svc (UNIT *uptr); -t_stat mtc_reset (DEVICE *dptr); -t_stat mtc_attach (UNIT *uptr, char *cptr); -t_stat mtc_detach (UNIT *uptr); -t_stat mt_map_err (UNIT *uptr, t_stat st); - -/* MTD data structures - - mtd_dev MTD device descriptor - mtd_unit MTD unit list - mtd_reg MTD register list -*/ - -DIB mt_dib[] = { - { MTD, 0, 0, 0, 0, &mtdio }, - { MTC, 0, 0, 0, 0, &mtcio } }; - -#define mtd_dib mt_dib[0] -#define mtc_dib mt_dib[1] - -UNIT mtd_unit = { UDATA (NULL, 0, 0) }; - -REG mtd_reg[] = { - { FLDATA (CMD, mtd_dib.cmd, 0), REG_HRO }, - { FLDATA (CTL, mtd_dib.ctl, 0), REG_HRO }, - { FLDATA (FLG, mtd_dib.flg, 0) }, - { FLDATA (FBF, mtd_dib.fbf, 0), REG_HRO }, - { BRDATA (DBUF, mtxb, 8, 8, DBSIZE) }, - { DRDATA (BPTR, mt_ptr, DB_V_SIZE + 1) }, - { DRDATA (BMAX, mt_max, DB_V_SIZE + 1) }, - { ORDATA (DEVNO, mtd_dib.devno, 6), REG_HRO }, - { NULL } }; - -MTAB mtd_mod[] = { - { MTUF_WLK, 0, "write enabled", "WRITEENABLED", NULL }, - { MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL }, - { MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT", - &sim_tape_set_fmt, &sim_tape_show_fmt, NULL }, - { MTAB_XTD | MTAB_VDV, 1, "DEVNO", "DEVNO", - &hp_setdev, &hp_showdev, &mtd_dev }, - { 0 } }; - -DEVICE mtd_dev = { - "MTD", &mtd_unit, mtd_reg, mtd_mod, - 1, 10, 16, 1, 8, 8, - NULL, NULL, &mtc_reset, - NULL, NULL, NULL, - &mtd_dib, DEV_DISABLE | DEV_DIS }; - -/* MTC data structures - - mtc_dev MTC device descriptor - mtc_unit MTC unit list - mtc_reg MTC register list - mtc_mod MTC modifier list -*/ - -UNIT mtc_unit = { UDATA (&mtc_svc, UNIT_ATTABLE + UNIT_ROABLE, 0) }; - -REG mtc_reg[] = { - { ORDATA (FNC, mtc_fnc, 8) }, - { ORDATA (STA, mtc_sta, 9) }, - { ORDATA (BUF, mtc_unit.buf, 8) }, - { FLDATA (CMD, mtc_dib.cmd, 0), REG_HRO }, - { FLDATA (CTL, mtc_dib.ctl, 0) }, - { FLDATA (FLG, mtc_dib.flg, 0) }, - { FLDATA (FBF, mtc_dib.fbf, 0) }, - { FLDATA (DTF, mtc_dtf, 0) }, - { FLDATA (FSVC, mtc_1st, 0) }, - { DRDATA (POS, mtc_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (CTIME, mtc_ctime, 24), REG_NZ + PV_LEFT }, - { DRDATA (GTIME, mtc_gtime, 24), REG_NZ + PV_LEFT }, - { DRDATA (XTIME, mtc_xtime, 24), REG_NZ + PV_LEFT }, - { FLDATA (STOP_IOE, mtc_stopioe, 0) }, - { ORDATA (DEVNO, mtc_dib.devno, 6), REG_HRO }, - { NULL } }; - -MTAB mtc_mod[] = { - { MTAB_XTD | MTAB_VDV, 1, "DEVNO", "DEVNO", - &hp_setdev, &hp_showdev, &mtd_dev }, - { 0 } }; - -DEVICE mtc_dev = { - "MTC", &mtc_unit, mtc_reg, mtc_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &mtc_reset, - NULL, &mtc_attach, &mtc_detach, - &mtc_dib, DEV_DISABLE | DEV_DIS }; - -/* IOT routines */ - -int32 mtdio (int32 inst, int32 IR, int32 dat) -{ -int32 devd; - -devd = IR & I_DEVMASK; /* get device no */ -switch (inst) { /* case on opcode */ -case ioFLG: /* flag clear/set */ - if ((IR & I_HC) == 0) { setFLG (devd); } /* STF */ - break; -case ioSFC: /* skip flag clear */ - if (FLG (devd) == 0) PC = (PC + 1) & VAMASK; - return dat; -case ioSFS: /* skip flag set */ - if (FLG (devd) != 0) PC = (PC + 1) & VAMASK; - return dat; -case ioOTX: /* output */ - mtc_unit.buf = dat & 0377; /* store data */ - break; -case ioMIX: /* merge */ - dat = dat | mtc_unit.buf; - break; -case ioLIX: /* load */ - dat = mtc_unit.buf; - break; -case ioCTL: /* control clear/set */ - if (IR & I_CTL) mtc_dtf = 0; /* CLC: clr xfer flop */ - break; -default: - break; } -if (IR & I_HC) { clrFLG (devd); } /* H/C option */ -return dat; -} - -int32 mtcio (int32 inst, int32 IR, int32 dat) -{ -int32 i, devc, devd, valid; -t_stat st; - -devc = IR & I_DEVMASK; /* get device no */ -devd = devc - 1; -switch (inst) { /* case on opcode */ -case ioFLG: /* flag clear/set */ - if ((IR & I_HC) == 0) { setFLG (devc); } /* STF */ - break; -case ioSFC: /* skip flag clear */ - if (FLG (devc) == 0) PC = (PC + 1) & VAMASK; - return dat; -case ioSFS: /* skip flag set */ - if (FLG (devc) != 0) PC = (PC + 1) & VAMASK; - return dat; -case ioOTX: /* output */ - dat = dat & 0377; - mtc_sta = mtc_sta & ~STA_REJ; /* clear reject */ - if (dat == FNC_CLR) { /* clear? */ - if (sim_is_active (&mtc_unit) && /* write in prog? */ - (mtc_fnc == FNC_WC) && (mt_ptr > 0)) { /* yes, bad rec */ - if (st = sim_tape_wrrecf (&mtc_unit, mtxb, mt_ptr | MTR_ERF)) - mt_map_err (&mtc_unit, st); } - if (((mtc_fnc == FNC_REW) || (mtc_fnc == FNC_RWS)) && - sim_is_active (&mtc_unit)) sim_cancel (&mtc_unit); - mtc_1st = mtc_dtf = 0; - mtc_sta = mtc_sta & STA_BOT; - clrCTL (devc); /* init device */ - clrFLG (devc); - clrCTL (devd); - clrFLG (devd); - return SCPE_OK; } - for (i = valid = 0; i < sizeof (mtc_cmd); i++) /* is fnc valid? */ - if (dat == mtc_cmd[i]) valid = 1; - if (!valid || sim_is_active (&mtc_unit) || /* is cmd valid? */ - ((mtc_sta & STA_BOT) && (dat == FNC_BSR)) || - (sim_tape_wrp (&mtc_unit) && - ((dat == FNC_WC) || (dat == FNC_GAP) || (dat == FNC_WFM)))) - mtc_sta = mtc_sta | STA_REJ; - else { - sim_activate (&mtc_unit, mtc_ctime); /* start tape */ - mtc_fnc = dat; /* save function */ - mtc_sta = STA_BUSY; /* unit busy */ - mt_ptr = 0; /* init buffer ptr */ - clrFLG (devc); /* clear flags */ - clrFLG (devd); - mtc_1st = 1; /* set 1st flop */ - mtc_dtf = 1; } /* set xfer flop */ - break; -case ioLIX: /* load */ - dat = 0; -case ioMIX: /* merge */ - dat = dat | (mtc_sta & ~(STA_LOCAL | STA_WLK | STA_BUSY)); - if (mtc_unit.flags & UNIT_ATT) { /* construct status */ - if (sim_is_active (&mtc_unit)) dat = dat | STA_BUSY; - if (sim_tape_wrp (&mtc_unit)) dat = dat | STA_WLK; } - else dat = dat | STA_BUSY | STA_LOCAL; - break; -case ioCTL: /* control clear/set */ - if (IR & I_CTL) { clrCTL (devc); } /* CLC */ - else { setCTL (devc); } /* STC */ - break; -default: - break; } -if (IR & I_HC) { clrFLG (devc); } /* H/C option */ -return dat; -} - -/* Unit service - - If rewind done, reposition to start of tape, set status - else, do operation, set done, interrupt - - Can't be write locked, can only write lock detached unit -*/ - -t_stat mtc_svc (UNIT *uptr) -{ -int32 devc, devd; -t_mtrlnt tbc; -t_stat st, r = SCPE_OK; - -devc = mtc_dib.devno; /* get device nos */ -devd = mtd_dib.devno; -if ((mtc_unit.flags & UNIT_ATT) == 0) { /* offline? */ - mtc_sta = STA_LOCAL | STA_REJ; /* rejected */ - setFLG (devc); /* set cch flg */ - return IORETURN (mtc_stopioe, SCPE_UNATT); } - -switch (mtc_fnc) { /* case on function */ - -case FNC_REW: /* rewind */ - sim_tape_rewind (uptr); /* BOT */ - mtc_sta = STA_BOT; /* update status */ - break; - -case FNC_RWS: /* rewind and offline */ - sim_tape_rewind (uptr); /* clear position */ - return sim_tape_detach (uptr); /* don't set cch flg */ - -case FNC_WFM: /* write file mark */ - if (st = sim_tape_wrtmk (uptr)) /* write tmk, err? */ - r = mt_map_err (uptr, st); /* map error */ - mtc_sta = STA_EOF; /* set EOF status */ - break; - -case FNC_GAP: /* erase gap */ - break; - -case FNC_FSR: /* space forward */ - if (st = sim_tape_sprecf (uptr, &tbc)) /* space rec fwd, err? */ - r = mt_map_err (uptr, st); /* map error */ - break; - -case FNC_BSR: /* space reverse */ - if (st = sim_tape_sprecr (uptr, &tbc)) /* space rec rev, err? */ - r = mt_map_err (uptr, st); /* map error */ - break; - -/* Unit service, continued */ - -case FNC_RC: /* read */ - if (mtc_1st) { /* first svc? */ - mtc_1st = mt_ptr = 0; /* clr 1st flop */ - st = sim_tape_rdrecf (uptr, mtxb, &mt_max, DBSIZE); /* read rec */ - if (st == MTSE_RECE) mtc_sta = mtc_sta | STA_PAR; /* rec in err? */ - else if (st != MTSE_OK) { /* other error? */ - r = mt_map_err (uptr, st); /* map error */ - if (r == SCPE_OK) { /* recoverable? */ - sim_activate (uptr, mtc_gtime); /* sched IRG */ - mtc_fnc = 0; /* NOP func */ - return SCPE_OK; } - break; } /* non-recov, done */ - if (mt_max < 12) { /* record too short? */ - mtc_sta = mtc_sta | STA_PAR; /* set flag */ - break; } - } - if (mt_ptr < mt_max) { /* more chars? */ - if (FLG (devd)) mtc_sta = mtc_sta | STA_TIM; - mtc_unit.buf = mtxb[mt_ptr++]; /* fetch next */ - setFLG (devd); /* set dch flg */ - sim_activate (uptr, mtc_xtime); /* re-activate */ - return SCPE_OK; } - sim_activate (uptr, mtc_gtime); /* schedule gap */ - mtc_fnc = 0; /* nop */ - return SCPE_OK; - -case FNC_WC: /* write */ - if (mtc_1st) mtc_1st = 0; /* no xfr on first */ - else { - if (mt_ptr < DBSIZE) { /* room in buffer? */ - mtxb[mt_ptr++] = mtc_unit.buf; - mtc_sta = mtc_sta & ~STA_BOT; } /* clear BOT */ - else mtc_sta = mtc_sta | STA_PAR; } - if (mtc_dtf) { /* xfer flop set? */ - setFLG (devd); /* set dch flag */ - sim_activate (uptr, mtc_xtime); /* re-activate */ - return SCPE_OK; } - if (mt_ptr) { /* write buffer */ - if (st = sim_tape_wrrecf (uptr, mtxb, mt_ptr)) { /* write, err? */ - r = mt_map_err (uptr, st); /* map error */ - break; } } /* done */ - sim_activate (uptr, mtc_gtime); /* schedule gap */ - mtc_fnc = 0; /* nop */ - return SCPE_OK; - -default: /* unknown */ - break; } - -setFLG (devc); /* set cch flg */ -mtc_sta = mtc_sta & ~STA_BUSY; /* not busy */ -return SCPE_OK; -} - -/* Map tape error status */ - -t_stat mt_map_err (UNIT *uptr, t_stat st) -{ -switch (st) { -case MTSE_FMT: /* illegal fmt */ -case MTSE_UNATT: /* unattached */ - mtc_sta = mtc_sta | STA_REJ; /* reject */ -case MTSE_OK: /* no error */ - return SCPE_IERR; /* never get here! */ -case MTSE_TMK: /* end of file */ - mtc_sta = mtc_sta | STA_EOF; /* eof */ - break; -case MTSE_IOERR: /* IO error */ - mtc_sta = mtc_sta | STA_PAR; /* error */ - if (mtc_stopioe) return SCPE_IOERR; - break; -case MTSE_INVRL: /* invalid rec lnt */ - mtc_sta = mtc_sta | STA_PAR; - return SCPE_MTRLNT; -case MTSE_RECE: /* record in error */ -case MTSE_EOM: /* end of medium */ - mtc_sta = mtc_sta | STA_PAR; /* error */ - break; -case MTSE_BOT: /* reverse into BOT */ - mtc_sta = mtc_sta | STA_BOT; /* set status */ - break; -case MTSE_WRP: /* write protect */ - mtc_sta = mtc_sta | STA_REJ; /* reject */ - break; } -return SCPE_OK; -} - -/* Reset routine */ - -t_stat mtc_reset (DEVICE *dptr) -{ -hp_enbdis_pair (&mtc_dev, &mtd_dev); /* make pair cons */ -mtc_fnc = 0; -mtc_1st = mtc_dtf = 0; -mtc_dib.cmd = mtd_dib.cmd = 0; /* clear cmd */ -mtc_dib.ctl = mtd_dib.ctl = 0; /* clear ctl */ -mtc_dib.flg = mtd_dib.flg = 0; /* clear flg */ -mtc_dib.fbf = mtd_dib.fbf = 0; /* clear fbf */ -sim_cancel (&mtc_unit); /* cancel activity */ -sim_tape_reset (&mtc_unit); -if (mtc_unit.flags & UNIT_ATT) mtc_sta = - (sim_tape_bot (&mtc_unit)? STA_BOT: 0) | - (sim_tape_wrp (&mtc_unit)? STA_WLK: 0); -else mtc_sta = STA_LOCAL | STA_BUSY; -return SCPE_OK; -} - -/* Attach routine */ - -t_stat mtc_attach (UNIT *uptr, char *cptr) -{ -t_stat r; - -r = sim_tape_attach (uptr, cptr); /* attach unit */ -if (r != SCPE_OK) return r; /* update status */ -mtc_sta = STA_BOT; -return r; -} - -/* Detach routine */ - -t_stat mtc_detach (UNIT* uptr) -{ -mtc_sta = 0; /* update status */ -return sim_tape_detach (uptr); /* detach unit */ -} diff --git a/HP2100/hp2100_mux.c b/HP2100/hp2100_mux.c deleted file mode 100644 index 0d0bb4d3..00000000 --- a/HP2100/hp2100_mux.c +++ /dev/null @@ -1,704 +0,0 @@ -/* hp2100_mux.c: HP 2100 12920A terminal multiplexor simulator - - 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"), - 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,muxl,muxc 12920A terminal multiplexor - - 09-May-03 RMS Added network device flag - 01-Nov-02 RMS Added 7B/8B support - 22-Aug-02 RMS Updated for changes to sim_tmxr - - The 12920A consists of three separate devices - - mux scanner (upper data card) - muxl lines (lower data card) - muxm modem control (control card) - - The lower data card has no CMD flop; the control card has no CMD flop. - The upper data card has none of the usual flops. -*/ - -#include "hp2100_defs.h" -#include "sim_sock.h" -#include "sim_tmxr.h" -#include - -#define MUX_LINES 16 /* user lines */ -#define MUX_ILINES 5 /* diag rcv only */ -#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 MUXU_INIT_POLL 8000 -#define MUXL_WAIT 500 - -/* Channel number (OTA upper, LIA lower or upper) */ - -#define MUX_V_CHAN 10 /* channel num */ -#define MUX_M_CHAN 037 -#define MUX_CHAN(x) (((x) >> MUX_V_CHAN) & MUX_M_CHAN) - -/* OTA, lower = parameters or data */ - -#define OTL_P 0100000 /* parameter */ -#define OTL_TX 0040000 /* transmit */ -#define OTL_ENB 0020000 /* enable */ -#define OTL_TPAR 0010000 /* xmt parity */ -#define OTL_ECHO 0010000 /* rcv echo */ -#define OTL_DIAG 0004000 /* diagnose */ -#define OTL_SYNC 0004000 /* sync */ -#define OTL_V_LNT 8 /* char length */ -#define OTL_M_LNT 07 -#define OTL_LNT(x) (((x) >> OTL_V_LNT) & OTL_M_LNT) -#define OTL_V_BAUD 0 /* baud rate */ -#define OTL_M_BAUD 0377 -#define OTL_BAUD(x) (((x) >> OTL_V_BAUD) & OTL_M_BAUD) -#define OTL_CHAR 01777 /* char mask */ - -/* LIA, lower = received data */ - -#define LIL_PAR 0100000 /* parity */ -#define PUT_DCH(x) (((x) & MUX_M_CHAN) << MUX_V_CHAN) -#define LIL_CHAR 01777 /* character */ - -/* LIA, upper = status */ - -#define LIU_SEEK 0100000 /* seeking NI */ -#define LIU_DG 0000010 /* diagnose */ -#define LIU_BRK 0000004 /* break */ -#define LIU_LOST 0000002 /* char lost */ -#define LIU_TR 0000001 /* trans/rcv */ - -/* OTA, control */ - -#define OTC_SCAN 0100000 /* scan */ -#define OTC_UPD 0040000 /* update */ -#define OTC_V_CHAN 10 /* channel */ -#define OTC_M_CHAN 017 -#define OTC_CHAN(x) (((x) >> OTC_V_CHAN) & OTC_M_CHAN) -#define OTC_EC2 0000200 /* enable Cn upd */ -#define OTC_EC1 0000100 -#define OTC_C2 0000040 /* Cn flops */ -#define OTC_C1 0000020 -#define OTC_ES2 0000010 /* enb comparison */ -#define OTC_ES1 0000004 -#define OTC_V_ES 2 -#define OTC_SS2 0000002 /* SSn flops */ -#define OTC_SS1 0000001 -#define OTC_RW (OTC_ES2|OTC_ES1|OTC_SS2|OTC_SS1) -#define RTS OCT_C2 /* C2 = rts */ -#define DTR OTC_C1 /* C1 = dtr */ - -/* LIA, control */ - -#define LIC_MBO 0140000 /* always set */ -#define LIC_V_CHAN 10 /* channel */ -#define LIC_M_CHAN 017 -#define PUT_CCH(x) (((x) & OTC_M_CHAN) << OTC_V_CHAN) -#define LIC_I2 0001000 /* change flags */ -#define LIC_I1 0000400 -#define LIC_S2 0000002 /* Sn flops */ -#define LIC_S1 0000001 -#define LIC_V_I 8 /* S1 to I1 */ -#define CDET LIC_S2 /* S2 = cdet */ -#define DSR LIC_S1 /* S1 = dsr */ - -#define LIC_TSTI(ch) (((muxc_lia[ch] ^ muxc_ota[ch]) & \ - ((muxc_ota[ch] & (OTC_ES2|OTC_ES1)) >> OTC_V_ES)) \ - << LIC_V_I) - -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 */ -uint16 mux_xpar[MUX_LINES]; /* xmt param */ -uint8 mux_rbuf[MUX_LINES + MUX_ILINES]; /* rcv buf */ -uint8 mux_xbuf[MUX_LINES]; /* xmt buf */ -uint8 mux_rchp[MUX_LINES + MUX_ILINES]; /* rcv chr pend */ -uint8 mux_xdon[MUX_LINES]; /* xmt done */ -uint8 muxc_ota[MUX_LINES]; /* ctrl: Cn,ESn,SSn */ -uint8 muxc_lia[MUX_LINES]; /* ctrl: Sn */ -uint32 mux_tps = 100; /* polls/second */ -uint32 muxl_ibuf = 0; /* low in: rcv data */ -uint32 muxl_obuf = 0; /* low out: param */ -uint32 muxu_ibuf = 0; /* upr in: status */ -uint32 muxu_obuf = 0; /* upr out: chan */ -uint32 muxc_chan = 0; /* ctrl chan */ -uint32 muxc_scan = 0; /* ctrl scan */ - -TMLN mux_ldsc[MUX_LINES] = { 0 }; /* line descriptors */ -TMXR mux_desc = { MUX_LINES, 0, 0, NULL }; /* mux descriptor */ - -DEVICE muxl_dev, muxu_dev, muxc_dev; -int32 muxlio (int32 inst, int32 IR, int32 dat); -int32 muxuio (int32 inst, int32 IR, int32 dat); -int32 muxcio (int32 inst, int32 IR, int32 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); -void mux_data_int (void); -void mux_ctrl_int (void); -void mux_diag (int32 c); - -static uint8 odd_par[256] = { - 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, /* 000-017 */ - 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, /* 020-037 */ - 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, /* 040-067 */ - 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, /* 060-077 */ - 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, /* 100-117 */ - 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, /* 120-137 */ - 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, /* 140-157 */ - 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, /* 160-177 */ - 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, /* 200-217 */ - 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, /* 220-237 */ - 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, /* 240-257 */ - 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, /* 260-277 */ - 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, /* 300-317 */ - 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, /* 320-337 */ - 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, /* 340-367 */ - 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1 }; /* 360-377 */ - -#define RCV_PAR(x) (odd_par[(x) & 0377]? LIL_PAR: 0) - -DIB mux_dib[] = { - { MUXL, 0, 0, 0, 0, &muxlio }, - { MUXU, 0, 0, 0, 0, &muxuio } }; - -#define muxl_dib mux_dib[0] -#define muxu_dib mux_dib[1] - -/* MUX data structures - - muxu_dev MUX device descriptor - muxu_unit MUX unit descriptor - muxu_reg MUX register list - muxu_mod MUX modifiers list -*/ - -UNIT muxu_unit = { UDATA (&muxi_svc, UNIT_ATTABLE, 0), MUXU_INIT_POLL }; - -REG muxu_reg[] = { - { ORDATA (IBUF, muxu_ibuf, 16) }, - { ORDATA (OBUF, muxu_obuf, 16) }, - { FLDATA (CMD, muxu_dib.cmd, 0), REG_HRO }, - { FLDATA (CTL, muxu_dib.ctl, 0), REG_HRO }, - { FLDATA (FLG, muxu_dib.flg, 0), REG_HRO }, - { FLDATA (FBF, muxu_dib.fbf, 0), REG_HRO }, - { ORDATA (DEVNO, muxu_dib.devno, 6), REG_HRO }, - { NULL } }; - -MTAB muxu_mod[] = { - { 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 }, - { MTAB_XTD|MTAB_VDV, 1, "DEVNO", "DEVNO", - &hp_setdev, &hp_showdev, &muxl_dev }, - { MTAB_XTD | MTAB_VDV, 1, NULL, "DISCONNECT", - &tmxr_dscln, NULL, &mux_desc }, - { 0 } }; - -DEVICE muxu_dev = { - "MUX", &muxu_unit, muxu_reg, muxu_mod, - 1, 10, 31, 1, 8, 8, - &tmxr_ex, &tmxr_dep, &mux_reset, - NULL, &mux_attach, &mux_detach, - &muxu_dib, DEV_NET | 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 } }; - -MTAB muxl_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 }, - { MTAB_XTD|MTAB_VDV, 1, "DEVNO", "DEVNO", - &hp_setdev, &hp_showdev, &muxl_dev }, - { 0 } }; - -REG muxl_reg[] = { - { FLDATA (CMD, muxl_dib.cmd, 0), REG_HRO }, - { FLDATA (CTL, muxl_dib.ctl, 0) }, - { FLDATA (FLG, muxl_dib.flg, 0) }, - { FLDATA (FBF, muxl_dib.fbf, 0) }, - { BRDATA (STA, mux_sta, 8, 16, MUX_LINES) }, - { BRDATA (RPAR, mux_rpar, 8, 16, MUX_LINES + MUX_ILINES) }, - { BRDATA (XPAR, mux_xpar, 8, 16, MUX_LINES) }, - { BRDATA (RBUF, mux_rbuf, 8, 8, MUX_LINES + MUX_ILINES) }, - { BRDATA (XBUF, mux_xbuf, 8, 8, MUX_LINES) }, - { BRDATA (RCHP, mux_rchp, 8, 1, MUX_LINES + MUX_ILINES) }, - { BRDATA (XDON, mux_xdon, 8, 1, MUX_LINES) }, - { URDATA (TIME, muxl_unit[0].wait, 10, 24, 0, - MUX_LINES, REG_NZ + PV_LEFT) }, - { ORDATA (DEVNO, muxl_dib.devno, 6), REG_HRO }, - { 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, - &muxl_dib, 0 }; - -/* MUXM data structures - - muxc_dev MUXM device descriptor - muxc_unit MUXM unit descriptor - muxc_reg MUXM register list - muxc_mod MUXM modifiers list -*/ - -DIB muxc_dib = { MUXC, 0, 0, 0, 0, &muxcio }; - -UNIT muxc_unit = { UDATA (NULL, 0, 0) }; - -REG muxc_reg[] = { - { FLDATA (CMD, muxc_dib.cmd, 0), REG_HRO }, - { FLDATA (CTL, muxc_dib.ctl, 0) }, - { FLDATA (FLG, muxc_dib.flg, 0) }, - { FLDATA (FBF, muxc_dib.fbf, 0) }, - { FLDATA (SCAN, muxc_scan, 0) }, - { ORDATA (CHAN, muxc_chan, 4) }, - { BRDATA (DSO, muxc_ota, 8, 6, MUX_LINES) }, - { BRDATA (DSI, muxc_lia, 8, 2, MUX_LINES) }, - { ORDATA (DEVNO, muxc_dib.devno, 6), REG_HRO }, - { NULL } }; - -MTAB muxc_mod[] = { - { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", - &hp_setdev, &hp_showdev, &muxc_dev }, - { 0 } }; - -DEVICE muxc_dev = { - "MUXM", &muxc_unit, muxc_reg, muxc_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &mux_reset, - NULL, NULL, NULL, - &muxc_dib, 0 }; - -/* IOT routines: data cards */ - -int32 muxlio (int32 inst, int32 IR, int32 dat) -{ -int32 dev, ln; - -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 */ - muxl_obuf = dat; /* store data */ - break; -case ioMIX: /* merge */ - dat = dat | muxl_ibuf; - break; -case ioLIX: /* load */ - dat = muxl_ibuf; - break; -case ioCTL: /* control clear/set */ - if (IR & I_CTL) { clrCTL (dev); } /* CLC */ - else { /* STC */ - setCTL (dev); /* set ctl */ - ln = MUX_CHAN (muxu_obuf); /* get chan # */ - if (muxl_obuf & OTL_P) { /* parameter set? */ - if (muxl_obuf & OTL_TX) { /* transmit? */ - if (ln < MUX_LINES) /* to valid line? */ - mux_xpar[ln] = muxl_obuf; } - else if (ln < (MUX_LINES + MUX_ILINES)) /* rcv, valid line? */ - mux_rpar[ln] = muxl_obuf; } - else if ((muxl_obuf & OTL_TX) && /* xmit data? */ - (ln < MUX_LINES)) { /* to valid line? */ - if (sim_is_active (&muxl_unit[ln])) /* still working? */ - mux_sta[ln] = mux_sta[ln] | LIU_LOST; - else sim_activate (&muxl_unit[ln], muxl_unit[ln].wait); - mux_xbuf[ln] = muxl_obuf & OTL_CHAR; } /* load buffer */ - } /* end STC */ - break; -default: - break; } -if (IR & I_HC) { /* H/C option */ - clrFLG (dev); /* clear flag */ - mux_data_int (); } /* look for new int */ -return dat; -} - -int32 muxuio (int32 inst, int32 IR, int32 dat) -{ -switch (inst) { /* case on opcode */ -case ioOTX: /* output */ - muxu_obuf = dat; /* store data */ - break; -case ioMIX: /* merge */ - dat = dat | muxu_ibuf; - break; -case ioLIX: /* load */ - dat = muxu_ibuf; - break; -default: - break; } -return dat; -} - -/* IOT routine: control card */ - -int32 muxcio (int32 inst, int32 IR, int32 dat) -{ -int32 dev, ln, t, old; - -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 */ - if (dat & OTC_SCAN) muxc_scan = 1; /* set scan flag */ - else muxc_scan = 0; - if (dat & OTC_UPD) { /* update? */ - ln = OTC_CHAN (dat); /* get channel */ - old = muxc_ota[ln]; /* save prior val */ - muxc_ota[ln] = (muxc_ota[ln] & ~OTC_RW) | /* save ESn,SSn */ - (dat & OTC_RW); - if (dat & OTC_EC2) muxc_ota[ln] = /* if EC2, upd C2 */ - (muxc_ota[ln] & ~OTC_C2) | (dat & OTC_C2); - if (dat & OTC_EC1) muxc_ota[ln] = /* if EC1, upd C1 */ - (muxc_ota[ln] & ~OTC_C1) | (dat & OTC_C1); - if ((muxl_unit[ln].flags & UNIT_MDM) && /* modem ctrl? */ - (old & DTR) && !(muxc_ota[ln] & DTR)) { /* DTR drop? */ - tmxr_msg (mux_ldsc[ln].conn, "\r\nLine hangup\r\n"); - tmxr_reset_ln (&mux_ldsc[ln]); /* reset line */ - muxc_lia[ln] = 0; } /* dataset off */ - } /* end update */ - break; -case ioLIX: /* load */ - dat = 0; -case ioMIX: /* merge */ - t = LIC_MBO | PUT_CCH (muxc_chan) | /* mbo, chan num */ - LIC_TSTI (muxc_chan) | /* I2, I1 */ - (muxc_ota[muxc_chan] & (OTC_ES2 | OTC_ES1)) | /* ES2, ES1 */ - (muxc_lia[muxc_chan] & (LIC_S2 | LIC_S1)); /* S2, S1 */ - dat = dat | t; /* return status */ - muxc_chan = (muxc_chan + 1) & LIC_M_CHAN; /* incr channel */ - break; -case ioCTL: /* ctrl clear/set */ - if (IR & I_CTL) { clrCTL (dev); } /* CLC */ - else { setCTL (dev); } /* STC */ - break; -default: - break; } -if (IR & I_HC) { /* H/C option */ - clrFLG (dev); /* clear flag */ - mux_ctrl_int (); } /* look for new int */ -return dat; -} - -/* Unit service - receive side - - Poll for new connections - Poll all active lines for input -*/ - -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 ((muxl_unit[ln].flags & UNIT_MDM) && /* modem ctrl? */ - (muxc_ota[ln] & DTR)) /* DTR? */ - muxc_lia[ln] = muxc_lia[ln] | CDET; /* set cdet */ - muxc_lia[ln] = muxc_lia[ln] | DSR; /* set dsr */ - mux_ldsc[ln].rcve = 1; } /* rcv enabled */ -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 (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? */ - } /* 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; -} - -/* Unit service - transmit side */ - -t_stat muxo_svc (UNIT *uptr) -{ -int32 c, ln = uptr - muxl_unit; /* line # */ - -if (mux_ldsc[ln].conn) { /* connected? */ - if (mux_ldsc[ln].xmte) { /* xmt enabled? */ - if ((mux_xbuf[ln] & OTL_SYNC) == 0) { /* start bit 0? */ - TMLN *lp = &mux_ldsc[ln]; /* get line */ - c = mux_xbuf[ln]; /* get char */ - 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_xpar[ln] & OTL_DIAG) /* xmt diag? */ - mux_diag (mux_xbuf[ln]); /* before munge */ - mux_xdon[ln] = 1; /* set done */ - tmxr_putc_ln (lp, 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 (!FLG (muxl_dib.devno)) mux_data_int (); /* scan for int */ -return SCPE_OK; -} - -/* Look for data interrupt */ - -void mux_data_int (void) -{ -int32 i; - -for (i = 0; i < MUX_LINES; i++) { /* rcv lines */ - if ((mux_rpar[i] & OTL_ENB) && mux_rchp[i]) { /* enabled, char? */ - muxl_ibuf = PUT_CCH (i) | mux_rbuf[i] | /* lo buf = char */ - RCV_PAR (mux_rbuf[i]); - muxu_ibuf = PUT_CCH (i) | mux_sta[i]; /* hi buf = stat */ - mux_rchp[i] = 0; /* clr char, stat */ - mux_sta[i] = 0; - setFLG (muxl_dib.devno); /* interrupt */ - return; } } -for (i = 0; i < MUX_LINES; i++) { /* xmt lines */ - if ((mux_xpar[i] & OTL_ENB) && mux_xdon[i]) { /* enabled, done? */ - muxu_ibuf = PUT_CCH (i) | mux_sta[i] | LIU_TR; /* hi buf = stat */ - mux_xdon[i] = 0; /* clr done, stat */ - mux_sta[i] = 0; - setFLG (muxl_dib.devno); /* interrupt */ - return; } } -for (i = MUX_LINES; i < (MUX_LINES + MUX_ILINES); i++) { /* diag lines */ - if ((mux_rpar[i] & OTL_ENB) && mux_rchp[i]) { /* enabled, char? */ - muxl_ibuf = PUT_CCH (i) | mux_rbuf[i] | /* lo buf = char */ - RCV_PAR (mux_rbuf[i]); - muxu_ibuf = PUT_CCH (i) | mux_sta[i] | LIU_DG; /* hi buf = stat */ - mux_rchp[i] = 0; /* clr char, stat */ - mux_sta[i] = 0; - setFLG (muxl_dib.devno); - return; } } -return; -} - -/* Look for control interrupt */ - -void mux_ctrl_int (void) -{ -int32 i; - -if (muxc_scan == 0) return; -for (i = 0; i < MUX_LINES; i++) { - muxc_chan = (muxc_chan + 1) & LIC_M_CHAN; /* step channel */ - if (LIC_TSTI (muxc_chan)) { /* status change? */ - setFLG (muxc_dib.devno); /* set flag */ - break; } } -return; -} - -/* Set diagnostic lines for given character */ - -void mux_diag (int32 c) -{ -int32 i; - -for (i = MUX_LINES; i < (MUX_LINES + MUX_ILINES); i++) { - 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; -} - -/* Reset an individual line */ - -void mux_reset_ln (int32 i) -{ -mux_rbuf[i] = mux_xbuf[i] = 0; /* clear state */ -mux_rpar[i] = mux_xpar[i] = 0; -mux_rchp[i] = mux_xdon[i] = 0; -mux_sta[i] = 0; -muxc_ota[i] = muxc_lia[i] = 0; /* clear modem */ -if (mux_ldsc[i].conn) /* connected? */ - muxc_lia[i] = muxc_lia[i] | DSR | /* cdet, dsr */ - (muxl_unit[i].flags & UNIT_MDM? CDET: 0); -sim_cancel (&muxl_unit[i]); -return; -} - -/* Reset routine */ - -t_stat mux_reset (DEVICE *dptr) -{ -int32 i, t; - -if (muxu_dev.flags & DEV_DIS) { /* enb/dis dev */ - muxl_dev.flags = muxu_dev.flags | DEV_DIS; - muxc_dev.flags = muxc_dev.flags | DEV_DIS; } -else { muxl_dev.flags = muxl_dev.flags & ~DEV_DIS; - muxc_dev.flags = muxc_dev.flags & ~DEV_DIS; } -muxl_dib.cmd = muxl_dib.ctl = 0; /* init lower */ -muxl_dib.flg = muxl_dib.fbf = 1; -muxu_dib.cmd = muxu_dib.ctl = 0; /* upper not */ -muxu_dib.flg = muxu_dib.fbf = 0; /* implemented */ -muxc_dib.cmd = muxc_dib.ctl = 0; /* init ctrl */ -muxc_dib.flg = muxc_dib.fbf = 1; -muxc_chan = muxc_scan = 0; /* init modem scan */ -if (muxu_unit.flags & UNIT_ATT) { /* master att? */ - if (!sim_is_active (&muxu_unit)) { - t = sim_rtcn_init (muxu_unit.wait, TMR_MUX); - sim_activate (&muxu_unit, t); } } /* activate */ -else sim_cancel (&muxu_unit); /* else stop */ -for (i = 0; i < MUX_LINES; i++) { - mux_desc.ldsc[i] = &mux_ldsc[i]; - mux_reset_ln (i); } -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 (muxu_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; -} - diff --git a/HP2100/hp2100_stddev.c b/HP2100/hp2100_stddev.c deleted file mode 100644 index e048401d..00000000 --- a/HP2100/hp2100_stddev.c +++ /dev/null @@ -1,704 +0,0 @@ -/* hp2100_stddev.c: HP2100 standard devices simulator - - 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 MERCHANTI_CTLILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - ROBERT M SUPNIK BE LII_CTLLE FOR ANY CLAIM, DAMAGES OR OTHER LII_CTLILITY, 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 12597A-002 paper tape reader - ptp 12597A-005 paper tape punch - tty 12531C buffered teleprinter interface - clk 12539C time base generator - - 25-Apr-03 RMS Added extended file support - 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 - Fixed clock to add calibration, proper start/stop - Added UC option to TTY output - 30-May-02 RMS Widened POS to 32b - 22-Mar-02 RMS Revised for dynamically allocated memory - 03-Nov-01 RMS Changed DEVNO to use extended SET/SHOW - 29-Nov-01 RMS Added read only unit support - 24-Nov-01 RMS Changed TIME to an array - 07-Sep-01 RMS Moved function prototypes - 21-Nov-00 RMS Fixed flag, buffer power up state - Added status input for ptp, tty - 15-Oct-00 RMS Added dynamic device number support - - The reader and punch, like most HP devices, have a command flop. The - teleprinter and clock do not. - - The clock autocalibrates. If the specified clock frequency is below - 10Hz, the clock service routine runs at 10Hz and counts down a repeat - counter before generating an interrupt. Autocalibration will not work - if the clock is running at 1Hz or less. - - Clock diagnostic mode corresponds to inserting jumper W2 on the 12539C. - This turns off autocalibration and divides the longest time intervals down - by 10**3. The clk_time values were chosen to allow the diagnostic to - pass its clock calibration test. -*/ - -#include "hp2100_defs.h" -#include -#define UNIT_V_8B (UNIT_V_UF + 0) /* 8B */ -#define UNIT_V_UC (UNIT_V_UF + 1) /* UC only */ -#define UNIT_V_DIAG (UNIT_V_UF + 2) /* diag mode */ -#define UNIT_8B (1 << UNIT_V_8B) -#define UNIT_UC (1 << UNIT_V_UC) -#define UNIT_DIAG (1 << UNIT_V_DIAG) - -#define PTP_LOW 0000040 /* low tape */ -#define TM_MODE 0100000 /* mode change */ -#define TM_KBD 0040000 /* enable keyboard */ -#define TM_PRI 0020000 /* enable printer */ -#define TM_PUN 0010000 /* enable punch */ -#define TP_BUSY 0100000 /* busy */ - -#define CLK_V_ERROR 4 /* clock overrun */ -#define CLK_ERROR (1 << CLK_V_ERROR) - -extern uint16 *M; -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 */ -int32 ttp_stopioe = 0; -int32 tty_buf = 0, tty_mode = 0; /* tty buffer, mode */ -int32 clk_select = 0; /* clock time select */ -int32 clk_error = 0; /* clock error */ -int32 clk_ctr = 0; /* clock counter */ -int32 clk_time[8] = /* clock intervals */ - { 155, 1550, 15500, 155000, 155000, 155000, 155000, 155000 }; -int32 clk_tps[8] = /* clock tps */ - { 10000, 1000, 100, 10, 10, 10, 10, 10 }; -int32 clk_rpt[8] = /* number of repeats */ - { 1, 1, 1, 1, 10, 100, 1000, 10000 }; - -DEVICE ptr_dev, ptp_dev, tty_dev, clk_dev; -int32 ptrio (int32 inst, int32 IR, int32 dat); -t_stat ptr_svc (UNIT *uptr); -t_stat ptr_reset (DEVICE *dptr); -t_stat ptr_boot (int32 unitno, DEVICE *dptr); -int32 ptpio (int32 inst, int32 IR, int32 dat); -t_stat ptp_svc (UNIT *uptr); -t_stat ptp_reset (DEVICE *dptr); -int32 ttyio (int32 inst, int32 IR, int32 dat); -t_stat tti_svc (UNIT *uptr); -t_stat tto_svc (UNIT *uptr); -t_stat tty_reset (DEVICE *dptr); -t_stat tty_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc); -int32 clkio (int32 inst, int32 IR, int32 dat); -t_stat clk_svc (UNIT *uptr); -t_stat clk_reset (DEVICE *dptr); -int32 clk_delay (int32 flg); - -/* PTR data structures - - ptr_dev PTR device descriptor - ptr_unit PTR unit descriptor - ptr_mod PTR modifiers - ptr_reg PTR register list -*/ - -DIB ptr_dib = { PTR, 0, 0, 0, 0, &ptrio }; - -UNIT ptr_unit = { - UDATA (&ptr_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0), - SERIAL_IN_WAIT }; - -REG ptr_reg[] = { - { ORDATA (BUF, ptr_unit.buf, 8) }, - { FLDATA (CMD, ptr_dib.cmd, 0) }, - { FLDATA (CTL, ptr_dib.ctl, 0) }, - { FLDATA (FLG, ptr_dib.flg, 0) }, - { FLDATA (FBF, ptr_dib.fbf, 0) }, - { DRDATA (POS, ptr_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, ptr_unit.wait, 24), PV_LEFT }, - { FLDATA (STOP_IOE, ptr_stopioe, 0) }, - { ORDATA (DEVNO, ptr_dib.devno, 6), REG_HRO }, - { NULL } }; - -MTAB ptr_mod[] = { - { MTAB_XTD | MTAB_VDV, 0, "DEVNO", "DEVNO", - &hp_setdev, &hp_showdev, &ptr_dev }, - { 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 descriptor - ptp_mod PTP modifiers - ptp_reg PTP register list -*/ - -DIB ptp_dib = { PTP, 0, 0, 0, 0, &ptpio }; - -UNIT ptp_unit = { - UDATA (&ptp_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT }; - -REG ptp_reg[] = { - { ORDATA (BUF, ptp_unit.buf, 8) }, - { FLDATA (CMD, ptp_dib.cmd, 0) }, - { FLDATA (CTL, ptp_dib.ctl, 0) }, - { FLDATA (FLG, ptp_dib.flg, 0) }, - { FLDATA (FBF, ptp_dib.fbf, 0) }, - { DRDATA (POS, ptp_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, ptp_unit.wait, 24), PV_LEFT }, - { FLDATA (STOP_IOE, ptp_stopioe, 0) }, - { ORDATA (DEVNO, ptp_dib.devno, 6), REG_HRO }, - { NULL } }; - -MTAB ptp_mod[] = { - { MTAB_XTD | MTAB_VDV, 0, "DEVNO", "DEVNO", - &hp_setdev, &hp_showdev, &ptp_dev }, - { 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 }; - -/* TTY data structures - - tty_dev TTY device descriptor - tty_unit TTY unit descriptor - tty_reg TTY register list - tty_mod TTy modifiers list -*/ - -#define TTI 0 -#define TTO 1 -#define TTP 2 - -DIB tty_dib = { TTY, 0, 0, 0, 0, &ttyio }; - -UNIT tty_unit[] = { - { UDATA (&tti_svc, UNIT_UC, 0), KBD_POLL_WAIT }, - { UDATA (&tto_svc, UNIT_UC, 0), SERIAL_OUT_WAIT }, - { UDATA (&tto_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_8B, 0), SERIAL_OUT_WAIT } }; - -REG tty_reg[] = { - { ORDATA (BUF, tty_buf, 8) }, - { ORDATA (MODE, tty_mode, 16) }, - { FLDATA (CMD, tty_dib.cmd, 0), REG_HRO }, - { FLDATA (CTL, tty_dib.ctl, 0) }, - { FLDATA (FLG, tty_dib.flg, 0) }, - { FLDATA (FBF, tty_dib.fbf, 0) }, - { DRDATA (KPOS, tty_unit[TTI].pos, T_ADDR_W), PV_LEFT }, - { DRDATA (KTIME, tty_unit[TTI].wait, 24), REG_NZ + PV_LEFT }, - { DRDATA (TPOS, tty_unit[TTO].pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TTIME, tty_unit[TTO].wait, 24), REG_NZ + PV_LEFT }, - { DRDATA (PPOS, tty_unit[TTP].pos, T_ADDR_W), PV_LEFT }, - { FLDATA (STOP_IOE, ttp_stopioe, 0) }, - { ORDATA (DEVNO, tty_dib.devno, 6), REG_HRO }, - { NULL } }; - -MTAB tty_mod[] = { - { UNIT_UC+UNIT_8B, UNIT_UC, "UC", "UC", &tty_set_mode }, - { UNIT_UC+UNIT_8B, 0 , "7b", "7B", &tty_set_mode }, - { UNIT_UC+UNIT_8B, UNIT_8B, "8b", "8B", &tty_set_mode }, - { MTAB_XTD | MTAB_VDV, 0, "DEVNO", "DEVNO", - &hp_setdev, &hp_showdev, &tty_dev }, - { 0 } }; - -DEVICE tty_dev = { - "TTY", tty_unit, tty_reg, tty_mod, - 3, 10, 31, 1, 8, 8, - NULL, NULL, &tty_reset, - NULL, NULL, NULL, - &tty_dib, 0 }; - -/* CLK data structures - - clk_dev CLK device descriptor - clk_unit CLK unit descriptor - clk_mod CLK modifiers - clk_reg CLK register list -*/ - -DIB clk_dib = { CLK, 0, 0, 0, 0, &clkio }; - -UNIT clk_unit = { - UDATA (&clk_svc, 0, 0) }; - -REG clk_reg[] = { - { ORDATA (SEL, clk_select, 3) }, - { DRDATA (CTR, clk_ctr, 14) }, - { FLDATA (CMD, clk_dib.cmd, 0), REG_HRO }, - { FLDATA (CTL, clk_dib.ctl, 0) }, - { FLDATA (FLG, clk_dib.flg, 0) }, - { FLDATA (FBF, clk_dib.fbf, 0) }, - { FLDATA (ERR, clk_error, CLK_V_ERROR) }, - { BRDATA (TIME, clk_time, 10, 24, 8) }, - { ORDATA (DEVNO, clk_dib.devno, 6), REG_HRO }, - { NULL } }; - -MTAB clk_mod[] = { - { 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 } }; - -DEVICE clk_dev = { - "CLK", &clk_unit, clk_reg, clk_mod, - 1, 0, 0, 0, 0, 0, - NULL, NULL, &clk_reset, - NULL, NULL, NULL, - &clk_dib, 0 }; - -/* Paper tape reader: IOT routine */ - -int32 ptrio (int32 inst, int32 IR, int32 dat) -{ -int32 dev; - -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 ioMIX: /* merge */ - dat = dat | ptr_unit.buf; - break; -case ioLIX: /* load */ - dat = ptr_unit.buf; - break; -case ioCTL: /* control clear/set */ - if (IR & I_CTL) { /* CLC */ - clrCMD (dev); /* clear cmd, ctl */ - clrCTL (dev); } - else { /* STC */ - setCMD (dev); /* set cmd, ctl */ - setCTL (dev); - sim_activate (&ptr_unit, ptr_unit.wait); } - break; -default: - break; } -if (IR & I_HC) { clrFLG (dev); } /* H/C option */ -return dat; -} - -/* Unit service */ - -t_stat ptr_svc (UNIT *uptr) -{ -int32 dev, temp; - -dev = ptr_dib.devno; /* get device no */ -clrCMD (dev); /* clear cmd */ -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; } - else perror ("PTR I/O error"); - clearerr (ptr_unit.fileref); - return SCPE_IOERR; } -setFLG (dev); /* set flag */ -ptr_unit.buf = temp & 0377; /* put byte in buf */ -ptr_unit.pos = ftell (ptr_unit.fileref); -return SCPE_OK; -} - -/* Reset routine - called from SCP, flags in DIB's */ - -t_stat ptr_reset (DEVICE *dptr) -{ -ptr_dib.cmd = ptr_dib.ctl = 0; /* clear cmd, ctl */ -ptr_dib.flg = ptr_dib.fbf = 1; /* set flg, fbf */ -ptr_unit.buf = 0; -sim_cancel (&ptr_unit); /* deactivate unit */ -return SCPE_OK; -} - -/* Paper tape reader bootstrap routine (HP 12992K ROM) */ - -#define LDR_BASE 077 -#define CHANGE_DEV (1 << 24) - -static const int32 pboot[IBL_LNT] = { - 0107700, /*ST CLC 0,C ; intr off */ - 0002401, /* CLA,RSS ; skip in */ - 0063756, /*CN LDA M11 ; feed frame */ - 0006700, /* CLB,CCE ; set E to rd byte */ - 0017742, /* JSB READ ; get #char */ - 0007306, /* CMB,CCE,INB,SZB ; 2's comp */ - 0027713, /* JMP *+5 ; non-zero byte */ - 0002006, /* INA,SZA ; feed frame ctr */ - 0027703, /* JMP *-3 */ - 0102077, /* HLT 77B ; stop */ - 0027700, /* JMP ST ; next */ - 0077754, /* STA WC ; word in rec */ - 0017742, /* JSB READ ; get feed frame */ - 0017742, /* JSB READ ; get address */ - 0074000, /* STB 0 ; init csum */ - 0077755, /* STB AD ; save addr */ - 0067755, /*CK LDB AD ; check addr */ - 0047777, /* ADB MAXAD ; below loader */ - 0002040, /* SEZ ; E =0 => OK */ - 0027740, /* JMP H55 */ - 0017742, /* JSB READ ; get word */ - 0040001, /* ADA 1 ; cont checksum */ - 0177755, /* STA AD,I ; store word */ - 0037755, /* ISZ AD */ - 0000040, /* CLE ; force wd read */ - 0037754, /* ISZ WC ; block done? */ - 0027720, /* JMP CK ; no */ - 0017742, /* JSB READ ; get checksum */ - 0054000, /* CPB 0 ; ok? */ - 0027702, /* JMP CN ; next block */ - 0102011, /* HLT 11 ; bad csum */ - 0027700, /* JMP ST ; next */ - 0102055, /*H55 HALT 55 ; bad address */ - 0027700, /* JMP ST ; next */ - 0000000, /*RD 0 */ - 0006600, /* CLB,CME ; E reg byte ptr */ - 0103700+CHANGE_DEV, /* STC RDR,C ; start reader */ - 0102300+CHANGE_DEV, /* SFS RDR ; wait */ - 0027745, /* JMP *-1 */ - 0106400+CHANGE_DEV, /* MIB RDR ; get byte */ - 0002041, /* SEZ,RSS ; E set? */ - 0127742, /* JMP RD,I ; no, done */ - 0005767, /* BLF,CLE,BLF ; shift byte */ - 0027744, /* JMP RD+2 ; again */ - 0000000, /*WC 000000 ; word count */ - 0000000, /*AD 000000 ; address */ - 0177765, /*M11 -11 ; feed count */ - 0, 0, 0, 0, 0, 0, 0, 0, /* unused */ - 0, 0, 0, 0, 0, 0, 0, /* unused */ - 0000000 }; /*MAXAD -ST ; max addr */ - -t_stat ptr_boot (int32 unitno, DEVICE *dptr) -{ -int32 i, dev; - -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_DEV) /* IO instr? */ - M[PC + i] = (pboot[i] + dev) & DMASK; - else M[PC + i] = pboot[i]; } -M[PC + LDR_BASE] = (~PC + 1) & DMASK; -return SCPE_OK; -} - -/* Paper tape punch: IOT routine */ - -int32 ptpio (int32 inst, int32 IR, int32 dat) -{ -int32 dev; - -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 ioLIX: /* load */ - dat = 0; -case ioMIX: /* merge */ - if ((ptp_unit.flags & UNIT_ATT) == 0) - dat = dat | PTP_LOW; /* out of tape? */ - break; -case ioOTX: /* output */ - ptp_unit.buf = dat; - break; -case ioCTL: /* control clear/set */ - if (IR & I_CTL) { /* CLC */ - clrCMD (dev); /* clear cmd, ctl */ - clrCTL (dev); } - else { /* STC */ - setCMD (dev); /* set cmd, ctl */ - setCTL (dev); - sim_activate (&ptp_unit, ptp_unit.wait); } - break; -default: - break; } -if (IR & I_HC) { clrFLG (dev); } /* H/C option */ -return dat; -} - -/* Unit service */ - -t_stat ptp_svc (UNIT *uptr) -{ -int32 dev; - -dev = ptp_dib.devno; /* get device no */ -clrCMD (dev); /* clear cmd */ -setFLG (dev); /* set flag */ -if ((ptp_unit.flags & UNIT_ATT) == 0) /* attached? */ - return IORETURN (ptp_stopioe, SCPE_UNATT); -if (putc (ptp_unit.buf, ptp_unit.fileref) == EOF) { /* output byte */ - perror ("PTP I/O error"); - clearerr (ptp_unit.fileref); - return SCPE_IOERR; } -ptp_unit.pos = ftell (ptp_unit.fileref); /* update position */ -return SCPE_OK; -} - -/* Reset routine */ - -t_stat ptp_reset (DEVICE *dptr) -{ -ptp_dib.cmd = ptp_dib.ctl = 0; /* clear cmd, ctl */ -ptp_dib.flg = ptp_dib.fbf = 1; /* set flg, fbf */ -ptp_unit.buf = 0; -sim_cancel (&ptp_unit); /* deactivate unit */ -return SCPE_OK; -} - -/* Terminal: IOT routine */ - -int32 ttyio (int32 inst, int32 IR, int32 dat) -{ -int32 dev; - -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 ioLIX: /* load */ - dat = 0; -case ioMIX: /* merge */ - dat = dat | tty_buf; - if (!(tty_mode & TM_KBD) && sim_is_active (&tty_unit[TTO])) - dat = dat | TP_BUSY; - break; -case ioOTX: /* output */ - if (dat & TM_MODE) tty_mode = dat & (TM_KBD|TM_PRI|TM_PUN); - tty_buf = dat & 0377; - break; -case ioCTL: /* control clear/set */ - if (IR & I_CTL) { clrCTL (dev); } /* CLC */ - else { /* STC */ - setCTL (dev); - if (!(tty_mode & TM_KBD)) /* output? */ - sim_activate (&tty_unit[TTO], tty_unit[TTO].wait); } - break; -default: - break; } -if (IR & I_HC) { clrFLG (dev); } /* H/C option */ -return dat; -} - -/* Unit service routines */ - -t_stat tto_out (int32 c) -{ -t_stat ret = SCPE_OK; - -if (tty_mode & TM_PRI) { /* printing? */ - if (tty_unit[TTO].flags & UNIT_UC) { /* UC only? */ - c = c & 0177; - if (islower (c)) c = toupper (c); } - else c = c & ((tty_unit[TTO].flags & UNIT_8B)? 0377: 0177); - ret = sim_putchar (c); /* output char */ - tty_unit[TTO].pos = tty_unit[TTO].pos + 1; } -if (tty_mode & TM_PUN) { /* punching? */ - if ((tty_unit[TTP].flags & UNIT_ATT) == 0) /* attached? */ - return IORETURN (ttp_stopioe, SCPE_UNATT); - if (putc (c, tty_unit[TTP].fileref) == EOF) { /* output char */ - perror ("TTP I/O error"); - clearerr (tty_unit[TTP].fileref); - return SCPE_IOERR; } - tty_unit[TTP].pos = ftell (tty_unit[TTP].fileref); } -return ret; -} - -t_stat tti_svc (UNIT *uptr) -{ -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 (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); -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 */ - if (c) return tto_out (c); } /* echo or punch? */ -return SCPE_OK; -} - -t_stat tto_svc (UNIT *uptr) -{ -int32 c, dev; - -dev = tty_dib.devno; /* get device no */ -setFLG (dev); /* set done flag */ -c = tty_buf; -tty_buf = 0377; /* defang buf */ -return tto_out (c); /* print and/or punch */ -} - -/* Reset routine */ - -t_stat tty_reset (DEVICE *dptr) -{ -tty_dib.cmd = tty_dib.ctl = 0; /* clear cmd, ctl */ -tty_dib.flg = tty_dib.fbf = 1; /* set flg, fbf */ -tty_mode = TM_KBD; /* enable input */ -tty_buf = 0; -sim_activate (&tty_unit[TTI], tty_unit[TTI].wait); /* activate poll */ -sim_cancel (&tty_unit[TTO]); /* cancel output */ -return SCPE_OK; -} - -t_stat tty_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -int32 u = uptr - tty_dev.units; - -if (u > 1) return SCPE_NOFNC; -tty_unit[TTI].flags = (tty_unit[TTI].flags & ~(UNIT_UC | UNIT_8B)) | val; -tty_unit[TTO].flags = (tty_unit[TTO].flags & ~(UNIT_UC | UNIT_8B)) | val; -return SCPE_OK; -} - -/* Clock: IOT routine */ - -int32 clkio (int32 inst, int32 IR, int32 dat) -{ -int32 dev; - -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 ioMIX: /* merge */ - dat = dat | clk_error; - break; -case ioLIX: /* load */ - dat = clk_error; - break; -case ioOTX: /* output */ - clk_select = dat & 07; /* save select */ - sim_cancel (&clk_unit); /* stop the clock */ - clrCTL (dev); /* clear control */ - break; -case ioCTL: /* control clear/set */ - if (IR & I_CTL) { /* CLC */ - clrCTL (dev); /* turn off clock */ - sim_cancel (&clk_unit); } /* deactivate unit */ - else { /* STC */ - setCTL (dev); /* set CTL */ - if (!sim_is_active (&clk_unit)) { /* clock running? */ - sim_activate (&clk_unit, - sim_rtc_init (clk_delay (0))); /* no, start clock */ - clk_ctr = clk_delay (1); } /* set repeat ctr */ - clk_error = 0; } /* clear error */ - break; -default: - break; } -if (IR & I_HC) { clrFLG (dev); } /* H/C option */ -return dat; -} - -/* Unit service */ - -t_stat clk_svc (UNIT *uptr) -{ -int32 tim, dev; - -dev = clk_dib.devno; /* get device no */ -if (!CTL (dev)) return SCPE_OK; /* CTL off? done */ -if (clk_unit.flags & UNIT_DIAG) /* diag mode? */ - tim = clk_delay (0); /* get fixed delay */ -else tim = sim_rtc_calb (clk_tps[clk_select]); /* calibrate delay */ -sim_activate (uptr, tim); /* reactivate */ -clk_ctr = clk_ctr - 1; /* decrement counter */ -if (clk_ctr <= 0) { /* end of interval? */ - tim = FLG (dev); - if (FLG (dev)) clk_error = CLK_ERROR; /* overrun? error */ - else { setFLG (dev); } /* else set flag */ - clk_ctr = clk_delay (1); } /* reset counter */ -return SCPE_OK; -} - -/* Reset routine */ - -t_stat clk_reset (DEVICE *dptr) -{ -clk_dib.cmd = clk_dib.ctl = 0; /* clear cmd, ctl */ -clk_dib.flg = clk_dib.fbf = 1; /* set flg, fbf */ -clk_error = 0; /* clear error */ -clk_select = 0; /* clear select */ -clk_ctr = 0; /* clear counter */ -sim_cancel (&clk_unit); /* deactivate unit */ -return SCPE_OK; -} - -/* Clock delay routine */ - -int32 clk_delay (int32 flg) -{ -int32 sel = clk_select; - -if ((clk_unit.flags & UNIT_DIAG) && (sel >= 4)) sel = sel - 3; -if (flg) return clk_rpt[sel]; -else return clk_time[sel]; -} diff --git a/HP2100/hp2100_sys.c b/HP2100/hp2100_sys.c deleted file mode 100644 index f0fce56a..00000000 --- a/HP2100/hp2100_sys.c +++ /dev/null @@ -1,580 +0,0 @@ -/* hp2100_sys.c: HP 2100 simulator interface - - 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. - - 22-Mar-02 RMS Revised for dynamically allocated memory - 14-Feb-02 RMS Added DMS instructions - 04-Feb-02 RMS Fixed bugs in alter/skip display and parsing - 01-Feb-02 RMS Added terminal multiplexor support - 16-Jan-02 RMS Added additional device support - 17-Sep-01 RMS Removed multiconsole support - 27-May-01 RMS Added multiconsole support - 14-Mar-01 RMS Revised load/dump interface (again) - 30-Oct-00 RMS Added examine to file support - 15-Oct-00 RMS Added dynamic device number support - 27-Oct-98 RMS V2.4 load interface -*/ - -#include "hp2100_defs.h" -#include - -extern DEVICE cpu_dev; -extern UNIT cpu_unit; -extern DEVICE dma0_dev, dma1_dev; -extern DEVICE ptr_dev, ptp_dev; -extern DEVICE tty_dev, clk_dev; -extern DEVICE lps_dev, lpt_dev; -extern DEVICE mtd_dev, mtc_dev; -extern DEVICE msd_dev, msc_dev; -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; - -/* SCP data structures and interface routines - - sim_name simulator name string - sim_PC pointer to saved PC register descriptor - sim_emax maximum number of words for examine/deposit - sim_devices array of pointers to simulated devices - sim_stop_messages array of pointers to stop messages - sim_load binary loader -*/ - -char sim_name[] = "HP 2100"; - -REG *sim_PC = &cpu_reg[0]; - -int32 sim_emax = 3; - -DEVICE *sim_devices[] = { - &cpu_dev, - &dma0_dev, - &dma1_dev, - &ptr_dev, - &ptp_dev, - &tty_dev, - &clk_dev, - &lps_dev, - &lpt_dev, - &dpd_dev, &dpc_dev, - &dqd_dev, &dqc_dev, - &drd_dev, &drc_dev, - &mtd_dev, &mtc_dev, - &msd_dev, &msc_dev, - &muxl_dev, &muxu_dev, &muxc_dev, - &ipli_dev, &iplo_dev, - NULL }; - -const char *sim_stop_messages[] = { - "Unknown error", - "Unimplemented instruction", - "Non-existent I/O device", - "HALT instruction", - "Breakpoint", - "Indirect address loop", - "Indirect address interrupt (should not happen!)", - "No connection on interprocessor link" }; - -/* Binary loader - - The binary loader consists of blocks preceded and trailed by zero frames. - A block consists of 16b words (punched big endian), as follows: - - count'xxx - origin - word 0 - : - word count-1 - checksum - - The checksum includes the origin but not the count. -*/ - -int32 fgetw (FILE *fileref) -{ -int c1, c2; - -if ((c1 = fgetc (fileref)) == EOF) return -1; -if ((c2 = fgetc (fileref)) == EOF) return -1; -return ((c1 & 0377) << 8) | (c2 & 0377); -} - -t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag) -{ -int32 origin, csum, zerocnt, count, word, i; - -if ((*cptr != 0) || (flag != 0)) return SCPE_ARG; -for (zerocnt = 1;; zerocnt = -10) { /* block loop */ - for (;; zerocnt++) { /* skip 0's */ - if ((count = fgetc (fileref)) == EOF) return SCPE_OK; - else if (count) break; - else if (zerocnt == 0) return SCPE_OK; } - if (fgetc (fileref) == EOF) return SCPE_FMT; - if ((origin = fgetw (fileref)) < 0) return SCPE_FMT; - csum = origin; /* seed checksum */ - for (i = 0; i < count; i++) { /* get data words */ - if ((word = fgetw (fileref)) < 0) return SCPE_FMT; - if (MEM_ADDR_OK (origin)) M[origin] = word; - origin = origin + 1; - csum = csum + word; } - if ((word = fgetw (fileref)) < 0) return SCPE_FMT; - if ((word ^ csum) & DMASK) return SCPE_CSUM; } -return SCPE_OK; -} - -/* Symbol tables */ - -#define I_V_FL 16 /* flag start */ -#define I_M_FL 017 /* flag mask */ -#define I_V_NPN 0 /* no operand */ -#define I_V_NPC 1 /* no operand + C */ -#define I_V_MRF 2 /* mem ref */ -#define I_V_ASH 3 /* alter/skip, shift */ -#define I_V_ESH 4 /* extended shift */ -#define I_V_EMR 5 /* extended mem ref */ -#define I_V_IO1 6 /* I/O + HC */ -#define I_V_IO2 7 /* I/O only */ -#define I_V_EGZ 010 /* ext grp, 1 op + 0 */ -#define I_V_EG2 011 /* ext grp, 2 op */ -#define I_NPN (I_V_NPN << I_V_FL) -#define I_NPC (I_V_NPC << I_V_FL) -#define I_MRF (I_V_MRF << I_V_FL) -#define I_ASH (I_V_ASH << I_V_FL) -#define I_ESH (I_V_ESH << I_V_FL) -#define I_EMR (I_V_EMR << I_V_FL) -#define I_IO1 (I_V_IO1 << I_V_FL) -#define I_IO2 (I_V_IO2 << I_V_FL) -#define I_EGZ (I_V_EGZ << I_V_FL) -#define I_EG2 (I_V_EG2 << I_V_FL) - -static const int32 masks[] = { - 0177777, 0176777, 0074000, 0170000, - 0177760, 0177777, 0176700, 0177700, - 0177777, 0177777 }; - -static const char *opcode[] = { - "NOP", "NOP", "AND", "JSB", - "XOR", "JMP", "IOR", "ISZ", - "ADA", "ADB" ,"CPA", "CPB", - "LDA", "LDB", "STA", "STB", - "DIAG", "ASL", "LSL", "TIMER", - "RRL", "ASR", "LSR", "RRR", - "MPY", "DIV", "DLD", "DST", - "FAD", "FSB", "FMP", "FDV", - "FIX", "FLT", - "STO", "CLO", "SOC", "SOS", - "HLT", "STF", "CLF", - "SFC", "SFS", "MIA", "MIB", - "LIA", "LIB", "OTA", "OTB", - "STC", "CLC", - "SYA", "USA", "PAA", "PBA", - "XMA", - "XLA", "XSA", "XCA", "LFA", - "RSA", "RVA", - "MBI", "MBF", - "MBW", "MWI", "MWF", "MWW", - "SYB", "USB", "PAB", "PBB", - "SSM", "JRS", - "XMM", "XMS", "XMB", - "XLB", "XSB", "XCB", "LFB", - "RSB", "RVB", "DJP", "DJS", - "SJP", "SJS", "UJP", "UJS", - "SAX", "SBX", "CAX", "CBX", - "LAX", "LBX", "STX", - "CXA", "CXB", "LDX", - "ADX", "XAX", "XBX", - "SAY", "SBY", "CAY", "CBY", - "LAY", "LBY", "STY", - "CYA", "CYB", "LDY", - "ADY", "XAY", "XBY", - "ISX", "DSX", "JLY", "LBT", - "SBT", "MBT", "CBT", "SBT", - "ISY", "DSY", "JPY", "SBS", - "CBS", "TBS", "CMW", "MVW", - NULL, /* decode only */ - NULL }; - -static const int32 opc_val[] = { - 0000000+I_NPN, 0002000+I_NPN, 0010000+I_MRF, 0014000+I_MRF, - 0020000+I_MRF, 0024000+I_MRF, 0030000+I_MRF, 0034000+I_MRF, - 0040000+I_MRF, 0044000+I_MRF, 0050000+I_MRF, 0054000+I_MRF, - 0060000+I_MRF, 0064000+I_MRF, 0070000+I_MRF, 0074000+I_MRF, - 0100000+I_NPN, 0100020+I_ESH, 0100040+I_ESH, 0100060+I_NPN, - 0100100+I_ESH, 0101020+I_ESH, 0101040+I_ESH, 0101100+I_ESH, - 0100200+I_EMR, 0100400+I_EMR, 0104200+I_EMR, 0104400+I_EMR, - 0105000+I_EMR, 0105020+I_EMR, 0105040+I_EMR, 0105060+I_EMR, - 0105100+I_NPN, 0105120+I_NPN, - 0102101+I_NPN, 0103101+I_NPN, 0102201+I_NPC, 0102301+I_NPC, - 0102000+I_IO1, 0102100+I_IO2, 0103100+I_IO2, - 0102200+I_IO2, 0102300+I_IO2, 0102400+I_IO1, 0106400+I_IO1, - 0102500+I_IO1, 0106500+I_IO1, 0102600+I_IO1, 0106600+I_IO1, - 0102700+I_IO1, 0106700+I_IO1, - 0101710+I_NPN, 0101711+I_NPN, 0101712+I_NPN, 0101713+I_NPN, - 0101722+I_NPN, - 0101724+I_EMR, 0101725+I_EMR, 0101726+I_EMR, 0101727+I_NPN, - 0101730+I_NPN, 0101731+I_NPN, - 0105702+I_NPN, 0105703+I_NPN, - 0105704+I_NPN, 0105705+I_NPN, 0105706+I_NPN, 0105707+I_NPN, - 0105710+I_NPN, 0105711+I_NPN, 0105712+I_NPN, 0105713+I_NPN, - 0105714+I_EMR, 0105715+I_EG2, - 0105720+I_NPN, 0105721+I_NPN, 0105722+I_NPN, - 0105724+I_EMR, 0105725+I_EMR, 0105726+I_EMR, 0105727+I_NPN, - 0105730+I_NPN, 0105731+I_NPN, 0105732+I_EMR, 0105733+I_EMR, - 0105734+I_EMR, 0105735+I_EMR, 0105736+I_EMR, 0105737+I_EMR, - 0101740+I_EMR, 0105740+I_EMR, 0101741+I_NPN, 0105741+I_NPN, - 0101742+I_EMR, 0105742+I_EMR, 0105743+I_EMR, - 0101744+I_NPN, 0105744+I_NPN, 0105745+I_EMR, - 0105746+I_EMR, 0101747+I_NPN, 0105747+I_NPN, - 0101750+I_EMR, 0105750+I_EMR, 0101751+I_NPN, 0105751+I_NPN, - 0101752+I_EMR, 0105752+I_EMR, 0105753+I_EMR, - 0101754+I_NPN, 0105754+I_NPN, 0105755+I_EMR, - 0105756+I_EMR, 0101757+I_NPN, 0105757+I_NPN, - 0105760+I_NPN, 0105761+I_NPN, 0105762+I_EMR, 0105763+I_NPN, - 0105764+I_NPN, 0105765+I_EGZ, 0105766+I_EGZ, 0105767+I_NPN, - 0105770+I_NPN, 0105771+I_NPN, 0105772+I_EMR, 0105773+I_EG2, - 0105774+I_EG2, 0105775+I_EG2, 0105776+I_EGZ, 0105777+I_EGZ, - 0000000+I_ASH, /* decode only */ - -1 }; - -/* Decode tables for shift and alter/skip groups */ - -static const char *stab[] = { - "ALS", "ARS", "RAL", "RAR", "ALR", "ERA", "ELA", "ALF", - "BLS", "BRS", "RBL", "RBR", "BLR", "ERB", "ELB", "BLF", - "CLA", "CMA", "CCA", "CLB", "CMB", "CCB", - "SEZ", "CLE", "CLE", "CME", "CCE", - "SSA", "SSB", "SLA", "SLB", - "ALS", "ARS", "RAL", "RAR", "ALR", "ERA", "ELA", "ALF", - "BLS", "BRS", "RBL", "RBR", "BLR", "ERB", "ELB", "BLF", - "INA", "INB", "SZA", "SZB", "RSS", - NULL }; - -static const int32 mtab[] = { - 0007700, 0007700, 0007700, 0007700, 0007700, 0007700, 0007700, 0007700, - 0007700, 0007700, 0007700, 0007700, 0007700, 0007700, 0007700, 0007700, - 0006400, 0007000, 0007400, 0006400, 0007000, 0007400, - 0002040, 0002040, 0002100, 0002200, 0002300, - 0006020, 0006020, 0004010, 0004010, - 0006027, 0006027, 0006027, 0006027, 0006027, 0006027, 0006027, 0006027, - 0006027, 0006027, 0006027, 0006027, 0006027, 0006027, 0006027, 0006027, - 0006004, 0006004, 0006002, 0006002, 0002001, - 0 }; - -static const int32 vtab[] = { - 0001000, 0001100, 0001200, 0001300, 0001400, 0001500, 0001600, 0001700, - 0005000, 0005100, 0005200, 0005300, 0005400, 0005500, 0005600, 0005700, - 0002400, 0003000, 0003400, 0006400, 0007000, 0007400, - 0002040, 0000040, 0002100, 0002200, 0002300, - 0002020, 0006020, 0000010, 0004010, - 0000020, 0000021, 0000022, 0000023, 0000024, 0000025, 0000026, 0000027, - 0004020, 0004021, 0004022, 0004023, 0004024, 0004025, 0004026, 0004027, - 0002004, 0006004, 0002002, 0006002, 0002001, - -1 }; - -/* Symbolic decode - - Inputs: - *of = output stream - addr = current PC - *val = pointer to data - *uptr = pointer to unit - sw = switches - Outputs: - return = status code -*/ - -#define FMTASC(x) ((x) < 040)? "<%03o>": "%c", (x) - -t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, - UNIT *uptr, int32 sw) -{ -int32 cflag, cm, i, j, inst, disp; - -cflag = (uptr == NULL) || (uptr == &cpu_unit); -inst = val[0]; -if (sw & SWMASK ('A')) { /* ASCII? */ - if (inst > 0377) return SCPE_ARG; - fprintf (of, FMTASC (inst & 0177)); - return SCPE_OK; } -if (sw & SWMASK ('C')) { /* characters? */ - fprintf (of, FMTASC ((inst >> 8) & 0177)); - fprintf (of, FMTASC (inst & 0177)); - 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 */ - fprintf (of, "%s", opcode[i]); /* opcode */ - break; - case I_V_NPC: /* no operands + C */ - fprintf (of, "%s", opcode[i]); - if (inst & I_HC) fprintf (of, " C"); - break; - case I_V_MRF: /* mem ref */ - disp = inst & I_DISP; /* displacement */ - fprintf (of, "%s ", opcode[i]); /* opcode */ - if (inst & I_CP) { /* current page? */ - if (cflag) fprintf (of, "%-o", (addr & I_PAGENO) | disp); - else fprintf (of, "C %-o", disp); } - else fprintf (of, "%-o", disp); /* page zero */ - if (inst & I_IA) fprintf (of, ",I"); - break; - case I_V_ASH: /* shift, alter-skip */ - cm = FALSE; - for (i = 0; mtab[i] != 0; i++) { - if ((inst & mtab[i]) == vtab[i]) { - inst = inst & ~(vtab[i] & 01777); - if (cm) fprintf (of, ","); - cm = TRUE; - fprintf (of, "%s", stab[i]); } } - if (!cm) return SCPE_ARG; /* nothing decoded? */ - break; - case I_V_ESH: /* extended shift */ - disp = inst & 017; /* shift count */ - if (disp == 0) disp = 16; - fprintf (of, "%s %d", opcode[i], disp); - break; - case I_V_EMR: /* extended mem ref */ - fprintf (of, "%s %-o", opcode[i], val[1] & VAMASK); - if (val[1] & I_IA) fprintf (of, ",I"); - return -1; /* extra word */ - case I_V_IO1: /* IOT with H/C */ - fprintf (of, "%s %-o", opcode[i], inst & I_DEVMASK); - if (inst & I_HC) fprintf (of, ",C"); - break; - case I_V_IO2: /* IOT */ - fprintf (of, "%s %-o", opcode[i], inst & I_DEVMASK); - break; - case I_V_EGZ: /* ext grp 1 op + 0 */ - fprintf (of, "%s %-o", opcode[i], val[1] & VAMASK); - if (val[1] & I_IA) fprintf (of, ",I"); - return -2; /* extra words */ - case I_V_EG2: /* ext grp 2 op */ - fprintf (of, "%s %-o", opcode[i], val[1] & VAMASK); - if (val[1] & I_IA) fprintf (of, ",I"); - fprintf (of, " %-o", val[2] & VAMASK); - if (val[2] & I_IA) fprintf (of, ",I"); - return -2; } /* extra words */ - return SCPE_OK; } /* end if */ - } /* end for */ -return SCPE_ARG; -} - -/* Get address with indirection - - Inputs: - *cptr = pointer to input string - Outputs: - val = address - -1 if error -*/ - -int32 get_addr (char *cptr) -{ -int32 d; -t_stat r; -char gbuf[CBUFSIZE]; - -cptr = get_glyph (cptr, gbuf, ','); /* get next field */ -d = get_uint (gbuf, 8, VAMASK, &r); /* construe as addr */ -if (r != SCPE_OK) return -1; -if (*cptr != 0) { /* more? */ - cptr = get_glyph (cptr, gbuf, 0); /* look for indirect */ - if (*cptr != 0) return -1; /* should be done */ - if (strcmp (gbuf, "I")) return -1; /* I? */ - d = d | I_IA; } -return d; -} - -/* Symbolic input - - Inputs: - *iptr = 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 *iptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw) -{ -int32 cflag, d, i, j, k, clef, tbits; -t_stat r, ret; -char *cptr, gbuf[CBUFSIZE]; - -cflag = (uptr == NULL) || (uptr == &cpu_unit); -while (isspace (*iptr)) iptr++; /* absorb spaces */ -if ((sw & SWMASK ('A')) || ((*iptr == '\'') && iptr++)) { /* ASCII char? */ - if (iptr[0] == 0) return SCPE_ARG; /* must have 1 char */ - val[0] = (t_value) iptr[0] & 0177; - return SCPE_OK; } -if ((sw & SWMASK ('C')) || ((*iptr == '"') && iptr++)) { /* char string? */ - if (iptr[0] == 0) return SCPE_ARG; /* must have 1 char */ - val[0] = (((t_value) iptr[0] & 0177) << 8) | - ((t_value) iptr[1] & 0177); - return SCPE_OK; } - -/* Instruction parse */ - -ret = SCPE_OK; -cptr = get_glyph (iptr, gbuf, 0); /* get opcode */ -for (i = 0; (opcode[i] != NULL) && (strcmp (opcode[i], gbuf) != 0) ; i++) ; -if (opcode[i]) { /* found opcode? */ - 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: /* no operand */ - break; - case I_V_NPC: /* no operand + C */ - if (*cptr != 0) { - cptr = get_glyph (cptr, gbuf, 0); - if (strcmp (gbuf, "C")) return SCPE_ARG; - val[0] = val[0] | I_HC; } - break; - case I_V_MRF: /* mem ref */ - cptr = get_glyph (cptr, gbuf, 0); /* get next field */ - if (k = (strcmp (gbuf, "C") == 0)) { /* C specified? */ - val[0] = val[0] | I_CP; - cptr = get_glyph (cptr, gbuf, 0); } - else if (k = (strcmp (gbuf, "Z") == 0)) { /* Z specified? */ - cptr = get_glyph (cptr, gbuf, ','); } - if ((d = get_addr (gbuf)) < 0) return SCPE_ARG; - if ((d & VAMASK) <= I_DISP) val[0] = val[0] | d; - else if (cflag && !k && (((addr ^ d) & I_PAGENO) == 0)) - val[0] = val[0] | (d & (I_IA | I_DISP)) | I_CP; - else return SCPE_ARG; - break; - case I_V_ESH: /* extended shift */ - cptr = get_glyph (cptr, gbuf, 0); - d = get_uint (gbuf, 10, 16, &r); - if ((r != SCPE_OK) || (d == 0)) return SCPE_ARG; - val[0] = val[0] | (d & 017); - break; - case I_V_EMR: /* extended mem ref */ - cptr = get_glyph (cptr, gbuf, 0); /* get next field */ - if ((d = get_addr (gbuf)) < 0) return SCPE_ARG; - val[1] = d; - ret = -1; - break; - case I_V_IO1: /* IOT + optional C */ - cptr = get_glyph (cptr, gbuf, ','); /* get device */ - d = get_uint (gbuf, 8, I_DEVMASK, &r); - if (r != SCPE_OK) return SCPE_ARG; - val[0] = val[0] | d; - if (*cptr != 0) { - cptr = get_glyph (cptr, gbuf, 0); - if (strcmp (gbuf, "C")) return SCPE_ARG; - val[0] = val[0] | I_HC; } - break; - case I_V_IO2: /* IOT */ - cptr = get_glyph (cptr, gbuf, 0); /* get device */ - d = get_uint (gbuf, 8, I_DEVMASK, &r); - if (r != SCPE_OK) return SCPE_ARG; - val[0] = val[0] | d; - break; - case I_V_EGZ: /* ext grp 1 op + 0 */ - cptr = get_glyph (cptr, gbuf, 0); /* get next field */ - if ((d = get_addr (gbuf)) < 0) return SCPE_ARG; - val[1] = d; - val[2] = 0; - ret = -2; - break; - case I_V_EG2: /* ext grp 2 op */ - cptr = get_glyph (cptr, gbuf, 0); /* get next field */ - if ((d = get_addr (gbuf)) < 0) return SCPE_ARG; - cptr = get_glyph (cptr, gbuf, 0); /* get next field */ - if ((k = get_addr (gbuf)) < 0) return SCPE_ARG; - val[1] = d; - val[2] = k; - ret = -2; - break; } /* end case */ - if (*cptr != 0) return SCPE_ARG; /* junk at end? */ - return ret; - } /* end if opcode */ - -/* Shift or alter-skip - - Each opcode is matched by a mask, specifiying the bits affected, and - the value, specifying the value. As opcodes are processed, the mask - values are used to specify which fields have already been filled in. - - The mask has two subfields, the type bits (A/B and A/S), and the field - bits. The type bits, once specified by any instruction, must be - consistent in all other instructions. The mask bits assure that no - field is filled in twice. - - Two special cases: - - 1. The dual shift field in shift requires checking how much of the - target word has been filled in before assigning the shift value. - To implement this, shifts are listed twice is the decode table. - If the current subopcode is a shift in the first part of the table - (entries 0..15), and CLE has been seen or the first shift field is - filled in, the code forces a mismatch. The glyph will match in - the second part of the table. - - 2. CLE processing must be deferred until the instruction can be - classified as shift or alter-skip, since it has two different - bit values in the two classes. To implement this, CLE seen is - recorded as a flag and processed after all other subopcodes. -*/ - -clef = FALSE; -tbits = 0; -val[0] = 0; -for (cptr = get_glyph (iptr, gbuf, ','); gbuf[0] != 0; - cptr = get_glyph (cptr, gbuf, ',')) { /* loop thru glyphs */ - if (strcmp (gbuf, "CLE") == 0) { /* CLE? */ - if (clef) return SCPE_ARG; /* already seen? */ - clef = TRUE; /* set flag */ - continue; } - for (i = 0; stab[i] != NULL; i++) { /* find subopcode */ - if ((strcmp (gbuf, stab[i]) == 0) && - ((i >= 16) || (!clef && ((val[0] & 001710) == 0)))) break; } - if (stab[i] == NULL) return SCPE_ARG; - if (tbits & mtab[i] & (I_AB | I_ASKP) & (vtab[i] ^ val[0])) - return SCPE_ARG; - if (tbits & mtab[i] & ~(I_AB | I_ASKP)) return SCPE_ARG; - tbits = tbits | mtab[i]; /* fill type+mask */ - val[0] = val[0] | vtab[i]; } /* fill value */ -if (clef) { /* CLE seen? */ - if (val[0] & I_ASKP) { /* alter-skip? */ - if (tbits & 0100) return SCPE_ARG; /* already filled in? */ - else val[0] = val[0] | 0100; } - else val[0] = val[0] | 040; } /* fill in shift */ -return ret; -} diff --git a/I1401/i1401_cd.c b/I1401/i1401_cd.c deleted file mode 100644 index 666c2b50..00000000 --- a/I1401/i1401_cd.c +++ /dev/null @@ -1,282 +0,0 @@ -/* i1401_cd.c: IBM 1402 card reader/punch - - 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. - - cdr card reader - cdp card punch - stack stackers (5 units) - 0 normal - 1 1 - 2 2/8 - 3 unused - 4 4 - - Cards are represented as ASCII text streams terminated by newlines. - This allows cards to be created and edited as normal files. - - 25-Apr-03 RMS Revised for extended file support - 30-May-02 RMS Widened POS to 32b - 30-Jan-02 RMS New zero footprint card bootstrap from Van Snyder - 29-Nov-01 RMS Added read only unit support - 13-Apr-01 RMS Revised for register arrays -*/ - -#include "i1401_defs.h" -#include - -extern uint8 M[]; -extern int32 ind[64], ssa, iochk; -extern char bcd_to_ascii[64]; -extern char ascii_to_bcd[128]; -int32 s1sel, s2sel, s4sel, s8sel; -char rbuf[CBUFSIZE]; /* > CDR_WIDTH */ -t_stat cdr_svc (UNIT *uptr); -t_stat cdr_boot (int32 unitno, DEVICE *dptr); -t_stat cdr_attach (UNIT *uptr, char *cptr); -t_stat cd_reset (DEVICE *dptr); - -/* Card reader data structures - - cdr_dev CDR descriptor - cdr_unit CDR unit descriptor - cdr_reg CDR register list -*/ - -UNIT cdr_unit = { - UDATA (&cdr_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0), 100 }; - -REG cdr_reg[] = { - { FLDATA (LAST, ind[IN_LST], 0) }, - { FLDATA (ERR, ind[IN_READ], 0) }, - { FLDATA (S1, s1sel, 0) }, - { FLDATA (S2, s2sel, 0) }, - { DRDATA (POS, cdr_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, cdr_unit.wait, 24), PV_LEFT }, - { BRDATA (BUF, rbuf, 8, 8, CDR_WIDTH) }, - { NULL } }; - -DEVICE cdr_dev = { - "CDR", &cdr_unit, cdr_reg, NULL, - 1, 10, 31, 1, 8, 7, - NULL, NULL, &cd_reset, - &cdr_boot, &cdr_attach, NULL }; - -/* CDP data structures - - cdp_dev CDP device descriptor - cdp_unit CDP unit descriptor - cdp_reg CDP register list -*/ - -UNIT cdp_unit = { - UDATA (NULL, UNIT_SEQ+UNIT_ATTABLE, 0) }; - -REG cdp_reg[] = { - { FLDATA (ERR, ind[IN_PNCH], 0) }, - { FLDATA (S4, s4sel, 0) }, - { FLDATA (S8, s8sel, 0) }, - { DRDATA (POS, cdp_unit.pos, T_ADDR_W), PV_LEFT }, - { NULL } }; - -DEVICE cdp_dev = { - "CDP", &cdp_unit, cdp_reg, NULL, - 1, 10, 31, 1, 8, 7, - NULL, NULL, &cd_reset, - NULL, NULL, NULL }; - -/* Stacker data structures - - stack_dev STACK device descriptor - stack_unit STACK unit descriptors - stack_reg STACK register list -*/ - -UNIT stack_unit[] = { - { UDATA (NULL, UNIT_SEQ+UNIT_ATTABLE, 0) }, - { UDATA (NULL, UNIT_SEQ+UNIT_ATTABLE, 0) }, - { UDATA (NULL, UNIT_SEQ+UNIT_ATTABLE, 0) }, - { UDATA (NULL, UNIT_DIS, 0) }, /* unused */ - { UDATA (NULL, UNIT_SEQ+UNIT_ATTABLE, 0) } }; - -REG stack_reg[] = { - { DRDATA (POS0, stack_unit[0].pos, T_ADDR_W), PV_LEFT }, - { DRDATA (POS1, stack_unit[1].pos, T_ADDR_W), PV_LEFT }, - { DRDATA (POS28, stack_unit[2].pos, T_ADDR_W), PV_LEFT }, - { DRDATA (POS4, stack_unit[4].pos, T_ADDR_W), PV_LEFT }, - { NULL } }; - -DEVICE stack_dev = { - "STKR", stack_unit, stack_reg, NULL, - 5, 10, 31, 1, 8, 7, - NULL, NULL, &cd_reset, - NULL, NULL, NULL }; - -/* Card read routine - - Modifiers have been checked by the caller - No modifiers are recognized (column binary is not implemented) -*/ - -t_stat read_card (int32 ilnt, int32 mod) -{ -int32 i; -t_stat r; - -if (sim_is_active (&cdr_unit)) { /* busy? */ - sim_cancel (&cdr_unit); /* cancel */ - if (r = cdr_svc (&cdr_unit)) return r; } /* process */ -if ((cdr_unit.flags & UNIT_ATT) == 0) return SCPE_UNATT; /* attached? */ -ind[IN_READ] = ind[IN_LST] = s1sel = s2sel = 0; /* default stacker */ -for (i = 0; i < CBUFSIZE; i++) rbuf[i] = 0; /* clear buffer */ -fgets (rbuf, CBUFSIZE, cdr_unit.fileref); /* read card */ -if (feof (cdr_unit.fileref)) return STOP_NOCD; /* eof? */ -if (ferror (cdr_unit.fileref)) { /* error? */ - perror ("Card reader I/O error"); - clearerr (cdr_unit.fileref); - if (iochk) return SCPE_IOERR; - ind[IN_READ] = 1; - return SCPE_OK; } -cdr_unit.pos = ftell (cdr_unit.fileref); /* update position */ -if (ssa) { /* if last cd on */ - getc (cdr_unit.fileref); /* see if more */ - if (feof (cdr_unit.fileref)) ind[IN_LST] = 1; /* eof? set flag */ - fseek (cdr_unit.fileref, cdr_unit.pos, SEEK_SET); } -for (i = 0; i < CDR_WIDTH; i++) { /* cvt to BCD */ - rbuf[i] = ascii_to_bcd[rbuf[i]]; - M[CDR_BUF + i] = (M[CDR_BUF + i] & WM) | rbuf[i]; } -M[CDR_BUF - 1] = 060; /* mem mark */ -sim_activate (&cdr_unit, cdr_unit.wait); /* activate */ -return SCPE_OK; -} - -/* Card reader service. If a stacker select is active, copy to the - selected stacker. Otherwise, copy to the normal stacker. If the - unit is unattached, simply exit. -*/ - -t_stat cdr_svc (UNIT *uptr) -{ -int32 i; - -if (s1sel) uptr = &stack_unit[1]; /* stacker 1? */ -else if (s2sel) uptr = &stack_unit[2]; /* stacker 2? */ -else uptr = &stack_unit[0]; /* then default */ -if ((uptr->flags & UNIT_ATT) == 0) return SCPE_OK; /* attached? */ -for (i = 0; i < CDR_WIDTH; i++) rbuf[i] = bcd_to_ascii[rbuf[i]]; -for (i = CDR_WIDTH - 1; (i >= 0) && (rbuf[i] == ' '); i--) rbuf[i] = 0; -rbuf[CDR_WIDTH] = 0; /* null at end */ -fputs (rbuf, uptr->fileref); /* write card */ -fputc ('\n', uptr->fileref); /* plus new line */ -if (ferror (uptr->fileref)) { /* error? */ - perror ("Card stacker I/O error"); - clearerr (uptr->fileref); - if (iochk) return SCPE_IOERR; } -uptr->pos = ftell (uptr->fileref); /* update position */ -return SCPE_OK; -} - -/* Card punch routine - - Modifiers have been checked by the caller - No modifiers are recognized (column binary is not implemented) -*/ - -t_stat punch_card (int32 ilnt, int32 mod) -{ -int32 i; -static char pbuf[CDP_WIDTH + 1]; /* + null */ -UNIT *uptr; - -if (s8sel) uptr = &stack_unit[2]; /* stack 8? */ -else if (s4sel) uptr = &stack_unit[4]; /* stack 4? */ -else uptr = &cdp_unit; /* normal output */ -if ((uptr->flags & UNIT_ATT) == 0) return SCPE_UNATT; /* attached? */ -ind[IN_PNCH] = s4sel = s8sel = 0; /* clear flags */ - -M[CDP_BUF - 1] = 012; /* set prev loc */ -for (i = 0; i < CDP_WIDTH; i++) pbuf[i] = bcd_to_ascii[M[CDP_BUF + i] & CHAR]; -for (i = CDP_WIDTH - 1; (i >= 0) && (pbuf[i] == ' '); i--) pbuf[i] = 0; -pbuf[CDP_WIDTH] = 0; /* trailing null */ -fputs (pbuf, uptr->fileref); /* output card */ -fputc ('\n', uptr->fileref); /* plus new line */ -if (ferror (uptr->fileref)) { /* error? */ - perror ("Card punch I/O error"); - clearerr (uptr->fileref); - if (iochk) return SCPE_IOERR; - ind[IN_PNCH] = 1; } -uptr->pos = ftell (uptr->fileref); /* update position */ -return SCPE_OK; -} - -/* Select stack routine - - Modifiers have been checked by the caller - Modifiers are 1, 2, 4, 8 for the respective stack -*/ - -t_stat select_stack (int32 ilnt, int32 mod) -{ -if (mod == 1) s1sel = 1; -else if (mod == 2) s2sel = 1; -else if (mod == 4) s4sel = 1; -else if (mod == 8) s8sel = 1; -return SCPE_OK; -} - -/* Card reader/punch reset */ - -t_stat cd_reset (DEVICE *dptr) -{ -ind[IN_LST] = ind[IN_READ] = ind[IN_PNCH] = 0; /* clear indicators */ -s1sel = s2sel = s4sel = s8sel = 0; /* clear stacker sel */ -sim_cancel (&cdr_unit); /* clear reader event */ -return SCPE_OK; -} - -/* Card reader attach */ - -t_stat cdr_attach (UNIT *uptr, char *cptr) -{ -ind[IN_LST] = ind[IN_READ] = 0; /* clear last card */ -return attach_unit (uptr, cptr); -} - -/* Bootstrap routine */ - -#define BOOT_START 0 -#define BOOT_LEN (sizeof (boot_rom) / sizeof (unsigned char)) - -static const unsigned char boot_rom[] = { - OP_R + WM, OP_NOP + WM }; /* R, NOP */ - -t_stat cdr_boot (int32 unitno, DEVICE *dptr) -{ -int32 i; -extern int32 saved_IS; - -for (i = 0; i < CDR_WIDTH; i++) M[CDR_BUF + i] = 0; /* clear buffer */ -for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i]; -saved_IS = BOOT_START; -return SCPE_OK; -} diff --git a/I1401/i1401_cpu.c b/I1401/i1401_cpu.c deleted file mode 100644 index bee63ac9..00000000 --- a/I1401/i1401_cpu.c +++ /dev/null @@ -1,1563 +0,0 @@ -/* i1401_cpu.c: IBM 1401 CPU simulator - - 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. - - 12-Jul-03 RMS Moved ASCII/BCD tables to included file - Revised fetch to model hardware - Removed length checking in fetch phase - 16-Mar-03 RMS Fixed mnemonic, instruction lengths, and reverse - scan length check bug for MCS - Fixed MCE bug, BS off by 1 if zero suppress - Fixed chaining bug, D lost if return to SCP - Fixed H branch, branch occurs after continue - Added check for invalid 8 character MCW, LCA - 03-Jun-03 RMS Added 1311 support - 22-May-02 RMS Added multiply and divide - 30-Dec-01 RMS Added old PC queue - 30-Nov-01 RMS Added extended SET/SHOW support - 10-Aug-01 RMS Removed register in declarations - 07-Dec-00 RMS Fixed bugs found by Charles Owen - -- 4,7 char NOPs are legal - -- 1 char B is chained BCE - -- MCE moves whole char after first - 14-Apr-99 RMS Changed t_addr to unsigned - - The register state for the IBM 1401 is: - - IS I storage address register (PC) - AS A storage address register (address of first operand) - BS B storage address register (address of second operand) - ind[0:63] indicators - SSA sense switch A - IOCHK I/O check - PRCHK process check - - The IBM 1401 is a variable instruction length, decimal data system. - Memory consists of 4000, 8000, 12000, or 16000 BCD characters, each - containing six bits of data and a word mark. There are no general - registers; all instructions are memory to memory, using explicit - addresses or an address pointer from a prior instruction. - - BCD numeric data consists of the low four bits of a character (DIGIT), - encoded as X, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, X, X, X, X, X. The high - two bits (ZONE) encode the sign of the data as +, +, -, +. Character - data uses all six bits of a character. Numeric and character fields are - delimited by a word mark. Fields are typically processed in descending - address order (low-order data to high-order data). - - The 1401 encodes a decimal address, and an index register number, in - three characters: - - character zone digit - addr + 0 <1:0> of thousands hundreds - addr + 1 index register # tens - addr + 2 <3:2> of thousands ones - - Normally the digit values 0, 11, 12, 13, 14, 15 are illegal in addresses. - However, in indexing, digits are passed through the adder, and illegal - values are normalized to legal counterparts. - - The 1401 has six instruction formats: - - op A and B addresses, if any, from AS and BS - op d A and B addresses, if any, from AS and BS - op aaa B address, if any, from BS - op aaa d B address, if any, from BS - op aaa bbb - op aaa bbb d - - where aaa is the A address, bbb is the B address, and d is a modifier. - The opcode has word mark set; all other characters have word mark clear. -*/ - -/* This routine is the instruction decode routine for the IBM 1401. - 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 - illegal addresses or instruction formats - I/O error in I/O simulator - - 2. Interrupts. The 1401 has no interrupt structure. - - 3. Non-existent memory. On the 1401, references to non-existent - memory halt the processor. - - 4. Adding I/O devices. These modules must be modified: - - i1401_cpu.c add device dispatching code to iodisp - i1401_sys.c add sim_devices table entry -*/ - -#include "i1401_defs.h" -#include "i1401_dat.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] = saved_IS - -/* These macros validate addresses. If an addresses error is detected, - they return an error status to the caller. These macros should only - be used in a routine that returns a t_stat value. -*/ - -#define MM(x) x = x - 1; \ - if (x < 0) { \ - x = BA + MAXMEMSIZE - 1; \ - reason = STOP_WRAP; \ - break; } - -#define PP(x) x = x + 1; \ - if (ADDR_ERR (x)) { \ - x = BA + (x % MAXMEMSIZE); \ - reason = STOP_WRAP; \ - break; } - -#define BRANCH if (ADDR_ERR (AS)) { \ - reason = STOP_INVBR; \ - break; } \ - if (cpu_unit.flags & XSA) BS = IS; \ - else BS = BA + 0; \ - PCQ_ENTRY; \ - IS = AS; - -uint8 M[MAXMEMSIZE] = { 0 }; /* main memory */ -int32 saved_IS = 0; /* saved IS */ -int32 AS = 0; /* AS */ -int32 BS = 0; /* BS */ -int32 D = 0; /* modifier */ -int32 as_err = 0, bs_err = 0; /* error flags */ -int32 hb_pend = 0; /* halt br pending */ -uint16 pcq[PCQ_SIZE] = { 0 }; /* PC queue */ -int32 pcq_p = 0; /* PC queue ptr */ -REG *pcq_r = NULL; /* PC queue reg ptr */ -int32 ind[64] = { 0 }; /* indicators */ -int32 ssa = 1; /* sense switch A */ -int32 prchk = 0; /* process check stop */ -int32 iochk = 0; /* I/O check stop */ -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); -int32 store_addr_h (int32 addr); -int32 store_addr_t (int32 addr); -int32 store_addr_u (int32 addr); -int32 div_add (int32 ap, int32 bp, int32 aend); -int32 div_sub (int32 ap, int32 bp, int32 aend); -void div_sign (int32 dvrc, int32 dvdc, int32 qp, int32 rp); -t_stat iomod (int32 ilnt, int32 mod, const int32 *tptr); -t_stat iodisp (int32 dev, int32 unit, int32 flag, int32 mod); - -extern t_stat read_card (int32 ilnt, int32 mod); -extern t_stat punch_card (int32 ilnt, int32 mod); -extern t_stat select_stack (int32 mod); -extern t_stat carriage_control (int32 mod); -extern t_stat write_line (int32 ilnt, int32 mod); -extern t_stat inq_io (int32 flag, int32 mod); -extern t_stat mt_io (int32 unit, int32 flag, int32 mod); -extern t_stat dp_io (int32 fnc, int32 flag, int32 mod); -extern t_stat mt_func (int32 unit, int32 mod); -extern t_stat sim_activate (UNIT *uptr, int32 delay); - -/* CPU data structures - - cpu_dev CPU device descriptor - cpu_unit CPU unit descriptor - cpu_reg CPU register list - cpu_mod CPU modifier list -*/ - -UNIT cpu_unit = { UDATA (NULL, UNIT_FIX + UNIT_BCD + STDOPT, - MAXMEMSIZE) }; - -REG cpu_reg[] = { - { DRDATA (IS, saved_IS, 14), PV_LEFT }, - { DRDATA (AS, AS, 14), PV_LEFT }, - { DRDATA (BS, BS, 14), PV_LEFT }, - { FLDATA (ASERR, as_err, 0) }, - { FLDATA (BSERR, bs_err, 0) }, - { ORDATA (D, D, 7) }, - { FLDATA (SSA, ssa, 0) }, - { FLDATA (SSB, ind[IN_SSB], 0) }, - { FLDATA (SSC, ind[IN_SSC], 0) }, - { FLDATA (SSD, ind[IN_SSD], 0) }, - { FLDATA (SSE, ind[IN_SSE], 0) }, - { FLDATA (SSF, ind[IN_SSF], 0) }, - { FLDATA (SSG, ind[IN_SSG], 0) }, - { FLDATA (EQU, ind[IN_EQU], 0) }, - { FLDATA (UNEQ, ind[IN_UNQ], 0) }, - { FLDATA (HIGH, ind[IN_HGH], 0) }, - { FLDATA (LOW, ind[IN_LOW], 0) }, - { FLDATA (OVF, ind[IN_OVF], 0) }, - { FLDATA (IOCHK, iochk, 0) }, - { FLDATA (PRCHK, prchk, 0) }, - { FLDATA (HBPEND, hb_pend, 0) }, - { BRDATA (ISQ, pcq, 10, 14, PCQ_SIZE), REG_RO+REG_CIRC }, - { DRDATA (ISQP, pcq_p, 6), REG_HRO }, - { ORDATA (WRU, sim_int_char, 8) }, - { NULL } }; - -MTAB cpu_mod[] = { - { XSA, XSA, "XSA", "XSA", NULL }, - { XSA, 0, "no XSA", "NOXSA", NULL }, - { HLE, HLE, "HLE", "HLE", NULL }, - { HLE, 0, "no HLE", "NOHLE", NULL }, - { BBE, BBE, "BBE", "BBE", NULL }, - { BBE, 0, "no BBE", "NOBBE", NULL }, - { MA, MA, "MA", 0, NULL }, - { MA, 0, "no MA", 0, NULL }, - { MR, MR, "MR", "MR", NULL }, - { MR, 0, "no MR", "NOMR", NULL }, - { EPE, EPE, "EPE", "EPE", NULL }, - { EPE, 0, "no EPE", "NOEPE", NULL }, - { MDV, MDV, "MDV", "MDV", NULL }, - { MDV, 0, "no MDV", "NOMDV", NULL }, - { UNIT_MSIZE, 4000, NULL, "4K", &cpu_set_size }, - { UNIT_MSIZE, 8000, NULL, "8K", &cpu_set_size }, - { UNIT_MSIZE, 12000, NULL, "12K", &cpu_set_size }, - { UNIT_MSIZE, 16000, NULL, "16K", &cpu_set_size }, - { 0 } }; - -DEVICE cpu_dev = { - "CPU", &cpu_unit, cpu_reg, cpu_mod, - 1, 10, 14, 1, 8, 7, - &cpu_ex, &cpu_dep, &cpu_reset, - NULL, NULL, NULL }; - -/* Tables */ - -/* Opcode table - length, dispatch, and option flags. This table is - used by the symbolic input routine to validate instruction lengths */ - -const int32 op_table[64] = { - 0, /* 00: illegal */ - L1 | L2 | L4 | L5, /* read */ - L1 | L2 | L4 | L5, /* write */ - L1 | L2 | L4 | L5, /* write and read */ - L1 | L2 | L4 | L5, /* punch */ - L1 | L4, /* read and punch */ - L1 | L2 | L4 | L5, /* write and read */ - L1 | L2 | L4 | L5, /* write, read, punch */ - L1, /* 10: read feed */ - L1, /* punch feed */ - 0, /* illegal */ - L1 | L4 | L7 | AREQ | BREQ | MA, /* modify address */ - L1 | L4 | L7 | AREQ | BREQ | MDV, /* multiply */ - 0, /* illegal */ - 0, /* illegal */ - 0, /* illegal */ - 0, /* 20: illegal */ - L1 | L4 | L7 | BREQ | NOWM, /* clear storage */ - L1 | L4 | L7 | AREQ | BREQ, /* subtract */ - 0, /* illegal */ - L5 | IO, /* magtape */ - L1 | L8 | BREQ, /* branch wm or zone */ - L1 | L8 | BREQ | BBE, /* branch if bit eq */ - 0, /* illegal */ - L1 | L4 | L7 | AREQ | BREQ, /* 30: move zones */ - L1 | L4 | L7 | AREQ | BREQ, /* move supress zero */ - 0, /* illegal */ - L1 | L4 | L7 | AREQ | BREQ | NOWM, /* set word mark */ - L1 | L4 | L7 | AREQ | BREQ | MDV, /* divide */ - 0, /* illegal */ - 0, /* illegal */ - 0, /* illegal */ - 0, /* 40: illegal */ - 0, /* illegal */ - L2 | L5, /* select stacker */ - L1 | L4 | L7 | L8 | BREQ | MLS | IO, /* load */ - L1 | L4 | L7 | L8 | BREQ | MLS | IO, /* move */ - HNOP | L1 | L2 | L4 | L5 | L7 | L8, /* nop */ - 0, /* illegal */ - L1 | L4 | L7 | AREQ | BREQ | MR, /* move to record */ - L1 | L4 | AREQ | MLS, /* 50: store A addr */ - 0, /* illegal */ - L1 | L4 | L7 | AREQ | BREQ, /* zero and subtract */ - 0, /* illegal */ - 0, /* illegal */ - 0, /* illegal */ - 0, /* illegal */ - 0, /* illegal */ - 0, /* 60: illegal */ - L1 | L4 | L7 | AREQ | BREQ, /* add */ - L1 | L4 | L5 | L8, /* branch */ - L1 | L4 | L7 | AREQ | BREQ, /* compare */ - L1 | L4 | L7 | AREQ | BREQ, /* move numeric */ - L1 | L4 | L7 | AREQ | BREQ, /* move char edit */ - L2 | L5, /* carriage control */ - 0, /* illegal */ - L1 | L4 | L7 | AREQ | MLS, /* 70: store B addr */ - 0, /* illegal */ - L1 | L4 | L7 | AREQ | BREQ, /* zero and add */ - HNOP | L1 | L2 | L4 | L5 | L7 | L8, /* halt */ - L1 | L4 | L7 | AREQ | BREQ, /* clear word mark */ - 0, /* illegal */ - 0, /* illegal */ - 0 }; /* illegal */ - -const int32 len_table[9] = { 0, L1, L2, 0, L4, L5, 0, L7, L8 }; - -/* Address character conversion tables. Illegal characters are marked by - the flag BA but also contain the post-adder value for indexing */ - -const int32 hun_table[64] = { - BA+000, 100, 200, 300, 400, 500, 600, 700, - 800, 900, 000, BA+300, BA+400, BA+500, BA+600, BA+700, - BA+1000, 1100, 1200, 1300, 1400, 1500, 1600, 1700, - 1800, 1900, 1000, BA+1300, BA+1400, BA+1500, BA+1600, BA+1700, - BA+2000, 2100, 2200, 2300, 2400, 2500, 2600, 2700, - 2800, 2900, 2000, BA+2300, BA+2400, BA+2500, BA+2600, BA+2700, - BA+3000, 3100, 3200, 3300, 3400, 3500, 3600, 3700, - 3800, 3900, 3000, BA+3300, BA+3400, BA+3500, BA+3600, BA+3700 }; - -const int32 ten_table[64] = { - BA+00, 10, 20, 30, 40, 50, 60, 70, - 80, 90, 00, BA+30, BA+40, BA+50, BA+60, BA+70, - X1+00, X1+10, X1+20, X1+30, X1+40, X1+50, X1+60, X1+70, - X1+80, X1+90, X1+00, X1+30, X1+40, X1+50, X1+60, X1+70, - X2+00, X2+10, X2+20, X2+30, X2+40, X2+50, X2+60, X2+70, - X2+80, X2+90, X2+00, X2+30, X2+40, X2+50, X2+60, X2+70, - X3+00, X3+10, X3+20, X3+30, X3+40, X3+50, X3+60, X3+70, - X3+80, X3+90, X3+00, X3+30, X3+40, X3+50, X3+60, X3+70 }; - -const int32 one_table[64] = { - BA+0, 1, 2, 3, 4, 5, 6, 7, - 8, 9, 0, BA+3, BA+4, BA+5, BA+6, BA+7, - BA+4000, 4001, 4002, 4003, 4004, 4005, 4006, 4007, - 4008, 4009, 4000, BA+4003, BA+4004, BA+4005, BA+4006, BA+4007, - BA+8000, 8001, 8002, 8003, 8004, 8005, 8006, 8007, - 8008, 8009, 8000, BA+8003, BA+8004, BA+8005, BA+8006, BA+8007, - BA+12000, 12001, 12002, 12003, 12004, 12005, 12006, 12007, - 12008, 12009, 12000, BA+12003, BA+12004, BA+12005, BA+12006, BA+12007 }; - -const int32 bin_to_bcd[16] = { - 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; - -const int32 bcd_to_bin[16] = { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 3, 4, 5, 6, 7 }; - -/* Indicator resets - a 1 marks an indicator that resets when tested */ - -static const int32 ind_table[64] = { - 0, 0, 0, 0, 0, 0, 0, 0, /* 00 - 07 */ - 0, 0, 0, 0, 0, 0, 0, 0, /* 10 - 17 */ - 0, 0, 0, 0, 0, 0, 0, 0, /* 20 - 27 */ - 0, 1, 1 , 0, 1, 0, 0, 0, /* 30 - 37 */ - 0, 0, 1, 0, 0, 0, 0, 0, /* 40 - 47 */ - 0, 0, 1, 0, 1, 0, 0, 0, /* 50 - 57 */ - 0, 0, 0, 0, 0, 0, 0, 0, /* 60 - 67 */ - 0, 0, 1, 0, 0, 0, 0, 0 }; /* 70 - 77 */ - -/* Character collation table for compare with HLE option */ - -static const int32 col_table[64] = { - 000, 067, 070, 071, 072, 073, 074, 075, - 076, 077, 066, 024, 025, 026, 027, 030, - 023, 015, 056, 057, 060, 061, 062, 063, - 064, 065, 055, 016, 017, 020, 021, 022, - 014, 044, 045, 046, 047, 050, 051, 052, - 053, 054, 043, 007, 010, 011, 012, 013, - 006, 032, 033, 034, 035, 036, 037, 040, - 041, 042, 031, 001, 002, 003, 004, 005 }; - -/* Summing table for two decimal digits, converted back to BCD - Also used for multiplying two decimal digits, converted back to BCD, - with carry forward -*/ - -static const int32 sum_table[100] = { - BCD_ZERO, BCD_ONE, BCD_TWO, BCD_THREE, BCD_FOUR, - BCD_FIVE, BCD_SIX, BCD_SEVEN, BCD_EIGHT, BCD_NINE, - BCD_ZERO, BCD_ONE, BCD_TWO, BCD_THREE, BCD_FOUR, - BCD_FIVE, BCD_SIX, BCD_SEVEN, BCD_EIGHT, BCD_NINE, - BCD_ZERO, BCD_ONE, BCD_TWO, BCD_THREE, BCD_FOUR, - BCD_FIVE, BCD_SIX, BCD_SEVEN, BCD_EIGHT, BCD_NINE, - BCD_ZERO, BCD_ONE, BCD_TWO, BCD_THREE, BCD_FOUR, - BCD_FIVE, BCD_SIX, BCD_SEVEN, BCD_EIGHT, BCD_NINE, - BCD_ZERO, BCD_ONE, BCD_TWO, BCD_THREE, BCD_FOUR, - BCD_FIVE, BCD_SIX, BCD_SEVEN, BCD_EIGHT, BCD_NINE, - BCD_ZERO, BCD_ONE, BCD_TWO, BCD_THREE, BCD_FOUR, - BCD_FIVE, BCD_SIX, BCD_SEVEN, BCD_EIGHT, BCD_NINE, - BCD_ZERO, BCD_ONE, BCD_TWO, BCD_THREE, BCD_FOUR, - BCD_FIVE, BCD_SIX, BCD_SEVEN, BCD_EIGHT, BCD_NINE, - BCD_ZERO, BCD_ONE, BCD_TWO, BCD_THREE, BCD_FOUR, - BCD_FIVE, BCD_SIX, BCD_SEVEN, BCD_EIGHT, BCD_NINE, - BCD_ZERO, BCD_ONE, BCD_TWO, BCD_THREE, BCD_FOUR, - BCD_FIVE, BCD_SIX, BCD_SEVEN, BCD_EIGHT, BCD_NINE, - BCD_ZERO, BCD_ONE, BCD_TWO, BCD_THREE, BCD_FOUR, - BCD_FIVE, BCD_SIX, BCD_SEVEN, BCD_EIGHT, BCD_NINE }; - -static const int32 cry_table[100] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 }; - -/* Legal modifier tables */ - -static const int32 w_mod[] = { BCD_S, BCD_SQUARE, -1 }; -static const int32 ss_mod[] = { 1, 2, 4, 8, -1 }; -static const int32 mtf_mod[] = { BCD_B, BCD_E, BCD_M, BCD_R, BCD_U, -1 }; - -t_stat sim_instr (void) -{ -extern int32 sim_interval; -int32 IS, ilnt, flags; -int32 op, xa, t, wm, ioind, dev, unit; -int32 a, b, i, asave, bsave; -int32 carry, lowprd, sign, ps; -int32 quo, ahigh, qs; -int32 qzero, qawm, qbody, qsign, qdollar, qaster, qdecimal; -t_stat reason, r1, r2; - -/* Restore saved state */ - - -IS = saved_IS; -if (as_err) AS = AS | BA; /* flag bad addresses */ -if (bs_err) BS = BS | BA; -as_err = bs_err = 0; /* reset error flags */ -reason = 0; - -/* Main instruction fetch/decode loop */ - -while (reason == 0) { /* loop until halted */ - -if (hb_pend) { /* halt br pending? */ - hb_pend = 0; /* clear flag */ - BRANCH; } /* execute branch */ - -saved_IS = IS; /* commit prev instr */ -if (sim_interval <= 0) { /* check clock queue */ - if (reason = sim_process_event ()) break; } - -if (sim_brk_summ && sim_brk_test (IS, SWMASK ('E'))) { /* breakpoint? */ - reason = STOP_IBKPT; /* stop simulation */ - break; } - -sim_interval = sim_interval - 1; - -/* Instruction fetch - 1401 fetch works as follows: - - - Each character fetched enters the B register. This register is not - visible; the variable t represents the B register. - - Except for the first and last cycles, each character fetched enters - the A register. This register is not visible; the variable D represents - the A register, because this is the instruction modifier for 2, 5, and 8 - character instructions. - - At the start of the second cycle (first address character), the A-address - register and, for most instructions, the B-address register, are cleared - to blanks. The simulator represents addresses in binary and creates the - effect of blanks (address is bad) if less than three A-address characters - are found. Further, the simulator accumulates only the A-address, and - replicates it to the B-address at the appropriate point. - - At the start of the fifth cycle (fourth address character), the B-address - register is cleared to blanks. Again, the simulator creates the effect of - blanks (address is bad) if less than three B-address characters are found. - - The 1401 does explicitly check for valid instruction lengths. Most 2,3,5,6 - character instructions will be invalid because the A-address or B-address - (or both) are invalid. -*/ - -if ((M[IS] & WM) == 0) { /* I-Op: WM under op? */ - reason = STOP_NOWM; /* no, error */ - break; } -op = M[IS] & CHAR; /* get opcode */ -flags = op_table[op]; /* get op flags */ -if ((flags == 0) || (flags & ALLOPT & ~cpu_unit.flags)) { - reason = STOP_NXI; /* illegal inst? */ - break; } -if (op == OP_SAR) BS = AS; /* SAR? save ASTAR */ -PP (IS); - -if ((t = M[IS]) & WM) goto CHECK_LENGTH; /* I-1: WM? 1 char inst */ -D = ioind = t; /* could be D char, % */ -AS = hun_table[t]; /* could be A addr */ -PP (IS); /* if %xy, BA is set */ - -if ((t = M[IS]) & WM) { /* I-2: WM? 2 char inst */ - AS = AS | BA; /* ASTAR bad */ - if (!(flags & MLS)) BS = AS; - goto CHECK_LENGTH; } -D = dev = t; /* could be D char, dev */ -AS = AS + ten_table[t]; /* build A addr */ -PP (IS); - -if ((t = M[IS]) & WM) { /* I-3: WM? 3 char inst */ - AS = AS | BA; /* ASTAR bad */ - if (!(flags & MLS)) BS = AS; - goto CHECK_LENGTH; } -D = unit = t; /* could be D char, unit */ -if (unit == BCD_ZERO) unit = 0; /* convert unit to binary */ -AS = AS + one_table[t]; /* finish A addr */ -xa = (AS >> V_INDEX) & M_INDEX; /* get index reg */ -if (xa && (ioind != 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]; - AS = (AS & INDEXMASK) % MAXMEMSIZE; } -if (!(flags & MLS)) BS = AS; /* not MLS? B = A */ -PP (IS); - -if ((t = M[IS]) & WM) goto CHECK_LENGTH; /* I-4: WM? 4 char inst */ -if ((op == OP_B) && (t == BCD_BLANK)) goto CHECK_LENGTH; /* BR + space? */ -D = t; /* could be D char */ -BS = hun_table[t]; /* could be B addr */ -PP (IS); - -if ((t = M[IS]) & WM) { /* I-5: WM? 5 char inst */ - BS = BS | BA; /* BSTAR bad */ - goto CHECK_LENGTH; } -D = t; /* could be D char */ -BS = BS + ten_table[t]; /* build B addr */ -PP (IS); - -if ((t = M[IS]) & WM) { /* I-6: WM? 6 char inst */ - BS = BS | BA; /* BSTAR bad */ - goto CHECK_LENGTH; } -D = t; /* could be D char */ -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 & INDEXMASK) % MAXMEMSIZE; } -PP (IS); - -if (flags & NOWM) goto CHECK_LENGTH; /* I-7: SWM? done */ -if ((t = M[IS]) & WM) goto CHECK_LENGTH; /* WM? 7 char inst */ -D = t; /* last char is D */ -while (((t = M[IS]) & WM) == 0) { /* I-8: repeats until WM */ - D = t; /* last char is D */ - PP (IS); } - -CHECK_LENGTH: -ilnt = IS - saved_IS; /* get lnt */ -//if (((flags & len_table [(ilnt <= 8)? ilnt: 8]) == 0) && /* valid lnt? */ -// ((flags & HNOP) == 0)) reason = STOP_INVL; -if ((flags & BREQ) && ADDR_ERR (BS)) reason = STOP_INVB; /* valid A? */ -if ((flags & AREQ) && ADDR_ERR (AS)) reason = STOP_INVA; /* valid B? */ -if (reason) break; /* error in fetch? */ -switch (op) { /* case on opcode */ - -/* Move/load character instructions A check B check - - MCW copy A to B, preserving B WM, here fetch - until either A or B WM - LCA copy A to B, overwriting B WM, here fetch - until A WM - - Instruction lengths: - - 1 chained A and B - 2,3 invalid A-address - 4 chained B address - 5,6 invalid B-address - 7 normal - 8+ normal + modifier -*/ - -case OP_MCW: /* move char */ - if ((ilnt >= 4) && (ioind == BCD_PERCNT)) { /* I/O form? */ - reason = iodisp (dev, unit, MD_NORM, D); /* dispatch I/O */ - break; } - if (ADDR_ERR (AS)) { /* check A addr */ - reason = STOP_INVA; - break; } - do { - wm = M[AS] | M[BS]; - M[BS] = (M[BS] & WM) | (M[AS] & CHAR); /* move char */ - MM (AS); MM (BS); } /* decr pointers */ - while ((wm & WM) == 0); /* stop on A,B WM */ - break; - -case OP_LCA: /* load char */ - if ((ilnt >= 4) && (ioind == BCD_PERCNT)) { /* I/O form? */ - 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 */ - while ((wm & WM) == 0); /* stop on A WM */ - break; - -/* Other move instructions A check B check - - MCM copy A to B, preserving B WM, fetch fetch - until record or group mark - MCS copy A to B, clearing B WM, until A WM; fetch fetch - reverse scan and suppress leading zeroes - MN copy A char digit to B char digit, fetch fetch - preserving B zone and WM - MZ copy A char zone to B char zone, fetch fetch - preserving B digit and WM - - Instruction lengths: - - 1 chained - 2,3 invalid A-address - 4 self (B-address = A-address) - 5,6 invalid B-address - 7 normal - 8+ normal + ignored modifier -*/ - -case OP_MCM: /* move to rec/group */ - do { - t = M[AS]; - M[BS] = (M[BS] & WM) | (M[AS] & CHAR); /* move char */ - PP (AS); PP (BS); } /* incr pointers */ - while (((t & CHAR) != BCD_RECMRK) && (t != (BCD_GRPMRK + WM))); - break; - -case OP_MCS: /* move suppress zero */ - bsave = BS; /* save B start */ - qzero = 1; /* set suppress */ - do { - wm = M[AS]; - M[BS] = M[AS] & ((BS != bsave)? CHAR: DIGIT); /* copy char */ - 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; } - while (BS < bsave); - PP (BS); /* BS end is B+1 */ - 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 */ - break; - -/* Branch instruction A check B check - - Instruction lengths: - - 1 branch if B char equals d, chained if branch here - 2,3 invalid B-address if branch here - 4 unconditional branch if branch - 5 branch if indicator[d] is set if branch - 6 invalid B-address if branch here - 7 branch if B char equals d, if branch here - d is last character of B-address - 8 branch if B char equals d if branch here -*/ - -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 { /* branch char eq */ - if (ADDR_ERR (BS)) { /* validate B addr */ - reason = STOP_INVB; - break; } - if ((M[BS] & CHAR) == D) { BRANCH; } /* char equal? */ - else { MM (BS); } } - break; - -/* Other branch instructions A check B check - - BWZ branch if (d<0>: B char WM) if branch fetch - (d<1>: B char zone = d zone) - BBE branch if B char & d non-zero if branch fetch - - Instruction lengths: - 1 chained - 2,3 invalid A-address and B-address - 4 self (B-address = A-address, d = last character of A-address) - 5,6 invalid B-address - 7 normal, d = last character of B-address - 8+ normal -*/ - -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 */ - break; - -case OP_BBE: /* branch if bit eq */ - if (M[BS] & D & CHAR) { BRANCH; } /* any bits set? */ - else { MM (BS); } /* decr pointer */ - break; - -/* Arithmetic instructions A check B check - - ZA move A to B, normalizing A sign, fetch fetch - preserving B WM, until B WM - ZS move A to B, complementing A sign, fetch fetch - preserving B WM, until B WM - A add A to B fetch fetch - S subtract A from B fetch fetch - C compare A to B fetch fetch - - Instruction lengths: - - 1 chained - 2,3 invalid A-address - 4 self (B-address = A-address) - 5,6 invalid B-address - 7 normal - 8+ normal + ignored modifier -*/ - -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); } - 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 */ - b = M[BS]; /* get B digit/sign */ - MM (AS); - qsign = ((a & ZONE) == BBIT) ^ ((b & ZONE) == BBIT) ^ (op == OP_S); - t = bcd_to_bin[a & DIGIT]; /* get A binary */ - t = bcd_to_bin[b & DIGIT] + (qsign? 10 - t: t); /* sum A + B */ - carry = (t >= 10); /* get carry */ - b = (b & ~DIGIT) | sum_table[t]; /* get result */ - if (qsign && ((b & BBIT) == 0)) b = b | ZONE; /* normalize sign */ - 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); } - 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]; } } - break; - -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 */ - 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; } - if (!(cpu_unit.flags & HLE)) /* no HLE? */ - ind[IN_EQU] = ind[IN_LOW] = ind[IN_HGH] = 0; - break; - -/* I/O instructions A check B check - - R read a card if branch - W write to line printer if branch - WR write and read if branch - P punch a card if branch - RP read and punch if branch - WP : write and punch if branch - WRP write read and punch if branch - RF read feed (nop) - PF punch feed (nop) - SS select stacker if branch - CC carriage control if branch - - Instruction lengths: - - 1 normal - 2,3 normal, with modifier - 4 branch; modifier, if any, is last character of branch address - 5 branch + modifier - 6+ normal, with modifier -*/ - -case OP_R: /* read */ - if (reason = iomod (ilnt, D, NULL)) break; /* valid modifier? */ - reason = read_card (ilnt, D); /* read card */ - BS = CDR_BUF + CDR_WIDTH; - if ((ilnt == 4) || (ilnt == 5)) { 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) || (ilnt == 5)) { 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) || (ilnt == 5)) { 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 */ - r1 = read_card (ilnt, D); /* read card */ - BS = CDR_BUF + CDR_WIDTH; - if ((ilnt == 4) || (ilnt == 5)) { 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 */ - r1 = punch_card (ilnt, D); /* punch card */ - BS = CDP_BUF + CDP_WIDTH; - if ((ilnt == 4) || (ilnt == 5)) { 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 */ - r1 = punch_card (ilnt, D); /* punch card */ - BS = CDP_BUF + CDP_WIDTH; - if ((ilnt == 4) || (ilnt == 5)) { 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 */ - r1 = read_card (ilnt, D); /* read card */ - r2 = punch_card (ilnt, D); /* punch card */ - BS = CDP_BUF + CDP_WIDTH; - if ((ilnt == 4) || (ilnt == 5)) { 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) || (ilnt == 5)) { BRANCH; } /* check for branch */ - break; - -case OP_CC: /* carriage control */ - if (reason = carriage_control (D)) break; /* car ctrl, error? */ - if ((ilnt == 4) || (ilnt == 5)) { BRANCH; } /* check for branch */ - break; - -/* MTF - magtape functions - must be at least 4 characters - - Instruction lengths: - - 1-3 invalid I/O address - 4 normal, d-character is unit - 5 normal - 6+ normal, d-character is last character -*/ - -case OP_MTF: /* magtape function */ - if (ilnt < 4) reason = STOP_INVL; /* too short? */ - else if (ioind != BCD_PERCNT) reason = STOP_INVA; - else if (reason = iomod (ilnt, D, mtf_mod)) break; /* valid modifier? */ - reason = mt_func (unit, D); /* mt func, error? */ - break; /* can't branch */ - -case OP_RF: case OP_PF: /* read, punch feed */ - break; /* nop's */ - -/* Move character and edit - - Control flags - qsign sign of A field (0 = +, 1 = minus) - qawm A field WM seen and processed - qzero zero suppression enabled - qbody in body (copying A field characters) - qdollar EPE only; $ seen in body - qaster EPE only; * seen in body - qdecimal EPE only; . seen on first rescan - - MCE operates in one to three scans, the first of which has three phases - - 1 right to left qbody = 0, qawm = 0 => right status - qbody = 1, qawm = 0 => body - qbody = 0, qawm = 1 => left status - 2 left to right - 3 right to left, extended print end only - - The first A field character is masked to its digit part, all others - are copied intact - - Instruction lengths: - - 1 chained - 2,3 invalid A-address - 4 self (B-address = A-address) - 5,6 invalid B-address - 7 normal - 8+ normal + ignored modifier -*/ - -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; } - if (b & WM) { /* one char B field? */ - 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 */ - qdollar = qaster = qdecimal = 0; /* clear EPE flags */ - -/* Edit pass 1 - from right to left, under B field control - - * in status or !epe, skip B; else, set qaster, repl with A - $ in status or !epe, skip B; else, set qdollar, repl with A - 0 in right status or body, if !qzero, set A WM; set qzero, repl with A - else, if !qzero, skip B; else, if (!B WM) set B WM - blank in right status or body, repl with A; else, skip B - C,R,- in status, blank B; else, skip B - , in status, blank B, else, skip B - & 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 */ - /* 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 */ - 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; } - -/* 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 */ - while ((b & WM) == 0); - - M[BS] = M[BS] & ~WM; /* clear B WM */ - if (!qdollar && !(qdecimal && qzero)) { /* rescan again? */ - BS++; /* BS = addr WM + 1 */ - break; } - if (qdecimal && qzero) qdollar = 0; /* no digits? clr $ */ - -/* 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 */ - break; /* done at last! */ - -/* Multiply. Comments from the PDP-10 based simulator by Len Fehskens. - - Multiply, with variable length operands, is necessarily done the same - way you do it with paper and pencil, except that partial products are - added into the incomplete final product as they are computed, rather - than at the end. The 1401 multiplier format allows the product to - be developed in place, without scratch storage. - - The A field contains the multiplicand, length LD. The B field must be - LD + 1 + length of multiplier. Locate the low order multiplier digit, - and at the same time zero out the product field. Then compute the sign - of the result. - - Instruction lengths: - - 1 chained - 2,3 invalid A-address - 4 self (B-address = A-address) - 5,6 invalid B-address - 7 normal - 8+ normal + ignored modifier -*/ - -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 */ - while ((a & WM) == 0); /* until A WM */ - if (reason) break; /* address err? */ - M[BS] = BCD_ZERO; /* zero hi prod */ - MM (BS); /* addr low mpyr */ - sign = ((M[asave] & ZONE) == BBIT) ^ ((M[BS] & ZONE) == BBIT); - -/* Outer loop on multiplier (BS) and product digits (ps), - inner loop on multiplicand digits (AS). - 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 */ - while ((b & WM) == 0); /* until mpyr done */ - M[lowprd] = M[lowprd] | ZONE; /* assume + */ - if (sign) M[lowprd] = M[lowprd] & ~ABIT; /* if minus, B only */ - break; - -/* Divide. Comments from the PDP-10 based simulator by Len Fehskens. - - Divide is done, like multiply, pretty much the same way you do it with - pencil and paper; successive subtraction of the divisor from a substring - of the dividend while counting up the corresponding quotient digit. - - Let LS be the length of the divisor, LD the length of the dividend: - - AS points to the low order divisor digit. - - BS points to the high order dividend digit. - - The low order dividend digit is identified by sign (zone) bits. - - To the left of the dividend is a zero field of length LS + 1. - The low quotient is at low dividend - LS - 1. As BS points to the - high dividend, the low dividend is at BS + LD - 1, so the low - quotient is at BS + LD - LS - 2. The longest possible quotient is - LD - LS + 1, so the first possible non-zero quotient bit will be - found as BS - 2. - - This pointer calculation assumes that the divisor has no leading zeroes. - For each leading zero, the start of the quotient will be one position - further left. - - Start by locating the high order non-zero digit of the divisor. This - also tests for a divide by zero. - - Instruction lengths: - - 1 chained - 2,3 invalid A-address - 4 self (B-address = A-address) - 5,6 invalid B-address - 7 normal - 8+ normal + ignored modifier -*/ - -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); } - 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; } - bsave = BS + (asave - ahigh); /* end subdivd */ - qs = (BS - 2) - (ahigh - (AS + 1)); /* quo start */ - -/* Divide loop - done with subroutines to keep the code clean. - In the loop, - - asave = low order divisor - bsave = low order subdividend - 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 */ - while ((b & ZONE) == 0); /* until B sign */ - if (reason) break; /* address err? */ - -/* At this point, - - AS = high order divisor - 1 - asave = unit position of divisor - b = unit character of dividend - bsave = unit position of remainder + 1 - qs = unit position of quotient + 1 -*/ - - div_sign (M[asave], b, qs - 1, bsave - 1); /* set signs */ - BS = qs - 2; /* BS = quo 10's pos */ - break; - -/* Word mark instructions A check B check - - SWM set WM on A char and B char fetch fetch - CWM clear WM on A char and B char fetch fetch - - Instruction lengths: - - 1 chained - 2,3 invalid A-address - 4 one operand (B-address = A-address) - 5,6 invalid B-address - 7 two operands (SWM cannot be longer than 7) - 8+ two operands + ignored modifier -*/ - -case OP_SWM: /* set word mark */ - M[BS] = M[BS] | WM; /* set A field 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; - -/* Clear storage instruction A check B check - - CS clear from B down to nearest hundreds if branch fetch - address - - Instruction lengths: - - 1 chained - 2,3 invalid A-address and B-address - 4 one operand (B-address = A-address) - 5,6 invalid B-address - 7 branch - 8+ one operand, branch ignored -*/ - -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; - -/* Modify address instruction A check B check - - MA add A addr and B addr, store at B addr fetch fetch - - Instruction lengths: - 1 chained - 2,3 invalid A-address and B-address - 4 self (B-address = A-address) - 5,6 invalid B-address - 7 normal - 8+ normal + ignored modifier -*/ - -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); - a = a + hun_table[M[AS] & CHAR]; MM (AS); - b = one_table[M[BS] & CHAR]; MM (BS); /* get B address */ - b = b + ten_table[M[BS] & CHAR]; MM (BS); - b = b + hun_table[M[BS] & CHAR]; MM (BS); - t = ((a + b) & INDEXMASK) % MAXMEMSIZE; /* compute sum */ - M[BS + 3] = (M[BS + 3] & WM) | store_addr_u (t); - M[BS + 2] = (M[BS + 2] & (WM + ZONE)) | store_addr_t (t); - M[BS + 1] = (M[BS + 1] & WM) | store_addr_h (t); - if (((a % 4000) + (b % 4000)) >= 4000) BS = BS + 2; /* carry? */ - break; - -/* Store address instructions A-check B-check - - SAR store A* at A addr fetch - SBR store B* at A addr fetch - - Instruction lengths: - 1 chained - 2,3 invalid A-address - 4 normal - 5+ B-address overwritten from instruction; - invalid address ignored -*/ - -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; - -/* NOP - no validity checking, all instructions length ok */ - -case OP_NOP: /* nop */ - break; - -/* HALT - unless length = 4 (branch), no validity checking; all lengths ok */ - -case OP_H: /* halt */ - if (ilnt == 4) hb_pend = 1; /* set pending branch */ - reason = STOP_HALT; /* stop simulator */ - saved_IS = IS; /* commit instruction */ - break; - -default: - reason = STOP_NXI; /* unimplemented */ - break; } /* end switch */ -} /* end while */ - -/* Simulation halted */ - -as_err = ADDR_ERR (AS); /* get addr err flags */ -bs_err = ADDR_ERR (BS); -AS = AS & ADDRMASK; /* clean addresses */ -BS = BS & ADDRMASK; -pcq_r->qptr = pcq_p; /* update pc q ptr */ -return reason; -} /* end sim_instr */ - -/* store addr_x - convert address to BCD character in x position - - Inputs: - addr = address to convert - Outputs: - char = converted address character -*/ - -int32 store_addr_h (int32 addr) -{ -int32 thous; - -thous = (addr / 1000) & 03; -return bin_to_bcd[(addr % 1000) / 100] | (thous << V_ZONE); -} - -int32 store_addr_t (int32 addr) -{ -return bin_to_bcd[(addr % 100) / 10]; -} - -int32 store_addr_u (int32 addr) -{ -int32 thous; - -thous = (addr / 1000) & 014; -return bin_to_bcd[addr % 10] | (thous << (V_ZONE - 2)); -} - -/* div_add - add string for divide */ - -int32 div_add (int32 ap, int32 bp, int32 aend) -{ -int32 a, b, c, r; - -c = 0; /* init carry */ -do { a = M[ap]; b = M[bp]; /* get operands */ - r = bcd_to_bin[b & DIGIT] + /* sum digits + c */ - bcd_to_bin[a & DIGIT] + c; - c = (r >= 10); /* set carry out */ - M[bp] = sum_table[r]; /* store result */ - ap--; bp--; } -while (ap >= aend); -return c; -} - -/* div_sub - substract string for divide */ - -int32 div_sub (int32 ap, int32 bp, int32 aend) -{ -int32 a, b, c, r; - -c = 0; /* init borrow */ -do { a = M[ap]; b = M[bp]; /* get operands */ - r = bcd_to_bin[b & DIGIT] - /* a - b - borrow */ - bcd_to_bin[a & DIGIT] - c; - c = (r < 0); /* set borrow out */ - M[bp] = sum_table[r + 10]; /* store result */ - ap--; bp--; } -while (ap >= aend); -b = M[bp] & CHAR; /* borrow position */ -if (b != BCD_ZERO) { /* non-zero? */ - r = bcd_to_bin[b & DIGIT] - c; /* subtract borrow */ - M[bp] = sum_table[r]; /* store result */ - return 0; } /* subtract worked */ -return c; /* return borrow */ -} - -/* div_sign - set signs for divide */ - -void div_sign (int32 dvrc, int32 dvdc, int32 qp, int32 rp) -{ -int32 sign = dvrc & ZONE; /* divisor sign */ - -M[rp] = M[rp] | ZONE; /* assume rem pos */ -if (sign == BBIT) M[rp] = M[rp] & ~ABIT; /* if dvr -, rem - */ -M[qp] = M[qp] | ZONE; /* assume quo + */ -if (((dvdc & ZONE) == BBIT) ^ (sign == BBIT)) /* dvr,dvd diff? */ - M[qp] = M[qp] & ~ABIT; /* make quo - */ -return; -} - -/* iomod - check on I/O modifiers - - Inputs: - ilnt = instruction length - mod = modifier character - tptr = pointer to table of modifiers, end is -1 - Output: - status = SCPE_OK if ok, STOP_INVM if invalid -*/ - -t_stat iomod (int32 ilnt, int32 mod, const int32 *tptr) -{ -if ((ilnt != 2) && (ilnt != 5) && (ilnt < 8)) return SCPE_OK; -if (tptr == NULL) return STOP_INVM; -do { if (mod == *tptr++) return SCPE_OK; } -while (*tptr >= 0); -return STOP_INVM; -} - -/* iodisp - dispatch load or move to I/O routine - - Inputs: - dev = device number - unit = unit number - flag = move (MD_NORM) vs load (MD_WM) - mod = modifier -*/ - -t_stat iodisp (int32 dev, int32 unit, int32 flag, int32 mod) -{ -if (dev == IO_INQ) return inq_io (flag, mod); /* inq terminal? */ -if (dev == IO_DP) return dp_io (unit, flag, mod); /* disk pack? */ -if (dev == IO_MT) return mt_io (unit, flag, mod); /* magtape? */ -if (dev == IO_MTB) { /* binary? */ - if (flag == MD_WM) return STOP_INVM; /* invalid */ - return mt_io (unit, MD_BIN, mod); } -return STOP_NXD; /* not implemented */ -} - -/* Reset routine */ - -t_stat cpu_reset (DEVICE *dptr) -{ -int32 i; - -for (i = 0; i < 64; i++) ind[i] = 0; /* clr indicators */ -ind[IN_UNC] = 1; /* ind[0] always on */ -AS = 0; as_err = 1; /* clear AS */ -BS = 0; bs_err = 1; /* clear BS */ -D = 0; /* clear D */ -hb_pend = 0; /* no halt br */ -pcq_r = find_reg ("ISQ", 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] & (WM + CHAR); -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 & (WM + CHAR); -return SCPE_OK; -} - -/* Memory size change */ - -t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -int32 mc = 0; -uint32 i; - -if ((val <= 0) || (val > MAXMEMSIZE) || ((val % 1000) != 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; -if (MEMSIZE > 4000) cpu_unit.flags = cpu_unit.flags | MA; -else cpu_unit.flags = cpu_unit.flags & ~MA; -return SCPE_OK; -} diff --git a/I1401/i1401_dat.h b/I1401/i1401_dat.h deleted file mode 100644 index 02e6ac00..00000000 --- a/I1401/i1401_dat.h +++ /dev/null @@ -1,57 +0,0 @@ -/* i1401_dat.h: IBM 1401 character conversion tables - - 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. -*/ - -/* ASCII to BCD conversion */ - -const char ascii_to_bcd[128] = { - 000, 000, 000, 000, 000, 000, 000, 000, /* 000 - 037 */ - 000, 000, 000, 000, 000, 000, 000, 000, - 000, 000, 000, 000, 000, 000, 000, 000, - 000, 000, 000, 000, 000, 000, 000, 000, - 000, 052, 077, 013, 053, 034, 060, 032, /* 040 - 077 */ - 017, 074, 054, 037, 033, 040, 073, 021, - 012, 001, 002, 003, 004, 005, 006, 007, - 010, 011, 015, 056, 076, 035, 016, 072, - 014, 061, 062, 063, 064, 065, 066, 067, /* 100 - 137 */ - 070, 071, 041, 042, 043, 044, 045, 046, - 047, 050, 051, 022, 023, 024, 025, 026, - 027, 030, 031, 075, 036, 055, 020, 057, - 000, 061, 062, 063, 064, 065, 066, 067, /* 140 - 177 */ - 070, 071, 041, 042, 043, 044, 045, 046, - 047, 050, 051, 022, 023, 024, 025, 026, - 027, 030, 031, 000, 000, 000, 000, 000 }; - -/* BCD to ASCII conversion - also the "full" print chain */ - -char bcd_to_ascii[64] = { - ' ', '1', '2', '3', '4', '5', '6', '7', - '8', '9', '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', '?', '.', ')', '[', '<', '"' }; diff --git a/I1401/i1401_defs.h b/I1401/i1401_defs.h deleted file mode 100644 index a93427fb..00000000 --- a/I1401/i1401_defs.h +++ /dev/null @@ -1,278 +0,0 @@ -/* i1401_defs.h: IBM 1401 simulator definitions - - 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. - - 16-Mar-03 RMS Fixed mnemonic for MCS - 03-Jun-02 RMS Added 1311 support - 14-Apr-99 RMS Converted t_addr to unsigned - - This simulator is based on the 1401 simulator written by Len Fehskens - with assistance from Sarah Lee Harris and Bob Supnik. This one's for - you, Len. I am grateful to Paul Pierce and Charles Owen for their help - in answering questions, gathering source material, and debugging. -*/ - -#include "sim_defs.h" - -/* Simulator stop codes */ - -#define STOP_NXI 1 /* unimpl instr */ -#define STOP_NXM 2 /* non-exist mem */ -#define STOP_NXD 3 /* non-exist dev */ -#define STOP_NOWM 4 /* no WM under op */ -#define STOP_INVA 5 /* invalid A addr */ -#define STOP_INVB 6 /* invalid B addr */ -#define STOP_INVL 7 /* invalid length */ -#define STOP_INVM 8 /* invalid modifier */ -#define STOP_INVBR 9 /* invalid branch */ -#define STOP_IBKPT 10 /* breakpoint */ -#define STOP_HALT 11 /* halt */ -#define STOP_INVMTU 12 /* invalid MT unit */ -#define STOP_MTZ 13 /* MT zero lnt rec */ -#define STOP_MTL 14 /* MT write lock */ -#define STOP_CCT 15 /* inv CCT channel */ -#define STOP_NOCD 16 /* no cards left */ -#define STOP_WRAP 17 /* AS, BS mem wrap */ -#define STOP_MCE1 18 /* MCE short A field */ -#define STOP_MCE2 19 /* MCE short B field */ -#define STOP_MCE3 20 /* MCE hanging $ */ -#define STOP_IOC 21 /* I/O check */ -#define STOP_INVDSC 22 /* invalid disk sector */ -#define STOP_INVDCN 23 /* invalid disk count */ -#define STOP_INVDSK 24 /* invalid disk unit */ -#define STOP_INVDFN 25 /* invalid disk func */ -#define STOP_INVDLN 26 /* invalid disk reclen */ -#define STOP_WRADIS 27 /* write address dis */ -#define STOP_WRCHKE 28 /* write check error */ -#define STOP_INVDAD 39 /* invalid disk addr */ -#define STOP_INVDCY 30 /* invalid direct seek */ - -/* Memory and devices */ - -#define MAXMEMSIZE 16000 /* max memory */ -#define MEMSIZE (cpu_unit.capac) /* current memory */ -#define CDR_BUF 1 /* card rdr buffer */ -#define CDR_WIDTH 80 /* card rdr width */ -#define CDP_BUF 101 /* card punch buffer */ -#define CDP_WIDTH 80 /* card punch width */ -#define LPT_BUF 201 /* line print buffer */ -#define LPT_WIDTH 132 /* line print width */ -#define CCT_LNT 132 /* car ctrl length */ -#define INQ_WIDTH 80 /* inq term width */ -#define ADDR_ERR(x) (((uint32) (x)) >= MEMSIZE) - -/* Binary address format - - <14:0> address, with index added in - <23:16> index register memory address - <25:24> address error bits -*/ - -#define ADDRMASK 037777 /* addr mask */ -#define INDEXMASK 077777 /* addr + index mask */ -#define V_INDEX 16 -#define M_INDEX 0177 -#define V_ADDRERR 24 -#define BA (1 << V_ADDRERR) /* bad addr digit */ -#define X1 (87 << V_INDEX) /* index reg 1 */ -#define X2 (92 << V_INDEX) /* index reg 2 */ -#define X3 (97 << V_INDEX) /* index reg 3 */ - -/* CPU instruction control flags. The flag definitions must be harmonized - with the UNIT flag definitions used by the simulator. */ - -/* Lengths */ - -#define L1 0001 /* 1: op */ -#define L2 0002 /* 2: op d */ -#define L4 0004 /* 4: op aaa */ -#define L5 0010 /* 5: op aaa d */ -#define L7 0020 /* 7: op aaa bbb */ -#define L8 0040 /* 8: op aaa bbb d */ - -/* CPU options, stored in cpu_unit.flags */ - -#define MDV (1 << (UNIT_V_UF + 0)) /* multiply/divide */ -#define MR (1 << (UNIT_V_UF + 1)) /* move record */ -#define XSA (1 << (UNIT_V_UF + 2)) /* index, store addr */ -#define EPE (1 << (UNIT_V_UF + 3)) /* expanded edit */ -#define MA (1 << (UNIT_V_UF + 4)) /* modify address */ -#define BBE (1 << (UNIT_V_UF + 5)) /* br bit equal */ -#define HLE (1 << (UNIT_V_UF + 6)) /* high/low/equal */ -#define UNIT_MSIZE (1 << (UNIT_V_UF + 7)) /* fake flag */ -#define ALLOPT (MDV + MR + XSA + EPE + MA + BBE + HLE) -#define STDOPT (MDV + MR + XSA + EPE + MA + BBE + HLE) - -/* Fetch control */ - -#define AREQ (1 << (UNIT_V_UF + 8)) /* validate A */ -#define BREQ (1 << (UNIT_V_UF + 9)) /* validate B */ -#define MLS (1 << (UNIT_V_UF + 10)) /* move load store */ -#define NOWM (1 << (UNIT_V_UF + 11)) /* no WM at end */ -#define HNOP (1 << (UNIT_V_UF + 12)) /* halt or nop */ -#define IO (1 << (UNIT_V_UF + 13)) /* IO */ -#define UNIT_BCD (1 << (UNIT_V_UF + 14)) /* BCD strings */ - -#if (UNIT_V_UF < 6) || ((UNIT_V_UF + 14) > 31) - Definition error: flags overlap -#endif - -/* BCD memory character format */ - -#define WM 0100 /* word mark */ -#define ZONE 0060 /* zone */ -#define BBIT 0040 /* 1 in valid sign */ -#define ABIT 0020 /* sign (1 = +) */ -#define DIGIT 0017 /* digit */ -#define CHAR 0077 /* character */ - -#define V_WM 6 -#define V_ZONE 4 -#define V_DIGIT 0 - -/* Interesting BCD characters */ - -#define BCD_BLANK 000 -#define BCD_ONE 001 -#define BCD_TWO 002 -#define BCD_THREE 003 -#define BCD_FOUR 004 -#define BCD_FIVE 005 -#define BCD_SIX 006 -#define BCD_SEVEN 007 -#define BCD_EIGHT 010 -#define BCD_NINE 011 -#define BCD_ZERO 012 -#define BCD_ALT 020 -#define BCD_S 022 -#define BCD_U 024 -#define BCD_W 026 -#define BCD_RECMRK 032 -#define BCD_COMMA 033 -#define BCD_PERCNT 034 -#define BCD_WM 035 -#define BCD_BS 036 -#define BCD_TS 037 -#define BCD_MINUS 040 -#define BCD_M 044 -#define BCD_R 051 -#define BCD_DOLLAR 053 -#define BCD_ASTER 054 -#define BCD_AMPER 060 -#define BCD_A 061 -#define BCD_B 062 -#define BCD_C 063 -#define BCD_E 065 -#define BCD_DECIMAL 073 -#define BCD_SQUARE 074 -#define BCD_GRPMRK 077 - -/* Opcodes */ - -#define OP_R 001 /* read */ -#define OP_W 002 /* write */ -#define OP_WR 003 /* write and read */ -#define OP_P 004 /* punch */ -#define OP_RP 005 /* read and punch */ -#define OP_WP 006 /* write and punch */ -#define OP_WRP 007 /* write read punch */ -#define OP_RF 010 /* reader feed */ -#define OP_PF 011 /* punch feed */ -#define OP_MA 013 /* modify address */ -#define OP_MUL 014 /* multiply */ -#define OP_CS 021 /* clear storage */ -#define OP_S 022 /* subtract */ -#define OP_MTF 024 /* magtape function */ -#define OP_BWZ 025 /* branch wm or zone */ -#define OP_BBE 026 /* branch bit equal */ -#define OP_MZ 030 /* move zone */ -#define OP_MCS 031 /* move suppr zeroes */ -#define OP_SWM 033 /* set word mark */ -#define OP_DIV 034 /* divide */ -#define OP_SS 042 /* select stacker */ -#define OP_LCA 043 /* load characters */ -#define OP_MCW 044 /* move characters */ -#define OP_NOP 045 /* no op */ -#define OP_MCM 047 /* move to rec/grp mk */ -#define OP_SAR 050 /* store A register */ -#define OP_ZS 052 /* zero and subtract */ -#define OP_A 061 /* add */ -#define OP_B 062 /* branch */ -#define OP_C 063 /* compare */ -#define OP_MN 064 /* move numeric */ -#define OP_MCE 065 /* move char and edit */ -#define OP_CC 066 /* carriage control */ -#define OP_SBR 070 /* store B register */ -#define OP_ZA 072 /* zero and add */ -#define OP_H 073 /* halt */ -#define OP_CWM 074 /* clear word mark */ - -/* I/O addresses */ - -#define IO_INQ 023 /* inquiry terminal */ -#define IO_MT 024 /* magtape */ -#define IO_MTB 062 /* binary magtape */ -#define IO_DP 066 /* 1311 diskpack */ - -/* I/O modes */ - -#define MD_NORM 0 /* normal (move) */ -#define MD_WM 1 /* word mark (load) */ -#define MD_BIN 2 /* binary */ - -/* Indicator characters */ - -#define IN_UNC 000 /* unconditional */ -#define IN_CC9 011 /* carr ctrl chan 9 */ -#define IN_CC12 014 /* carr ctrl chan 12 */ -#define IN_UNQ 021 /* unequal */ -#define IN_EQU 022 /* equal */ -#define IN_LOW 023 /* low */ -#define IN_HGH 024 /* high */ -#define IN_DPW 025 /* parity/compare check */ -#define IN_LNG 026 /* wrong lnt record */ -#define IN_UNA 027 /* unequal addr cmp */ -#define IN_DSK 030 /* disk error */ -#define IN_OVF 031 /* overflow */ -#define IN_LPT 032 /* printer error */ -#define IN_PRO 034 /* process check */ -#define IN_DBY 036 /* disk busy */ -#define IN_END 042 /* end indicator */ -#define IN_TAP 043 /* tape error */ -#define IN_ACC 045 /* access error */ -#define IN_BSY 047 /* printer busy */ -#define IN_INR 050 /* inquiry request */ -#define IN_PCB 051 /* printer carr busy */ -#define IN_PNCH 052 /* punch error */ -#define IN_INC 054 /* inquiry clear */ -#define IN_LST 061 /* last card */ -#define IN_SSB 062 /* sense switch B */ -#define IN_SSC 063 /* sense switch C */ -#define IN_SSD 064 /* sense switch D */ -#define IN_SSE 065 /* sense switch E */ -#define IN_SSF 066 /* sense switch F */ -#define IN_SSG 067 /* sense switch G */ -#define IN_READ 072 /* reader error */ - -#define CRETIOE(f,c) return ((f)? (c): SCPE_OK) diff --git a/I1401/i1401_doc.txt b/I1401/i1401_doc.txt deleted file mode 100644 index 83d4b9d0..00000000 --- a/I1401/i1401_doc.txt +++ /dev/null @@ -1,503 +0,0 @@ -To: Users -From: Bob Supnik -Subj: IBM 1401 Simulator Usage -Date: 15-Jul-2003 - - COPYRIGHT NOTICE - -The following copyright notice applies to both the SIMH source and binary: - - 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"), - 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 IBM 1401 simulator. - - -1. Simulator Files - -sim/ sim_defs.h - sim_rev.h - sim_sock.h - sim_tape.h - sim_tmxr.h - scp.c - scp_tty.c - sim_sock.c - sim_tape.c - sim_tmxr.c - -sim/i1401/ i1401_defs.h - i1401_dat.h - i1401_cpu.c - i1401_cd.c - i1401_iq.c - i1401_lp.c - i1401_dp.c - i1401_mt.c - i1401_sys.c - -2. IBM 1401 Features - -The IBM 1401 simulator is configured as follows: - -device simulates -name(s) - -CPU IBM 1401 CPU with 16K of memory -CDR,CDP IBM 1402 card reader/punch -LPT IBM 1403 line printer -INQ IBM 1407 inquiry terminal -DP IBM 1311 disk pack with five drives -MT IBM 729 7-track magnetic tape controller with six drives - -The IBM 1401 simulator implements many unique stop conditions. On almost -any kind of error the simulator stops: - - unimplemented opcode - reference to non-existent memory - reference to non-existent device - no word mark under opcode - invalid A address - invalid B address - invalid instruction length - invalid modifier character - invalid branch address - invalid magtape unit number - invalid magtape record length - write to locked magtape drive - skip to unpunched carriage control tape channel - card reader hopper empty - address register wrap-around - single character A field in MCE - single character B field in MCE - hanging $ in MCE with EPE enabled - I/O check with I/O stop switch set - invalid disk drive - invalid disk sector address - invalid disk sector count - invalid disk address compare - -The LOAD command is used to load a line printer carriage-control tape. -The DUMP command is not implemented. - -2.1 CPU - -The CPU options include a number of special features and the size of main -memory. Note that the Modify Address special feature is always included -when memory size is greater than 4K. - - SET CPU XSA enable advanced programming special feature - SET CPU NOXSA disable advanced programming - SET CPU HLE enable high/low/equal special feature - SET CPU NOHLE disable high/low/equal - SET CPU BBE enable branch on bit equal special feature - SET CPU NOBBE disable branch on bit equal - SET CPU MR enable move record special feature - SET CPU NOMR disable move record - SET CPU EPE enable extended print edit special feature - SET CPU NOEPE disable extended print edit - SET CPU MDV enable multiply/divide special feature - 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 - -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. Initially, memory size is 16K, and all special -features are enabled. - -Memory is implemented as 7 bit BCD characters, as follows: - - 6 5 4 3 2 1 0 - - word B bit A bit 8 4 2 1 - mark <-- zone --> <-------- digit --------> - -In BCD, the decimal digits 0-9 are (octal) values 012, 001, 002, 003, 004, -005, 006, 007, 010, 011, respectively. Signs are encoded in the zone bits, -with 00, 01, and 11 being positive, and 10 being negative. - -CPU registers include the visible state of the processor. The 1401 has no -interrupt system. - - name size comments - - IS 14 instruction storage address register (PC) - AS 14 A storage address register - BS 14 B storage address register - ASERR 1 AS invalid flag - BSERR 1 BS invalid flag - SSA 1 sense switch A - SSB 1 sense switch B - SSC 1 sense switch C - SSD 1 sense switch D - SSE 1 sense switch E - SSF 1 sense switch F - SSG 1 sense switch G - EQU 1 equal compare indicator - UNEQ 1 unequal compare indicator - HIGH 1 high compare indicator - LOW 1 low compare indicator - OVF 1 overflow indicator - IOCHK 1 I/O check switch - PRCHK 1 process check switch - ISQ[0:63] 14 IS prior to last branch; - most recent IS change first - WRU 8 interrupt character - -2.2 1402 Card Reader/Punch (CDR, CDP, STKR) - -The IBM 1402 card/reader punch is simulated as three independent devices: -the card reader (CDR), the card punch (CDP), and the reader and punch -stackers (STKR). STRK units 0, 1, 2, and 4 correspond to the reader -normal stacker, reader stacker 1, shared stacker 2/8, and punch stacker -4, respectively. - -The card reader supports the BOOT command. BOOT CDR reads a card image -into locations 1-80, sets a word mark under location 1, clears storage, -and then transfers control to location 1. - -The card reader reads data from disk files, while the punch and stackers -write data to disk files. Cards are simulated as ASCII text lines with -terminating newlines; column binary is not supported. For each unit, -the POS register specifies the number of the next data item to be read or -written. Thus, by changing POS, the user can backspace or advance these -devices. - -The card reader registers are: - - name size comments - - LAST 1 last card indicator - ERR 1 error indicator - S1 1 stacker 1 select flag - S2 1 stacker 2 select flag - POS 32 position - TIME 24 delay window for stacker select - BUF[0:79] 8 reader buffer - -The card punch registers are: - - ERR 1 error indicator - S4 1 stacker 4 select flag - S8 1 stacker 8 select flag - -The stacker registers are: - - POS0 32 position, normal reader stack - POS1 32 position, reader stacker 1 - POS2 32 position, shared stacker 2/8 - POS4 32 position, punch stacker 4 - -Error handling is as follows: - - device error processed as - - reader end of file if SSA set, set LAST indicator - on next Read, report error and stop - - reader,punch not attached report error and stop - OS I/O error print error message - if IOCHK set, report error and stop - otherwise, set ERR indicator - - stacker not attached ignored - OS I/O error print error message - if IOCHK set, report error and stop - -2.3 1403 Line Printer (LPT) - -The IBM 1403 line printer (LPT) writes its data, converted to ASCII, to -a disk file. The line printer supports three different print character -sets or "chains": - - SET LPT PCF full 64 character chain - SET LPT PCA 48 character business chain - SET LPT PCH 48 character FORTRAN chain - -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 1 and 12; a column number of zero denotes top of form. The -following are all legal carriage control specifications: - - no punch - (5) 5 lines with no punches - 1,5,7,8 columns 1, 5, 7, 8 punched - (10)2 10 lines with column 2 punched - 1,0 column 1 punched; top of form - -The default form is 66 lines long, with column 1 and the top of form mark -on line 1, and the rest blank. - -The line printer registers are: - - name size comments - - LINES 8 number of newlines after next print - LFLAG 1 carriage control flag (1 = skip, 0 = space) - CCTP 8 carriage control tape pointer - CCTL 8 carriage control tape length (read only) - ERR 1 error indicator - POS 32 position - CCT[0:131] 32 carriage control tape array - -Error handling is as follows: - - error processed as - - not attached report error and stop - - OS I/O error print error message - if IOCHK set, report error and stop - otherwise, set ERR indicator - -2.4 1407 Inquiry Terminal (INQ) - -The IBM 1407 inquiry terminal (INQ) is a half-duplex console. It polls -the console keyboard periodically for inquiry requests. The inquiry -terminal registers are: - - name size comments - - INQC 7 inquiry request character (initially ESC) - INR 1 inquiry request indicator - INC 1 inquiry cleared indicator - TIME 24 polling interval - -When the 1401 CPU requests input from the keyboard, the message [Enter] -is printed out, followed by a new line. The CPU hangs waiting for input -until either the return/enter key is pressed, or the inquiry request -character is typed in. The latter cancels the type-in and sets INC. - -The inquiry terminal has no errors. - -2.5 1311 Disk Pack (DP) - -The disk pack controller supports 5 drives, numbered 0 through 4. Disk -pack options include the ability to enable address writing (formatting). - - SET DPn ADDROFF set unit n address enable off - SET DPn ADDRON set unit n address enable on - -Units can also be set ONLINE or OFFLINE. - -Unlike most simulated disks, the 1311 includes explicit representation -for sector addresses. This is to support non-standard formats, such as -the inclusion of the drive number in the sector address. As a result, -1311 sectors are 106 characters long: 6 address characters and 100 -data characters. If the 1311 has not been formatted, the addresses -are blanks and are synthesized, if needed, based on the sector number. - -The 1311 also supports two modes of operation: move mode and load mode. -In move mode, word marks are ignored on writes and left untouched on reads, -and sectors hold 100 characters. In load mode, word marks are included -on writes and stored on reads, and sectors hold 90 characters. No attempt -is made to deal with sectors written in load mode and read in move mode, -or vice versa; on a real 1401, this causes a fatal parity error. - -The disk pack controller implements these registers: - - name size comments - - ACC 1 access error indicator - PWC 1 parity or write check error indicator - WLR 1 wrong length record error indicator - UNA 1 unequal address compare error indicator - DSK 1 any disk error indicator - BSY 1 disk access busy indicator - LASTF 3 most recent function - TIME 24 seek time - -The 1311 has a primative overlapped seek capability. If TIME is set -non-zero, the 1311 will report itself busy for the specified amount -of time following a seek. This allows programs to utilize the seek -time for processing. - -Error handling is as follows: - - error processed as - - not attached set DSK indicator - if IOCHK set, report error and stop - -1311 data files are buffered in memory; therefore, end of file and OS -I/O errors cannot occur. - -2.6 729 Magnetic Tape (MT) - -The magnetic tape controller supports six drives, numbered 1 through 6. -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 simulator -supports the BOOT command. BOOT MT reads the first record off tape, -starting at location 1, and then branches to it. - -The magnetic tape controller implements these registers: - - name size comments - - END 1 end of file indicator - ERR 1 error indicator - PAR 1 parity error indicator - POS1..6 32 position, drives 1..6 - -Error handling is as follows: - - error processed as - - not attached report error and stop - - end of file set error indicator - - OS I/O error print error message - set error indicator - if IOCHK set, report error and stop - -2.7 Symbolic Display and Input - -The IBM 1401 simulator implements symbolic display and input. Display is -controlled by command line switches: - - -c display as single character - (BCD for CPU and MT, ASCII for others) - -s display as wordmark terminated BCD string - (CPU only) - -m display instruction mnemonics - (CPU only) - -d display 50 characters per line, with word - marks denoted by "1" on the line below - -In a CPU character display, word marks are denoted by ~. - -Input parsing is controlled by the first character typed in or by command -line switches: - - ' or " or -c or -s characters (BCD for CPU and MT, ASCII - for others) - alphabetic instruction mnemonic - numeric octal number - -Instruction input is free format, with spaces separating fields. There -are six instruction formats: 1, 2, 4, 5, 7, and 8 characters: - - 1 character opcode - 2 character opcode 'modifier - 4 character opcode address - 5 character opcode address 'modifier - 7 character opcode address address - 8 character opcode address address 'modifier - -Addresses are always decimal, except for special I/O addresses in the A -field, which may be specified as %xy, where x denotes the device and y -the unit number. - -For the CPU, string input may encompass multiple characters. A word mark -is denoted by ~ and must precede the character to be marked. All other -devices can only accept single character input, without word marks. - -2.7 Character Sets - -The IBM 1401 uses a 6b character code called BCD (binary coded decimal). -Some of the characters have no equivalent in ASCII and require different -representations: - -BCD ASCII IBM 1401 print -code representation character chains - -00 space -01 1 -02 2 -03 3 -04 4 -05 5 -06 6 -07 7 -10 8 -11 9 -12 0 -13 # = in H chain -14 @ ' in H chain -15 : blank in A, H chains -16 > blank in A, H chains -17 ( tape mark blank in A, H chains -20 ^ alternate blank blank in A, H chains -21 / -22 S -23 T -24 U -25 V -26 W -27 X -30 Y -31 Z -32 ' record mark -33 , -34 % ( in H chain -35 = word mark blank in A, H chains -36 \ blank in A, H chains -37 + blank in A, H chains -40 - -41 J -42 K -43 L -44 M -45 N -46 O -47 P -50 Q -51 R -52 ! -53 $ -54 * -55 ] blank in A, H chains -56 ; blank in A, H chains -57 _ delta blank in A, H chains -60 & -61 A -62 B -63 C -64 D -65 E -66 F -67 G -70 H -71 I -72 ? -73 . -74 ) lozenge -75 [ blank in A, H chains -76 < blank in A, H chains -77 " group mark blank in A, H chains diff --git a/I1401/i1401_dp.c b/I1401/i1401_dp.c deleted file mode 100644 index 1e2a0686..00000000 --- a/I1401/i1401_dp.c +++ /dev/null @@ -1,555 +0,0 @@ -/* i1401_dp.c: IBM 1311 disk simulator - - 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"), - 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 1311 disk pack - - 18-Oct-02 RMS Fixed bug in address comparison logic - 19-Sep-02 RMS Minor edit for consistency with 1620 - 15-Jun-02 RMS Reworked address comparison logic - - The 1311 disk pack has 100 cylinders, 10 tracks/cylinder, 20 sectors/track. - Each sector contains 106 characters of information: - - 6c sector address - 100c sector data - - By default, a sector's address field will be '000000', which is illegal. - This is interpreted to mean the implied sector number that would be in - place if the disk pack had been formatted with sequential sector numbers. - - The sector data can be 100 characters without word marks, or 90 characters - with word marks. Load mode transfers 90 characters per sector with - word marks, move mode transfers 100 characters per sector without word - marks. No attempt is made to catch incompatible writes (eg, load mode - write followed by move mode read). -*/ - -#include "i1401_defs.h" - -#define DP_NUMDR 5 /* #drives */ -#define UNIT_V_WAE (UNIT_V_UF + 0) /* write addr enab */ -#define UNIT_WAE (1 << UNIT_V_WAE) - -/* Disk format */ - -#define DP_ADDR 6 /* address */ -#define DP_DATA 100 /* data */ -#define DP_NUMCH (DP_ADDR + DP_DATA) - -#define DP_NUMSC 20 /* #sectors */ -#define DP_NUMSF 10 /* #surfaces */ -#define DP_NUMCY 100 /* #cylinders */ -#define DP_TOTSC (DP_NUMCY*DP_NUMSF*DP_NUMSC) -#define DP_SIZE (DP_TOTSC*DP_NUMCH) - -/* Disk control field */ - -#define DCF_DRV 0 /* drive select */ -#define DCF_SEC 1 /* sector addr */ -#define DCF_SEC_LEN 6 -#define DCF_CNT (DCF_SEC + DCF_SEC_LEN) /* sector count */ -#define DCF_CNT_LEN 3 -#define DCF_LEN (DCF_CNT + DCF_CNT_LEN) -#define DCF_DIR 1 /* direct seek */ -#define DCF_DIR_LEN 4 -#define DCF_DIR_FL (DCF_DIR + DCF_DIR_LEN) /* direct seek flag */ -#define DCF_DSEEK 0xB - -/* Functions */ - -#define FNC_SEEK 0 /* seek */ -#define FNC_CHECK 3 /* check */ -#define FNC_READ 1 /* read sectors */ -#define FNC_RSCO 5 /* read sec cnt overlay */ -#define FNC_RTRK 6 /* read track */ -#define FNC_WOFF 10 /* offset for write */ -#define FNC_WRITE 11 /* write sectors */ -#define FNC_WRSCO 15 /* write sec cnt overlay */ -#define FNC_WRTRK 16 /* write track */ - -#define CYL u3 /* current cylinder */ - -extern uint8 M[]; /* memory */ -extern int32 ind[64]; -extern int32 AS, BS, iochk; -extern int32 bcd_to_bin[16]; -extern int32 bin_to_bcd[16]; -extern UNIT cpu_unit; - -int32 dp_lastf = 0; /* prior function */ -int32 dp_time = 0; /* seek time */ - -t_stat dp_reset (DEVICE *dptr); -t_stat dp_rdadr (UNIT *uptr, int32 sec, int32 flg, int32 wchk); -t_stat dp_rdsec (UNIT *uptr, int32 sec, int32 flg, int32 wchk); -t_stat dp_wradr (UNIT *uptr, int32 sec, int32 flg); -t_stat dp_wrsec (UNIT *uptr, int32 sec, int32 flg); -int32 dp_fndsec (UNIT *uptr, int32 sec, int32 dcf); -t_stat dp_nexsec (UNIT *uptr, int32 psec, int32 dcf); -t_bool dp_zeroad (uint8 *ap); -t_bool dp_cmp_ad (uint8 *ap, int32 dcf); -int32 dp_trkop (int32 drv, int32 sec); -int32 dp_cvt_bcd (int32 ad, int32 len); -void dp_cvt_bin (int32 ad, int32 len, int32 val, int32 flg); -int32 dp_get_cnt (int32 dcf); -void dp_fill (UNIT *uptr, uint32 da, int32 cnt); - -/* DP data structures - - dp_dev DSK device descriptor - dp_unit DSK unit list - dp_reg DSK register list - dp_mod DSK modifier list -*/ - -UNIT dp_unit[] = { - { UDATA (NULL, UNIT_FIX + UNIT_DISABLE + UNIT_ATTABLE + - UNIT_BUFABLE + UNIT_MUSTBUF + UNIT_BCD, DP_SIZE) }, - { UDATA (NULL, UNIT_FIX + UNIT_DISABLE + UNIT_ATTABLE + - UNIT_BUFABLE + UNIT_MUSTBUF + UNIT_BCD, DP_SIZE) }, - { UDATA (NULL, UNIT_FIX + UNIT_DISABLE + UNIT_ATTABLE + - UNIT_BUFABLE + UNIT_MUSTBUF + UNIT_BCD, DP_SIZE) }, - { UDATA (NULL, UNIT_FIX + UNIT_DISABLE + UNIT_ATTABLE + - UNIT_BUFABLE + UNIT_MUSTBUF + UNIT_BCD, DP_SIZE) }, - { UDATA (NULL, UNIT_FIX + UNIT_DISABLE + UNIT_ATTABLE + - UNIT_BUFABLE + UNIT_MUSTBUF + UNIT_BCD, DP_SIZE) } }; - -REG dp_reg[] = { - { FLDATA (ACC, ind[IN_ACC], 0) }, - { FLDATA (PWC, ind[IN_DPW], 0) }, - { FLDATA (WLR, ind[IN_LNG], 0) }, - { FLDATA (UNA, ind[IN_UNA], 0) }, - { FLDATA (ERR, ind[IN_DSK], 0) }, - { FLDATA (BSY, ind[IN_DBY], 0) }, - { DRDATA (LASTF, dp_lastf, 3) }, - { DRDATA (TIME, dp_time, 24), PV_LEFT }, - { URDATA (CYL, dp_unit[0].CYL, 10, 8, 0, - DP_NUMDR, PV_LEFT + REG_RO) }, - { NULL } }; - -MTAB dp_mod[] = { - { UNIT_WAE, 0, "write address disabled", "ADDROFF", NULL }, - { UNIT_WAE, UNIT_WAE, "write address enabled", "ADDRON", NULL }, - { 0 } }; - -DEVICE dp_dev = { - "DP", dp_unit, dp_reg, dp_mod, - DP_NUMDR, 10, 21, 1, 8, 7, - NULL, NULL, &dp_reset, - NULL, NULL, NULL }; - -/* Disk IO routine - - Inputs: - fnc = function character - flg = load vs move mode - mod = modifier character - Outputs: - status = status -*/ - -t_stat dp_io (int32 fnc, int32 flg, int32 mod) -{ -int32 dcf, drv, sec, psec, cnt, qwc, qzr, diff; -UNIT *uptr; -t_stat r; - -dcf = BS; /* save DCF addr */ -qwc = 0; /* not wcheck */ -ind[IN_DPW] = ind[IN_LNG] = ind[IN_UNA] = 0; /* clr indicators */ -ind[IN_DSK] = ind[IN_ACC] = ind[IN_DBY] = 0; -if (sim_is_active (&dp_unit[0])) { /* ctlr busy? */ - ind[IN_DBY] = ind[IN_DSK] = 1; /* set indicators */ - return SCPE_OK; } /* done */ - -AS = dcf + 6; /* AS for most ops */ -BS = dcf + DCF_CNT - 1; /* minimum DCF */ -if (ADDR_ERR (BS)) return STOP_WRAP; /* DCF in memory? */ -if (M[dcf] & BBIT) drv = M[dcf + DCF_SEC + 1] & 0xE; /* impl sel? cyl 8-4-2 */ -else drv = M[dcf] & DIGIT; /* get drive sel */ -if ((drv == 0) || (drv & 1) || (drv > BCD_ZERO)) /* bad drive #? */ - return STOP_INVDSK; -drv = bcd_to_bin[drv] >> 1; /* convert */ -uptr = dp_dev.units + drv; /* get unit ptr */ -if ((uptr->flags & UNIT_ATT) == 0) { /* attached? */ - ind[IN_DSK] = ind[IN_ACC] = 1; /* no, error */ - CRETIOE (iochk, SCPE_UNATT); } - -if ((fnc == FNC_SEEK) && /* seek and */ - (M[dcf + DCF_DIR_FL] & DCF_DSEEK) == DCF_DSEEK) { /* direct flag? */ - diff = dp_cvt_bcd (dcf + DCF_DIR, DCF_DIR_LEN); /* cvt diff */ - 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 */ - 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; } - sim_activate (&dp_unit[0], dp_time); /* set ctlr busy */ - return SCPE_OK; } /* done! */ - -sec = dp_cvt_bcd (dcf + DCF_SEC, DCF_SEC_LEN); /* cvt sector */ -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; - sim_activate (&dp_unit[0], dp_time); /* set ctlr busy */ - return SCPE_OK; } /* done! */ - -BS = dcf + DCF_LEN; /* full DCF */ -if (ADDR_ERR (BS)) return STOP_WRAP; /* DCF in memory? */ -cnt = dp_get_cnt (dcf); /* get count */ -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 */ -else if (mod == BCD_R) dp_lastf = fnc; /* read? save func */ -else return STOP_INVM; /* other? error */ - -switch (fnc) { /* case on function */ -case FNC_RSCO: /* read sec cnt ov */ - BS = dcf + DCF_CNT; /* set count back */ - /* fall thru */ -case FNC_READ: /* read */ - psec = dp_fndsec (uptr, sec, dcf); /* find sector */ - if (psec < 0) CRETIOE (iochk, STOP_INVDAD); /* addr cmp error? */ - for (;;) { /* loop */ - qzr = (--cnt == 0); /* set zero latch */ - dp_cvt_bin (dcf + DCF_CNT, DCF_CNT_LEN, cnt, MD_WM); /* redo count */ - if (r = dp_rdsec (uptr, psec, flg, qwc)) /* read sector */ - break; - cnt = dp_get_cnt (dcf); /* get new count */ - if (cnt < 0) return STOP_INVDCN; /* bad count? */ - if (qzr) break; /* zero latch? done */ - sec++; psec++; /* next sector */ - dp_cvt_bin (dcf + DCF_SEC, DCF_SEC_LEN, sec, flg); /* rewr sec */ - if (r = dp_nexsec (uptr, psec, dcf)) break; /* find next */ - } - break; /* done, clean up */ - -case FNC_RTRK: /* read track */ - AS = dcf + 9; /* special AS */ - psec = dp_trkop (drv, sec); /* start of track */ - for (;;) { /* loop */ - qzr = (--cnt == 0); /* set zero latch */ - dp_cvt_bin (dcf + DCF_CNT, DCF_CNT_LEN, cnt, MD_WM); /* redo count */ - if (r = dp_rdadr (uptr, psec, flg, qwc)) /* read addr */ - break; /* error? */ - if (r = dp_rdsec (uptr, psec, flg, qwc)) /* read data */ - break; /* error? */ - cnt = dp_get_cnt (dcf); /* get new count */ - if (cnt < 0) return STOP_INVDCN; /* bad count? */ - if (qzr) break; /* zero latch? done */ - psec = dp_trkop (drv, sec) + ((psec + 1) % DP_NUMSC); } - break; /* done, clean up */ - -case FNC_WRSCO: /* write sec cnt ov */ - BS = dcf + DCF_CNT; /* set count back */ - /* fall through */ -case FNC_WRITE: /* read */ - psec = dp_fndsec (uptr, sec, dcf); /* find sector */ - if (psec < 0) CRETIOE (iochk, STOP_INVDAD); /* addr cmp error? */ - for (;;) { /* loop */ - qzr = (--cnt == 0); /* set zero latch */ - dp_cvt_bin (dcf + DCF_CNT, DCF_CNT_LEN, cnt, MD_WM); /* rewr cnt */ - if (r = dp_wrsec (uptr, psec, flg)) break; /* write data */ - if (qzr) break; /* zero latch? done */ - sec++; psec++; /* next sector */ - dp_cvt_bin (dcf + DCF_SEC, DCF_SEC_LEN, sec, flg); /* rewr sec */ - if (r = dp_nexsec (uptr, psec, dcf)) break; /* find next */ - } - break; /* done, clean up */ - -case FNC_WRTRK: /* write track */ - if ((uptr->flags & UNIT_WAE) == 0) /* enabled? */ - return STOP_WRADIS; - AS = dcf + 9; /* special AS */ - psec = dp_trkop (drv, sec); /* start of track */ - for (;;) { /* loop */ - qzr = (--cnt == 0); /* set zero latch */ - dp_cvt_bin (dcf + DCF_CNT, DCF_CNT_LEN, cnt, MD_WM); /* redo count */ - if (r = dp_wradr (uptr, psec, flg)) break; /* write addr */ - if (r = dp_wrsec (uptr, psec, flg)) break; /* write data */ - if (qzr) break; /* zero latch? done */ - psec = dp_trkop (drv, sec) + ((psec + 1) % DP_NUMSC); } - break; /* done, clean up */ - -default: /* unknown */ - return STOP_INVDFN; } - -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; } } -CRETIOE (iochk || !ind[IN_DSK], r); /* return status */ -} - -/* Read or compare address with memory */ - -t_stat dp_rdadr (UNIT *uptr, int32 sec, int32 flg, int32 qwc) -{ -int32 i; -uint8 ac; -int32 da = (sec % DP_TOTSC) * DP_NUMCH; /* char number */ -uint8 *ap = ((uint8 *) uptr->filebuf) + da; /* buf ptr */ -t_bool zad = dp_zeroad (ap); /* zero address */ -static const int32 dec_tab[DP_ADDR] = /* powers of 10 */ - { 100000, 10000, 1000, 100, 10, 1} ; - -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; } - 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 */ - 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; } } - else if (flg) M[BS] = ac & CHAR; /* load mode */ - else M[BS] = (M[BS] & WM) | (ac & CHAR); /* move mode */ - ap++; BS++; /* adv ptrs */ - if (ADDR_ERR (BS)) return STOP_WRAP; } -return SCPE_OK; -} - -/* Read or compare data with memory */ - -t_stat dp_rdsec (UNIT *uptr, int32 sec, int32 flg, int32 qwc) -{ -int32 i, lim; -int32 da = (sec % DP_TOTSC) * DP_NUMCH; /* char number */ -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; } - 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; } } - else if (flg) M[BS] = *ap & (WM | CHAR); /* load mode */ - else M[BS] = (M[BS] & WM) | (*ap & CHAR); /* word mode */ - ap++; BS++; /* adv ptrs */ - if (ADDR_ERR (BS)) return STOP_WRAP; } -return SCPE_OK; -} - -/* Write address to disk */ - -t_stat dp_wradr (UNIT *uptr, int32 sec, int32 flg) -{ -int32 i; -uint32 da = (sec % DP_TOTSC) * DP_NUMCH; /* char number */ -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; } - 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; - da++; ap++; BS++; /* adv ptrs */ - if (ADDR_ERR (BS)) return STOP_WRAP; } -return SCPE_OK; -} - -/* Write data to disk */ - -t_stat dp_wrsec (UNIT *uptr, int32 sec, int32 flg) -{ -int32 i, lim; -uint32 da = ((sec % DP_TOTSC) * DP_NUMCH) + DP_ADDR; /* char number */ -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; } - 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; - da++; ap++; BS++; /* adv ptrs */ - if (ADDR_ERR (BS)) return STOP_WRAP; } -return SCPE_OK; -} - -/* Find sector */ - -int32 dp_fndsec (UNIT *uptr, int32 sec, int32 dcf) -{ -int32 ctrk = sec % (DP_NUMSF * DP_NUMSC); /* curr trk-sec */ -int32 psec = ((uptr->CYL) * (DP_NUMSF * DP_NUMSC)) + ctrk; -int32 da = psec * DP_NUMCH; /* char number */ -uint8 *ap = ((uint8 *) uptr->filebuf) + da; /* buf ptr */ -int32 i; - -if (dp_zeroad (ap)) return psec; /* addr zero? ok */ -if (dp_cmp_ad (ap, dcf)) return psec; /* addr comp? ok */ -psec = psec - (psec % DP_NUMSC); /* sector 0 */ -for (i = 0; i < DP_NUMSC; i++, psec++) { /* check track */ - da = psec * DP_NUMCH; /* char number */ - ap = ((uint8 *) uptr->filebuf) + da; /* word pointer */ - if (dp_zeroad (ap)) continue; /* no implicit match */ - if (dp_cmp_ad (ap, dcf)) return psec; } /* match? */ -ind[IN_UNA] = ind[IN_DSK] = 1; /* no match */ -return -1; -} - -/* Find next sector - must be sequential, cannot cross cylinder boundary */ - -t_stat dp_nexsec (UNIT *uptr, int32 psec, int32 dcf) -{ -int32 ctrk = psec % (DP_NUMSF * DP_NUMSC); /* curr trk-sec */ -int32 da = psec * DP_NUMCH; /* word number */ -uint8 *ap = ((uint8 *) uptr->filebuf) + da; /* buf ptr */ - -if (ctrk) { /* not trk zero? */ - if (dp_zeroad (ap)) return SCPE_OK; /* addr zero? ok */ - if (dp_cmp_ad (ap, dcf)) return SCPE_OK; } /* addr comp? ok */ -ind[IN_UNA] = ind[IN_DSK] = 1; /* no, error */ -return STOP_INVDAD; -} - -/* Test for zero address */ - -t_bool dp_zeroad (uint8 *ap) -{ -int32 i; - -for (i = 0; i < DP_ADDR; i++, ap++) { /* loop thru addr */ - if (*ap & CHAR) return FALSE; } /* nonzero? lose */ -return TRUE; /* all zeroes */ -} - -/* Compare disk address to memory sector address - always omit word marks */ - -t_bool dp_cmp_ad (uint8 *ap, int32 dcf) -{ -int32 i; -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 TRUE; /* compare ok */ -} - -/* Track operation setup */ - -int32 dp_trkop (int32 drv, int32 sec) -{ -int32 ctrk = (sec / DP_NUMSC) % DP_NUMSF; - -return ((drv * DP_TOTSC) + (dp_unit[drv].CYL * DP_NUMSF * DP_NUMSC) + - (ctrk * DP_NUMSC)); -} - -/* Convert DCF BCD field to binary */ - -int32 dp_cvt_bcd (int32 ad, int32 len) -{ -uint8 c; -int32 r; - -for (r = 0; len > 0; len--) { /* loop thru char */ - c = M[ad] & DIGIT; /* get digit */ - if ((c == 0) || (c > BCD_ZERO)) return -1; /* invalid? */ - r = (r * 10) + bcd_to_bin[c]; /* cvt to bin */ - ad++; } /* next digit */ -return r; -} - -/* Convert binary to DCF BCD field */ - -void dp_cvt_bin (int32 ad, int32 len, int32 val, int32 flg) -{ -int32 r; - -for ( ; len > 0; len--) { /* loop thru char */ - r = val % 10; /* get digit */ - if (flg) M[ad + len - 1] = bin_to_bcd[r]; /* load mode? */ - else M[ad + len - 1] = (M[ad + len - 1] & WM) | bin_to_bcd[r]; - val = val / 10; } -return; -} - -/* Get and validate count */ - -int32 dp_get_cnt (int32 dcf) -{ -int32 cnt = dp_cvt_bcd (dcf + DCF_CNT, DCF_CNT_LEN); /* get new count */ -if (cnt < 0) return -1; /* bad count? */ -if (cnt == 0) return 1000; /* 0 => 1000 */ -return cnt; -} - -/* Fill sector buffer with blanks */ - -void dp_fill (UNIT *uptr, uint32 da, int32 cnt) -{ -while (cnt-- > 0) { /* fill with blanks */ - *(((uint8 *) uptr->filebuf) + da) = BCD_BLANK; - if (da >= uptr->hwmark) uptr->hwmark = da + 1; - da++; } -return; -} - -/* Reset routine */ - -t_stat dp_reset (DEVICE *dptr) -{ -int32 i; - -for (i = 0; i < DP_NUMDR; i++) dp_unit[i].CYL = 0; /* reset cylinder */ -dp_lastf = 0; /* clear state */ -ind[IN_DPW] = ind[IN_LNG] = ind[IN_UNA] = 0; /* clr indicators */ -ind[IN_DSK] = ind[IN_ACC] = ind[IN_DBY] = 0; -sim_cancel (&dp_unit[0]); /* cancel timer */ -return SCPE_OK; -} diff --git a/I1401/i1401_iq.c b/I1401/i1401_iq.c deleted file mode 100644 index 5e8c5691..00000000 --- a/I1401/i1401_iq.c +++ /dev/null @@ -1,155 +0,0 @@ -/* i1401_iq.c: IBM 1407 inquiry terminal - - 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. - - 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 -*/ - -#include "i1401_defs.h" -#include - -extern volatile int32 stop_cpu; -extern uint8 M[]; -extern int32 BS, iochk, ind[64]; -extern char ascii_to_bcd[128], bcd_to_ascii[64]; -extern UNIT cpu_unit; - -int32 inq_char = 033; /* request inq */ -t_stat inq_svc (UNIT *uptr); -t_stat inq_reset (DEVICE *dptr); - -void puts_tty (char *cptr); - -/* INQ data structures - - inq_dev INQ device descriptor - inq_unit INQ unit descriptor - inq_reg INQ register list -*/ - -UNIT inq_unit = { UDATA (&inq_svc, 0, 0), KBD_POLL_WAIT }; - -REG inq_reg[] = { - { ORDATA (INQC, inq_char, 7) }, - { FLDATA (INR, ind[IN_INR], 0) }, - { FLDATA (INC, ind[IN_INC], 0) }, - { DRDATA (TIME, inq_unit.wait, 24), REG_NZ + PV_LEFT }, - { NULL } }; - -DEVICE inq_dev = { - "INQ", &inq_unit, inq_reg, NULL, - 1, 10, 31, 1, 8, 7, - NULL, NULL, &inq_reset, - NULL, NULL, NULL }; - -/* Terminal I/O - - Modifiers have not been checked; legal modifiers are R and W -*/ - -t_stat inq_io (int32 flag, int32 mod) -{ -int32 i, t, wm_seen = 0; - -ind[IN_INC] = 0; /* clear inq clear */ -switch (mod) { /* case on mod */ -case BCD_R: /* input */ -/* if (ind[IN_INR] == 0) return SCPE_OK; /* return if no req */ - 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) || - (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 (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: - return STOP_INVM; } /* invalid mod */ -} - -/* Unit service - polls for WRU or inquiry request */ - -t_stat inq_svc (UNIT *uptr) -{ -int32 temp; - -sim_activate (&inq_unit, inq_unit.wait); /* continue poll */ -if ((temp = sim_poll_kbd ()) < SCPE_KFLAG) return temp; /* no char or error? */ -if ((temp & 0177) == inq_char) ind[IN_INR] = 1; /* set indicator */ -return SCPE_OK; -} - -/* Output multiple characters */ - -void puts_tty (char *cptr) -{ -if (cptr == NULL) return; -while (*cptr != 0) sim_putchar (*cptr++); -return; -} - -/* Reset routine */ - -t_stat inq_reset (DEVICE *dptr) -{ -ind[IN_INR] = ind[IN_INC] = 0; /* clear indicators */ -sim_activate (&inq_unit, inq_unit.wait); /* activate poll */ -return SCPE_OK; -} diff --git a/I1401/i1401_lp.c b/I1401/i1401_lp.c deleted file mode 100644 index 696b6f32..00000000 --- a/I1401/i1401_lp.c +++ /dev/null @@ -1,233 +0,0 @@ -/* i1401_lp.c: IBM 1403 line printer simulator - - 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. - - lpt 1403 line printer - - 25-Apr-03 RMS Revised for extended file support - 30-May-02 RMS Widened POS to 32b - 13-Apr-01 RMS Revised for register arrays -*/ - -#include "i1401_defs.h" - -extern uint8 M[]; -extern char bcd_to_ascii[64]; -extern int32 iochk, ind[64]; - -int32 cct[CCT_LNT] = { 03 }; -int32 cctlnt = 66, cctptr = 0, lines = 0, lflag = 0; - -t_stat lpt_reset (DEVICE *dptr); -t_stat lpt_attach (UNIT *uptr, char *cptr); -t_stat space (int32 lines, int32 lflag); - -char bcd_to_pca[64] = { - ' ', '1', '2', '3', '4', '5', '6', '7', - '8', '9', '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', '&', '.', ')', ' ', ' ', ' ' }; -char bcd_to_pch[64] = { - ' ', '1', '2', '3', '4', '5', '6', '7', - '8', '9', '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', '&', '.', ')', ' ', ' ', ' ' }; -char *pch_table[4] = { - bcd_to_ascii, bcd_to_pca, bcd_to_pch, bcd_to_ascii }; - -#define UNIT_V_PCHAIN (UNIT_V_UF + 0) -#define UNIT_M_PCHAIN 03 -#define M_PCF 00 /* full */ -#define M_PCA 01 /* business */ -#define M_PCH 02 /* Fortran */ -#define UNIT_PCHAIN (UNIT_M_PCHAIN << UNIT_V_PCHAIN) -#define PCF (M_PCF << UNIT_V_PCHAIN) -#define PCA (M_PCA << UNIT_V_PCHAIN) -#define PCH (M_PCH << UNIT_V_PCHAIN) -#define GET_PCHAIN(x) (((x) >> UNIT_V_PCHAIN) & UNIT_M_PCHAIN) -#define CHP(ch,val) ((val) & (1 << (ch))) - -/* LPT data structures - - lpt_dev LPT device descriptor - lpt_unit LPT unit descriptor - lpt_reg LPT register list -*/ - -UNIT lpt_unit = { - UDATA (NULL, UNIT_SEQ+UNIT_ATTABLE, 0) }; - -REG lpt_reg[] = { - { FLDATA (ERR, ind[IN_LPT], 0) }, - { DRDATA (POS, lpt_unit.pos, T_ADDR_W), PV_LEFT }, - { BRDATA (CCT, cct, 8, 32, CCT_LNT) }, - { DRDATA (LINES, lines, 8), PV_LEFT }, - { DRDATA (CCTP, cctptr, 8), PV_LEFT }, - { DRDATA (CCTL, cctlnt, 8), REG_RO + PV_LEFT }, - { NULL } }; - -MTAB lpt_mod[] = { - { UNIT_PCHAIN, PCF, "F chain", "PCF", NULL }, - { UNIT_PCHAIN, PCA, "A chain", "PCA", NULL }, - { UNIT_PCHAIN, PCH, "H chain", "PCH", 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 }; - -/* Print routine - - Modifiers have been checked by the caller - SQUARE = word mark mode - S = suppress automatic newline -*/ - -t_stat write_line (int32 ilnt, int32 mod) -{ -int32 i, t, wm, sup; -char *pch; -static char lbuf[LPT_WIDTH + 1]; /* + null */ - -if ((lpt_unit.flags & UNIT_ATT) == 0) return SCPE_UNATT; /* attached? */ -wm = ((ilnt == 2) || (ilnt == 5)) && (mod == BCD_SQUARE); -sup = ((ilnt == 2) || (ilnt == 5)) && (mod == BCD_S); -ind[IN_LPT] = 0; /* clear error */ -pch = pch_table[GET_PCHAIN (lpt_unit.flags)]; /* get print chain */ -for (i = 0; i < LPT_WIDTH; i++) { /* convert print buf */ - t = M[LPT_BUF + i]; - if (wm) lbuf[i] = (t & WM)? '1': ' '; /* wmarks -> 1 or sp */ - else lbuf[i] = pch[t & CHAR]; } /* normal */ -M[LPT_BUF + 1] = 0; /* trailing null */ -for (i = LPT_WIDTH - 1; (i >= 0) && (lbuf[i] == ' '); i--) lbuf[i] = 0; -fputs (lbuf, lpt_unit.fileref); /* write line */ -if (lines) space (lines, lflag); /* cc action? do it */ -else if (sup == 0) space (1, FALSE); /* default? 1 line */ -else { fputc ('\r', lpt_unit.fileref); /* sup -> overprint */ - lpt_unit.pos = ftell (lpt_unit.fileref); } /* update position */ -lines = lflag = 0; /* clear cc action */ -if (ferror (lpt_unit.fileref)) { /* error? */ - perror ("Line printer I/O error"); - clearerr (lpt_unit.fileref); - if (iochk) return SCPE_IOERR; - ind[IN_LPT] = 1; } -return SCPE_OK; -} - -/* Carriage control routine - - The modifier has not been checked, its format is - <5:4> = 00, skip to channel now - = 01, space lines after - = 10, space lines now - = 11, skip to channel after - <3:0> = number of lines or channel number -*/ - -t_stat carriage_control (int32 mod) -{ -int32 i, action; - -action = (mod & ZONE) >> V_ZONE; /* get mod type */ -mod = mod & DIGIT; /* isolate value */ -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); } - 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; } - return SCPE_OK; -case 2: /* space now */ - if (mod <= 3) return space (mod, FALSE); - return SCPE_OK; -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; } } - return STOP_CCT; } /* runaway channel */ -return SCPE_OK; -} - -/* Space routine - space or skip n lines - - Inputs: - count = number of lines to space or skip - sflag = skip (TRUE) or space (FALSE) -*/ - -t_stat space (int32 count, int32 sflag) -{ -int32 i; - -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); } -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; -return SCPE_OK; -} - -/* Reset routine */ - -t_stat lpt_reset (DEVICE *dptr) -{ -cctptr = 0; /* clear cct ptr */ -lines = lflag = 0; /* no cc action */ -ind[IN_LPT] = 0; -return SCPE_OK; -} - -/* Attach routine */ - -t_stat lpt_attach (UNIT *uptr, char *cptr) -{ -cctptr = 0; /* clear cct ptr */ -lines = 0; /* no cc action */ -ind[IN_LPT] = 0; -return attach_unit (uptr, cptr); -} diff --git a/I1401/i1401_mt.c b/I1401/i1401_mt.c deleted file mode 100644 index d5888b8b..00000000 --- a/I1401/i1401_mt.c +++ /dev/null @@ -1,329 +0,0 @@ -/* i1401_mt.c: IBM 1401 magnetic tape simulator - - 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. - - mt 7-track magtape - - 16-Aug-03 RMS End-of-record on load read works like move read - (verified on real 1401) - Added diagnostic read (space forward) - 25-Apr-03 RMS Revised for extended file support - 28-Mar-03 RMS Added multiformat support - 15-Mar-03 RMS Fixed end-of-record on load read yet again - 28-Feb-03 RMS Modified for magtape library - 31-Oct-02 RMS Added error record handling - 10-Oct-02 RMS Fixed end-of-record on load read writes WM plus GM - 30-Sep-02 RMS Revamped error handling - 28-Aug-02 RMS Added end of medium support - 12-Jun-02 RMS End-of-record on move read preserves old WM under GM - (found by Van Snyder) - 03-Jun-02 RMS Modified for 1311 support - 30-May-02 RMS Widened POS to 32b - 22-Apr-02 RMS Added protection against bad record lengths - 30-Jan-02 RMS New zero footprint tape bootstrap from Van Snyder - 20-Jan-02 RMS Changed write enabled modifier - 29-Nov-01 RMS Added read only unit support - 18-Apr-01 RMS Changed to rewind tape before boot - 07-Dec-00 RMS Widened display width from 6 to 8 bits to see record lnt - CEO Added tape bootstrap - 14-Apr-99 RMS Changed t_addr to unsigned - 04-Oct-98 RMS V2.4 magtape format - - Magnetic tapes are represented as a series of variable 16b records - of the form: - - 32b byte count - byte 0 - byte 1 - : - byte n-2 - byte n-1 - 32b byte count - - If the byte count is odd, the record is padded with an extra byte - of junk. File marks are represented by a byte count of 0. -*/ - -#include "i1401_defs.h" -#include "sim_tape.h" - -#define MT_NUMDR 7 /* #drives */ -#define MT_MAXFR (MAXMEMSIZE * 2) /* max transfer */ - -extern uint8 M[]; /* memory */ -extern int32 ind[64]; -extern int32 BS, iochk; -extern UNIT cpu_unit; -uint8 dbuf[MT_MAXFR]; /* tape buffer */ -t_stat mt_reset (DEVICE *dptr); -t_stat mt_boot (int32 unitno, DEVICE *dptr); -t_stat mt_map_status (t_stat st); -UNIT *get_unit (int32 unit); - -/* MT data structures - - mt_dev MT device descriptor - mt_unit MT unit list - mt_reg MT register list - mt_mod MT modifier list -*/ - -UNIT mt_unit[] = { - { UDATA (NULL, UNIT_DIS, 0) }, /* doesn't exist */ - { UDATA (NULL, UNIT_DISABLE + UNIT_ATTABLE + - UNIT_ROABLE + UNIT_BCD, 0) }, - { UDATA (NULL, UNIT_DISABLE + UNIT_ATTABLE + - UNIT_ROABLE + UNIT_BCD, 0) }, - { UDATA (NULL, UNIT_DISABLE + UNIT_ATTABLE + - UNIT_ROABLE + UNIT_BCD, 0) }, - { UDATA (NULL, UNIT_DISABLE + UNIT_ATTABLE + - UNIT_ROABLE + UNIT_BCD, 0) }, - { UDATA (NULL, UNIT_DISABLE + UNIT_ATTABLE + - UNIT_ROABLE + UNIT_BCD, 0) }, - { UDATA (NULL, UNIT_DISABLE + UNIT_ATTABLE + - UNIT_ROABLE + UNIT_BCD, 0) } }; - -REG mt_reg[] = { - { FLDATA (END, ind[IN_END], 0) }, - { FLDATA (ERR, ind[IN_TAP], 0) }, - { DRDATA (POS1, mt_unit[1].pos, T_ADDR_W), PV_LEFT + REG_RO }, - { DRDATA (POS2, mt_unit[2].pos, T_ADDR_W), PV_LEFT + REG_RO }, - { DRDATA (POS3, mt_unit[3].pos, T_ADDR_W), PV_LEFT + REG_RO }, - { DRDATA (POS4, mt_unit[4].pos, T_ADDR_W), PV_LEFT + REG_RO }, - { DRDATA (POS5, mt_unit[5].pos, T_ADDR_W), PV_LEFT + REG_RO }, - { DRDATA (POS6, mt_unit[6].pos, T_ADDR_W), PV_LEFT + REG_RO }, - { NULL } }; - -MTAB mt_mod[] = { - { MTUF_WLK, 0, "write enabled", "WRITEENABLED", NULL }, - { MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL }, - { MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT", - &sim_tape_set_fmt, &sim_tape_show_fmt, 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, &sim_tape_attach, &sim_tape_detach }; - -/* Function routine - - Inputs: - unit = unit character - mod = modifier character - Outputs: - status = status -*/ - -t_stat mt_func (int32 unit, int32 mod) -{ -t_mtrlnt tbc; -UNIT *uptr; -t_stat st; - -if ((uptr = get_unit (unit)) == NULL) return STOP_INVMTU; /* valid unit? */ -if ((uptr->flags & UNIT_ATT) == 0) return SCPE_UNATT; /* attached? */ -switch (mod) { /* case on modifier */ - -case BCD_A: /* diagnostic read */ - ind[IN_END] = 0; /* clear end of file */ - st = sim_tape_sprecf (uptr, &tbc); /* space fwd */ - break; - -case BCD_B: /* backspace */ - ind[IN_END] = 0; /* clear end of file */ - st = sim_tape_sprecr (uptr, &tbc); /* space rev */ - break; /* end case */ - -case BCD_E: /* erase = nop */ - if (sim_tape_wrp (uptr)) return STOP_MTL; - return SCPE_OK; - -case BCD_M: /* write tapemark */ - st = sim_tape_wrtmk (uptr); /* write tmk */ - break; - -case BCD_R: /* rewind */ - sim_tape_rewind (uptr); /* update position */ - return SCPE_OK; - -case BCD_U: /* unload */ - sim_tape_rewind (uptr); /* update position */ - return detach_unit (uptr); /* detach */ - -default: - return STOP_INVM; } - -return mt_map_status (st); -} - -/* Read and write routines - - Inputs: - unit = unit character - flag = normal, word mark, or binary mode - mod = modifier character - Outputs: - status = status - - Fine point: after a read, the system writes a group mark just - beyond the end of the record. However, first it checks for a - GM + WM; if present, the GM + WM is not changed. Otherwise, - an MCW read sets a GM, preserving the current WM; while an LCA - read sets a GM and clears the WM. -*/ - -t_stat mt_io (int32 unit, int32 flag, int32 mod) -{ -int32 t, wm_seen; -t_mtrlnt i, tbc; -t_stat st; -UNIT *uptr; - -if ((uptr = get_unit (unit)) == NULL) return STOP_INVMTU; /* valid unit? */ -if ((uptr->flags & UNIT_ATT) == 0) return SCPE_UNATT; /* attached? */ - -switch (mod) { -case BCD_R: /* read */ - ind[IN_TAP] = ind[IN_END] = 0; /* clear error */ - wm_seen = 0; /* no word mk seen */ - st = sim_tape_rdrecf (uptr, dbuf, &tbc, MT_MAXFR); /* read rec */ - if (st == MTSE_RECE) ind[IN_TAP] = 1; /* rec in error? */ - else if (st != MTSE_OK) break; /* stop on error */ - 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)) { /* not GM+WM at end? */ -/* if (flag == MD_WM) M[BS] = BCD_GRPMRK; /* LCA: clear WM */ -/* else M[BS] = (M[BS] & WM) | BCD_GRPMRK; } /* MCW: save WM */ - M[BS] = (M[BS] & WM) | BCD_GRPMRK; /* write GM, save WM */ - BS++; /* adv BS */ - if (ADDR_ERR (BS)) { /* check final BS */ - BS = BA | (BS % MAXMEMSIZE); - return STOP_WRAP; } - break; - -case BCD_W: - if (uptr->flags & MTUF_WRP) return STOP_MTL; /* locked? */ - 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; } } - st = sim_tape_wrrecf (uptr, dbuf, tbc); /* write record */ - if (ADDR_ERR (BS)) { /* check final BS */ - BS = BA | (BS % MAXMEMSIZE); - return STOP_WRAP; } - break; -default: - return STOP_INVM; } - -return mt_map_status (st); -} - -/* Get unit pointer from unit number */ - -UNIT *get_unit (int32 unit) -{ -if ((unit <= 0) || (unit >= MT_NUMDR)) return NULL; -return mt_dev.units + unit; -} - -/* Map tape status */ - -t_stat mt_map_status (t_stat st) -{ -switch (st) { -case MTSE_OK: /* no error */ -case MTSE_BOT: /* reverse into BOT */ - break; -case MTSE_FMT: /* illegal fmt */ - return SCPE_IERR; -case MTSE_UNATT: /* not attached */ - return SCPE_UNATT; -case MTSE_INVRL: /* invalid rec lnt */ - return SCPE_MTRLNT; -case MTSE_TMK: /* end of file */ - ind[IN_END] = 1; /* set end mark */ - break; -case MTSE_IOERR: /* IO error */ - ind[IN_TAP] = 1; /* set error */ - if (iochk) return SCPE_IOERR; - break; -case MTSE_RECE: /* record in error */ -case MTSE_EOM: /* end of medium */ - ind[IN_TAP] = 1; /* set error */ - break; -case MTSE_WRP: /* write protect */ - return STOP_MTL; } -return SCPE_OK; -} - -/* Reset routine */ - -t_stat mt_reset (DEVICE *dptr) -{ -int32 i; -UNIT *uptr; - -for (i = 0; i < MT_NUMDR; i++) { /* clear pos flag */ - if (uptr = get_unit (i)) MT_CLR_PNU (uptr); } -ind[IN_END] = ind[IN_TAP] = 0; /* clear indicators */ -return SCPE_OK; -} - -/* Bootstrap routine */ - -t_stat mt_boot (int32 unitno, DEVICE *dptr) -{ -extern int32 saved_IS; - -sim_tape_rewind (&mt_unit[unitno]); /* force rewind */ -BS = 1; /* set BS = 001 */ -mt_io (unitno, MD_WM, BCD_R); /* LDA %U1 001 R */ -saved_IS = 1; -return SCPE_OK; -} diff --git a/I1401/i1401_sys.c b/I1401/i1401_sys.c deleted file mode 100644 index 27e61090..00000000 --- a/I1401/i1401_sys.c +++ /dev/null @@ -1,339 +0,0 @@ -/* i1401_sys.c: IBM 1401 simulator interface - - 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. - - 16-Mar-03 RMS Fixed mnemonic for MCS - 03-Jun-02 RMS Added 1311 support - 18-May-02 RMS Added -D feature from Van Snyder - 26-Jan-02 RMS Fixed H, NOP with no trailing wm (found by Van Snyder) - 17-Sep-01 RMS Removed multiconsole support - 13-Jul-01 RMS Fixed bug in symbolic output (found by Peter Schorn) - 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 -*/ - -#include "i1401_defs.h" -#include - -#define LINE_LNT 80 -extern DEVICE cpu_dev, inq_dev, lpt_dev; -extern DEVICE cdr_dev, cdp_dev, stack_dev; -extern DEVICE dp_dev, mt_dev; -extern UNIT cpu_unit; -extern REG cpu_reg[]; -extern uint8 M[]; -extern char bcd_to_ascii[64], ascii_to_bcd[128]; -extern char *get_glyph (char *cptr, char *gbuf, char term); -extern int32 store_addr_h (int32 addr); -extern int32 store_addr_t (int32 addr); -extern int32 store_addr_u (int32 addr); - -/* SCP data structures and interface routines - - sim_name simulator name string - sim_PC pointer to saved PC register descriptor - sim_emax maximum number of words for examine/deposit - sim_devices array of pointers to simulated devices - sim_stop_messages array of pointers to stop messages - sim_load binary loader -*/ - -char sim_name[] = "IBM 1401"; - -REG *sim_PC = &cpu_reg[0]; - -int32 sim_emax = LINE_LNT; - -DEVICE *sim_devices[] = { - &cpu_dev, - &inq_dev, - &cdr_dev, - &cdp_dev, - &stack_dev, - &lpt_dev, - &mt_dev, - &dp_dev, - NULL }; - -const char *sim_stop_messages[] = { - "Unknown error", - "Unimplemented instruction", - "Non-existent memory", - "Non-existent device", - "No WM at instruction start", - "Invalid A address", - "Invalid B address", - "Invalid instruction length", - "Invalid modifer", - "Invalid branch address", - "Breakpoint", - "HALT instruction", - "Invalid MT unit number", - "Invalid MT record length", - "Write to locked MT unit", - "Skip to unpunched CCT channel", - "Card reader empty", - "Address register wrap", - "MCE data field too short", - "MCE control field too short", - "MCE EPE hanging $", - "I/O check", - "Invalid disk sector address", - "Invalid disk sector count", - "Invalid disk unit", - "Invalid disk function", - "Invalid disk record length", - "Write track while disabled", - "Write check error", - "Disk address miscompare", - "Direct seek cylinder exceeds maximum" - }; - -/* Binary loader -- 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 cct[0:lnt-1], cctlnt contains the - number of entries -*/ - -t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag) -{ -int32 col, rpt, ptr, mask, cctbuf[CCT_LNT]; -t_stat r; -extern int32 cctlnt, cctptr, cct[CCT_LNT]; -char cbuf[CBUFSIZE], gbuf[CBUFSIZE]; - -if ((*cptr != 0) || (flag != 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, 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 */ - for ( ; rpt > 0; rpt--) { /* store vals */ - if (ptr >= CCT_LNT) return SCPE_FMT; - cctbuf[ptr++] = mask; } } -if (ptr == 0) return SCPE_FMT; -cctlnt = ptr; -cctptr = 0; -for (rpt = 0; rpt < cctlnt; rpt++) cct[rpt] = cctbuf[rpt]; -return SCPE_OK; -} - -/* Symbol table */ - -const char *opcode[64] = { - NULL, "R", "W", "WR", "P", "RP", "WP", "WRP", - "RF", "WF", NULL, "MA", "MUL", NULL, NULL, NULL, - NULL, "CS", "S", NULL, "MTF", "BWZ", "BBE", NULL, - "MZ", "MCS", NULL, "SWM", "DIV", NULL, NULL, NULL, - NULL, NULL, "SS", "LCA", "MCW", "NOP", NULL, "MCM", - "SAR", NULL, "ZS", NULL, NULL, NULL, NULL, NULL, - NULL, "A", "B", "C", "MN", "MCE", "CC", NULL, - "SBR", NULL, "ZA", "H", "CWM", NULL, NULL, NULL }; - -/* Print an address from three characters */ - -void fprint_addr (FILE *of, t_value *dig) -{ -int32 addr, xa; -extern int32 hun_table[64], ten_table[64], one_table[64]; - -addr = hun_table[dig[0]] + ten_table[dig[1]] + one_table[dig[2]]; -xa = (addr >> V_INDEX) & M_INDEX; -if (xa) fprintf (of, " %d,%d", addr & ADDRMASK, ((xa - (X1 >> V_INDEX)) / 5) + 1); -else if (addr >= MAXMEMSIZE) fprintf (of, " %d*", addr & ADDRMASK); -else fprintf (of, " %d", addr); -return; -} - -/* Symbolic decode - - Inputs: - *of = output stream - addr = current address - *val = values to decode - *uptr = pointer to unit - sw = switches - Outputs: - return = if >= 0, error code - if < 0, number of extra words retired -*/ - -#define FMTASC(x) ((x) < 040)? "<%03o>": "%c", (x) - -t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, - UNIT *uptr, int32 sw) -{ -int32 op, flags, ilnt, i, t; -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]); - else fprintf (of, FMTASC (t & 0177)); - return SCPE_OK; } -if ((uptr != NULL) && (uptr != &cpu_unit)) return SCPE_ARG; /* CPU? */ -if (sw & SWMASK ('D')) { /* dump? */ - for (i = 0; i < 50; i++) fprintf (of, "%c", bcd_to_ascii[val[i]&CHAR]) ; - fprintf (of, "\n\t"); - for (i = 0; i < 50; i++) fprintf (of, (val[i]&WM)? "1": " ") ; - 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]); } - while ((i < LINE_LNT) && ((val[i] & WM) == 0)); - return -(i - 1); } -if ((sw & SWMASK ('M')) == 0) return SCPE_ARG; - -if ((val[0] & WM) == 0) return STOP_NOWM; /* WM under op? */ -op = val[0]& CHAR; /* isolate op */ -flags = op_table[op]; /* get flags */ -for (ilnt = 1; ilnt < sim_emax; ilnt++) if (val[ilnt] & WM) break; -if ((flags & (NOWM | HNOP)) && (ilnt > 7)) ilnt = 7; /* cs, swm, h, nop? */ -else if ((op == OP_B) && (ilnt > 4) && (val[4] == BCD_BLANK)) ilnt = 4; -else if ((ilnt > 8) && (op != OP_NOP)) ilnt = 8; /* cap length */ -if (((flags & len_table[ilnt]) == 0) && /* valid lnt, */ - ((op != OP_NOP) == 0)) return STOP_INVL; /* nop? */ -fprintf (of, "%s",opcode[op]); /* print opcode */ -if (ilnt > 2) { /* A address? */ - if (((flags & IO) || (op == OP_NOP)) && (val[1] == BCD_PERCNT)) - fprintf (of, " %%%c%c", bcd_to_ascii[val[2]], bcd_to_ascii[val[3]]); - else fprint_addr (of, &val[1]); } -if (ilnt > 5) fprint_addr (of, &val[4]); /* B address? */ -if ((ilnt == 2) || (ilnt == 5) || (ilnt == 8)) /* d character? */ - fprintf (of, " '%c", bcd_to_ascii[val[ilnt - 1]]); -return -(ilnt - 1); /* return # chars */ -} - -/* get_addr - get address + index pair */ - -t_stat get_addr (char *cptr, t_value *val) -{ -int32 addr, index; -t_stat r; -char gbuf[CBUFSIZE]; - -cptr = get_glyph (cptr, gbuf, ','); /* get address */ -addr = get_uint (gbuf, 10, MAXMEMSIZE, &r); -if (r != SCPE_OK) return SCPE_ARG; -if (*cptr != 0) { /* more? */ - cptr = get_glyph (cptr, gbuf, ' '); - index = get_uint (gbuf, 10, 3, &r); - if ((r != SCPE_OK) || (index == 0)) return SCPE_ARG; } -else index = 0; -if (*cptr != 0) return SCPE_ARG; -val[0] = store_addr_h (addr); -val[1] = store_addr_t (addr) | (index << V_ZONE); -val[2] = store_addr_u (addr); -return SCPE_OK; -} - -/* get_io - get I/O address */ - -t_stat get_io (char *cptr, t_value *val) -{ -if ((cptr[0] != '%') || (cptr[3] != 0) || !isalnum (cptr[1]) || - !isalnum (cptr[2])) return SCPE_ARG; -val[0] = BCD_PERCNT; -val[1] = ascii_to_bcd[cptr[1]]; -val[2] = ascii_to_bcd[cptr[2]]; -return SCPE_OK; -} - -/* Symbolic input - - Inputs: - *cptr = pointer to input string - addr = current PC - *uptr = pointer to unit - *val = pointer to output values - sw = switches - Outputs: - status = > 0 error code - <= 0 -number of extra words -*/ - -t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw) -{ -int32 i, op, ilnt, t, cflag, wm_seen; -extern int32 op_table[64], len_table[9]; -char gbuf[CBUFSIZE]; - -cflag = (uptr == NULL) || (uptr == &cpu_unit); -while (isspace (*cptr)) cptr++; /* absorb spaces */ -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; } - if ((i == 0) || wm_seen) return SCPE_ARG; - return -(i-1); } - -if (cflag == 0) return SCPE_ARG; /* CPU only */ -cptr = get_glyph (cptr, gbuf, 0); /* get opcode */ -for (op = 0; op < 64; op++) /* look it up */ - if (opcode[op] && strcmp (gbuf, opcode[op]) == 0) break; -if (op >= 64) return SCPE_ARG; /* successful? */ -val[0] = op | WM; /* store opcode */ -cptr = get_glyph (cptr, gbuf, 0); /* get addr or d */ -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 */ - 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? */ - val[ilnt] = ascii_to_bcd[t]; /* save D char */ - ilnt = ilnt + 1; } -else if (gbuf[0] != 0) return SCPE_ARG; /* not done? */ -if ((op_table[op] & len_table[ilnt]) == 0) return STOP_INVL; -return -(ilnt - 1); -} diff --git a/I1620/i1620_cd.c b/I1620/i1620_cd.c deleted file mode 100644 index 4c3ecb86..00000000 --- a/I1620/i1620_cd.c +++ /dev/null @@ -1,405 +0,0 @@ -/* i1620_cd.c: IBM 1622 card reader/punch - - 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"), - 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. - - cdr 1622 card reader - cdp 1622 card punch - - 25-Apr-03 RMS Revised for extended file support - - Cards are represented as ASCII text streams terminated by newlines. - This allows cards to be created and edited as normal files. -*/ - -#include "i1620_defs.h" - -#define CD_LEN 80 - -extern uint8 M[MAXMEMSIZE]; -extern uint8 ind[NUM_IND]; -extern UNIT cpu_unit; -extern int32 io_stop; - -char cdr_buf[CD_LEN + 2]; -char cdp_buf[CD_LEN + 2]; - -t_stat cdr_reset (DEVICE *dptr); -t_stat cdr_attach (UNIT *uptr, char *cptr); -t_stat cdr_boot (int32 unitno, DEVICE *dptr); -t_stat cdr_read (void); -t_stat cdp_reset (DEVICE *dptr); -t_stat cdp_write (uint32 len); -t_stat cdp_num (uint32 pa, uint32 ndig, t_bool dump); - -/* Card reader data structures - - cdr_dev CDR descriptor - cdr_unit CDR unit descriptor - cdr_reg CDR register list -*/ - -UNIT cdr_unit = { - UDATA (NULL, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0) }; - -REG cdr_reg[] = { - { FLDATA (LAST, ind[IN_LAST], 0) }, - { DRDATA (POS, cdr_unit.pos, T_ADDR_W), PV_LEFT }, - { NULL } }; - -DEVICE cdr_dev = { - "CDR", &cdr_unit, cdr_reg, NULL, - 1, 10, 31, 1, 8, 7, - NULL, NULL, &cdr_reset, - &cdr_boot, &cdr_attach, NULL }; - -/* CDP data structures - - cdp_dev CDP device descriptor - cdp_unit CDP unit descriptor - cdp_reg CDP register list -*/ - -UNIT cdp_unit = { - UDATA (NULL, UNIT_SEQ+UNIT_ATTABLE, 0) }; - -REG cdp_reg[] = { - { DRDATA (POS, cdp_unit.pos, T_ADDR_W), PV_LEFT }, - { NULL } }; - -DEVICE cdp_dev = { - "CDP", &cdp_unit, cdp_reg, NULL, - 1, 10, 31, 1, 8, 7, - NULL, NULL, &cdp_reset, - NULL, NULL, NULL }; - -/* Data tables. The card reader presents unusual problems. - - Unique codes needed for 11-2-8 (uses !) and 12-7-8 (uses ") . - - Can punch both 11 (-) and 11-0 (uses ]). - On input, the nul and nl generated by C are converted to - spaces; tabs and line feeds are also converted to spaces. - -/* Card reader (ASCII) to numeric (one digit) */ - -const char cdr_to_num[128] = { - 0x00, -1, -1, -1, -1, -1, -1, -1, /* 00 */ - -1, 0x00, 0x00, -1, -1, 0x00, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, /* 10 */ - -1, -1, -1, -1, -1, -1, -1, -1, - 0x00, 0x1A, 0x1F, 0x00, 0x1B, 0x0A, 0x0F, 0x0A, /* !"#$%&' */ - 0x0C, 0x0C, 0x1C, 0x00, 0x0B, 0x10, 0x1B, 0x01, /* ()*+,-./ */ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 01234567 */ - 0x08, 0x09, 0x00, 0x1E, 0x1E, 0x0B, 0x0E, 0x1A, /* 89:;<=>? */ - 0x0C, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* @ABCDEFG */ - 0x08, 0x09, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, /* HIJKLMNO */ - 0x17, 0x18, 0x19, 0x02, 0x03, 0x04, 0x05, 0x06, /* PQRSTUVW */ - 0x07, 0x08, 0x09, 0x00, 0x0E, 0x10, 0x0F, 0x1F, /* XYZ[\]^_ */ - -1, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* abcdefg */ - 0x08, 0x09, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, /* hijklmno */ - 0x17, 0x18, 0x19, 0x02, 0x03, 0x04, 0x05, 0x06, /* pqrstuvw */ - 0x07, 0x08, 0x09, -1, -1, -1, -1, -1 }; /* xyz */ - -/* Numeric (flag + digit) to card punch (ASCII) */ - -const char num_to_cdp[32] = { - '0', '1', '2', '3', '4', '5', '6', '7', /* 0 */ - '8', '9', '\'', ',', ' ', '&', ' ', '&', - ']', 'J', 'K', 'L', 'M', 'N', 'O', 'P', /* F + 0 */ - 'Q', 'R', '!', '$', -1, -1, -1, '"' }; - -/* Card reader (ASCII) to alphameric (two digits) - - 11-2-8 (!) reads as 5A - 11-7-8 (_) reads as 5F - 12-2-8 (?) reads inconsistently (here 02) - 12-6-8 (<) reads inconsistently (here 5E) - 12-7-8 (") reads as 5F -*/ - -const char cdr_to_alp[128] = { - 0x00, -1, -1, -1, -1, -1, -1, -1, /* 00 */ - -1, 0x00, 0x00, -1, -1, 0x00, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, /* 10 */ - -1, -1, -1, -1, -1, -1, -1, -1, - 0x00, 0x5A, 0x5F, 0x60, 0x13, 0x0A, 0x0F, 0x0A, /* !"#$%&' */ - 0x24, 0x04, 0x14, 0x10, 0x23, 0x20, 0x03, 0x21, /* ()*+,-./ */ - 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 01234567 */ - 0x78, 0x79, 0x70, 0x5E, 0x5E, 0x33, 0x0E, 0x02, /* 89:;<=>? */ - 0x34, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* @ABCDEFG */ - 0x48, 0x49, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, /* HIJKLMNO */ - 0x57, 0x58, 0x59, 0x62, 0x63, 0x64, 0x65, 0x66, /* PQRSTUVW */ - 0x67, 0x68, 0x69, 0x40, 0x0E, 0x50, 0x0F, 0x5F, /* XYZ[\]^_ */ - -1, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* abcdefg */ - 0x48, 0x49, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, /* hijklmno */ - 0x57, 0x58, 0x59, 0x62, 0x63, 0x64, 0x65, 0x66, /* pqrstuvw */ - 0x67, 0x68, 0x69, -1, -1, -1, -1, -1 }; /* xyz */ - -/* Alphameric (two digits) to card punch (ASCII). Oddities: - - 02 -> 12-2-8 (?), symmetric - 07 -> 12-7-8 ("), reads as 5F - 12 -> 11-2-8 (!), reads as 5A - 15 -> 11,0 (]), reads as 50 - 22 -> 0-2-8 ('), reads as 0A - 32 -> 2-8 (%), reads as 0A - 5B -> 11-3-8 (=), reads as 13 - 6A -> 0-2-8 ('), reads as 0A - 6B -> 0-3-8 (,), reads as 23 - AA -> 0-2-8 ('), reads as 0A - - There is no way to punch 0-5-8 (#), 0-6-8 (\), - 11-5-8 (]), 11-6-8 (;), 11-7-8 (_), - 12-5-8 ([), or 12-6-8 (<) -*/ - -const char alp_to_cdp[256] = { - ' ', -1, '?', '.', ')', -1, -1, '"', /* 00 */ - -1, -1, '\'', -1, -1, -1, -1, '&', - '+', -1, '!', '$', '*', ']', -1, -1, /* 10 */ - -1, -1, -1, -1, -1, -1, -1, -1, - '-', '/', '\'', ',', '(', -1, -1, -1, /* 20 */ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, '%', '=', '@', ':', ' ', -1, /* 30 */ - -1, -1, '\'', -1, -1, -1, -1, '&', - -1, 'A', 'B', 'C', 'D', 'E', 'F', 'G', /* 40 */ - 'H', 'I', -1, -1, -1, -1, -1, -1, - '_', 'J', 'K', 'L', 'M', 'N', 'O', 'P', /* 50 */ - 'Q', 'R', '?', '=', -1, -1, -1, '"', - -1, '/', 'S', 'T', 'U', 'V', 'W', 'X', /* 60 */ - 'Y', 'Z', '\'', ',', -1, -1, -1, -1, - '0', '1', '2', '3', '4', '5', '6', '7', /* 70 */ - '8', '9', -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, /* 80 */ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, /* 90 */ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, /* A0 */ - -1, -1, '\'', -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, /* B0 */ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, /* C0 */ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, /* D0 */ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, /* E0 */ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, /* F0 */ - -1, -1, -1, -1, -1, -1, -1, -1 }; - -/* Card reader IO routine - - - Hard errors stop the operation and halt the system. - - Invalid characters place a blank in memory and set RDCHK. - If IO stop is set, the system halts at the end of the operation. -*/ - -t_stat cdr (uint32 op, uint32 pa, uint32 f0, uint32 f1) -{ -int32 i; -int8 cdc; -t_stat r, inv = SCPE_OK; - -switch (op) { /* case on op */ -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 */ - 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 */ - break; -default: /* invalid function */ - return STOP_INVFNC; } -CRETIOE (io_stop, inv); -} - -/* Fill card reader buffer - all errors are hard errors */ - -t_stat cdr_read (void) -{ -int32 i; - -ind[IN_LAST] = 0; /* clear last card */ -if ((cdr_unit.flags & UNIT_ATT) == 0) { /* attached? */ - ind[IN_RDCHK] = 1; /* no, error */ - return SCPE_UNATT; } - -for (i = 0; i < CD_LEN + 1; i++) cdr_buf[i] = ' '; /* clear buffer */ -fgets (cdr_buf, CD_LEN, cdr_unit.fileref); /* read card */ -if (feof (cdr_unit.fileref)) return STOP_NOCD; /* eof? */ -if (ferror (cdr_unit.fileref)) { /* error? */ - ind[IN_RDCHK] = 1; /* set read check */ - perror ("CDR I/O error"); - clearerr (cdr_unit.fileref); - return SCPE_IOERR; } -cdr_unit.pos = ftell (cdr_unit.fileref); /* update position */ -getc (cdr_unit.fileref); /* see if more */ -if (feof (cdr_unit.fileref)) ind[IN_LAST] = 1; /* eof? set last */ -fseek (cdr_unit.fileref, cdr_unit.pos, SEEK_SET); /* "backspace" */ -return SCPE_OK; -} - -/* Card reader attach */ - -t_stat cdr_attach (UNIT *uptr, char *cptr) -{ -ind[IN_LAST] = 0; /* clear last card */ -return attach_unit (uptr, cptr); -} - -/* Card reader reset */ - -t_stat cdr_reset (DEVICE *dptr) -{ -ind[IN_LAST] = 0; /* clear last card */ -return SCPE_OK; -} - -/* Bootstrap routine */ - -const static uint8 boot_rom[] = { - 3, 6, 1, 9, 9, 0, 1, 0, 0, 5, 0, 0, /* RNCD 19901 */ - 2, 5, 0, 0, 0, 8, 0, 1, 9, 9, 1, 0x10, /* TD 80,-19910 */ - 3, 1, 1, 9, 9, 0, 0x15, 1, 9, 9, 2, 0, /* TR -19905,19920 */ - 2, 5, 1, 9, 9, 1, 0x10, 0, 0, 0, 8, 0, /* TD -19910,80 */ - 4, 9, 1, 9, 9, 1, 0x15, 0, 0, 0, 0, 0 }; /* BR -19915 */ - -#define BOOT_START 0 -#define BOOT_LEN (sizeof (boot_rom) / sizeof (uint8)) - -t_stat cdr_boot (int32 unitno, DEVICE *dptr) -{ -int32 i; -extern int32 saved_PC; - -if ((cpu_unit.flags & IF_IA) == 0) return SCPE_NOFNC; /* must have IA */ -for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i]; -saved_PC = BOOT_START; -return SCPE_OK; -} - -/* Card punch IO routine - - - Hard errors stop the operation and halt the system. - - Invalid characters stop the operation and set WRCHK. - If IO stop is set, the system halts. -*/ - -t_stat cdp (uint32 op, uint32 pa, uint32 f0, uint32 f1) -{ -int32 i; -int8 cdc; -uint8 z, d; - -switch (op) { /* decode op */ -case OP_DN: - return cdp_num (pa, 20000 - (pa % 20000), TRUE); /* dump numeric */ -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 */ - return cdp_write (CD_LEN); /* punch buffer */ -default: /* invalid function */ - return STOP_INVFNC; } -return SCPE_OK; -} - -/* Punch card numeric */ - -t_stat cdp_num (uint32 pa, uint32 ndig, t_bool dump) -{ -int32 i, ncd, len; -uint8 d; -int8 cdc; -t_stat r; - -ncd = ndig / CD_LEN; /* number of cards */ -while (ncd-- >= 0) { /* until done */ - len = (ncd >= 0)? CD_LEN: (ndig % CD_LEN); /* card length */ - if (len == 0) break; - for (i = 0; i < len; i++) { /* one card */ - d = M[pa] & (FLAG | DIGIT); /* get char */ - if (dump && (d == FLAG)) cdc = '-'; /* dump? F+0 is diff */ - else cdc = num_to_cdp[d]; /* translate */ - if (cdc < 0) { /* bad char? */ - ind[IN_WRCHK] = 1; /* set write check */ - CRETIOE (io_stop, STOP_INVCHR); } /* stop */ - cdp_buf[i] = cdc; /* store in buf */ - PP (pa); } /* incr mem addr */ - r = cdp_write (len); /* punch card */ - if (r != SCPE_OK) return r; } /* error? */ -return SCPE_OK; -} - -/* Write punch card buffer - all errors are hard errors */ - -t_stat cdp_write (uint32 len) -{ -if ((cdp_unit.flags & UNIT_ATT) == 0) { /* attached? */ - ind[IN_WRCHK] = 1; /* no, error */ - return SCPE_UNATT; } - -while ((len > 0) && (cdp_buf[len - 1] == ' ')) --len; /* trim spaces */ -cdp_buf[len] = '\n'; /* newline, null */ -cdp_buf[len + 1] = 0; - -if (fputs (cdp_buf, cdp_unit.fileref) == EOF) { /* write card */ - ind[IN_WRCHK] = 1; /* error? */ - perror ("CDP I/O error"); - clearerr (cdp_unit.fileref); - return SCPE_IOERR; } -cdp_unit.pos = ftell (cdp_unit.fileref); /* count char */ -return SCPE_OK; -} - -/* Reset card punch */ - -t_stat cdp_reset (DEVICE *dptr) -{ -return SCPE_OK; -} diff --git a/I1620/i1620_cpu.c b/I1620/i1620_cpu.c deleted file mode 100644 index f6cfa8ec..00000000 --- a/I1620/i1620_cpu.c +++ /dev/null @@ -1,1884 +0,0 @@ -/* i1620_cpu.c: IBM 1620 CPU simulator - - 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"), - 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 CPU module incorporates code and comments from the 1620 simulator by - Geoff Kuenning, with his permission. - - 21-Aug-03 RMS Fixed bug in immediate index add (found by Michael Short) - 25-Apr-03 RMS Changed t_addr to uint32 throughout - 18-Oct-02 RMS Fixed bugs in invalid result testing (found by Hans Pufal) - - The simulated register state for the IBM 1620 is: - - 1620 sim comment - - IR1 [PC] program counter - IR2 instruction register 2 (subroutine return address) - OR1 [QAR] Q address - OR2 [PAR] P address - PR1 manual save address - ind[0:99] indicators - - Additional internal registers OR3, PR2, and PR3 are not simulated. - - The IBM 1620 is a fixed instruction length, variable data length, decimal - data system. Memory consists of 20000 - 60000 BCD digits, each containing - four bits of data and a flag. There are no general registers; all - instructions are memory to memory. - - The 1620 uses a fixed, 12 digit instruction format: - - oo ppppp qqqqq - - where - - oo = opcode - ppppp = P (usually destination) address - qqqqq = Q (usually source) address - - Immediate instructions use the qqqqq field as the second operand. - - The 1620 Model 1 uses table lookups for add and multiply; for that reason, - it was nicknamed CADET (Can't Add, Doesn't Even Try). The Model 2 does - adds in hardware and uses the add table memory for index registers. -*/ - -/* This routine is the instruction decode routine for the IBM 1620. - 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 - illegal addresses or instruction formats - I/O error in I/O simulator - - 2. Interrupts. The 1620 has no interrupt structure. - - 3. Non-existent memory. On the 1620, all memory references - are modulo the memory size. - - 4. Adding I/O devices. These modules must be modified: - - i1620_cpu.c add iodisp table entry - i1620_sys.c add sim_devices table entry -*/ - -#include "i1620_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] = saved_PC - -uint8 M[MAXMEMSIZE] = { 0 }; /* main memory */ -uint32 saved_PC = 0; /* saved PC */ -uint32 IR2 = 1; /* inst reg 2 */ -uint32 PAR = 0; /* P address */ -uint32 QAR = 0; /* Q address */ -uint32 PR1 = 1; /* proc reg 1 */ -uint32 iae = 1; /* ind addr enb */ -uint32 idxe = 0; /* index enable */ -uint32 idxb = 0; /* index band */ -uint32 io_stop = 1; /* I/O stop */ -uint32 ar_stop = 1; /* arith stop */ -int32 ind_max = 16; /* iadr nest limit */ -uint16 pcq[PCQ_SIZE] = { 0 }; /* PC queue */ -int32 pcq_p = 0; /* PC queue ptr */ -REG *pcq_r = NULL; /* PC queue reg ptr */ -uint8 ind[NUM_IND] = { 0 }; /* indicators */ - -extern int32 sim_int_char; -extern int32 sim_interval; -extern int32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */ -extern FILE *sim_log; - -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_opt1 (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat cpu_set_opt2 (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_size (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat cpu_set_save (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat cpu_set_table (UNIT *uptr, int32 val, char *cptr, void *desc); - -int32 get_2d (uint32 ad); -t_stat get_addr (uint32 alast, int32 lnt, t_bool indexok, uint32 *addr); -t_stat cvt_addr (uint32 alast, int32 lnt, t_bool signok, int32 *val); -t_stat get_idx (uint32 aidx); -t_stat xmt_field (uint32 d, uint32 s, uint32 skp); -t_stat xmt_record (uint32 d, uint32 s, t_bool cpy); -t_stat xmt_index (uint32 d, uint32 s); -t_stat xmt_divd (uint32 d, uint32 s); -t_stat xmt_tns (uint32 d, uint32 s); -t_stat xmt_tnf (uint32 d, uint32 s); -t_stat add_field (uint32 d, uint32 s, t_bool sub, t_bool sto, uint32 skp, int32 *sta); -uint32 add_one_digit (uint32 dst, uint32 src, uint32 *cry); -t_stat mul_field (uint32 mpc, uint32 mpy); -t_stat mul_one_digit (uint32 mpyd, uint32 mpcp, uint32 prop, uint32 last); -t_stat div_field (uint32 dvd, uint32 dvr, int32 *ez); -t_stat div_one_digit (uint32 dvd, uint32 dvr, uint32 max, uint32 *quod, uint32 *quop); -t_stat oct_to_dec (uint32 tbl, uint32 s); -t_stat dec_to_oct (uint32 d, uint32 tbl, int32 *ez); -t_stat or_field (uint32 d, uint32 s); -t_stat and_field (uint32 d, uint32 s); -t_stat xor_field (uint32 d, uint32 s); -t_stat com_field (uint32 d, uint32 s); -void upd_ind (void); - -extern tty (uint32 op, uint32 pa, uint32 f0, uint32 f1); -extern ptp (uint32 op, uint32 pa, uint32 f0, uint32 f1); -extern ptr (uint32 op, uint32 pa, uint32 f0, uint32 f1); -extern cdp (uint32 op, uint32 pa, uint32 f0, uint32 f1); -extern cdr (uint32 op, uint32 pa, uint32 f0, uint32 f1); -extern dp (uint32 op, uint32 pa, uint32 f0, uint32 f1); -extern lpt (uint32 op, uint32 pa, uint32 f0, uint32 f1); -extern btp (uint32 op, uint32 pa, uint32 f0, uint32 f1); -extern btr (uint32 op, uint32 pa, uint32 f0, uint32 f1); - -extern t_stat fp_add (uint32 d, uint32 s, t_bool sub); -extern t_stat fp_mul (uint32 d, uint32 s); -extern t_stat fp_div (uint32 d, uint32 s); -extern t_stat fp_fsl (uint32 d, uint32 s); -extern t_stat fp_fsr (uint32 d, uint32 s); - -/* CPU data structures - - cpu_dev CPU device descriptor - cpu_unit CPU unit descriptor - cpu_reg CPU register list - cpu_mod CPU modifier list -*/ - -UNIT cpu_unit = { UDATA (NULL, UNIT_FIX+UNIT_BCD+MI_STD, MAXMEMSIZE) }; - -REG cpu_reg[] = { - { DRDATA (PC, saved_PC, 16), PV_LEFT }, - { DRDATA (IR2, IR2, 16), PV_LEFT }, - { DRDATA (PR1, PR1, 16), PV_LEFT }, - { DRDATA (PAR, PAR, 16), PV_LEFT + REG_RO }, - { DRDATA (QAR, QAR, 16), PV_LEFT + REG_RO }, - { FLDATA (SW1, ind[IN_SW1], 0) }, - { FLDATA (SW2, ind[IN_SW2], 0) }, - { FLDATA (SW3, ind[IN_SW3], 0) }, - { FLDATA (SW4, ind[IN_SW4], 0) }, - { FLDATA (HP, ind[IN_HP], 0) }, - { FLDATA (EZ, ind[IN_EZ], 0) }, - { FLDATA (OVF, ind[IN_OVF], 0) }, - { FLDATA (EXPCHK, ind[IN_EXPCHK], 0) }, - { FLDATA (RDCHK, ind[IN_RDCHK], 0) }, - { FLDATA (WRCHK, ind[IN_WRCHK], 0) }, - { FLDATA (ARSTOP, ar_stop, 0) }, - { FLDATA (IOSTOP, io_stop, 0) }, - { BRDATA (IND, ind, 10, 1, NUM_IND) }, - { FLDATA (IAE, iae, 0) }, - { FLDATA (IDXE, idxe, 0) }, - { FLDATA (IDXB, idxb, 0) }, - { DRDATA (INDMAX, ind_max, 16), REG_NZ + PV_LEFT }, - { BRDATA (PCQ, pcq, 10, 14, PCQ_SIZE), REG_RO+REG_CIRC }, - { ORDATA (PCQP, pcq_p, 6), REG_HRO }, - { ORDATA (WRU, sim_int_char, 8) }, - { NULL } }; - -MTAB cpu_mod[] = { - { IF_IA, IF_IA, "IA", "IA", &cpu_set_opt1 }, - { IF_IA, 0, "no IA", "NOIA", &cpu_set_opt1 }, - { IF_EDT, IF_EDT, "EDT", "EDT", &cpu_set_opt1 }, - { IF_EDT, 0, "no EDT", "NOEDT", &cpu_set_opt1 }, - { IF_DIV, IF_DIV, "DIV", "DIV", &cpu_set_opt1 }, - { IF_DIV, 0, "no DIV", "NODIV", &cpu_set_opt1 }, - { IF_FP, IF_FP, "FP", "FP", NULL }, - { IF_FP, 0, "no FP", "NOFP", NULL }, - { IF_BIN, IF_BIN, "BIN", "BIN", &cpu_set_opt2 }, - { IF_BIN, 0, "no BIN", "NOBIN", &cpu_set_opt2 }, - { IF_IDX, IF_IDX, "IDX", "IDX", &cpu_set_opt2 }, - { IF_IDX, 0, "no IDX", "NOIDX", &cpu_set_opt2 }, - { IF_MII, IF_MII, "Model 2", "MOD2", &cpu_set_model }, - { IF_MII, 0, "Model 1", "MOD1", &cpu_set_model }, - { UNIT_MSIZE, 20000, NULL, "20K", &cpu_set_size }, - { UNIT_MSIZE, 40000, NULL, "40K", &cpu_set_size }, - { UNIT_MSIZE, 60000, NULL, "60K", &cpu_set_size }, - { UNIT_MSIZE, 0, NULL, "SAVE", &cpu_set_save }, - { UNIT_MSIZE, 0, NULL, "TABLE", &cpu_set_table }, - { 0 } }; - -DEVICE cpu_dev = { - "CPU", &cpu_unit, cpu_reg, cpu_mod, - 1, 10, 18, 1, 16, 5, - &cpu_ex, &cpu_dep, &cpu_reset, - NULL, NULL, NULL }; - -/* Instruction table */ - -const int32 op_table[100] = { - 0, /* 0 */ - IF_FP + IF_VPA + IF_VQA, /* FADD */ - IF_FP + IF_VPA + IF_VQA, /* FSUB */ - IF_FP + IF_VPA + IF_VQA, /* FMUL */ - 0, - IF_FP + IF_VPA + IF_VQA, /* FSL */ - IF_FP + IF_MII + IF_VPA + IF_VQA, /* TFL */ - IF_FP + IF_MII + IF_VPA + IF_VQA, /* BTFL */ - IF_FP + IF_VPA + IF_VQA, /* FSR */ - IF_FP + IF_VPA + IF_VQA, /* FDV */ - IF_MII + IF_VPA + IF_IMM, /* 10: BTAM */ - IF_VPA + IF_IMM, /* AM */ - IF_VPA + IF_IMM, /* SM */ - IF_VPA + IF_IMM, /* MM */ - IF_VPA + IF_IMM, /* CM */ - IF_VPA + IF_IMM, /* TDM */ - IF_VPA + IF_IMM, /* TFM */ - IF_VPA + IF_IMM, /* BTM */ - IF_DIV + IF_VPA + IF_IMM, /* LDM */ - IF_DIV + IF_VPA + IF_IMM, /* DM */ - IF_MII + IF_VPA + IF_VQA, /* 20: BTA */ - IF_VPA + IF_VQA, /* A */ - IF_VPA + IF_VQA, /* S */ - IF_VPA + IF_VQA, /* M */ - IF_VPA + IF_VQA, /* C */ - IF_VPA + IF_VQA, /* TD */ - IF_VPA + IF_VQA, /* TF */ - IF_VPA + IF_VQA, /* BT */ - IF_DIV + IF_VPA + IF_VQA, /* LD */ - IF_DIV + IF_VPA + IF_VQA, /* D */ - IF_MII + IF_VPA + IF_VQA, /* 30: TRNM */ - IF_VPA + IF_VQA, /* TR */ - IF_VPA, /* SF */ - IF_VPA, /* CF */ - IF_VPA, /* K */ - IF_VPA, /* DN */ - IF_VPA, /* RN */ - IF_VPA, /* RA */ - IF_VPA, /* WN */ - IF_VPA, /* WA */ - 0, /* 40 */ - 0, /* NOP */ - 0, /* BB */ - IF_VPA + IF_VQA, /* BD */ - IF_VPA + IF_VQA, /* BNF */ - IF_VPA + IF_VQA, /* BNR */ - IF_VPA, /* BI */ - IF_VPA, /* BNI */ - 0, /* H */ - IF_VPA, /* B */ - 0, /* 50 */ - 0, - 0, - 0, - 0, - IF_VPA + IF_VQA, /* BNG - disk sys */ - 0, - 0, - 0, - 0, - IF_MII + IF_VPA, /* 60: BS */ - IF_IDX + IF_VPA + IF_NQX, /* BX */ - IF_IDX + IF_VPA + IF_IMM, /* BXM */ - IF_IDX + IF_VPA + IF_NQX, /* BCX */ - IF_IDX + IF_VPA + IF_IMM, /* BCXM */ - IF_IDX + IF_VPA + IF_NQX, /* BLX */ - IF_IDX + IF_VPA + IF_IMM, /* BLXM */ - IF_IDX + IF_VPA + IF_NQX, /* BSX */ - 0, - 0, - IF_IDX + IF_VPA + IF_VQA, /* 70: MA */ - IF_EDT + IF_VPA + IF_VQA, /* MF */ - IF_EDT + IF_VPA + IF_VQA, /* MF */ - IF_EDT + IF_VPA + IF_VQA, /* TNF */ - 0, - 0, - 0, - 0, - 0, - 0, - 0, /* 80 */ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - IF_BIN + IF_VPA + IF_4QA, /* 90: BBT */ - IF_BIN + IF_VPA + IF_4QA, /* BMK */ - IF_BIN + IF_VPA + IF_VQA, /* ORF */ - IF_BIN + IF_VPA + IF_VQA, /* ANDF */ - IF_BIN + IF_VPA + IF_VQA, /* CPLF */ - IF_BIN + IF_VPA + IF_VQA, /* EORF */ - IF_BIN + IF_VPA + IF_VQA, /* OTD */ - IF_BIN + IF_VPA + IF_VQA, /* DTO */ - 0, - 0 - }; - -/* IO dispatch table */ - -t_stat (*iodisp[NUM_IO])(uint32 op, uint32 pa, uint32 f0, uint32 f1) = { - NULL, &tty, &ptp, &ptr, &cdp, /* 00 - 09 */ - &cdr, NULL, &dp, NULL, &lpt, - NULL, NULL, NULL, NULL, NULL, /* 10 - 19 */ - NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, /* 20 - 29 */ - NULL, NULL, NULL, NULL, NULL, - NULL, NULL, &btp, &btr, NULL, /* 30 - 39 */ - NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, /* 40 - 49 */ - NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, /* 50 - 59 */ - NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, /* 60 - 69 */ - NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, /* 70 - 79 */ - NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, /* 80 - 89 */ - NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, /* 90 - 99 */ - NULL, NULL, NULL, NULL, NULL }; - -/* Indicator table: -1 = illegal, +1 = resets when tested */ - -const int32 ind_table[NUM_IND] = { - -1, 0, 0, 0, 0, -1, 1, 1, -1, 1, /* 00 - 09 */ - -1, 0, 0, 0, 1, 1, 1, 1, -1, 0, /* 10 - 19 */ - -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, /* 20 - 29 */ - 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, /* 30 - 39 */ - -1, -1, 1, -1, -1, -1, -1, -1, -1, -1, /* 40 - 49 */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 50 - 59 */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 60 - 69 */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 70 - 79 */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 80 - 89 */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }; /* 90 - 99 */ - -/* Add table for 1620 Model 1 */ - -const uint8 std_add_table[ADD_TABLE_LEN] = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, - 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, - 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, - 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, - 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, - 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, - 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, - 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18 }; - - -/* Add table for 1620 Model 2 ("hardware add") */ - -const uint8 sum_table[20] = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19 }; - -/* Multiply table */ - -const uint8 std_mul_table[MUL_TABLE_LEN] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1, 0, 2, 0, 3, 0, 4, 0, - 0, 0, 2, 0, 4, 0, 6, 0, 8, 0, - 0, 0, 3, 0, 6, 0, 9, 0, 2, 1, - 0, 0, 4, 0, 8, 0, 2, 1, 6, 1, - 0, 0, 5, 0, 0, 1, 5, 1, 0, 2, - 0, 0, 6, 0, 2, 1, 8, 1, 4, 2, - 0, 0, 7, 0, 4, 1, 1, 2, 8, 2, - 0, 0, 8, 0, 6, 1, 4, 2, 2, 3, - 0, 0, 9, 0, 8, 1, 7, 2, 6, 3, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 5, 0, 6, 0, 7, 0, 8, 0, 9, 0, - 0, 1, 2, 1, 4, 1, 6, 1, 8, 1, - 5, 1, 8, 1, 1, 2, 4, 2, 7, 2, - 0, 2, 4, 2, 8, 2, 2, 3, 6, 3, - 5, 2, 0, 3, 5, 3, 0, 4, 5, 4, - 0, 3, 6, 3, 2, 4, 8, 4, 4, 5, - 5, 3, 2, 4, 9, 4, 6, 5, 3, 6, - 0, 4, 8, 4, 6, 5, 4, 6, 2, 7, - 5, 4, 4, 5, 3, 6, 2, 7, 1, 8 }; - -#define BRANCH(x) PCQ_ENTRY; PC = (x) -#define GET_IDXADDR(x) ((idxb? IDX_B: IDX_A) + ((x) * ADDR_LEN) + (ADDR_LEN - 1)) - -t_stat sim_instr (void) -{ -uint32 PC, pla, qla, f0, f1; -int32 i, t, idx, flags, sta, dev, op; -t_stat reason; - -/* Restore saved state */ - -PC = saved_PC; -if ((cpu_unit.flags & IF_IA) == 0) iae = 0; -if ((cpu_unit.flags & IF_IDX) == 0) idxe = idxb = 0; -upd_ind (); /* update indicators */ -reason = 0; - -/* Main instruction fetch/decode loop */ - -while (reason == 0) { /* loop until halted */ -saved_PC = PC; /* commit prev instr */ -if (sim_interval <= 0) { /* check clock queue */ - if (reason = sim_process_event ()) break; } - -if (sim_brk_summ && sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */ - reason = STOP_IBKPT; /* stop simulation */ - break; } - -sim_interval = sim_interval - 1; - -/* Instruction fetch and address decode */ - -if (PC & 1) { /* PC odd? */ - reason = STOP_INVIAD; /* stop */ - break; } - -op = get_2d (PC); /* get opcode */ -if (op < 0) { /* invalid? */ - reason = STOP_INVINS; - break; } -flags = op_table[op]; /* get op, flags */ -if ((flags & ALLOPT) && /* need option? */ - !(flags & ALLOPT & cpu_unit.flags)) { /* any set? */ - reason = STOP_INVINS; /* no, error */ - break; } - -pla = ADDR_A (PC, I_PL); /* P last addr */ -qla = ADDR_A (PC, I_QL); /* Q last addr */ -if (flags & IF_VPA) { /* need P? */ - reason = get_addr (pla, 5, TRUE, &PAR); /* get P addr */ - if (reason != SCPE_OK) break; } /* stop if error */ -if (flags & (IF_VQA | IF_4QA | IF_NQX)) { /* need Q? */ - reason = get_addr (qla, /* get Q addr */ - ((flags & IF_4QA)? 4: 5), /* 4 or 5 digits */ - ((flags & IF_NQX)? FALSE: TRUE), /* not or indexed */ - &QAR); - if (reason != SCPE_OK) { /* stop if invalid */ - reason = reason + (STOP_INVQDG - STOP_INVPDG); - break; } } -else if (flags & IF_IMM) QAR = qla; /* immediate? */ -PC = PC + INST_LEN; /* advance PC */ -switch (op) { /* case on op */ - -/* Transmit digit - P,Q are valid */ - -case OP_TD: -case OP_TDM: - M[PAR] = M[QAR] & (FLAG | DIGIT); /* move dig, flag */ - break; - -/* Transmit field - P,Q are valid */ - -case OP_TF: -case OP_TFM: - reason = xmt_field (PAR, QAR, 1); /* xmit field */ - break; - -/* Transmit record - P,Q are valid */ - -case OP_TR: - reason = xmt_record (PAR, QAR, TRUE); /* xmit record */ - break; - -/* Transmit record no record mark - P,Q are valid */ - -case OP_TRNM: - reason = xmt_record (PAR, QAR, FALSE); /* xmit record but */ - break; /* not rec mark */ - -/* Set flag - P is valid */ - -case OP_SF: - M[PAR] = M[PAR] | FLAG; /* set flag on P */ - break; - -/* Clear flag - P is valid */ - -case OP_CF: - M[PAR] = M[PAR] & ~FLAG; /* clear flag on P */ - break; - -/* Branch - P is valid */ - -case OP_B: - BRANCH (PAR); /* branch to P */ - break; - -/* Branch and transmit - P,Q are valid */ - -case OP_BT: -case OP_BTM: - reason = xmt_field (ADDR_S (PAR, 1), QAR, 1); /* xmit field to P-1 */ - IR2 = PC; /* save PC */ - BRANCH (PAR); /* branch to P */ - break; - -/* Branch and transmit floating - P,Q are valid */ - -case OP_BTFL: - reason = xmt_field (ADDR_S (PAR, 1), QAR, 3); /* skip 3 flags */ - IR2 = PC; /* save PC */ - BRANCH (PAR); /* branch to P */ - break; - -/* Branch and transmit address - P,Q are valid */ - -case OP_BTA: -case OP_BTAM: - reason = xmt_field (ADDR_S (PAR, 1), QAR, 4); /* skip 4 flags */ - IR2 = PC; /* save PC */ - BRANCH (PAR); /* branch to P */ - break; - -/* Branch back */ - -case OP_BB: - if (PR1 != 1) { /* PR1 valid? */ - BRANCH (PR1); /* return to PR1 */ - PR1 = 1; } /* invalidate */ - else if (IR2 != 1) { /* IR2 valid? */ - BRANCH (IR2); /* return to IR2 */ - IR2 = 1; } /* invalidate */ - else reason = STOP_INVRTN; /* MAR check */ - break; - -/* Branch on digit (zero) - P,Q are valid */ - -case OP_BD: - if ((M[QAR] & DIGIT) == 0) { /* digit == 0? */ - BRANCH (PAR); } /* branch */ - break; - -/* Branch no flag - P,Q are valid */ - -case OP_BNF: - if ((M[QAR] & FLAG) == 0) { /* flag == 0? */ - BRANCH (PAR); } /* branch */ - break; - -/* Branch no record mark (8-2 not set) - P,Q are valid */ - -case OP_BNR: - if ((M[QAR] & REC_MARK) != REC_MARK) { /* not rec mark? */ - BRANCH (PAR); } /* branch */ - break; - -/* Branch no group mark - P,Q are valid */ - -case OP_BNG: - if ((M[QAR] & DIGIT) != GRP_MARK) { /* not grp mark? */ - BRANCH (PAR); } /* branch */ - break; - -/* Branch (no) indicator - P is valid */ - -case OP_BI: -case OP_BNI: - upd_ind (); /* update indicators */ - t = get_2d (ADDR_A (saved_PC, I_BR)); /* get ind number */ - if ((t < 0) || (ind_table[t] < 0)) { /* not valid? */ - reason = STOP_INVIND; /* stop */ - break; } - if ((ind[t] != 0) ^ (op == OP_BNI)) { /* ind value correct? */ - BRANCH (PAR); } /* branch */ - if (ind_table[t] > 0) ind[t] = 0; /* reset if needed */ - break; - -/* Add/subtract/compare - P,Q are valid */ - -case OP_A: -case OP_AM: - reason = add_field (PAR, QAR, FALSE, TRUE, 0, &sta); /* add, store */ - if (sta == ADD_CARRY) ind[IN_OVF] = 1; /* cout => ovflo */ - if (ar_stop && ind[IN_OVF]) reason = STOP_OVERFL; - break; - -case OP_S: -case OP_SM: - reason = add_field (PAR, QAR, TRUE, TRUE, 0, &sta); /* sub, store */ - if (sta == ADD_CARRY) ind[IN_OVF] = 1; /* cout => ovflo */ - if (ar_stop && ind[IN_OVF]) reason = STOP_OVERFL; - break; - -case OP_C: -case OP_CM: - reason = add_field (PAR, QAR, TRUE, FALSE, 0, &sta); /* sub, nostore */ - if (sta == ADD_CARRY) ind[IN_OVF] = 1; /* cout => ovflo */ - if (ar_stop && ind[IN_OVF]) reason = STOP_OVERFL; - break; - -/* Multiply - P,Q are valid */ - -case OP_M: -case OP_MM: - reason = mul_field (PAR, QAR); /* multiply */ - break; - -/* IO instructions - P is valid */ - -case OP_RA: -case OP_WA: - if ((PAR & 1) == 0) { /* P even? */ - reason = STOP_INVEAD; /* stop */ - break; } -case OP_K: -case OP_DN: -case OP_RN: -case OP_WN: - dev = get_2d (ADDR_A (saved_PC, I_IO)); /* get IO dev */ - f0 = M[ADDR_A (saved_PC, I_CTL)] & DIGIT; /* get function */ - f1 = M[ADDR_A (saved_PC, I_CTL + 1)] & DIGIT; - if ((dev < 0) || (iodisp[dev] == NULL)) /* undefined dev? */ - reason = STOP_INVIO; /* stop */ - else reason = iodisp[dev] (op, PAR, f0, f1); /* call device */ - break; - -/* Divide special feature instructions */ - -case OP_LD: -case OP_LDM: - for (i = 0; i < PROD_AREA_LEN; i++) /* clear prod area */ - M[PROD_AREA + i] = 0; - t = M[QAR] & FLAG; /* save Q sign */ - reason = xmt_divd (PAR, QAR); /* xmit dividend */ - M[PROD_AREA + PROD_AREA_LEN - 1] |= t; /* set sign */ - break; - -/* Divide - P,Q are valid */ - -case OP_D: -case OP_DM: - reason = div_field (PAR, QAR, &t); /* divide */ - ind[IN_EZ] = t; /* set indicator */ - if ((reason == STOP_OVERFL) && !ar_stop) /* ovflo stop? */ - reason = SCPE_OK; /* no */ - break; - -/* Edit special feature instructions */ - -/* Move flag - P,Q are valid */ - -case OP_MF: - M[PAR] = (M[PAR] & ~FLAG) | (M[QAR] & FLAG); /* copy Q flag */ - M[QAR] = M[QAR] & ~FLAG; /* clr Q flag */ - break; - -/* Transmit numeric strip - P,Q are valid, P is source */ - -case OP_TNS: - if ((PAR & 1) == 0) { /* P must be odd */ - reason = STOP_INVEAD; - break; } - reason = xmt_tns (QAR, PAR); /* xmit and strip */ - break; - -/* Transmit numeric fill - P,Q are valid */ - -case OP_TNF: - if ((PAR & 1) == 0) { /* P must be odd */ - reason = STOP_INVEAD; - break; } - reason = xmt_tnf (PAR, QAR); /* xmit and strip */ - break; - -/* Index special feature instructions */ - -/* Move address - P,Q are valid */ - -case OP_MA: - for (i = 0; i < ADDR_LEN; i++) { /* move 5 digits */ - M[PAR] = (M[PAR] & FLAG) | (M[QAR] & DIGIT); - MM (PAR); MM (QAR); } - break; - -/* Branch load index - P,Q are valid, Q not indexed */ - -case OP_BLX: -case OP_BLXM: - idx = get_idx (ADDR_A (saved_PC, I_QL - 1)); /* get index */ - if (idx < 0) { /* disabled? */ - reason = STOP_INVIDX; /* stop */ - break; } - xmt_index (GET_IDXADDR (idx), QAR); /* copy Q to idx */ - BRANCH (PAR); /* branch to P */ - break; - -/* Branch store index - P,Q are valid, Q not indexed */ - -case OP_BSX: - idx = get_idx (ADDR_A (saved_PC, I_QL - 1)); /* get index */ - if (idx < 0) { /* disabled? */ - reason = STOP_INVIDX; /* stop */ - break; } - xmt_index (QAR, GET_IDXADDR (idx)); /* copy idx to Q */ - BRANCH (PAR); /* branch to P */ - break; - -/* Branch and modify index - P,Q are valid, Q not indexed */ - -case OP_BX: - idx = get_idx (ADDR_A (saved_PC, I_QL - 1)); /* get index */ - if (idx < 0) { /* disabled? */ - reason = STOP_INVIDX; /* stop */ - break; } - reason = add_field (GET_IDXADDR (idx), QAR, FALSE, TRUE, 0, &sta); - if (ar_stop && ind[IN_OVF]) reason = STOP_OVERFL; - BRANCH (PAR); /* branch to P */ - break; - -case OP_BXM: - idx = get_idx (ADDR_A (saved_PC, I_QL - 1)); /* get index */ - if (idx < 0) { /* disabled? */ - reason = STOP_INVIDX; /* stop */ - break; } - reason = add_field (GET_IDXADDR (idx), QAR, FALSE, TRUE, 3, &sta); - if (ar_stop && ind[IN_OVF]) reason = STOP_OVERFL; - BRANCH (PAR); /* branch to P */ - break; - -/* Branch conditionally and modify index - P,Q are valid, Q not indexed */ - -case OP_BCX: - idx = get_idx (ADDR_A (saved_PC, I_QL - 1)); /* get index */ - if (idx < 0) { /* disabled? */ - reason = STOP_INVIDX; /* stop */ - break; } - reason = add_field (GET_IDXADDR (idx), QAR, FALSE, TRUE, 0, &sta); - if (ar_stop && ind[IN_OVF]) reason = STOP_OVERFL; - if ((ind[IN_EZ] == 0) && (sta == ADD_NOCRY)) { /* ~z, ~c, ~sign chg? */ - BRANCH (PAR); } /* branch */ - break; - -case OP_BCXM: - idx = get_idx (ADDR_A (saved_PC, I_QL - 1)); /* get index */ - if (idx < 0) { /* disabled? */ - reason = STOP_INVIDX; /* stop */ - break; } - reason = add_field (GET_IDXADDR (idx), QAR, FALSE, TRUE, 3, &sta); - if (ar_stop && ind[IN_OVF]) reason = STOP_OVERFL; - if ((ind[IN_EZ] == 0) && (sta == ADD_NOCRY)) { /* ~z, ~c, ~sign chg? */ - BRANCH (PAR); } /* branch */ - break; - -/* Branch and select - P is valid */ - -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; - case 1: - idxe = 1; idxb = 0; /* index band A */ - break; - case 2: - idxe = idxb = 1; /* index band B */ - break; - case 8: - iae = 0; /* indirect off */ - break; - case 9: - iae = 1; /* indirect on */ - break; - default: - reason = STOP_INVSEL; /* undefined */ - break; } - BRANCH (PAR); - break; - -/* Binary special feature instructions */ - -/* Branch on bit - P,Q are valid, Q is 4d address */ - -case OP_BBT: - t = M[ADDR_A (saved_PC, I_Q)]; /* get Q0 digit */ - if (t & M[QAR] & DIGIT) { /* match to mem? */ - BRANCH (PAR); } /* branch */ - break; - -/* Branch on mask - P,Q are valid, Q is 4d address */ - -case OP_BMK: - t = M[ADDR_A (saved_PC, I_Q)]; /* get Q0 digit */ - if (((t ^ M[QAR]) & /* match to mem? */ - ((t & FLAG)? (FLAG + DIGIT): DIGIT)) == 0) { - BRANCH (PAR); } /* branch */ - break; - -/* Or - P,Q are valid */ - -case OP_ORF: - reason = or_field (PAR, QAR); /* OR fields */ - break; - -/* AND - P,Q are valid */ - -case OP_ANDF: - reason = and_field (PAR, QAR); /* AND fields */ - break; - -/* Exclusive or - P,Q are valid */ - -case OP_EORF: - reason = xor_field (PAR, QAR); /* XOR fields */ - break; - -/* Complement - P,Q are valid */ - -case OP_CPLF: - reason = com_field (PAR, QAR); /* COM field */ - break; - -/* Octal to decimal - P,Q are valid */ - -case OP_OTD: - reason = oct_to_dec (PAR, QAR); /* convert */ - break; - -/* Decimal to octal - P,Q are valid */ - -case OP_DTO: - reason = dec_to_oct (PAR, QAR, &t); /* convert */ - ind[IN_EZ] = t; /* set indicator */ - if (ar_stop && ind[IN_OVF]) reason = STOP_OVERFL; - break; - -/* Floating point special feature instructions */ - -case OP_FADD: - reason = fp_add (PAR, QAR, FALSE); /* add */ - if (ar_stop && ind[IN_EXPCHK]) reason = STOP_EXPCHK; - break; - -case OP_FSUB: - reason = fp_add (PAR, QAR, TRUE); /* subtract */ - if (ar_stop && ind[IN_EXPCHK]) reason = STOP_EXPCHK; - break; - -case OP_FMUL: - reason = fp_mul (PAR, QAR); /* multiply */ - if (ar_stop && ind[IN_EXPCHK]) reason = STOP_EXPCHK; - break; - -case OP_FDIV: - reason = fp_div (PAR, QAR); /* divide */ - if (ar_stop && ind[IN_OVF]) reason = STOP_FPDVZ; - if (ar_stop && ind[IN_EXPCHK]) reason = STOP_EXPCHK; - break; - -case OP_FSL: - reason = fp_fsl (PAR, QAR); /* shift left */ - break; - -case OP_FSR: - reason = fp_fsr (PAR, QAR); /* shift right */ - break; - -/* Halt */ - -case OP_H: - saved_PC = PC; /* commit inst */ - reason = STOP_HALT; /* stop */ - break; - -/* NOP */ - -case OP_NOP: - break; - -/* Invalid instruction code */ - -default: - reason = STOP_INVINS; /* stop */ - break; } /* end switch */ - } /* end while */ - -/* Simulation halted */ - -pcq_r->qptr = pcq_p; /* update pc q ptr */ -upd_ind (); -return reason; -} - -/* Utility routines */ - -/* Get 2 digit field - - Inputs: - ad = address of high digit - Outputs: - val = field converted to binary - -1 if bad digit -*/ - -int32 get_2d (uint32 ad) -{ -int32 d, d1; - -d = M[ad] & DIGIT; /* get 1st digit */ -d1 = M[ADDR_A (ad, 1)] & DIGIT; /* get 2nd digit */ -if (BAD_DIGIT (d) || BAD_DIGIT (d1)) return -1; /* bad? error */ -return ((d * 10) + d1); /* cvt to binary */ -} - -/* Get address routine - - Inputs: - alast = address of low digit - lnt = length - indexok = TRUE if indexing allowed - &addr = pointer to address output - Output: - return = error status (in terms of P address) - addr = address converted to binary - - Notes: - - If indexing produces a negative result, the effective address is - the 10's complement of the result - - An address that exceeds memory produces a MAR check stop -*/ - -t_stat get_addr (uint32 alast, int32 lnt, t_bool indexok, uint32 *reta) -{ -uint8 indir; -int32 cnt, idx, idxa, idxv, addr; - -if (iae) indir = FLAG; /* init indirect */ -else indir = 0; - -cnt = 0; /* count depth */ -do { indir = indir & M[alast]; /* get indirect */ - if (cvt_addr (alast, lnt, FALSE, &addr)) /* cvt addr to bin */ - return STOP_INVPDG; /* bad? */ - idx = get_idx (ADDR_S (alast, 1)); /* get index reg num */ - if (indexok && (idx > 0)) { /* indexable? */ - idxa = GET_IDXADDR (idx); /* get idx reg addr */ - if (cvt_addr (idxa, ADDR_LEN, TRUE, &idxv)) /* cvt idx reg */ - return STOP_INVPDG; - addr = addr + idxv; /* add in index */ - if (addr < 0) addr = addr + 100000; } /* -? 10's comp */ - if (addr >= (int32) MEMSIZE) return STOP_INVPAD;/* invalid addr? */ - alast = addr; /* new address */ - lnt = ADDR_LEN; } /* std len */ -while (indir && (cnt++ < ind_max)); -if (cnt > ind_max) return STOP_INVPIA; /* indir too deep? */ -*reta = addr; /* return address */ -return SCPE_OK; -} - -/* Convert address to binary - - Inputs: - alast = address of low digit - lnt = length - signok = TRUE if signed - val = address of output - Outputs: - status = 0 if ok, != 0 if error -*/ - -t_stat cvt_addr (uint32 alast, int32 lnt, t_bool signok, int32 *val) -{ -int32 sign = 0, addr = 0, t; - -if (signok && (M[alast] & FLAG)) sign = 1; /* signed? */ -alast = alast - lnt; /* find start */ -do { PP (alast); /* incr mem addr */ - t = M[alast] & DIGIT; /* get digit */ - if (BAD_DIGIT (t)) return STOP_INVDIG; /* bad? error */ - addr = (addr * 10) + t; } /* cvt to bin */ -while (--lnt > 0); -if (sign) *val = -addr; /* minus? */ -else *val = addr; -return SCPE_OK; -} - -/* Get index register number - - Inputs: - aidx = address of low digit - Outputs: - index = >0 if indexed - =0 if not indexed - <0 if indexing disabled -*/ - -t_stat get_idx (uint32 aidx) -{ -int32 i, idx; - -if (idxe == 0) return -1; /* indexing off? */ -for (i = idx = 0; i < 3; i++) { /* 3 flags worth */ - if (M[aidx] & FLAG) idx = idx | (1 << i); /* test flag */ - MM (aidx); } /* next digit */ -return idx; -} - -/* Update indicators routine */ - -void upd_ind (void) -{ -ind[IN_HPEZ] = ind[IN_HP] | ind[IN_EZ]; /* HPEZ = HP | EZ */ -ind[IN_DERR] = ind[IN_DACH] | ind[IN_DWLR] | ind[IN_DCYO]; -ind[IN_ANYCHK] = ind[IN_RDCHK] | ind[IN_WRCHK] | /* ANYCHK = all chks */ - ind[IN_MBREVEN] | ind[IN_MBRODD] | - ind[IN_PRCHK] | ind[IN_DACH]; -ind[IN_IXN] = ind[IN_IXA] = ind[IN_IXB] = 0; /* clr index indics */ -if (!idxe) ind[IN_IXN] = 1; /* off? */ -else if (!idxb) ind[IN_IXA] = 1; /* on, band A? */ -else ind[IN_IXB] = 1; /* no, band B */ -return; -} - -/* Transmit routines */ - -/* Transmit field from 's' to 'd' - ignore first 'skp' flags */ - -t_stat xmt_field (uint32 d, uint32 s, uint32 skp) -{ -uint32 cnt = 0; -uint8 t; - -do { t = M[d] = M[s] & (FLAG | DIGIT); /* copy src to dst */ - MM (d); MM (s); /* decr mem addrs */ - if (cnt++ >= MEMSIZE) return STOP_FWRAP; } /* (stop runaway) */ -while (((t & FLAG) == 0) || (cnt <= skp)); /* until flag */ -return SCPE_OK; -} - -/* Transmit record from 's' to 'd' - copy record mark if 'cpy' = TRUE */ - -t_stat xmt_record (uint32 d, uint32 s, t_bool cpy) -{ -uint32 cnt = 0; - -while ((M[s] & REC_MARK) != REC_MARK) { /* until rec mark */ - M[d] = M[s] & (FLAG | DIGIT); /* copy src to dst */ - PP (d); PP (s); /* incr mem addrs */ - if (cnt++ >= MEMSIZE) return STOP_RWRAP; } /* (stop runaway) */ -if (cpy) M[d] = M[s] & (FLAG | DIGIT); /* copy rec mark */ -return SCPE_OK; -} - -/* Transmit index from 's' to 'd' - fixed five character field */ - -t_stat xmt_index (uint32 d, uint32 s) -{ -int32 i; - -M[d] = M[s] & (FLAG | DIGIT); /* preserve sign */ -MM (d); MM (s); /* decr mem addrs */ -for (i = 0; i < ADDR_LEN - 2; i++) { /* copy 3 digits */ - M[d] = M[s] & DIGIT; /* without flags */ - MM (d); MM (s); } /* decr mem addrs */ -M[d] = (M[s] & DIGIT) | FLAG; /* set flag on last */ -return SCPE_OK; -} - -/* Transmit dividend from 'd' to 's' - clear flag on first digit */ - -t_stat xmt_divd (uint32 d, uint32 s) -{ -uint32 cnt = 0; - -M[d] = M[s] & DIGIT; /* first w/o flag */ -do { MM (d); MM (s); /* decr mem addrs */ - M[d] = M[s] & (FLAG | DIGIT); /* copy src to dst */ - if (cnt++ >= MEMSIZE) return STOP_FWRAP; } /* (stop runaway) */ -while ((M[d] & FLAG) == 0); /* until src flag */ -return SCPE_OK; -} - -/* Transmit numeric strip from 's' to 'd' - s is odd */ - -t_stat xmt_tns (uint32 d, uint32 s) -{ -uint32 cnt = 0; -uint8 t, z; - -t = M[s] & DIGIT; /* get units */ -z = M[s - 1] & DIGIT; /* get zone */ -if ((z == 1) || (z == 5) || ((z == 2) && (t == 0))) /* 1x, 5x, 20? */ - M[d] = t | FLAG; /* set flag */ -else M[d] = t; /* else clear flag */ -do { MM (d); /* decr mem addrs */ - s = ADDR_S (s, 2); - t = M[d] & FLAG; /* save dst flag */ - M[d] = M[s] & (FLAG | DIGIT); /* copy src to dst */ - if (cnt >= MEMSIZE) return STOP_FWRAP; /* (stop runaway) */ - cnt = cnt + 2; } -while (t == 0); /* until dst flag */ -M[d] = M[d] | FLAG; /* set flag at end */ -return SCPE_OK; -} - -/* Transmit numeric fill from 's' to 'd' - d is odd */ - -t_stat xmt_tnf (uint32 d, uint32 s) -{ -uint32 cnt = 0; -uint8 t; - -t = M[s]; /* get 1st digit */ -M[d] = t & DIGIT; /* store */ -M[d - 1] = (t & FLAG)? 5: 7; /* set sign from flag */ -do { MM (s); /* decr mem addr */ - d = ADDR_S (d, 2); - t = M[s]; /* get src digit */ - M[d] = t & DIGIT; /* move to dst, no flag */ - M[d - 1] = 7; /* set zone */ - if (cnt >= MEMSIZE) return STOP_FWRAP; /* (stop runaway) */ - cnt = cnt + 2; } -while ((t & FLAG) == 0); /* until src flag */ -return SCPE_OK; -} - -/* Add routine - - Inputs: - d = destination field low (P) - s = source field low (Q) - sub = TRUE if subtracting - sto = TRUE if storing - skp = number of source field flags, beyond sign, to ignore - Output: - return = status - sta = ADD_NOCRY: no carry out, no sign change - ADD_SCHNG: sign change - ADD_CARRY: carry out - - Reference Manual: "When the sum is zero, the sign of the P field - is retained." -*/ - -t_stat add_field (uint32 d, uint32 s, t_bool sub, t_bool sto, uint32 skp, int32 *sta) -{ -uint32 cry, src, dst, res, comp, dp, dsv; -uint32 src_f = 0, cnt = 0, dst_f; - -*sta = ADD_NOCRY; /* assume no cry */ -dsv = d; /* save dst */ -comp = ((M[d] ^ M[s]) & FLAG) ^ (sub? FLAG: 0); /* set compl flag */ -cry = 0; /* clr carry */ -ind[IN_HP] = ((M[d] & FLAG) == 0); /* set sign from res */ -ind[IN_EZ] = 1; /* assume zero */ - -dst = M[d] & DIGIT; /* 1st digits */ -src = M[s] & DIGIT; -if (BAD_DIGIT (dst) || BAD_DIGIT (src)) /* bad digit? */ - return STOP_INVDIG; -if (comp) src = 10 - src; /* complement? */ -res = add_one_digit (dst, src, &cry); /* add */ -if (sto) M[d] = (M[d] & FLAG) | res; /* store */ -MM (d); MM (s); /* decr mem addrs */ -do { dst = M[d] & DIGIT; /* get dst digit */ - dst_f = M[d] & FLAG; /* get dst flag */ - if (src_f) src = 0; /* src done? src = 0 */ - else { - src = M[s] & DIGIT; /* get src digit */ - if (cnt >= skp) src_f = M[s] & FLAG; /* get src flag */ - MM (s); } /* decr src addr */ - if (BAD_DIGIT (dst) || BAD_DIGIT (src)) /* bad digit? */ - return STOP_INVDIG; - if (comp) src = 9 - src; /* complement? */ - res = add_one_digit (dst, src, &cry); /* add */ - if (sto) M[d] = dst_f | res; /* store */ - MM (d); /* decr dst addr */ - if (cnt++ >= MEMSIZE) return STOP_FWRAP; } /* (stop runaway) */ -while (dst_f == 0); /* until dst done */ -if (!src_f) ind[IN_OVF] = 1; /* !src done? ovf */ -if (comp && !cry && !ind[IN_EZ]) { /* recomp needed? */ - ind[IN_HP] = ind[IN_HP] ^ 1; /* flip indicator */ - if (sto) { /* storing? */ - for (cry = 1, dp = dsv; dp != d; ) { /* rescan */ - dst = M[dp] & DIGIT; /* get dst digit */ - res = add_one_digit (9 - dst, 0, &cry); /* "add" */ - M[dp] = (M[dp] & FLAG) | res; /* store */ - MM (dp); } /* decr dst addr */ - M[dsv] = M[dsv] ^ FLAG; } /* compl sign */ - *sta = ADD_SIGNC; /* sign changed */ - return SCPE_OK; } /* end if recomp */ -if (ind[IN_EZ]) ind[IN_HP] = 0; /* res = 0? clr HP */ -if (!comp && cry) *sta = ADD_CARRY; /* set status */ -return SCPE_OK; -} - -/* Add one digit via table (Model 1) or "hardware" (Model 2) */ - -uint32 add_one_digit (uint32 dst, uint32 src, uint32 *cry) -{ -uint32 res; - -if (*cry) src = src + 1; /* cry in? incr src */ -if (src >= 10) { /* src > 10? */ - src = src - 10; /* src -= 10 */ - *cry = 1; } /* carry out */ -else *cry = 0; /* else no carry */ -if (cpu_unit.flags & IF_MII) /* Model 2? */ - res = sum_table[dst + src]; /* "hardware" */ -else res = M[ADD_TABLE + (dst * 10) + src]; /* table lookup */ -if (res & FLAG) *cry = 1; /* carry out? */ -if (res & DIGIT) ind[IN_EZ] = 0; /* nz? clr ind */ -return res & DIGIT; -} - -/* Multiply routine - - Inputs: - mpc = multiplicand address - mpy = multiplier address - Outputs: - return = status - - Reference manual: "A zero product may have a negative or positive sign, - depending on the signs of the fields at the P and Q addresses." -*/ - -t_stat mul_field (uint32 mpc, uint32 mpy) -{ -int32 i; -uint32 pro; /* prod pointer */ -uint32 mpyd, mpyf; /* mpy digit, flag */ -uint32 cnt = 0; /* counter */ -uint8 sign; /* final sign */ -t_stat r; - -PR1 = 1; /* step on PR1 */ -for (i = 0; i < PROD_AREA_LEN; i++) /* clr prod area */ - M[PROD_AREA + i] = 0; -sign = (M[mpc] & FLAG) ^ (M[mpy] & FLAG); /* get final sign */ -ind[IN_HP] = (sign == 0); /* set indicators */ -ind[IN_EZ] = 1; -pro = PROD_AREA + PROD_AREA_LEN - 1; /* product ptr */ - -/* Loop on multiplier (mpy) and product (pro) digits */ - -do { mpyd = M[mpy] & DIGIT; /* multiplier digit */ - mpyf = (M[mpy] & FLAG) && (cnt != 0); /* last digit flag */ - if (BAD_DIGIT (mpyd)) return STOP_INVDIG; /* bad? */ - r = mul_one_digit (mpyd, mpc, pro, mpyf); /* prod += mpc*mpy_dig */ - if (r != SCPE_OK) return r; /* error? */ - MM (mpy); MM (pro); /* decr mpyr, prod addrs */ - if (cnt++ > MEMSIZE) return STOP_FWRAP; } /* (stop runaway) */ -while ((mpyf == 0) || (cnt <= 1)); /* until mpyr flag */ - -if (ind[IN_EZ]) ind[IN_HP] = 0; /* res = 0? clr HP */ -M[PROD_AREA + PROD_AREA_LEN - 1] |= sign; /* set final sign */ -return SCPE_OK; -} - -/* Multiply step - - Inputs: - mpyd = multiplier digit (tested valid) - mpcp = multiplicand low address - prop = product low address - last = last iteration flag (set flag on high product) - Outputs: - prod += multiplicand * multiplier_digit - return = status - - The multiply table address is constructed as follows: - - double the multiplier digit - - use the 10's digit of the doubled result, + 1, as the 100's digit - of the table address - - use the multiplicand digit as the 10's digit of the table address - - use the unit digit of the doubled result as the unit digit of the - table address - EZ indicator is cleared if a non-zero digit is ever generated -*/ - -t_stat mul_one_digit (uint32 mpyd, uint32 mpcp, uint32 prop, uint32 last) -{ -uint32 mpta, mptb; /* mult table */ -uint32 mptd; /* mult table digit */ -uint32 mpcd, mpcf; /* mpc digit, flag */ -uint32 prwp; /* prod working ptr */ -uint32 prod; /* product digit */ -uint32 cry; /* carry */ -uint32 mpcc, cryc; /* counters */ - -mptb = MUL_TABLE + ((mpyd <= 4)? (mpyd * 2): /* set mpy table 100's, */ - (((mpyd - 5) * 2) + 100)); /* 1's digits */ - -/* Inner loop on multiplicand (mpcp) and product (prop) digits */ - -mpcc = 0; /* multiplicand ctr */ -do { prwp = prop; /* product working ptr */ - mpcd = M[mpcp] & DIGIT; /* multiplicand digit */ - mpcf = M[mpcp] & FLAG; /* multiplicand flag */ - if (BAD_DIGIT (mpcd)) return STOP_INVDIG; /* bad? */ - mpta = mptb + (mpcd * 10); /* mpy table 10's digit */ - cry = 0; /* init carry */ - mptd = M[mpta] & DIGIT; /* mpy table digit */ - if (BAD_DIGIT (mptd)) return STOP_INVDIG; /* bad? */ - prod = M[prwp] & DIGIT; /* product digit */ - if (BAD_DIGIT (prod)) return STOP_INVDIG; /* bad? */ - M[prwp] = add_one_digit (prod, mptd, &cry); /* add mpy tbl to prod */ - MM (prwp); /* decr working ptr */ - mptd = M[mpta + 1] & DIGIT; /* mpy table digit */ - if (BAD_DIGIT (mptd)) return STOP_INVDIG; /* bad? */ - prod = M[prwp] & DIGIT; /* product digit */ - if (BAD_DIGIT (prod)) return STOP_INVDIG; /* bad? */ - M[prwp] = add_one_digit (prod, mptd, &cry); /* add mpy tbl to prod */ - cryc = 0; /* (stop runaway) */ - while (cry) { /* propagate carry */ - MM (prwp); /* decr working ptr */ - prod = M[prwp] & DIGIT; /* product digit */ - if (BAD_DIGIT (prod)) return STOP_INVDIG; /* bad? */ - M[prwp] = add_one_digit (prod, 0, &cry); /* add cry */ - if (cryc++ > MEMSIZE) return STOP_FWRAP; } - MM (mpcp); MM (prop); /* decr mpc, prod ptrs */ - if (mpcc++ > MEMSIZE) return STOP_FWRAP; } -while ((mpcf == 0) || (mpcc <= 1)); /* until mpcf flag */ -if (last) - M[prop] = M[prop] | FLAG; /* flag high product */ -return SCPE_OK; -} - -/* Divide routine - comments from Geoff Kuenning's 1620 simulator - - The destination of the divide is given by: - - 100 - <# digits in quotient> - - Which is more easily calculated as: - - 100 - <# digits in divisor> - <# digits in dividend> - - The quotient goes into 99 minus the divisor length. The - remainder goes into 99. The load dividend instruction (above) - should have specified a P address of 99 minus the size of the - divisor. - - Note that this all implies that "dest" points to the *leftmost* - digit of the dividend. - - After the division, the assumed decimal point will be as many - positions to the left as there are digits in the divisor. In - other words, a 4-digit divisor will produce 4 (assumed) decimal - places. - - There are other ways to do these things. In particular, the - load-dividend instruction doesn't have to specify the above - formula; if it's done differently, then you don't have to get - decimal places. This is not well-explained in the books I have. - - How to divide on a 1620: - - The dividend is the field at 99: - - 90 = _1234567890 - - The divisor is somewhere else in memory: - - _03 - - The divide operation specifies the left-most digit of the - dividend as the place to begin trial subtractions: - - DM 90,3 - - The loop works as follows: - - 1. Call the left-most digit of the dividend "current_dividend". - Call the location current_dividend - - "quotient_digit". - 2. Clear the flag at current_dividend, and set one at - quotient_digit. - - 88 = _001234567890, q_d = 88, c_d = 90 - [Not actually done; divisor length controls subtract.] - 3. Subtract the divisor from the field at current-dividend, - using normal 1620 rules, except that signs are ignored. - Continue these subtractions until either 10 subtractions - have been done, or you get a negative result: - - 88 = _00_2234567890, q_d = 88, c_d = 90 - 4. If 10 subtractions have been done, set the overflow - indicator and abort. Otherwise, add the divisor back to - correct for the oversubtraction: - - 88 = _001234567890, q_d = 88, c_d = 90 - 5. Store the (net) number of subtractions in quotient_digit: - - 88 = _001234567890, q_d = 88, c_d = 90 - 6. If this is not the first pass, clear the flag at - quotient_digit. Increment quotient_digit and - current_dividend, and set a flag at the new - quotient_digit: - - 88 = _0_01234567890, q_d = 89, c_d = 91 - [If first pass, set a flag at quotient digit.] - 7. If current_dividend is not 100, repeat steps 3 through 7. - 8. Set flags at 99 and quotient_digit - 1 according to the - rules of algebra: the quotient's sign is the exclusive-or - of the signs of the divisor and dividend, and the - remainder has the sign of the dividend: - - 10 / 3 = 3 remainder 1 - 10 / -3 = -3 remainder 1 - -10 / 3 = -3 remainder -1 - -10 / -3 = 3 remainder -1 - - This preserves the relationship dd = q * dv + r. - - Our example continues as follows for steps 3 through 7: - - 3. 88 = _0_00_334567890, q_d = 89, c_d = 91 - 4. 88 = _0_00034567890 - 5. 88 = _0_40034567890 - 6. 88 = _04_0034567890, q_d = 90, c_d = 92 - 3. 88 = _04_00_34567890 - 4. 88 = _04_0004567890 - 5. 88 = _04_1004567890 - 6. 88 = _041_004567890, q_d = 91, c_d = 93 - 3. 88 = _041_00_2567890 - 4. 88 = _041_001567890 - 5. 88 = _041_101567890 - 6. 88 = _0411_01567890, q_d = 92, c_d = 94 - 3. 88 = _0411_00_367890 - 4. 88 = _0411_00067890 - 5. 88 = _0411_50067890 - 6. 88 = _04115_0067890, q_d = 93, c_d = 95 - 3. 88 = _04115_00_37890 - 4. 88 = _04115_0007890 - 5. 88 = _04115_2007890 - 6. 88 = _041152_007890, q_d = 94, c_d = 96 - 3. 88 = _041152_00_2890 - 4. 88 = _041152_001890 - 5. 88 = _041152_201890 - 6. 88 = _0411522_01890, q_d = 95, c_d = 97 - 3. 88 = _0411522_00_390 - 4. 88 = _0411522_00090 - 5. 88 = _0411522_60090 - 6. 88 = _04115226_0090, q_d = 96, c_d = 98 - 3. 88 = _04115226_00_30 - 4. 88 = _04115226_0000 - 5. 88 = _04115226_3000 - 6. 88 = _041152263_000, q_d = 97, c_d = 99 - 3. 88 = _041152263_00_3 - 4. 88 = _041152263_000 - 5. 88 = _041152263_000 - 6. 88 = _0411522630_00, q_d = 98, c_d = 100 - - In the actual code below, we elide several of these steps in - various ways for convenience and efficiency. - - Note that the EZ indicator is NOT valid for divide, because it - is cleared by any non-zero result in an intermediate add. The - code maintains its own EZ indicator for the quotient. -*/ - -t_stat div_field (uint32 dvd, uint32 dvr, int32 *ez) -{ -uint32 quop, quod, quos; /* quo ptr, dig, sign */ -uint32 dvds; /* dvd sign */ -t_bool first = TRUE; /* first pass */ -t_stat r; - -dvds = (M[PROD_AREA + PROD_AREA_LEN - 1]) & FLAG; /* dividend sign */ -quos = dvds ^ (M[dvr] & FLAG); /* quotient sign */ -ind[IN_HP] = (quos == 0); /* set indicators */ -*ez = 1; - -/* Loop on current dividend, high order digit at dvd */ - -do { r = div_one_digit (dvd, dvr, 10, &quod, &quop); /* dev quo digit */ - if (r != SCPE_OK) return r; /* error? */ - -/* Store quotient digit and advance current dividend pointer */ - - if (first) { /* first pass? */ - if (quod >= 10) { /* overflow? */ - ind[IN_OVF] = 1; /* set indicator */ - return STOP_OVERFL; } /* stop */ - M[quop] = FLAG | quod; /* set flag on quo */ - first = FALSE; } - else M[quop] = quod; /* store quo digit */ - if (quod) *ez = 0; /* if nz, clr ind */ - PP (dvd); } /* incr dvd ptr */ -while (dvd != (PROD_AREA + PROD_AREA_LEN)); /* until end prod */ - -/* Division done. Set signs of quo, rem, set flag on high order remainder */ - -if (*ez) ind[IN_HP] = 0; /* res = 0? clr HP */ -M[PROD_AREA + PROD_AREA_LEN - 1] |= dvds; /* remainder sign */ -M[quop] = M[quop] | quos; /* quotient sign */ -PP (quop); /* high remainder */ -M[quop] = M[quop] | FLAG; /* set flag */ -return SCPE_OK; -} - -/* Divide step - - Inputs: - dvd = current dividend address (high digit) - dvr = divisor address (low digit) - max = max number of iterations before overflow - &quod = address to store quotient digit - &quop = address to store quotient pointer (can be NULL) - Outputs: - return = status - - Divide step calculates a quotient digit by repeatedly subtracting the - divisor from the current dividend. The divisor's length controls the - subtraction; dividend flags are ignored. -*/ - -t_stat div_one_digit (uint32 dvd, uint32 dvr, uint32 max, - uint32 *quod, uint32 *quop) -{ -uint32 dvrp, dvrd, dvrf; /* dvr ptr, dig, flag */ -uint32 dvdp, dvdd; /* dvd ptr, dig */ -uint32 qd, cry; /* quo dig, carry */ -uint32 cnt; - -for (qd = 0; qd < max; qd++) { /* devel quo dig */ - dvrp = dvr; /* divisor ptr */ - dvdp = dvd; /* dividend ptr */ - cnt = 0; - cry = 1; /* carry in = 1 */ - do { /* sub dvr fm dvd */ - dvdd = M[dvdp] & DIGIT; /* dividend digit */ - if (BAD_DIGIT (dvdd)) return STOP_INVDIG; /* bad? */ - dvrd = M[dvrp] & DIGIT; /* divisor digit */ - dvrf = M[dvrp] & FLAG; /* divisor flag */ - if (BAD_DIGIT (dvrd)) return STOP_INVDIG; /* bad? */ - M[dvdp] = add_one_digit (dvdd, 9 - dvrd, &cry); /* sub */ - MM (dvdp); MM (dvrp); /* decr ptrs */ - if (cnt++ > MEMSIZE) return STOP_FWRAP; } /* (stop runaway) */ - while ((dvrf == 0) || (cnt <= 1)); /* until dvr flag */ - if (!cry) { /* !cry = borrow */ - dvdd = M[dvdp] & DIGIT; /* borrow digit */ - if (BAD_DIGIT (dvdd)) return STOP_INVDIG; /* bad? */ - M[dvdp] = add_one_digit (dvdd, 9, &cry); } /* sub */ - if (!cry) break; } /* !cry = negative */ - -/* Add back the divisor to correct for the negative result */ - -dvrp = dvr; /* divisor ptr */ -dvdp = dvd; /* dividend ptr */ -cnt = 0; -cry = 0; /* carry in = 0 */ -do { dvdd = M[dvdp] & DIGIT; /* dividend digit */ - dvrd = M[dvrp] & DIGIT; /* divisor digit */ - dvrf = M[dvrp] & FLAG; /* divisor flag */ - M[dvdp] = add_one_digit (dvdd, dvrd, &cry); /* add */ - MM (dvdp); MM (dvrp); cnt++; } /* decr ptrs */ -while ((dvrf == 0) || (cnt <= 1)); /* until dvr flag */ -if (cry) { /* carry out? */ - dvdd = M[dvdp] & DIGIT; /* borrow digit */ - M[dvdp] = add_one_digit (dvdd, 0, &cry); } /* add */ -if (quop != NULL) *quop = dvdp; /* set quo addr */ -*quod = qd; /* set quo digit */ -return SCPE_OK; -} - -/* Logical operation routines (and, or, xor, complement) - - Inputs: - d = destination address - s = source address - Output: - return = status - - Destination flags are preserved; EZ reflects the result. - COM does not obey normal field length restrictions. -*/ - -t_stat or_field (uint32 d, uint32 s) -{ -uint32 cnt = 0; -int32 t; - -ind[IN_EZ] = 1; /* assume result zero */ -do { t = M[s]; /* get src */ - M[d] = (M[d] & FLAG) | ((M[d] | t) & 07); /* OR src to dst */ - if (M[d] & DIGIT) ind[IN_EZ] = 0; /* nz dig? clr ind */ - MM (d); MM (s); /* decr pointers */ - if (cnt++ >= MEMSIZE) return STOP_FWRAP; } /* (stop runaway) */ -while (((t & FLAG) == 0) || (cnt <= 1)); /* until src flag */ -return SCPE_OK; -} - -t_stat and_field (uint32 d, uint32 s) -{ -uint32 cnt = 0; -int32 t; - -ind[IN_EZ] = 1; /* assume result zero */ -do { t = M[s]; /* get src */ - M[d] = (M[d] & FLAG) | ((M[d] & t) & 07); /* AND src to dst */ - if (M[d] & DIGIT) ind[IN_EZ] = 0; /* nz dig? clr ind */ - MM (d); MM (s); /* decr pointers */ - if (cnt++ >= MEMSIZE) return STOP_FWRAP; } /* (stop runaway) */ -while (((t & FLAG) == 0) || (cnt <= 1)); /* until src flag */ -return SCPE_OK; -} - -t_stat xor_field (uint32 d, uint32 s) -{ -uint32 cnt = 0; -int32 t; - -ind[IN_EZ] = 1; /* assume result zero */ -do { t = M[s]; /* get src */ - M[d] = (M[d] & FLAG) | ((M[d] ^ t) & 07); /* XOR src to dst */ - if (M[d] & DIGIT) ind[IN_EZ] = 0; /* nz dig? clr ind */ - MM (d); MM (s); /* decr pointers */ - if (cnt++ >= MEMSIZE) return STOP_FWRAP; } /* (stop runaway) */ -while (((t & FLAG) == 0) || (cnt <= 1)); /* until src flag */ -return SCPE_OK; -} - -t_stat com_field (uint32 d, uint32 s) -{ -uint32 cnt = 0; -int32 t; - -ind[IN_EZ] = 1; /* assume result zero */ -do { t = M[s]; /* get src */ - M[d] = (t & FLAG) | ((t ^ 07) & 07); /* comp src to dst */ - if (M[d] & DIGIT) ind[IN_EZ] = 0; /* nz dig? clr ind */ - MM (d); MM (s); /* decr pointers */ - if (cnt++ >= MEMSIZE) return STOP_FWRAP; } /* (stop runaway) */ -while ((t & FLAG) == 0); /* until src flag */ -return SCPE_OK; -} - -/* Octal to decimal - - Inputs: - tbl = conversion table address (low digit) - s = source address - Outputs: - product area = converted source - result = status - - OTD is a cousin of multiply. The octal digits in the source are - multiplied by successive values in the conversion table, and the - results are accumulated in the product area. Although the manual - does not say, this code assumes that EZ and HP are affected. - */ - -t_stat oct_to_dec (uint32 tbl, uint32 s) -{ -uint32 cnt = 0, tblc; -uint32 i, sd, sf, tf, sign; -t_stat r; - -for (i = 0; i < PROD_AREA_LEN; i++) /* clr prod area */ - M[PROD_AREA + i] = 0; -sign = M[s] & FLAG; /* save sign */ -ind[IN_EZ] = 1; /* set indicators */ -ind[IN_HP] = (sign == 0); -do { sd = M[s] & DIGIT; /* src digit */ - sf = M[s] & FLAG; /* src flag */ - r = mul_one_digit (sd, tbl, PROD_AREA + PROD_AREA_LEN - 1, sf); - if (r != SCPE_OK) return r; /* err? */ - 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; } - while (tf == 0); /* until flag */ - if (cnt++ > MEMSIZE) return STOP_FWRAP; } /* (stop runaway) */ -while (sf == 0); -if (ind[IN_EZ]) ind[IN_HP] = 0; /* res = 0? clr HP */ -M[PROD_AREA + PROD_AREA_LEN - 1] |= sign; /* set sign */ -return SCPE_OK; -} - -/* Decimal to octal - - Inputs: - d = destination address - tbl = conversion table address (low digit of highest power) - &ez = address of soft EZ indicator - product area = field to convert - Outputs: - return = status - - DTO is a cousin to divide. The number in the product area is repeatedly - divided by successive values in the conversion table, and the quotient - digits are stored in the destination. Although the manual does not say, - this code assumes that EZ and HP are affected. - */ - -t_stat dec_to_oct (uint32 d, uint32 tbl, int32 *ez) -{ -uint32 sign, octd, t; -t_bool first = TRUE; -uint32 ctr = 0; -t_stat r; - -sign = M[PROD_AREA + PROD_AREA_LEN - 1] & FLAG; /* input sign */ -*ez = 1; /* set indicators */ -ind[IN_HP] = (sign == 0); -for ( ;; ) { - r = div_one_digit (PROD_AREA + PROD_AREA_LEN - 1, /* divide */ - tbl, 8, &octd, NULL); - if (r != SCPE_OK) return r; /* error? */ - if (first) { /* first pass? */ - if (octd >= 8) { /* overflow? */ - ind[IN_OVF] = 1; /* set indicator */ - return SCPE_OK; } /* stop */ - M[d] = FLAG | octd; /* set flag on quo */ - first = FALSE; } - else M[d] = octd; /* store quo digit */ - if (octd) *ez = 0; /* if nz, clr ind */ - PP (tbl); /* incr tbl addr */ - if ((M[tbl] & REC_MARK) == REC_MARK) break; /* record mark? */ - PP (tbl); /* skip flag */ - if ((M[tbl] & REC_MARK) == REC_MARK) break; /* record mark? */ - do { PP (tbl); /* look for F, rec mk */ - t = M[tbl]; } - while (((t & FLAG) == 0) && ((t & REC_MARK) != REC_MARK)); - MM (tbl); /* step back one */ - PP (d); /* incr quo addr */ - if (ctr++ > MEMSIZE) return STOP_FWRAP; } /* (stop runaway) */ -if (*ez) ind[IN_HP] = 0; /* res = 0? clr HP */ -M[d] = M[d] | sign; /* set result sign */ -return SCPE_OK; -} - -/* Reset routine */ - -t_stat cpu_reset (DEVICE *dptr) -{ -int32 i; -static t_bool one_time = TRUE; - -PR1 = IR2 = 1; /* invalidate PR1,IR2 */ -ind[0] = 0; -for (i = IN_SW4 + 1; i < NUM_IND; i++) ind[i] = 0; /* init indicators */ -if (cpu_unit.flags & IF_IA) iae = 1; /* indirect enabled? */ -else iae = 0; -idxe = idxb = 0; /* indexing off */ -pcq_r = find_reg ("PCQ", NULL, dptr); /* init old PC queue */ -if (pcq_r) pcq_r->qptr = 0; -else return SCPE_IERR; -sim_brk_types = sim_brk_dflt = SWMASK ('E'); /* init breakpoints */ -upd_ind (); /* update indicators */ -if (one_time) cpu_set_table (&cpu_unit, 1, NULL, NULL); /* set default tables */ -one_time = FALSE; -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] & (FLAG | DIGIT); -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 & (FLAG | DIGIT); -return SCPE_OK; -} - -/* Memory size change */ - -t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -int32 mc = 0; -uint32 i; - -if ((val <= 0) || (val > MAXMEMSIZE) || ((val % 1000) != 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; -} - -/* Model change */ - -t_stat cpu_set_model (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -if (val) cpu_unit.flags = (cpu_unit.flags & (UNIT_SCP | UNIT_BCD | MII_OPT)) | - IF_DIV | IF_IA | IF_EDT; -else cpu_unit.flags = cpu_unit.flags & (UNIT_SCP | UNIT_BCD | MI_OPT); -return SCPE_OK; -} - -/* Set/clear Model 1 option */ - -t_stat cpu_set_opt1 (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -if (cpu_unit.flags & IF_MII) { - printf ("Feature is standard on 1620 Model 2\n"); - if (sim_log) fprintf (sim_log, "Feature is standard on 1620 Model 2\n"); - return SCPE_NOFNC; } -return SCPE_OK; -} - -/* Set/clear Model 2 option */ - -t_stat cpu_set_opt2 (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -if (!(cpu_unit.flags & IF_MII)) { - printf ("Feature is not available on 1620 Model 1\n"); - if (sim_log) fprintf (sim_log, "Feature is not available on 1620 Model 1\n"); - return SCPE_NOFNC; } -return SCPE_OK; -} - -/* Front panel save */ - -t_stat cpu_set_save (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -if (saved_PC & 1) return SCPE_NOFNC; -PR1 = saved_PC; -return SCPE_OK; -} - -/* Set standard add/multiply tables */ - -t_stat cpu_set_table (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -int32 i; - -for (i = 0; i < MUL_TABLE_LEN; i++) /* set mul table */ - M[MUL_TABLE + i] = std_mul_table[i]; -if (((cpu_unit.flags & IF_MII) == 0) || val) { /* set add table */ - for (i = 0; i < ADD_TABLE_LEN; i++) - M[ADD_TABLE + i] = std_add_table[i]; } -return SCPE_OK; -} diff --git a/I1620/i1620_defs.h b/I1620/i1620_defs.h deleted file mode 100644 index b07cde33..00000000 --- a/I1620/i1620_defs.h +++ /dev/null @@ -1,221 +0,0 @@ -/* i1620_defs.h: IBM 1620 simulator definitions - - 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"), - 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 simulator is based on the 1620 simulator written by Geoff Kuenning. - I am grateful to Al Kossow, the Computer History Museum, and the IBM Corporate - Archives for their help in gathering documentation about the IBM 1620. - - 18-Oct-02 RMS Fixed bug in ADDR_S macro (found by Hans Pufal) -*/ - -#include "sim_defs.h" /* simulator defns */ - -/* Simulator stop codes */ - -#define STOP_HALT 1 /* HALT */ -#define STOP_IBKPT 2 /* breakpoint */ -#define STOP_INVINS 3 /* invalid instruction */ -#define STOP_INVDIG 4 /* invalid digit */ -#define STOP_INVCHR 5 /* invalid char */ -#define STOP_INVIND 6 /* invalid indicator */ -#define STOP_INVPDG 7 /* invalid P addr digit */ -#define STOP_INVPAD 8 /* invalid P addr */ -#define STOP_INVPIA 9 /* invalid P indir addr */ -#define STOP_INVQDG 10 /* invalid Q addr digits */ -#define STOP_INVQAD 11 /* invalid Q addr */ -#define STOP_INVQIA 12 /* invalid Q indir addr */ -#define STOP_INVIO 13 /* invalid IO address */ -#define STOP_INVRTN 14 /* invalid return */ -#define STOP_INVFNC 15 /* invalid function */ -#define STOP_INVIAD 16 /* invalid instr addr */ -#define STOP_INVSEL 17 /* invalid select */ -#define STOP_INVIDX 18 /* invalid index instr */ -#define STOP_INVEAD 19 /* invalid even addr */ -#define STOP_INVDCF 20 /* invalid DCF addr */ -#define STOP_INVDRV 21 /* invalid disk drive */ -#define STOP_INVDSC 22 /* invalid disk sector */ -#define STOP_INVDCN 23 /* invalid disk count */ -#define STOP_INVDBA 24 /* invalid disk buf addr */ -#define STOP_DACERR 25 /* disk addr comp err */ -#define STOP_DWCERR 26 /* disk wr check err */ -#define STOP_CYOERR 27 /* cylinder ovflo err */ -#define STOP_WRLERR 28 /* wrong rec lnt err */ -#define STOP_CCT 29 /* runaway CCT */ -#define STOP_FWRAP 30 /* field wrap */ -#define STOP_RWRAP 31 /* record wrap */ -#define STOP_NOCD 32 /* no card in reader */ -#define STOP_OVERFL 33 /* overflow */ -#define STOP_EXPCHK 34 /* exponent error */ -#define STOP_WRADIS 35 /* write addr disabled */ -#define STOP_FPLNT 36 /* invalid fp length */ -#define STOP_FPUNL 37 /* fp lengths unequal */ -#define STOP_FPMF 38 /* no flag on exp */ -#define STOP_FPDVZ 39 /* divide by zero */ - -/* Memory */ - -#define MAXMEMSIZE 60000 /* max mem size */ -#define MEMSIZE (cpu_unit.capac) /* act memory size */ - -/* Processor parameters */ - -#define INST_LEN 12 /* inst length */ -#define ADDR_LEN 5 /* addr length */ -#define MUL_TABLE 100 /* multiply table */ -#define MUL_TABLE_LEN 200 -#define ADD_TABLE 300 /* add table */ -#define ADD_TABLE_LEN 100 -#define IDX_A 300 /* index A base */ -#define IDX_B 340 /* index B base */ -#define PROD_AREA 80 /* product area */ -#define PROD_AREA_LEN 20 /* product area */ -#define PROD_AREA_END (PROD_AREA + PROD_AREA_LEN) - -/* Branch indicator codes */ - -#define NUM_IND 100 /* number of indicators */ - -#define IN_SW1 1 /* sense switch 1 */ -#define IN_SW2 2 /* sense switch 2 */ -#define IN_SW3 3 /* sense switch 3 */ -#define IN_SW4 4 /* sense switch 4 */ -#define IN_RDCHK 6 /* read check (I/O error) */ -#define IN_WRCHK 7 /* write check (I/O error) */ -#define IN_LAST 9 /* last card was just read */ -#define IN_HP 11 /* high or positive result */ -#define IN_EZ 12 /* equal or zero result */ -#define IN_HPEZ 13 /* high/positive or equal/zero */ -#define IN_OVF 14 /* overflow */ -#define IN_EXPCHK 15 /* floating exponent check */ -#define IN_MBREVEN 16 /* even parity check */ -#define IN_MBRODD 17 /* odd parity check */ -#define IN_ANYCHK 19 /* any of read, write, even/odd */ -#define IN_PRCHK 25 /* printer check */ -#define IN_IXN 30 /* IX neither */ -#define IN_IXA 31 /* IX A band */ -#define IN_IXB 32 /* IX B band */ -#define IN_PRCH9 33 /* printer chan 9 */ -#define IN_PRCH12 34 /* printer chan 12 */ -#define IN_PRBSY 35 /* printer busy */ -#define IN_DACH 36 /* disk addr/data check */ -#define IN_DWLR 37 /* disk rec length */ -#define IN_DCYO 38 /* disk cyl overflow */ -#define IN_DERR 39 /* disk any error */ - -/* I/O channel codes */ - -#define NUM_IO 100 /* number of IO chan */ - -#define IO_TTY 1 /* console typewriter */ -#define IO_PTP 2 /* paper-tape punch */ -#define IO_PTR 3 /* paper-tape reader */ -#define IO_CDP 4 /* card punch */ -#define IO_CDR 5 /* card reader */ -#define IO_DSK 7 /* disk */ -#define IO_LPT 9 /* line printer */ -#define IO_BTP 32 /* binary ptp */ -#define IO_BTR 33 /* binary ptr */ - -#define LPT_WIDTH 120 /* line print width */ -#define CCT_LNT 132 /* car ctrl length */ - -#define CRETIOE(f,c) return ((f)? (c): SCPE_OK) - -/* Memory representation: flag + BCD digit per byte */ - -#define FLAG 0x10 -#define DIGIT 0x0F -#define REC_MARK 0xA -#define NUM_BLANK 0xC -#define GRP_MARK 0xF -#define BAD_DIGIT(x) ((x) > 9) - -/* Instruction format */ - -#define I_OP 0 /* opcode */ -#define I_P 2 /* P start */ -#define I_PL 6 /* P end */ -#define I_Q 7 /* Q start */ -#define I_QL 11 /* Q end */ -#define I_IO 8 /* IO select */ -#define I_BR 8 /* indicator select */ -#define I_CTL 10 /* control select */ -#define I_SEL 11 /* BS select */ - -#define ADDR_A(x,a) ((((x) + (a)) >= MEMSIZE)? ((x) + (a) - MEMSIZE): ((x) + (a))) -#define ADDR_S(x,a) (((x) < (a))? ((x) - (a) + MEMSIZE): ((x) - (a))) -#define PP(x) x = ADDR_A(x,1) -#define MM(x) x = ADDR_S(x,1) - -/* CPU options, stored in cpu_unit.flags */ -/* Decoding flags must be part of the same definition set */ - -#define UNIT_SCP ((1 << UNIT_V_UF) - 1) /* mask of SCP flags */ -#define IF_MII (1 << (UNIT_V_UF + 0)) /* model 2 */ -#define IF_DIV (1 << (UNIT_V_UF + 1)) /* automatic divide */ -#define IF_IA (1 << (UNIT_V_UF + 2)) /* indirect addressing */ -#define IF_EDT (1 << (UNIT_V_UF + 3)) /* edit */ -#define IF_FP (1 << (UNIT_V_UF + 4)) /* floating point */ -#define IF_BIN (1 << (UNIT_V_UF + 5)) /* binary */ -#define IF_IDX (1 << (UNIT_V_UF + 6)) /* indexing */ -#define IF_VPA (1 << (UNIT_V_UF + 7)) /* valid P addr */ -#define IF_VQA (1 << (UNIT_V_UF + 8)) /* valid Q addr */ -#define IF_4QA (1 << (UNIT_V_UF + 9)) /* 4 char Q addr */ -#define IF_NQX (1 << (UNIT_V_UF + 10)) /* no Q indexing */ -#define IF_IMM (1 << (UNIT_V_UF + 11)) /* immediate */ -#define UNIT_BCD (1 << (UNIT_V_UF + 12)) /* BCD coded */ -#define UNIT_MSIZE (1 << (UNIT_V_UF + 13)) /* fake flag */ -#define ALLOPT (IF_DIV + IF_IA + IF_EDT + IF_FP + IF_BIN + IF_IDX) -#define MI_OPT (IF_DIV + IF_IA + IF_EDT + IF_FP) -#define MI_STD (IF_DIV + IF_IA + IF_EDT) -#define MII_OPT (ALLOPT) -#define MII_STD (IF_DIV + IF_IA + IF_EDT + IF_BIN + IF_IDX) - -/* Add status codes */ - -#define ADD_NOCRY 0 /* no carry out */ -#define ADD_CARRY 1 /* carry out */ -#define ADD_SIGNC 2 /* sign change */ - -/* Opcodes */ - -enum opcodes { - OP_FADD = 1, OP_FSUB, OP_FMUL, /* 00 - 09 */ - OP_FSL = 5, OP_TFL, OP_BTFL, OP_FSR, OP_FDIV, - OP_BTAM = 10, OP_AM, OP_SM, OP_MM, OP_CM, /* 10 - 19 */ - OP_TDM, OP_TFM, OP_BTM, OP_LDM, OP_DM, - OP_BTA = 20, OP_A, OP_S, OP_M, OP_C, /* 20 - 29 */ - OP_TD, OP_TF, OP_BT, OP_LD, OP_D, - OP_TRNM = 30, OP_TR, OP_SF, OP_CF, OP_K, /* 30 - 39 */ - OP_DN, OP_RN, OP_RA, OP_WN, OP_WA, - OP_NOP = 41, OP_BB, OP_BD, OP_BNF, /* 40 - 49 */ - OP_BNR, OP_BI, OP_BNI, OP_H, OP_B, - OP_BNG = 55, - OP_BS = 60, OP_BX, OP_BXM, OP_BCX, OP_BCXM, /* 60 - 69 */ - OP_BLX, OP_BLXM, OP_BSX, - OP_MA = 70, OP_MF, OP_TNS, OP_TNF, /* 70 - 79 */ - /* 80 - 89 */ - OP_BBT = 90, OP_BMK, OP_ORF, OP_ANDF, OP_CPLF, /* 90 - 99 */ - OP_EORF, OP_OTD, OP_DTO }; diff --git a/I1620/i1620_doc.txt b/I1620/i1620_doc.txt deleted file mode 100644 index 2f408e54..00000000 --- a/I1620/i1620_doc.txt +++ /dev/null @@ -1,518 +0,0 @@ -To: Users -From: Bob Supnik -Subj: IBM 1620 Simulator Usage -Date: 15-Apr-2003 - - COPYRIGHT NOTICE - -The following copyright notice applies to both the SIMH source and binary: - - 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"), - 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 IBM 1620 simulator. This simulator is based on -Geoff Kuenning's 1620 simulator, which is used by permission. - -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/i1620/ i1620_defs.h - i1620_cpu.c - i1620_fp.c - i1620_tty.c - i1620_pt.c - i1620_cd.c - i1620_lp.c - i1620_dp.c - i1620_sys.c - -2. IBM 1620 Features - -The IBM 1620 simulator is configured as follows: - -device simulates -name(s) - -CPU IBM 1620 Model 1 or Model 2 CPU with 20K to 60K of memory - Model 1 options: indirect addressing, automatic divide, - edit instructions, floating point - Model 2 options: indexing, binary capability, floating point -TTY IBM console terminal -PTR IBM 1621 paper tape reader -PTP IBM 1624 paper tape punch -CDR,CDP IBM 1622 card reader/punch -LPT IBM 1443 line printer -DP IBM 1311 disk pack with four drives - -The IBM 1620 simulator implements many unique stop conditions. On almost -any kind of error the simulator stops: - - unimplemented opcode - reference to non-existent device - invalid digit - invalid alphameric character - invalid P address digit - invalid Q address digit - indirect address limit exceeded - invalid odd address - invalid even address - invalid function - invalid indicator - invalid return address register - skip to unpunched carriage control tape channel - card reader hopper empty - overflow with arithmetic stop switch set - I/O error with I/O stop switch set - invalid disk drive - invalid disk sector address - invalid disk sector count - invalid disk buffer address - disk address compare error - disk cylinder overflow error - disk write check error - field exceeds memory - record exceeds memory - floating point mantissa exceeds maximum length - floating point mantissas not the same length - floating point exponent check with arithmetic stop switch set - floating point exponent missing high flag - -The LOAD command is used to load a line printer carriage-control tape. -The DUMP command is not implemented. - -2.1 CPU - -The CPU options include the CPU model (Model 1 or Model 2), a number of -special features, and the size of main memory. - - SET CPU IA enable indirect addressing - SET CPU NOIA disable indirect addressing - SET CPU EDT enable extra editing instructions - SET CPU NOEDT disable extra editing instructions - SET CPU DIV enable divide instructions - SET CPU NODIV disable divide instructions - SET CPU IDX enable indexing - SET CPU NOIDX disable indexing - SET CPU BIN enable binary instructions - SET CPU NOBIN disable binary instructions - SET CPU FP enable floating point instructions - SET CPU NOFP disable floating point instructions - SET CPU MOD1 set Model 1 - SET CPU MOD2 set Model 2 - SET CPU 20K set memory size = 20K - SET CPU 40K set memory size = 40K - SET CPU 60K set memory size = 60K - -Model 1 options include IA, EDT, DIV, and FP; the first three are on by -default. Model 2 options include IDX, BIN, and FP; IA, EDT, and DIV are -standard on the Model 2. - -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. Initially, the CPU is a Model 1, memory size is -20K, and indirect addressing, editing instructions, and divide are enabled. - -Memory is implemented as 5 bit BCD digits, as follows: - - 4 3 2 1 0 - - flag 8 4 2 1 - <-------- digit --------> - -In BCD, the decimal digits 0-9 are (hex) values 0x0, 0x1, 0x2, 0x3, 0x4, -0x5, 0x6, 0x7, 0x8, 0x9, respectively. 0xA is record mark, 0xC non- -punching blank, and 0xF group mark, respectively. - -CPU registers include the visible state of the processor. The 1620 has no -interrupt system. - - name size comments - - IR1 16 instruction storage address register (PC) - IR2 16 return register - PR1 16 processor register 1 - PAR 16 P address register (OR2) - QAR 16 Q address register (OR1) - SS1 1 sense switch 1 - SS2 1 sense switch 2 - SS3 1 sense switch 3 - SS4 1 sense switch 4 - HP 1 high/positive indicator - EZ 1 equal/zero indicator - ARCHK 1 arithmetic check (overflow) indicator - EXPCHK 1 exponent check indicator - RDCHK 1 read check indicator - WRCHK 1 write check indicator - ARSTOP 1 arithmetic check stop switch - IOSTOP 1 I/O check stop switch - IND[0:99] 1 indicator array - IAE 1 indirect address enable (Model 2 only) - IDXE 1 indexing enable (Model 2 only) - IDXB 1 indexing band select (Model 2 only) - IR1Q[0:63] 16 IR1 prior to last branch; - most recent IR1 change first - WRU 8 interrupt character - -2.2 Console Typewriter (TTY) - -The console typewriter (TTY) is a half-duplex console. The typewriter -registers are: - - name size comments - - COL 7 current column - TIME 24 polling interval - -When the 1620 CPU requests input from the keyboard, a reverse apostrophe -(`) is printed. The CPU hangs waiting for input until the return/enter -key is pressed. The typewriter has no errors. - -2.3 1621 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 supports the BOOT command. BOOT PTR starts the -standard paper tape boot sequence at location 0. - -The paper tape reader implements these registers: - - name size comments - - POS 32 position in the input file - -Error handling is as follows: - - error IOCHK processed as - - not attached x set RDCHK indicator, report error, stop - - end of file x set RDCHK indicator, report error, stop - - OS I/O error x set RDCHK indicator, report error, stop - - parity error 1 set RDCHK indicator, report error, stop - 0 set RDCHK indicator - -2.4 1624 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 - - POS 32 position in the output file - -Error handling is as follows: - - error IOCHK processed as - - not attached x set WRCHK indicator, report error, stop - - OS I/O error x set WRCHK indicator, report error, stop - - invalid char 1 set WRCHK indicator, report error, stop - 0 set WRCHK indicator - -2.5 1622 Card Reader/Punch (CDR, CDP) - -The IBM 1402 card/reader punch is simulated as two independent devices: -the card reader (CDR) and the card punch (CDP). - -The card reader supports the BOOT command. BOOT CDR starts the standard -card boot sequence at location 0. - -The card reader reads data from a disk file, while the punch writes data -to a disk file. Cards are simulated as ASCII text lines with terminating -newlines. For each unit, the POS register specifies the number of the -next data item to be read or written. Thus, by changing POS, the user -can backspace or advance these devices. - -The card reader registers are: - - name size comments - - LAST 1 last card indicator - POS 32 position - -The card punch registes are: - - name size comments - - POS 32 position - -Card reader error handling is as follows: - - error IOCHK processed as - - end of file x set RDCHK indicator, report error, stop - - not attached x set RDCHK indicator, report error, stop - - OS I/O error x set RDCHK indicator, report error, stop - - invalid char 1 set RDCHK indicator, report error, stop - 0 set RDCHK indicator - -Card punch error handling is as follows: - - error IOCHK processed as - - not attached x set WRCHK indicator, report error, stop - - OS I/O error x set WRCHK indicator, report error, stop - - invalid char 1 set WRCHK indicator, report error, stop - 0 set WRCHK indicator - -2.6 1443 Line Printer (LPT) - -The IBM 1443 line printer (LPT) writes its data, converted to ASCII, to -a disk file. 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 1 and 12; a column number of zero denotes top of form. The -following are all legal carriage control specifications: - - no punch - (5) 5 lines with no punches - 1,5,7,8 columns 1, 5, 7, 8 punched - (10)2 10 lines with column 2 punched - 1,0 column 1 punched; top of form - -The default form is 66 lines long, with column 1 and the top of form mark -on line 1, and the rest blank. - -The line printer registers are: - - name size comments - - LBUF[0:119] 7 line buffer - BPTR 7 buffer pointer - PCTL 8 saved print control directive - PRCHK 1 print check indicator - PRCH9 1 channel 9 indicator - PRCH12 1 channel 12 indicator - POS 32 position - CCT[0:131] 32 carriage control tape array - CCTP 8 carriage control tape pointer - CCTL 8 carriage control tape length (read only) - -Error handling is as follows: - - error IOCHK processed as - - not attached x set PRCHK, WRCHK indicators, report error, stop - - OS I/O error x set PRCHK, WRCHK indicators, report error, stop - - invalid char 1 set PRCHK, WRCHK indicator, report error, stop - 0 set PRCHK, WRCHK indicator - -2.7 1311 Disk Pack (DP) - -The disk pack controller supports 4 drives, numbered 0 through 3. Disk -pack options include the ability to enable address writing (formatting). - - SET DPn ADDROFF set unit n address enable off - SET DPn ADDRON set unit n address enable on - -Units can also be set ONLINE or OFFLINE. - -Unlike most simulated disks, the 1311 includes explicit representation -for sector addresses. This is to support non-standard formats, such as -the inclusion of the drive number in the sector address. As a result, -1311 sectors are 105 digits long: 5 address digits and 100 data digits. -If the 1311 has not been formatted, the addresses are zeroes and are -synthesized, if needed, based on the sector number. - -The disk pack controller implements these registers: - - name size comments - - ADCHK 1 address check (compare error) indicator - WLRC 1 wrong length record check indicator - CYLO 1 cylinder overflow check indicator - ERR 1 disk error indicator - DPSTOP 1 disk check stop - -Error handling is as follows: - - error DPCHK processed as - - not attached x set ERR indicator, report error, stop - -1311 data files are buffered in memory; therefore, end of file and OS -I/O errors cannot occur. - -2.8 Symbolic Display and Input - -The IBM 1620 simulator implements symbolic display and input. Display is -controlled by command line switches: - - -c display as single character (alphameric - for CPU and DP, ASCII for others) - -s display as flag terminated numeric string - (CPU and DP only) - -m display instruction mnemonics - (CPU and DP only) - -d display 50 characters per line, with word - marks denoted by "_" on the line above - -In a CPU string display, word marks are denoted by ~. - -Input parsing is controlled by the first character typed in or by command -line switches: - - ' or -c character (alphameric for CPU and DP, ASCII - for others) - " or -s numeric string (CPU and DP only) - alphabetic instruction mnemonic (CPU and DP only) - numeric octal number - -Instruction input is free format and consists of an opcode and up to -three operands: - - op {+/-}ppppp{(idx)},{+-}qqqqq{(idx)},flags - -The p address and, if present, the q address, are always decimal. A -plus sign is ignored; a minus sign denotes indirect addressing (or a -negative immediate operand). If indexing is enabled, addresses may -be indexed; index registers are decimal numbers between 1 and 7. The -flags field is used to set extra flags on the instruction. It consists -of digit numbers in ascending order, with no separators. For example, - - AM -12345(5),67890,110 - -translates into - _ _ ___ _ - 111234567890 - -The flag over digits 3 and 5 specify the P index register; the flag -over digit 6 specifies the P indirect address; the flag over digit 7 -marks the end of the immediate Q operand; and the flags over digits -1 and 10 are specified by the third field. - -2.9 Character Sets - -The IBM 1620 uses single digits to represent numbers, and pairs of -digits to represent characters (alphameric coding). Only a small -number of the 256 possible alphameric codings have legitimate values. -Further, the translation between alphameric and devices varied from -device to device. The simulator implements a code called 1620 ASCII, -which allows all 64 possible card codes to be represented by upper -case ASCII characters. In addition, lower case alphabetic characters -are accepted on input as equivalent to upper case. - -Card code PT code RA RN LPT WA ASCII representation - - C 0 0 blank blank -12 XOC 10 0 + + -11 X 20 F+0 - - -0 O 70 0 0 0 -1 1 71 1 1 1 -2 2 72 2 2 2 -3 C21 73 3 3 3 -4 4 74 4 4 4 -5 C41 75 5 5 5 -6 C42 76 6 6 6 -7 421 77 7 7 7 -8 8 78 8 8 8 -9 C81 79 9 9 9 -12 + 1 XO1 41 1 A A -12 + 2 XO2 42 2 B B -12 + 3 XOC21 43 3 C C -12 + 4 XO4 44 4 D D -12 + 5 XOC41 45 5 E E -12 + 6 XOC42 46 6 F F -12 + 7 XO421 47 7 G G -12 + 8 XO8 48 8 H H -12 + 9 XOC81 49 9 I I -11 + 1 XC1 51 F+1 J J -11 + 2 XC2 52 F+2 K K -11 + 3 X21 53 F+3 L L -11 + 4 XC4 54 F+4 M M -11 + 5 X41 55 F+5 N N -11 + 6 X42 56 F+6 O O -11 + 7 XC421 57 F+7 P P -11 + 8 XC8 58 F+8 Q Q -11 + 9 X81 59 F+9 R R -0 + 1 OC1 21 1 / / -0 + 2 OC2 62 2 S S -0 + 3 O21 63 3 T T -0 + 4 OC4 64 4 U U -0 + 5 O41 65 5 V V -0 + 6 O42 66 6 W W -0 + 7 OC421 67 7 X X -0 + 8 OC8 68 8 Y Y -0 + 9 O81 69 9 Z Z -2 + 8 C82 ? 0A A na % -3 + 8 821 33 B = = -4 + 8 C84 34 C @ @ -5 + 8 841 70 0 0 : -6 + 8 842 ? 0E E na > -7 + 8 C8421 ? 0F F na ^ -12 + 2 + 8 XOC82 ? 5A ? F+A na ? -12 + 3 + 8 XO821 3 ? F+B . . -12 + 4 + 8 XOC84 4 C ) ) -12 + 5 + 8 XO841 40 0 na [ -12 + 6 + 8 XO842 ? 5E ? F+E na < -12 + 7 + 8 XOC8421 5F F+F na " -11 + 2 + 8 X82 5A F+A na ! -11 + 3 + 8 XC821 13 F+B $ $ -11 + 4 + 8 X84 14 F+C * * -11 + 5 + 8 XC841 50 F+0 - ] -11 + 6 + 8 XC842 ? 5E ? F+E na ; -11 + 7 + 8 X8421 5F F+F na _ -0 + 2 + 8 O82 0A A na ' -0 + 3 + 8 OC821 23 B , , -0 + 4 + 8 O84 24 C ( ( -0 + 5 + 8 OC841 60 0 na # -0 + 6 + 8 OC842 0E E na \ -0 + 7 + 8 O8421 0F F na & - - 2 ? - 12 ! - 22 ' - 32 0 - 35 : - 36 blank -11 + 0 50 - ] diff --git a/I1620/i1620_dp.c b/I1620/i1620_dp.c deleted file mode 100644 index 10f2a16c..00000000 --- a/I1620/i1620_dp.c +++ /dev/null @@ -1,463 +0,0 @@ -/* i1620_dp.c: IBM 1311 disk simulator - - 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"), - 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 1311 disk pack - - The 1311 disk pack has 100 cylinders, 10 tracks/cylinder, 20 sectors/track. - Each sector contains 105 characters of information: - - 5c sector address - 100c sector data - - By default, a sector's address field will be '00000', which is interpreted - to mean the implied sector number that would be in place if the disk pack - had been formatted with sequential sector numbers. - - 18-Oct-02 RMS Fixed bug in error testing (found by Hans Pufal) -*/ - -#include "i1620_defs.h" - -#define DP_NUMDR 4 /* #drives */ -#define UNIT_V_WAE (UNIT_V_UF + 0) /* write addr enab */ -#define UNIT_WAE (1 << UNIT_V_WAE) - -/* Disk format */ - -#define DP_ADDR 5 /* address */ -#define DP_DATA 100 /* data */ -#define DP_NUMCH (DP_ADDR + DP_DATA) - -#define DP_NUMSC 20 /* #sectors */ -#define DP_NUMSF 10 /* #surfaces */ -#define DP_NUMCY 100 /* #cylinders */ -#define DP_TOTSC (DP_NUMCY * DP_NUMSF * DP_NUMSC) -#define DP_SIZE (DP_TOTSC * DP_NUMCH) - -/* Disk control field */ - -#define DCF_DRV 0 /* drive select */ -#define DCF_SEC 1 /* sector addr */ -#define DCF_SEC_LEN 5 -#define DCF_CNT (DCF_SEC + DCF_SEC_LEN) /* sector count */ -#define DCF_CNT_LEN 3 -#define DCF_ADR (DCF_CNT + DCF_CNT_LEN) /* buffer address */ -#define DCF_ADR_LEN 5 -#define DCF_LEN (DCF_ADR + DCF_ADR_LEN) - -/* Functions */ - -#define FNC_SEEK 1 /* seek */ -#define FNC_SEC 0 /* sectors */ -#define FNC_WCH 1 /* write check */ -#define FNC_NRL 2 /* no rec lnt chk */ -#define FNC_TRK 4 /* tracks */ -#define FNC_WRI 8 /* write offset */ - -#define CYL u3 /* current cylinder */ - -extern uint8 M[MAXMEMSIZE]; /* memory */ -extern uint8 ind[NUM_IND]; -extern UNIT cpu_unit; - -int32 dp_stop = 1; /* disk err stop */ -uint32 dp_ba = 0; /* buffer addr */ - -t_stat dp_reset (DEVICE *dptr); -t_stat dp_rdadr (UNIT *uptr, int32 sec, int32 qnr, int32 qwc); -t_stat dp_rdsec (UNIT *uptr, int32 sec, int32 qnr, int32 qwc); -t_stat dp_wradr (UNIT *uptr, int32 sec, int32 qnr); -t_stat dp_wrsec (UNIT *uptr, int32 sec, int32 qnr); -int32 dp_fndsec (UNIT *uptr, int32 sec, t_bool rd); -t_stat dp_nexsec (UNIT *uptr, int32 sec, int32 psec, t_bool rd); -t_bool dp_zeroad (uint8 *ap); -int32 dp_cvt_ad (uint8 *ap); -int32 dp_trkop (int32 drv, int32 sec); -int32 dp_cvt_bcd (uint32 ad, int32 len); -void dp_fill (UNIT *uptr, uint32 da, int32 cnt); -t_stat dp_tstgm (uint32 c, int32 qnr); - -/* DP data structures - - dp_dev DP device descriptor - dp_unit DP unit list - dp_reg DP register list - dp_mod DP modifier list -*/ - -UNIT dp_unit[] = { - { UDATA (NULL, UNIT_FIX + UNIT_DISABLE + UNIT_ATTABLE + - UNIT_BUFABLE + UNIT_MUSTBUF + UNIT_BCD, DP_SIZE) }, - { UDATA (NULL, UNIT_FIX + UNIT_DISABLE + UNIT_ATTABLE + - UNIT_BUFABLE + UNIT_MUSTBUF + UNIT_BCD, DP_SIZE) }, - { UDATA (NULL, UNIT_FIX + UNIT_DISABLE + UNIT_ATTABLE + - UNIT_BUFABLE + UNIT_MUSTBUF + UNIT_BCD, DP_SIZE) }, - { UDATA (NULL, UNIT_FIX + UNIT_DISABLE + UNIT_ATTABLE + - UNIT_BUFABLE + UNIT_MUSTBUF + UNIT_BCD, DP_SIZE) } }; - -REG dp_reg[] = { - { FLDATA (ADCHK, ind[IN_DACH], 0) }, - { FLDATA (WLRC, ind[IN_DWLR], 0) }, - { FLDATA (CYLO, ind[IN_DCYO], 0) }, - { FLDATA (ERR, ind[IN_DERR], 0) }, - { FLDATA (DPSTOP, dp_stop, 0) }, - { URDATA (CYL, dp_unit[0].CYL, 10, 8, 0, - DP_NUMDR, PV_LEFT + REG_RO) }, - { NULL } }; - -MTAB dp_mod[] = { - { UNIT_WAE, 0, "write address disabled", "ADDROFF", NULL }, - { UNIT_WAE, UNIT_WAE, "write address enabled", "ADDRON", NULL }, - { 0 } }; - -DEVICE dp_dev = { - "DP", dp_unit, dp_reg, dp_mod, - DP_NUMDR, 10, 21, 1, 16, 5, - NULL, NULL, &dp_reset, - NULL, NULL, NULL }; - -/* Disk IO routine */ - -t_stat dp (uint32 op, uint32 pa, uint32 f0, uint32 f1) -{ -int32 drv, sa, sec, psec, cnt, qwc, qnr, t; -UNIT *uptr; -t_stat r; - -if (pa & 1) return STOP_INVDCF; /* dcf must be even */ -ind[IN_DACH] = ind[IN_DWLR] = 0; /* clr indicators */ -ind[IN_DERR] = ind[IN_DCYO] = 0; -sa = ADDR_A (pa, DCF_SEC); /* ptr to sector */ -if (((dp_unit[0].flags & UNIT_DIS) == 0) && /* only drive 0? */ - (dp_unit[1].flags & UNIT_DIS) && - (dp_unit[2].flags & UNIT_DIS) && - (dp_unit[3].flags & UNIT_DIS)) drv = 0; /* ignore drv select */ -else drv = (((M[pa] & 1)? M[pa]: M[sa]) & 0xE) >> 1; /* drive # */ -if (drv >= DP_NUMDR) return STOP_INVDRV; /* invalid? */ -uptr = dp_dev.units + drv; /* get unit ptr */ -if ((uptr->flags & UNIT_ATT) == 0) { /* attached? */ - ind[IN_DERR] = 1; /* no, error */ - CRETIOE (dp_stop, SCPE_UNATT); } - -sec = dp_cvt_bcd (sa, DCF_SEC_LEN); /* cvt sector */ -if ((sec < 0) || (sec >= (DP_NUMDR * DP_TOTSC))) /* bad sector? */ - return STOP_INVDSC; -if (op == OP_K) { /* seek? */ - if (f1 != FNC_SEEK) return STOP_INVFNC; /* really? */ - uptr->CYL = (sec / (DP_NUMSF * DP_NUMSC)) % /* set cyl # */ - DP_NUMCY; - return SCPE_OK; } /* done! */ - -cnt = dp_cvt_bcd (ADDR_A (pa, DCF_CNT), DCF_CNT_LEN); /* get count */ -t = dp_cvt_bcd (ADDR_A (pa, DCF_ADR), DCF_ADR_LEN); /* get address */ -if ((t < 0) || (t & 1)) return STOP_INVDBA; /* bad address? */ -dp_ba = t; /* save addr */ - -if (f1 >= FNC_WRI) return STOP_INVFNC; /* invalid func? */ -if (op == OP_RN) qwc = f1 & FNC_WCH; /* read? set wch */ -else if (op == OP_WN) { /* write? */ - if (op & FNC_WCH) return STOP_INVFNC; /* cant check */ - f1 = f1 + FNC_WRI; } /* offset fnc */ -else return STOP_INVFNC; /* not R or W */ -qnr = f1 & FNC_NRL; /* no rec check? */ - -switch (f1 & ~(FNC_WCH | FNC_NRL)) { /* case on function */ -case FNC_SEC: /* read sectors */ - if (cnt <= 0) return STOP_INVDCN; /* bad count? */ - psec = dp_fndsec (uptr, sec, TRUE); /* find sector */ - if (psec < 0) CRETIOE (dp_stop, STOP_DACERR); /* error? */ - do { /* loop on count */ - if (r = dp_rdsec (uptr, psec, qnr, qwc)) /* read sector */ - break; - sec++; psec++; } /* next sector */ - while ((--cnt > 0) && - ((r = dp_nexsec (uptr, sec, psec, TRUE)) == SCPE_OK)); - break; /* done, clean up */ - -case FNC_TRK: /* read track */ - psec = dp_trkop (drv, sec); /* start of track */ - for (cnt = 0; cnt < DP_NUMSC; cnt++) { /* full track */ - if (r = dp_rdadr (uptr, psec, qnr, qwc)) /* read addr */ - break; /* error? */ - if (r = dp_rdsec (uptr, psec, qnr, qwc)) /* read data */ - break; /* error? */ - psec = dp_trkop (drv, sec) + ((psec + 1) % DP_NUMSC); } - break; /* done, clean up */ - -case FNC_SEC + FNC_WRI: /* write */ - if (cnt <= 0) return STOP_INVDCN; /* bad count? */ - psec = dp_fndsec (uptr, sec, FALSE); /* find sector */ - if (psec < 0) CRETIOE (dp_stop, STOP_DACERR); /* error? */ - do { /* loop on count */ - if (r = dp_tstgm (M[dp_ba], qnr)) break; /* start with gm? */ - if (r = dp_wrsec (uptr, psec, qnr)) break; /* write data */ - sec++; psec++; } /* next sector */ - while ((--cnt > 0) && - ((r = dp_nexsec (uptr, sec, psec, FALSE)) == SCPE_OK)); - break; /* done, clean up */ - -case FNC_TRK + FNC_WRI: /* write track */ - if ((uptr->flags & UNIT_WAE) == 0) /* enabled? */ - return STOP_WRADIS; - psec = dp_trkop (drv, sec); /* start of track */ - for (cnt = 0; cnt < DP_NUMSC; cnt++) { /* full track */ - if (r = dp_tstgm (M[dp_ba], qnr)) break; /* start with gm? */ - if (r = dp_wradr (uptr, psec, qnr)) break; /* write addr */ - if (r = dp_wrsec (uptr, psec, qnr)) break; /* write data */ - psec = dp_trkop (drv, sec) + ((psec + 1) % DP_NUMSC); } - break; /* done, clean up */ - -default: /* unknown */ - return STOP_INVFNC; } - -if ((r == SCPE_OK) && !qnr) { /* eor check? */ - if ((M[dp_ba] & DIGIT) != GRP_MARK) { /* GM at end? */ - ind[IN_DWLR] = ind[IN_DERR] = 1; /* no, error */ - r = STOP_WRLERR; } } -if ((r != SCPE_OK) && /* error? */ - (dp_stop || !ind[IN_DERR])) return r; /* iochk or stop? */ -return SCPE_OK; /* continue */ -} - -/* Read or compare address with memory */ - -t_stat dp_rdadr (UNIT *uptr, int32 sec, int32 qnr, int32 qwc) -{ -int32 i; -uint8 ad; -int32 da = (sec % DP_TOTSC) * DP_NUMCH; /* char number */ -uint8 *ap = ((uint8 *) uptr->filebuf) + da; /* buf ptr */ -t_bool zad = dp_zeroad (ap); /* zero address */ -static const int32 dec_tab[DP_ADDR] = /* powers of 10 */ - { 10000, 1000, 100, 10, 1} ; - -for (i = 0; i < DP_ADDR; i++) { /* copy/check addr */ - if (zad) { /* addr zero? */ - ad = sec / dec_tab[i]; /* get addr digit */ - sec = sec % dec_tab[i]; } /* get remainder */ - else ad = *ap; /* addr digit */ - if (qwc) { /* write check? */ - if (dp_tstgm (M[dp_ba], qnr)) /* grp mrk in mem? */ - return STOP_WRLERR; /* yes, error */ - if (!zad && (M[dp_ba] != ad)) { /* digits equal? */ - ind[IN_DACH] = ind[IN_DERR] = 1; /* no, error */ - return STOP_DWCERR; } } - else M[dp_ba] = ad & (FLAG | DIGIT); /* store digit */ - if (dp_tstgm (*ap, qnr)) return STOP_WRLERR; /* grp mrk on disk? */ - ap++; PP (dp_ba); } /* adv ptrs */ -return SCPE_OK; -} - -/* Read or compare data with memory */ - -t_stat dp_rdsec (UNIT *uptr, int32 sec, int32 qnr, int32 qwc) -{ -int32 i; -int32 da = (sec % DP_TOTSC) * DP_NUMCH; /* char number */ -uint8 *ap = ((uint8 *) uptr->filebuf) + da + DP_ADDR; /* buf ptr */ - -for (i = 0; i < DP_DATA; i++) { /* copy data */ - if (qwc) { /* write check? */ - if (dp_tstgm (M[dp_ba], qnr)) /* grp mrk in mem? */ - return STOP_WRLERR; /* yes, error */ - if (M[dp_ba] != *ap) { /* dig+flags equal? */ - ind[IN_DACH] = ind[IN_DERR] = 1; /* no, error */ - return STOP_DWCERR; } } - else M[dp_ba] = *ap & (FLAG | DIGIT); /* flag + digit */ - if (dp_tstgm (*ap, qnr)) return STOP_WRLERR; /* grp mrk on disk? */ - ap++; PP (dp_ba); } /* adv ptrs */ -return SCPE_OK; -} - -/* Write address to disk */ - -t_stat dp_wradr (UNIT *uptr, int32 sec, int32 qnr) -{ -int32 i; -uint32 da = (sec % DP_TOTSC) * DP_NUMCH; /* char number */ -uint8 *ap = ((uint8 *) uptr->filebuf) + da; /* buf ptr */ - -for (i = 0; i < DP_ADDR; i++) { /* copy address */ - *ap = M[dp_ba] & (FLAG | DIGIT); /* flag + digit */ - if (da >= uptr->hwmark) uptr->hwmark = da + 1; - if (dp_tstgm (*ap, qnr)) { /* grp mrk fm mem? */ - dp_fill (uptr, da + 1, DP_NUMCH - i - 1); /* fill addr+data */ - return STOP_WRLERR; } /* error */ - da++; ap++; PP (dp_ba); /* adv ptrs */ - } -return SCPE_OK; -} - -/* Write data to disk */ - -t_stat dp_wrsec (UNIT *uptr, int32 sec, int32 qnr) -{ -int32 i; -uint32 da = ((sec % DP_TOTSC) * DP_NUMCH) + DP_ADDR; /* char number */ -uint8 *ap = ((uint8 *) uptr->filebuf) + da; /* buf ptr */ - -for (i = 0; i < DP_DATA; i++) { /* copy data */ - *ap = M[dp_ba] & (FLAG | DIGIT); /* get character */ - if (da >= uptr->hwmark) uptr->hwmark = da + 1; - if (dp_tstgm (*ap, qnr)) { /* grp mrk fm mem? */ - dp_fill (uptr, da + 1, DP_DATA - i - 1); /* fill data */ - return STOP_WRLERR; } /* error */ - da++; ap++; PP (dp_ba); /* adv ptrs */ - } -return SCPE_OK; -} - -/* Find sector */ - -int32 dp_fndsec (UNIT *uptr, int32 sec, t_bool rd) -{ -int32 ctrk = sec % (DP_NUMSF * DP_NUMSC); /* curr trk-sec */ -int32 psec = ((uptr->CYL) * (DP_NUMSF * DP_NUMSC)) + ctrk; -int32 da = psec * DP_NUMCH; /* char number */ -uint8 *ap = ((uint8 *) uptr->filebuf) + da; /* buf ptr */ -int32 dskad, i; - -if (dp_zeroad (ap)) return psec; /* addr zero? ok */ -dskad = dp_cvt_ad (ap); /* cvt addr */ -if (dskad == sec) { /* match? */ - if (rd || ((*ap & FLAG) == 0)) return psec; /* read or !wprot? */ - ind[IN_DACH] = ind[IN_DERR] = 1; /* no match */ - return -1; } -psec = psec - (psec % DP_NUMSC); /* sector 0 */ -for (i = 0; i < DP_NUMSC; i++, psec++) { /* check track */ - da = psec * DP_NUMCH; /* char number */ - ap = ((uint8 *) uptr->filebuf) + da; /* word pointer */ - if (dp_zeroad (ap)) continue; /* no implicit match */ - dskad = dp_cvt_ad (ap); /* cvt addr */ - if (dskad == sec) { /* match? */ - if (rd || ((*ap & FLAG) == 0)) return psec; /* read or !wprot? */ - ind[IN_DACH] = ind[IN_DERR] = 1; /* no match */ - return -1; } } -ind[IN_DACH] = ind[IN_DERR] = 1; /* no match */ -return -1; -} - -/* Find next sector - must be sequential, cannot cross cylinder boundary */ - -t_stat dp_nexsec (UNIT *uptr, int32 sec, int32 psec, t_bool rd) -{ -int32 ctrk = psec % (DP_NUMSF * DP_NUMSC); /* curr trk-sec */ -int32 da = psec * DP_NUMCH; /* word number */ -uint8 *ap = ((uint8 *) uptr->filebuf) + da; /* buf ptr */ -int32 dskad; - -if (ctrk) { /* not trk zero? */ - if (dp_zeroad (ap)) return SCPE_OK; /* addr zero? ok */ - dskad = dp_cvt_ad (ap); /* cvt addr */ - if ((dskad == sec) && /* match? */ - (rd || ((*ap & FLAG) == 0))) return SCPE_OK; /* read or !wprot? */ - ind[IN_DACH] = ind[IN_DERR] = 1; /* no, error */ - return STOP_DACERR; } -ind[IN_DCYO] = ind[IN_DERR] = 1; /* cyl overflow */ -return STOP_CYOERR; -} - -/* Test for zero address */ - -t_bool dp_zeroad (uint8 *ap) -{ -int32 i; - -for (i = 0; i < DP_ADDR; i++, ap++) { /* loop thru addr */ - if (*ap & DIGIT) return FALSE; } /* nonzero? lose */ -return TRUE; /* all zeroes */ -} - -/* Test for group mark when enabled */ - -t_stat dp_tstgm (uint32 c, int32 qnr) -{ -if (!qnr && ((c & DIGIT) == GRP_MARK)) { /* premature GM? */ - ind[IN_DWLR] = ind[IN_DERR] = 1; /* error */ - return STOP_WRLERR; } -return SCPE_OK; -} - -/* Convert disk address to binary - invalid char force bad address */ - -int32 dp_cvt_ad (uint8 *ap) -{ -int32 i, r; -uint8 c; - -for (i = r = 0; i < DP_ADDR; i++, ap++) { /* loop thru addr */ - c = *ap & DIGIT; /* get digit */ - if (BAD_DIGIT (c)) return -1; /* bad digit? */ - r = (r * 10) + c; } /* bcd to binary */ -return r; -} - -/* Track operation setup */ - -int32 dp_trkop (int32 drv, int32 sec) -{ -int32 ctrk = (sec / DP_NUMSC) % DP_NUMSF; - -return ((drv * DP_TOTSC) + (dp_unit[drv].CYL * DP_NUMSF * DP_NUMSC) + - (ctrk * DP_NUMSC)); -} - -/* Convert DCF BCD field to binary */ - -int32 dp_cvt_bcd (uint32 ad, int32 len) -{ -uint8 c; -int32 r; - -for (r = 0; len > 0; len--) { /* loop thru char */ - c = M[ad] & DIGIT; /* get digit */ - if (BAD_DIGIT (c)) return -1; /* invalid? */ - r = (r * 10) + c; /* cvt to bin */ - PP (ad); } /* next digit */ -return r; -} - -/* Fill sector buffer with zero */ - -void dp_fill (UNIT *uptr, uint32 da, int32 cnt) -{ -while (cnt-- > 0) { /* fill with zeroes*/ - *(((uint8 *) uptr->filebuf) + da) = 0; - if (da >= uptr->hwmark) uptr->hwmark = da + 1; - da++; } -return; -} - -/* Reset routine */ - -t_stat dp_reset (DEVICE *dptr) -{ -int32 i; - -for (i = 0; i < DP_NUMDR; i++) dp_unit[i].CYL = 0; /* reset cylinder */ -ind[IN_DACH] = ind[IN_DWLR] = 0; /* clr indicators */ -ind[IN_DERR] = ind[IN_DCYO] = 0; -return SCPE_OK; -} diff --git a/I1620/i1620_fp.c b/I1620/i1620_fp.c deleted file mode 100644 index 0cb54a96..00000000 --- a/I1620/i1620_fp.c +++ /dev/null @@ -1,388 +0,0 @@ -/* i1620_fp.c: IBM 1620 floating point simulator - - 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"), - 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 IBM 1620 uses a variable length floating point format, with a fixed - two digit decimal exponent and a variable length decimal mantissa: - - _ S_S - M.......MEE - - where S represents flag bits if the mantissa or exponent are negative. -*/ - -#include "i1620_defs.h" - -#define FP_LMAX 100 /* max fp mant lnt */ -#define FP_EMAX 99 /* max fp exponent */ - -/* Unpacked floating point operand */ - -struct fp_opnd { - int32 sign; /* 0 => +, 1 => - */ - int32 exp; /* binary exponent */ - uint32 lnt; /* mantissa length */ - uint32 addr; /* mantissa addr */ - uint32 zero; /* 0 => nz, 1 => zero */ -}; - -typedef struct fp_opnd FPA; - -extern uint8 M[MAXMEMSIZE]; /* main memory */ -extern uint8 ind[NUM_IND]; /* indicators */ -extern UNIT cpu_unit; - -t_stat fp_scan_mant (uint32 ad, uint32 *lnt, uint32 *zro); -t_stat fp_zero (FPA *fp); - -extern t_stat xmt_field (uint32 d, uint32 s, uint32 skp); -extern t_stat add_field (uint32 d, uint32 s, t_bool sub, t_bool sto, int32 *sta); -extern t_stat mul_field (uint32 d, uint32 s); -extern t_stat xmt_divd (uint32 d, uint32 s); -extern t_stat div_field (uint32 dvd, uint32 dvr, int32 *ez); - -/* Unpack and validate a floating point argument */ - -t_stat fp_unpack (uint32 ad, FPA *fp) -{ -uint8 d0, d1, esign; - -esign = M[ad] & FLAG; /* get exp sign */ -d0 = M[ad] & DIGIT; /* get exp lo digit */ -MM (ad); -if ((M[ad] & FLAG) == 0) return STOP_FPMF; /* no flag on hi exp? */ -d1 = M[ad] & DIGIT; /* get exp hi digit */ -MM (ad); -fp->addr = ad; /* save mant addr */ -if (BAD_DIGIT (d1) || BAD_DIGIT (d0)) return STOP_INVDIG; /* exp bad dig? */ -fp->exp = ((d1 * 10) + d0) * (esign? -1: 1); /* convert exponent */ -fp->sign = (M[ad] & FLAG)? 1: 0; /* get mantissa sign */ -return fp_scan_mant (fp->addr, &(fp->lnt), &(fp->zero)); -} - -/* Unpack and validate source and destination arguments */ - -t_stat fp_unpack_two (uint32 dad, uint32 sad, FPA *dfp, FPA *sfp) -{ -t_stat r; - -if ((r = fp_unpack (dad, dfp)) != SCPE_OK) return r; /* unpack dst */ -if ((r = fp_unpack (sad, sfp)) != SCPE_OK) return r; /* unpack src */ -if (sfp->lnt != dfp->lnt) return STOP_FPUNL; /* lnts must be equal */ -return SCPE_OK; -} - -/* Pack floating point result */ - -t_stat fp_pack (FPA *fp) -{ -int32 e; -uint32 i, mad; - -e = (fp->exp >= 0)? fp->exp: -fp->exp; /* get |exp| */ -if (e > FP_EMAX) { /* too big? */ - ind[IN_EXPCHK] = 1; /* set indicator */ - if (fp->exp < 0) return fp_zero (fp); /* underflow? */ - mad = fp->addr; - for (i = 0; i < fp->lnt; i++) { /* mant = 99...99 */ - M[mad] = (M[mad] & FLAG) | 9; - MM (mad); } - e = FP_EMAX; } /* cap at max */ -M[ADDR_A (fp->addr, 1)] = (e / 10) | FLAG; /* high exp digit */ -M[ADDR_A (fp->addr, 2)] = (e % 10) | /* low exp digit */ - ((fp->exp < 0)? FLAG: 0); -return SCPE_OK; -} - -/* Shift mantissa right n positions */ - -void fp_rsh (FPA *fp, uint32 n) -{ -uint32 i, sad, dad; - -if (n == 0) return; /* zero? done */ -sad = ADDR_S (fp->addr, n); /* src = addr - n */ -dad = fp->addr; /* dst = n */ -for (i = 0; i < fp->lnt; i++) { /* move digits */ - if (i >= (fp->lnt - n)) M[dad] = M[dad] & FLAG; - else M[dad] = (M[dad] & FLAG) | (M[sad] & DIGIT); - MM (dad); - MM (sad); } -return; -} - -/* Shift mantissa left 1 position */ - -void fp_lsh_1 (FPA *fp) -{ -uint32 i, mad, nxt; - -mad = ADDR_S (fp->addr, fp->lnt - 1); /* hi order digit */ -for (i = 0; i < (fp->lnt - 1); i++) { /* move lnt-1 digits */ - nxt = ADDR_A (mad, 1); - M[mad] = (M[mad] & FLAG) | (M[nxt] & DIGIT); - mad = nxt; } -M[mad] = M[mad] & FLAG; /* clear last digit */ -return; -} - -/* Clear floating point number */ - -t_stat fp_zero (FPA *fp) -{ -uint32 i, mad = fp->addr; - -for (i = 0; i < fp->lnt; i++) { /* clear mantissa */ - M[mad] = (i? M[mad] & FLAG: 0); /* clear sign bit */ - MM (mad); } -M[ADDR_A (fp->addr, 1)] = FLAG + 9; /* exp = -99 */ -M[ADDR_A (fp->addr, 2)] = FLAG + 9; /* exp = -99 */ -ind[IN_EZ] = 1; /* result = 0 */ -ind[IN_HP] = 0; -return SCPE_OK; -} - -/* Scan floating point mantissa for length and (optionally) zero */ - -t_stat fp_scan_mant (uint32 ad, uint32 *lnt, uint32 *zro) -{ -uint8 d, l, z; - -z = 1; /* assume zero */ -for (l = 1; l <= FP_LMAX; l++) { /* scan to get length */ - d = M[ad] & DIGIT; /* get mant digit */ - if (d) z = 0; /* non-zero? */ - if ((l != 1) && (M[ad] & FLAG)) { /* flag past first dig? */ - *lnt = l; /* set returns */ - if (zro) *zro = z; - return SCPE_OK; } - MM (ad); } -return STOP_FPLNT; /* too long */ -} - -/* Copy floating point mantissa */ - -void fp_copy_mant (uint32 d, uint32 s, uint32 l) -{ -uint32 i; - -if (ind[IN_HP]) M[d] = M[d] & ~FLAG; /* clr/set sign */ -else M[d] = M[d] | FLAG; -for (i = 0; i < l; i++) { /* copy src */ - M[d] = (M[d] & FLAG) | (M[s] & DIGIT); /* preserve flags */ - MM (d); - MM (s); } -return; -} - -/* Compare floating point mantissa */ - -int32 fp_comp_mant (uint32 d, uint32 s, uint32 l) -{ -uint8 i, dd, sd; - -d = ADDR_S (d, l - 1); /* start of mantissa */ -s = ADDR_S (s, l - 1); -for (i = 0; i < l; i++) { /* compare dst:src */ - dd = M[d] & DIGIT; /* get dst digit */ - sd = M[s] & DIGIT; /* get src digit */ - if (dd > sd) return 1; /* >? done */ - if (dd < sd) return -1; /* = ((int32) dfp.lnt))) { /* src = 0, or too small? */ - if (dfp.zero) return fp_zero (&dfp); /* res = dst, zero? */ - ind[IN_EZ] = 0; /* res nz, set EZ, HP */ - ind[IN_HP] = (dfp.sign == 0); - return SCPE_OK; } -if (dfp.zero || (dif <= -((int32) dfp.lnt))) { /* dst = 0, or too small? */ - if (sfp.zero) return fp_zero (&dfp); /* res = src, zero? */ - r = xmt_field (d, s, 3); /* copy src to dst */ - ind[IN_EZ] = 0; /* res nz, set EZ, HP */ - ind[IN_HP] = (dfp.sign == 0); - return r; } - -if (dif > 0) { /* dst exp > src exp? */ - sad = sfp.addr; /* save src in save area */ - for (i = 0; i < sfp.lnt; i++) { - sav_src[i] = M[sad]; - MM (sad); } - fp_rsh (&sfp, dif); } /* denormalize src */ -else if (dif < 0) { /* dst exp < src exp? */ - dfp.exp = sfp.exp; /* res exp = src exp */ - fp_rsh (&dfp, -dif); } /* denormalize dst */ -r = add_field (dfp.addr, sfp.addr, sub, TRUE, &sta); /* add mant, set EZ, HP */ -if (dif > 0) { /* src denormalized? */ - sad = sfp.addr; /* restore src from */ - for (i = 0; i < sfp.lnt; i++) { /* save area */ - M[sad] = sav_src[i]; - MM (sad); } } -if (r != SCPE_OK) return r; /* add error? */ - -hi = ADDR_S (dfp.addr, dfp.lnt - 1); /* addr of hi digit */ -if (sta == ADD_CARRY) { /* carry out? */ - fp_rsh (&dfp, 1); /* shift mantissa */ - M[hi] = FLAG + 1; /* high order 1 */ - dfp.exp = dfp.exp + 1; - ind[IN_EZ] = 0; /* not zero */ - ind[IN_HP] = (dfp.sign == 0); } /* set HP */ -else if (ind[IN_EZ]) return fp_zero (&dfp); /* result zero? */ -else { while ((M[hi] & DIGIT) == 0) { /* until normalized */ - fp_lsh_1 (&dfp); /* left shift */ - dfp.exp = dfp.exp - 1; } } /* decr exponent */ - -return fp_pack (&dfp); /* pack and exit */ -} - -/* Floating point multiply */ - -t_stat fp_mul (uint32 d, uint32 s) -{ -FPA sfp, dfp; -uint32 pad; -t_stat r; - -r = fp_unpack_two (d, s, &dfp, &sfp); /* unpack operands */ -if (r != SCPE_OK) return r; /* error? */ -if (sfp.zero || dfp.zero) return fp_zero (&dfp); /* either zero? */ - -r = mul_field (dfp.addr, sfp.addr); /* mul, set EZ, HP */ -if (r != SCPE_OK) return r; -if (M[ADDR_S (PROD_AREA_END, 2 * dfp.lnt)] & DIGIT) { /* hi prod dig set? */ - pad = ADDR_S (PROD_AREA_END - 1, dfp.lnt); /* no normalization */ - dfp.exp = dfp.exp + sfp.exp; } /* res exp = sum */ -else { pad = ADDR_S (PROD_AREA_END, dfp.lnt); /* 'normalize' 1 */ - dfp.exp = dfp.exp + sfp.exp - 1; } /* res exp = sum - 1 */ -fp_copy_mant (dfp.addr, pad, dfp.lnt); /* copy prod to mant */ - -return fp_pack (&dfp); /* pack and exit */ -} - -/* Floating point divide */ - -t_stat fp_div (uint32 d, uint32 s) -{ -FPA sfp, dfp; -uint32 i, pad, a100ml, a99ml; -int32 ez; -t_stat r; - -r = fp_unpack_two (d, s, &dfp, &sfp); /* unpack operands */ -if (r != SCPE_OK) return r; /* error? */ -if (sfp.zero) { /* divide by zero? */ - ind[IN_OVF] = 1; /* dead jim */ - return SCPE_OK; } -if (dfp.zero) return fp_zero (&dfp); /* divide into zero? */ - -for (i = 0; i < PROD_AREA_LEN; i++) /* clear prod area */ - M[PROD_AREA + i] = 0; -a100ml = ADDR_S (PROD_AREA_END, dfp.lnt); /* 100 - lnt */ -a99ml = ADDR_S (PROD_AREA_END - 1, dfp.lnt); /* 99 - lnt */ -if (fp_comp_mant (dfp.addr, sfp.addr, dfp.lnt) >= 0) { /* |Mdst| >= |Msrc|? */ - pad = a100ml; - dfp.exp = dfp.exp - sfp.exp + 1; } /* res exp = diff + 1 */ -else { pad = a99ml; - dfp.exp = dfp.exp - sfp.exp; } /* res exp = diff */ -r = xmt_divd (pad, dfp.addr); /* xmt dividend */ -if (r != SCPE_OK) return r; /* error? */ -r = div_field (a100ml, sfp.addr, &ez); /* divide fractions */ -if (r != SCPE_OK) return r; /* error? */ -if (ez) return fp_zero (&dfp); /* result zero? */ - -ind[IN_HP] = ((dfp.sign ^ sfp.sign) == 0); /* set res sign */ -ind[IN_EZ] = 0; /* not zero */ -fp_copy_mant (dfp.addr, a99ml, dfp.lnt); /* copy result */ - -return fp_pack (&dfp); -} - -/* Floating shift right */ - -t_stat fp_fsr (uint32 d, uint32 s) -{ -uint32 cnt; -uint8 t; - -if (d == s) return SCPE_OK; /* no move? */ - -cnt = 0; -M[d] = (M[d] & FLAG) | (M[s] & DIGIT); /* move 1st wo flag */ -do { MM (d); /* decr ptrs */ - MM (s); - t = M[d] = M[s] & (FLAG | DIGIT); /* copy others */ - if (cnt++ > MEMSIZE) return STOP_FWRAP; } /* (stop runaway) */ -while ((t & FLAG) == 0); /* until src flag */ - -cnt = 0; -do { MM (d); /* decr pointer */ - t = M[d]; /* save old val */ - M[d] = 0; /* zero field */ - if (cnt++ > MEMSIZE) return STOP_FWRAP; } /* (stop runaway) */ -while ((t & FLAG) == 0); /* until dst flag */ -return SCPE_OK; -} - -/* Floating shift left - note that dst is addr of high order digit */ - -t_stat fp_fsl (uint32 d, uint32 s) -{ -uint32 i, lnt; -uint8 sign; -t_stat r; - -if (d == s) return SCPE_OK; -sign = M[s] & FLAG; /* get src sign */ -r = fp_scan_mant (s, &lnt, NULL); /* get src length */ -if (r != SCPE_OK) return r; /* error? */ -s = ADDR_S (s, lnt - 1); /* hi order src */ -M[d] = M[s] & (FLAG | DIGIT); /* move 1st w flag */ -M[s] = M[s] & ~FLAG; /* clr flag from src */ -for (i = 1; i < lnt; i++) { /* move src to dst */ - PP (d); /* incr ptrs */ - PP (s); - M[d] = M[s] & DIGIT; } /* move just digit */ -PP (d); /* incr pointer */ -while ((M[d] & FLAG) == 0) { /* until flag */ - M[d] = 0; /* clear field */ - PP (d); } -if (sign) M[d] = FLAG; /* -? zero under sign */ -return SCPE_OK; -} diff --git a/I1620/i1620_lp.c b/I1620/i1620_lp.c deleted file mode 100644 index 28283f61..00000000 --- a/I1620/i1620_lp.c +++ /dev/null @@ -1,316 +0,0 @@ -/* i1620_lp.c: IBM 1443 line printer simulator - - 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"), - 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 1443 line printer - - 25-Apr-03 RMS Revised for extended file support -*/ - -#include "i1620_defs.h" - -#define LPT_BSIZE 197 /* buffer size */ - -#define K_IMM 0x10 /* control now */ -#define K_LIN 0x20 /* spc lines */ -#define K_CH10 0x40 /* chan 10 */ -#define K_LCNT 0x03 /* line count */ -#define K_CHAN 0x0F /* channel */ - -extern uint8 M[MAXMEMSIZE]; -extern uint8 ind[NUM_IND]; -extern UNIT cpu_unit; -extern uint32 io_stop; - -uint32 cct[CCT_LNT] = { 03 }; /* car ctrl tape */ -int32 cct_lnt = 66, cct_ptr = 0; /* cct len, ptr */ -int32 lpt_bptr = 0; /* lpt buf ptr */ -char lpt_buf[LPT_BSIZE + 1]; /* lpt buf */ -int32 lpt_savctrl = 0; /* saved spc ctrl */ - -t_stat lpt_svc (UNIT *uptr); -t_stat lpt_reset (DEVICE *dptr); -t_stat lpt_attach (UNIT *uptr, char *cptr); -void lpt_buf_init (void); -t_stat lpt_num (uint32 pa, uint32 len, uint32 f1); -t_stat lpt_print (void); -t_stat lpt_space (int32 lines, int32 lflag); - -#define CHP(ch,val) ((val) & (1 << (ch))) - -/* LPT data structures - - lpt_dev LPT device descriptor - lpt_unit LPT unit descriptor - lpt_reg LPT register list -*/ - -UNIT lpt_unit = { - UDATA (&lpt_svc, UNIT_SEQ+UNIT_ATTABLE, 50) }; - -REG lpt_reg[] = { - { BRDATA (LBUF, lpt_buf, 8, 8, LPT_BSIZE + 1) }, - { DRDATA (BPTR, lpt_bptr, 8) }, - { HRDATA (PCTL, lpt_savctrl, 8) }, - { FLDATA (PRCHK, ind[IN_PRCHK], 0) }, - { FLDATA (PRCH9, ind[IN_PRCH9], 0) }, - { FLDATA (PRCH12, ind[IN_PRCH12], 0) }, - { FLDATA (PRBSY, ind[IN_PRBSY], 0) }, - { DRDATA (POS, lpt_unit.pos, T_ADDR_W), PV_LEFT }, - { BRDATA (CCT, cct, 8, 32, CCT_LNT) }, - { DRDATA (CCTP, cct_ptr, 8), PV_LEFT }, - { DRDATA (CCTL, cct_lnt, 8), REG_RO + PV_LEFT }, - { NULL } }; - -DEVICE lpt_dev = { - "LPT", &lpt_unit, lpt_reg, NULL, - 1, 10, 31, 1, 8, 7, - NULL, NULL, &lpt_reset, - NULL, &lpt_attach, NULL }; - -/* Data tables */ - -/* Numeric (flag plus digit) to lineprinter (ASCII) */ - -const char num_to_lpt[32] = { - '0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', '\'', ' ', '@', ':', ' ', 'G', - '-', 'J', 'K', 'L', 'M', 'N', 'O', 'P', - 'Q', 'R', 'W', ' ', '*', ' ', -1, 'X' }; - -/* Alphameric (digit pair) to lineprinter (ASCII) */ - -const char alp_to_lpt[256] = { - ' ', -1, '?', '.', ')', -1, -1, -1, /* 00 */ - -1, -1, -1, -1, -1, -1, -1, -1, - '+', -1, '!', '$', '*', ' ', -1, -1, /* 10 */ - -1, -1, -1, -1, -1, -1, -1, -1, - '-', '/', '\'', ',', '(', -1, -1, -1, /* 20 */ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, '0', '=', '@', ':', -1, -1, /* 30 */ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 'A', 'B', 'C', 'D', 'E', 'F', 'G', /* 40 */ - 'H', 'I', -1, -1, -1, -1, -1, -1, - '-', 'J', 'K', 'L', 'M', 'N', 'O', 'P', /* 50 */ - 'Q', 'R', -1, -1, -1, -1, -1, -1, - -1, '/', 'S', 'T', 'U', 'V', 'W', 'X', /* 60 */ - 'Y', 'Z', -1, -1, -1, -1, -1, -1, - '0', '1', '2', '3', '4', '5', '6', '7', /* 70 */ - '8', '9', -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, /* 80 */ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, /* 90 */ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, /* A0 */ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, /* B0 */ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, /* C0 */ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, /* D0 */ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, /* E0 */ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, /* F0 */ - -1, -1, -1, -1, -1, -1, -1, -1 }; - -/* Line printer IO routine - - - Hard errors halt the system. - - Invalid characters print a blank, set the WRCHK and PRCHK - flags, and halt the system if IO stop is set. -*/ - -t_stat lpt (uint32 op, uint32 pa, uint32 f0, uint32 f1) -{ -int8 lpc; -uint8 z, d; -t_stat r, inv = SCPE_OK; - -sim_cancel (&lpt_unit); /* "stall" until */ -ind[IN_PRBSY] = 0; /* printer free */ - -switch (op) { /* decode op */ -case OP_K: /* control */ - lpt_savctrl = (f0 << 4) | f1; /* form ctrl */ - if (lpt_savctrl & K_IMM) return lpt_print (); /* immediate? */ - break; -case OP_DN: - return lpt_num (pa, 20000 - (pa % 20000), f1); /* dump numeric */ -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 */ - if ((f1 & 1) == 0) { ; /* print now? */ - r = lpt_print (); /* print line */ - if (r != SCPE_OK) return r; } - CRETIOE (io_stop, inv); -default: /* invalid function */ - return STOP_INVFNC; } -return SCPE_OK; -} - -/* Print numeric */ - -t_stat lpt_num (uint32 pa, uint32 len, uint32 f1) -{ -uint32 end; -uint8 d; -int8 lpc; -t_stat r, inv = SCPE_OK; - -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; - 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 */ - lpt_buf[lpt_bptr++] = lpc & 0x7F; /* fill buffer */ - PP (pa); } /* incr mem addr */ -if ((f1 & 1) == 0) { /* print now? */ - r = lpt_print (); /* print line */ - if (r != SCPE_OK) return r; } -CRETIOE (io_stop, inv); -} - -/* Print and space */ - -t_stat lpt_print (void) -{ -int32 i, chan, ctrl = lpt_savctrl; - -if ((lpt_unit.flags & UNIT_ATT) == 0) { /* not attached? */ - ind[IN_PRCHK] = ind[IN_WRCHK] = 1; /* wr, pri check */ - return SCPE_UNATT; } - -ind[IN_PRBSY] = 1; /* print busy */ -sim_activate (&lpt_unit, lpt_unit.time); /* start timer */ - -for (i = LPT_WIDTH; i <= LPT_BSIZE; i++) /* clear unprintable */ - lpt_buf[i] = ' '; -while ((lpt_bptr > 0) && (lpt_buf[lpt_bptr - 1] == ' ')) - lpt_buf[--lpt_bptr] = 0; /* trim buffer */ -if (lpt_bptr) { /* any line? */ - fputs (lpt_buf, lpt_unit.fileref); /* print */ - 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; } } - -lpt_savctrl = 0x61; /* reset ctrl */ -if ((ctrl & K_LIN) == ((ctrl & K_IMM)? 0: K_LIN)) /* space lines? */ - return lpt_space (ctrl & K_LCNT, FALSE); -chan = lpt_savctrl & K_CHAN; /* basic chan */ -if (lpt_savctrl & K_CH10) { /* chan 10-12? */ - if (chan == 0) chan = 10; - else if (chan == 3) chan = 11; - else if (chan == 4) chan = 12; - else chan = 0; } -if ((chan == 0) || (chan > 12)) return STOP_INVFNC; -for (i = 1; i < cct_lnt + 1; i++) { /* sweep thru cct */ - if (CHP (chan, cct[(cct_ptr + i) % cct_lnt])) - return lpt_space (i, TRUE); } -return STOP_CCT; /* runaway channel */ -} - -/* Space routine - space or skip n lines - - Inputs: - count = number of lines to space or skip - sflag = skip (TRUE) or space (FALSE) -*/ - -t_stat lpt_space (int32 count, int32 sflag) -{ -int32 i; - -cct_ptr = (cct_ptr + count) % cct_lnt; /* adv cct, mod lnt */ -if (sflag && CHP (0, cct[cct_ptr])) /* skip, top of form? */ - fputs ("\n\f", lpt_unit.fileref); /* nl, ff */ -else { for (i = 0; i < count; i++) /* count lines */ - fputc ('\n', lpt_unit.fileref); } -lpt_unit.pos = ftell (lpt_unit.fileref); /* update position */ -ind[IN_PRCH9] = CHP (9, cct[cct_ptr]) != 0; /* set indicators */ -ind[IN_PRCH12] = CHP (12, cct[cct_ptr]) != 0; -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; } -return SCPE_OK; -} - -/* Unit service - clear printer busy */ - -t_stat lpt_svc (UNIT *uptr) -{ -ind[IN_PRBSY] = 0; -return SCPE_OK; -} - -/* Initialize lpt buffer */ - -void lpt_buf_init (void) -{ -int32 i; - -lpt_bptr = 0; -for (i = 0; i < LPT_WIDTH + 1; i++) lpt_buf[i] = 0; -return; -} - -/* Reset routine */ - -t_stat lpt_reset (DEVICE *dptr) -{ -lpt_buf_init (); /* clear buffer */ -cct_ptr = 0; /* clear cct ptr */ -lpt_savctrl = 0x61; /* clear cct action */ -ind[IN_PRCHK] = ind[IN_PRBSY] = 0; /* clear indicators */ -ind[IN_PRCH9] = ind[IN_PRCH12] = 0; -return SCPE_OK; -} - -/* Attach routine */ - -t_stat lpt_attach (UNIT *uptr, char *cptr) -{ -lpt_reset (&lpt_dev); -return attach_unit (uptr, cptr); -} diff --git a/I1620/i1620_pt.c b/I1620/i1620_pt.c deleted file mode 100644 index 2f213077..00000000 --- a/I1620/i1620_pt.c +++ /dev/null @@ -1,436 +0,0 @@ -/* i1620_pt.c: IBM 1621/1624 paper tape reader/punch simulator - - 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"), - 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 1621 paper tape reader - ptp 1624 paper tape punch - - 25-Apr-03 RMS Revised for extended file support -*/ - -#include "i1620_defs.h" - -#define PT_EL 0x80 /* end record */ -#define PT_X 0x40 /* X */ -#define PT_O 0x20 /* O */ -#define PT_C 0x10 /* C */ -#define PT_FD 0x7F /* deleted */ - -extern uint8 M[MAXMEMSIZE]; -extern uint8 ind[NUM_IND]; -extern UNIT cpu_unit; -extern uint32 io_stop; - -t_stat ptr_reset (DEVICE *dptr); -t_stat ptr_boot (int32 unitno, DEVICE *dptr); -t_stat ptr_read (uint8 *c, t_bool ignfeed); -t_stat ptp_reset (DEVICE *dptr); -t_stat ptp_write (uint32 c); -t_stat ptp_num (uint32 pa, uint32 len); - -/* PTR data structures - - ptr_dev PTR device descriptor - ptr_unit PTR unit descriptor - ptr_reg PTR register list -*/ - -UNIT ptr_unit = { - UDATA (NULL, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0) }; - -REG ptr_reg[] = { - { DRDATA (POS, ptr_unit.pos, T_ADDR_W), PV_LEFT }, - { NULL } }; - -DEVICE ptr_dev = { - "PTR", &ptr_unit, ptr_reg, NULL, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &ptr_reset, - &ptr_boot, NULL, NULL }; - -/* PTP data structures - - ptp_dev PTP device descriptor - ptp_unit PTP unit descriptor - ptp_reg PTP register list -*/ - -UNIT ptp_unit = { - UDATA (NULL, UNIT_SEQ+UNIT_ATTABLE, 0) }; - -REG ptp_reg[] = { - { DRDATA (POS, ptp_unit.pos, T_ADDR_W), PV_LEFT }, - { NULL } }; - -DEVICE ptp_dev = { - "PTP", &ptp_unit, ptp_reg, NULL, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &ptp_reset, - NULL, NULL, NULL }; - -/* Data tables */ - -/* Paper tape reader odd parity chart: 1 = bad, 0 = ok */ - -const int8 bad_par[128] = { - 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, /* 00 */ - 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, /* 10 */ - 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, /* 20 */ - 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, /* 30 */ - 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, /* 40 */ - 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, /* 50 */ - 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, /* 60 */ - 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0 }; /* 70 */ - -/* Paper tape read (7b) to numeric (one digit) */ - -const int8 ptr_to_num[128] = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* - */ - 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x00, 0x0E, 0x0F, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* C */ - 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x00, 0x0E, 0x0F, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* O */ - 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x00, 0x0E, 0x0F, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* OC */ - 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x00, 0x0E, 0x0F, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* X */ - 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x10, 0x1E, 0x1F, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* XC */ - 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x10, 0x1E, 0x1F, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* XO */ - 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x00, 0x0E, 0x0F, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* XOC */ - 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x00, 0x0E, 0x0F }; - -/* Paper tape read (7b) to alphameric (two digits) - Codes XO82, 82, XO842, 842 do not have consistent translations -*/ - -const int8 ptr_to_alp[128] = { - 0x00, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* - */ - 0x78, 0x79, -1, 0x33, 0x34, 0x70, -1, 0x0F, - 0x00, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* C */ - 0x78, 0x79, -1, 0x33, 0x34, 0x70, -1, 0x0F, - 0x70, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* O */ - 0x68, 0x69, 0x0A, 0x23, 0x24, 0x60, 0x0E, 0x0F, - 0x70, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* OC */ - 0x68, 0x69, 0x0A, 0x23, 0x24, 0x60, 0x0E, 0x0F, - 0x20, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* X */ - 0x58, 0x59, 0x5A, 0x13, 0x14, 0x50, 0x5E, 0x5F, - 0x20, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* XC */ - 0x58, 0x59, 0x5A, 0x13, 0x14, 0x50, 0x5E, 0x5F, - 0x10, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* XO */ - 0x48, 0x49, -1, 0x03, 0x04, 0x40, -1, 0x7F, - 0x10, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* XOC */ - 0x48, 0x49, -1, 0x03, 0x04, 0x40, -1, 0x7F }; - -/* Numeric (flag + digit) to paper tape punch */ - -const int8 num_to_ptp[32] = { - 0x20, 0x01, 0x02, 0x13, 0x04, 0x15, 0x16, 0x07, /* 0 */ - 0x08, 0x19, 0x2A, 0x3B, 0x1C, 0x0D, 0x3E, 0x3F, - 0x40, 0x51, 0x52, 0x43, 0x54, 0x45, 0x46, 0x57, /* F + 0 */ - 0x58, 0x49, 0x4A, 0x5B, 0x4C, 0x5D, 0x5E, 0x4F }; - -/* Alphameric (two digits) to paper tape punch */ - -const int8 alp_to_ptp[256] = { - 0x10, -1, 0x7A, 0x6B, 0x7C, -1, -1, 0x7F, /* 00 */ - -1, -1, 0x2A, -1, -1, -1, -1, 0x1F, - 0x70, -1, 0x4A, 0x5B, 0x4C, -1, -1, -1, /* 10 */ - -1, -1, -1, -1, -1, -1, -1, -1, - 0x40, 0x31, 0x2A, 0x3B, 0x2C, -1, -1, -1, /* 20 */ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 0x1A, 0x0B, 0x1C, 0x0D, 0x0E, -1, /* 30 */ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 0x61, 0x62, 0x73, 0x64, 0x75, 0x76, 0x67, /* 40 */ - 0x68, 0x79, -1, -1, -1, -1, -1, -1, - 0x40, 0x51, 0x52, 0x43, 0x54, 0x45, 0x46, 0x57, /* 50 */ - 0x58, 0x49, 0x4A, -1, -1, -1, -1, 0x4F, - -1, 0x31, 0x32, 0x23, 0x34, 0x25, 0x26, 0x37, /* 60 */ - 0x38, 0x29, -1, -1, -1, -1, -1, -1, - 0x20, 0x01, 0x02, 0x13, 0x04, 0x15, 0x16, 0x07, /* 70 */ - 0x08, 0x19, 0x7A, -1, -1, -1, -1, 0x7F, - -1, -1, -1, -1, -1, -1, -1, -1, /* 80 */ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, /* 90 */ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, /* A0 */ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, /* B0 */ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, /* C0 */ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, /* D0 */ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, /* E0 */ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, /* F0 */ - -1, -1, -1, -1, -1, -1, -1, -1 }; - -/* Paper tape reader IO routine - - - Hard errors halt the operation and the system. - - Parity errors place an invalid character in memory and set - RDCHK, but the read continues until end of record. If IO - stop is set, the system then halts. -*/ - -t_stat ptr (uint32 op, uint32 pa, uint32 f0, uint32 f1) -{ -uint32 i; -int8 mc; -uint8 ptc; -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 */ - 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 */ - break; -default: /* invalid function */ - return STOP_INVFNC; } -return STOP_RWRAP; -} - -/* Binary paper tape reader IO routine - see above for error handling */ - -t_stat btr (uint32 op, uint32 pa, uint32 f0, uint32 f1) -{ -uint32 i; -uint8 ptc; -t_stat r, inv = SCPE_OK; - -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 */ - break; -default: /* invalid function */ - return STOP_INVFNC; } -return STOP_RWRAP; -} - -/* Read ptr frame - all errors are 'hard' errors and halt the system */ - -t_stat ptr_read (uint8 *c, t_bool ignfeed) -{ -int32 temp; - -if ((ptr_unit.flags & UNIT_ATT) == 0) { /* attached? */ - ind[IN_RDCHK] = 1; /* no, error */ - 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; } - *c = temp & 0377; /* save char */ - ptr_unit.pos = ptr_unit.pos + 1; } /* incr file addr */ -while (ignfeed && (*c == PT_FD)); /* until not feed */ -return SCPE_OK; -} - -/* Reset routine */ - -t_stat ptr_reset (DEVICE *dptr) -{ -return SCPE_OK; -} - -/* Bootstrap routine */ - -const static uint8 boot_rom[] = { - 4, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* NOP */ - 3, 6, 0, 0, 0, 3, 1, 0, 0, 3, 0, 0, /* RNPT 31 */ - 2, 5, 0, 0, 0, 7, 1, 0, 0, 0, 0, 0, /* TD 71,loc */ - 3, 6, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, /* RNPT loc1 */ - 2, 6, 0, 0, 0, 6, 6, 0, 0, 0, 3, 5, /* TF 66,35 */ - 1, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* TDM loc2,loc3 */ - 4, 9, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0 }; /* BR 12 */ - -#define BOOT_START 0 -#define BOOT_LEN (sizeof (boot_rom) / sizeof (uint8)) - -t_stat ptr_boot (int32 unitno, DEVICE *dptr) -{ -int32 i; -extern int32 saved_PC; - -for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i]; -saved_PC = BOOT_START; -return SCPE_OK; -} - -/* Paper tape punch IO routine - - - Hard errors halt the operation and the system. - - Parity errors stop the operation and set WRCHK. - If IO stop is set, the system then halts. -*/ - -t_stat ptp (uint32 op, uint32 pa, uint32 f0, uint32 f1) -{ -uint32 i; -int8 ptc; -uint8 z, d; -t_stat r; - -switch (op) { /* decode op */ -case OP_DN: - return ptp_num (pa, 20000 - (pa % 20000)); /* dump numeric */ -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 */ - break; -default: /* invalid function */ - return STOP_INVFNC; } -return STOP_RWRAP; -} - -/* Binary paper tape punch IO routine - see above for error handling */ - -t_stat btp (uint32 op, uint32 pa, uint32 f0, uint32 f1) -{ -uint32 i; -uint8 ptc, z, d; -t_stat r; - -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 */ - break; -default: /* invalid function */ - return STOP_INVFNC; } -return STOP_RWRAP; -} - -/* Punch tape numeric - cannot generate parity errors */ - -t_stat ptp_num (uint32 pa, uint32 len) -{ -t_stat r; -uint8 d; -uint32 i, end; - -end = pa + len; -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 */ - r = ptp_write (num_to_ptp[d]); /* write */ - if (r != SCPE_OK) return r; /* error? */ - PP (pa); } /* incr mem addr */ -return STOP_RWRAP; -} - -/* Write ptp frame - all errors are hard errors */ - -t_stat ptp_write (uint32 c) -{ -if ((ptp_unit.flags & UNIT_ATT) == 0) { /* attached? */ - ind[IN_WRCHK] = 1; /* no, error */ - return SCPE_UNATT; } - -if (putc (c, ptp_unit.fileref) == EOF) { /* write char */ - ind[IN_WRCHK] = 1; /* error? */ - perror ("PTP I/O error"); - clearerr (ptp_unit.fileref); - return SCPE_IOERR; } -ptp_unit.pos = ptp_unit.pos + 1; /* count char */ -return SCPE_OK; -} - -/* Reset routine */ - -t_stat ptp_reset (DEVICE *dptr) -{ -return SCPE_OK; -} diff --git a/I1620/i1620_sys.c b/I1620/i1620_sys.c deleted file mode 100644 index 43951d1d..00000000 --- a/I1620/i1620_sys.c +++ /dev/null @@ -1,491 +0,0 @@ -/* i1620_sys.c: IBM 1620 simulator interface - - 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"), - 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 "i1620_defs.h" -#include - -#define LINE_LNT 50 - -extern DEVICE cpu_dev, tty_dev; -extern DEVICE ptr_dev, ptp_dev; -extern DEVICE lpt_dev; -extern DEVICE cdr_dev, cdp_dev; -extern DEVICE dp_dev; -extern UNIT cpu_unit; -extern REG cpu_reg[]; -extern uint8 M[MAXMEMSIZE]; -extern char cdr_to_alp[128], alp_to_cdp[256]; - -/* SCP data structures and interface routines - - sim_name simulator name string - sim_PC pointer to saved PC register descriptor - sim_emax maximum number of words for examine/deposit - sim_devices array of pointers to simulated devices - sim_stop_messages array of pointers to stop messages - sim_load binary loader -*/ - -char sim_name[] = "IBM 1620"; - -REG *sim_PC = &cpu_reg[0]; - -int32 sim_emax = LINE_LNT; - -DEVICE *sim_devices[] = { - &cpu_dev, - &tty_dev, - &ptr_dev, - &ptp_dev, - &cdr_dev, - &cdp_dev, - &lpt_dev, - &dp_dev, - NULL }; - -const char *sim_stop_messages[] = { - "Unknown error", - "HALT instruction", - "Breakpoint", - "Invalid instruction", - "Invalid digit", - "Invalid character", - "Invalid indicator", - "Invalid digit in P address", - "Invalid P address", - "P address exceeds indirect address limit", - "Invalid digit in Q address", - "Invalid Q address", - "Q address exceeds indirect address limit", - "Invalid IO device", - "Invalid return register", - "Invalid IO function", - "Instruction address must be even", - "Invalid select code", - "Index instruction with no band selected", - "P address must be odd", - "DCF address must be even", - "Invalid disk drive", - "Invalid disk sector address", - "Invalid disk sector count", - "Invalid disk buffer address", - "Disk address compare error", - "Disk write check error", - "Disk cylinder overflow error", - "Disk wrong length record error", - "Invalid CCT", - "Field exceeds memory", - "Record exceeds memory", - "No card in reader", - "Overflow check", - "Exponent check", - "Write address function disabled", - "Floating point mantissa too long", - "Floating point mantissa lengths unequal", - "Floating point exponent flag missing", - "Floating point divide by zero" }; - -/* Binary loader -- 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 cct[0:lnt-1], cctlnt contains the - number of entries -*/ - -t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag) -{ -int32 col, rpt, ptr, mask, cctbuf[CCT_LNT]; -t_stat r; -extern int32 cct_lnt, cct_ptr, cct[CCT_LNT]; -char cbuf[CBUFSIZE], gbuf[CBUFSIZE]; - -if ((*cptr != 0) || (flag != 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, 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 */ - for ( ; rpt > 0; rpt--) { /* store vals */ - if (ptr >= CCT_LNT) return SCPE_FMT; - cctbuf[ptr++] = mask; } } -if (ptr == 0) return SCPE_FMT; -cct_lnt = ptr; -cct_ptr = 0; -for (rpt = 0; rpt < cct_lnt; rpt++) cct[rpt] = cctbuf[rpt]; -return SCPE_OK; -} - -/* Symbol table */ - -struct opc { - char *str; /* mnemonic */ - uint32 opv; /* opcode & flags */ - uint32 qv; /* q field */ -}; - -#define I_V_FL 16 /* flags */ -#define I_M_QX 0x01 /* Q indexable */ -#define I_M_QM 0x02 /* Q immediate */ -#define I_M_QNP 0x00 /* Q no print */ -#define I_M_QCP 0x04 /* Q cond print */ -#define I_M_QP 0x08 /* Q print */ -#define I_M_PCP 0x00 /* P cond print */ -#define I_M_PP 0x10 /* P print */ -#define I_GETQF(x) (((x) >> I_V_FL) & 0x03) -#define I_GETQP(x) (((x) >> I_V_FL) & 0x0C) -#define I_GETPP(x) (((x) >> I_V_FL) & 0x10) - -#define I_2 ((I_M_PP | I_M_QP | I_M_QX) << I_V_FL) -#define I_2M ((I_M_PP | I_M_QP | I_M_QM) << I_V_FL) -#define I_2X ((I_M_PP | I_M_QP | I_M_QX | I_M_QM) << I_V_FL) -#define I_2S ((I_M_PP | I_M_QP) << I_V_FL) -#define I_1 ((I_M_PP | I_M_QCP) << I_V_FL) -#define I_1E ((I_M_PP | I_M_QNP) << I_V_FL) -#define I_0 ((I_M_PCP | I_M_QCP) << I_V_FL) -#define I_0E ((I_M_PCP | I_M_QNP) << I_V_FL) - -struct opc opcode[] = { - { "RNTY", 36+I_1E, 100 }, { "RATY", 37+I_1E, 100 }, - { "WNTY", 38+I_1E, 100 }, { "WATY", 39+I_1E, 100 }, - { "DNTY", 35+I_1E, 100 }, { "SPTY", 34+I_0E, 101 }, - { "RCTY", 34+I_0E, 102 }, { "BKTY", 34+I_0E, 103 }, - { "IXTY", 34+I_0E, 104 }, { "TBTY", 34+I_0E, 108 }, - { "RNPT", 36+I_1E, 300 }, { "RAPT", 37+I_1E, 300 }, - { "WNPT", 38+I_1E, 200 }, { "WAPT", 39+I_1E, 200 }, - { "DNPT", 35+I_1E, 200 }, - { "RNCD", 36+I_1E, 500 }, { "RACD", 37+I_1E, 500 }, - { "WNCD", 38+I_1E, 400 }, { "WACD", 39+I_1E, 400 }, - { "DNCD", 35+I_1E, 400 }, - { "PRN", 38+I_1E, 900 }, { "PRNS", 38+I_1E, 901 }, - { "PRA", 39+I_1E, 900 }, { "PRAS", 39+I_1E, 901 }, - { "PRD", 35+I_1E, 900 }, { "PRDS", 35+I_1E, 901 }, - { "SK", 34+I_1E, 701 }, - { "RDGN", 36+I_1E, 700 }, { "CDGN", 36+I_1E, 701 }, - { "RDN", 36+I_1E, 702 }, { "CDN", 36+I_1E, 703 }, - { "RTGN", 36+I_1E, 704 }, { "CTGN", 36+I_1E, 705 }, - { "RTN", 36+I_1E, 706 }, { "CTN", 36+I_1E, 707 }, - { "WDGN", 38+I_1E, 700 }, { "WDN", 38+I_1E, 702 }, - { "WTGN", 38+I_1E, 704 }, { "WTN", 38+I_1E, 706 }, - { "RBPT", 37+I_1E, 3300 }, { "WBPT", 39+I_1E, 3200 }, - { "BC1", 46+I_1E, 100 }, { "BNC1", 47+I_1E, 100 }, - { "BC2", 46+I_1E, 200 }, { "BNC2", 47+I_1E, 200 }, - { "BC3", 46+I_1E, 300 }, { "BNC3", 47+I_1E, 300 }, - { "BC4", 46+I_1E, 400 }, { "BNC4", 47+I_1E, 400 }, - { "BLC", 46+I_1E, 900 }, { "BNLC", 47+I_1E, 900 }, - { "BH", 46+I_1E, 1100 }, { "BNH", 47+I_1E, 1100 }, - { "BP", 46+I_1E, 1100 }, { "BNP", 47+I_1E, 1100 }, - { "BE", 46+I_1E, 1200 }, { "BNE", 47+I_1E, 1200 }, - { "BZ", 46+I_1E, 1200 }, { "BNZ", 47+I_1E, 1200 }, - { "BNL", 46+I_1E, 1300 }, { "BL", 47+I_1E, 1300 }, - { "BNN", 46+I_1E, 1300 }, { "BN", 47+I_1E, 1300 }, - { "BV", 46+I_1E, 1400 }, { "BNV", 47+I_1E, 1400 }, - { "BXV", 46+I_1E, 1500 }, { "BNXV", 47+I_1E, 1500 }, - { "BA", 46+I_1E, 1900 }, { "BNA", 47+I_1E, 1900 }, - { "BNBS", 46+I_1E, 3000 }, { "BEBS", 47+I_1E, 3000 }, - { "BBAS", 46+I_1E, 3100 }, { "BANS", 47+I_1E, 3100 }, - { "BBBS", 46+I_1E, 3200 }, { "BBNS", 47+I_1E, 3200 }, - { "BCH9", 46+I_1E, 3300 }, - { "BCOV", 46+I_1E, 3400 }, - { "BSNX", 60+I_1E, 0 }, { "BSBA", 60+I_1E, 1 }, - { "BSBB", 60+I_1E, 2 }, - { "BSNI", 60+I_1E, 8 }, { "BSIA", 60+I_1E, 9 }, - - { "FADD", 1+I_2, 0 }, { "FSUB", 2+I_2, 0 }, - { "FMUL", 3+I_2, 0 }, { "FSL", 5+I_2, 0 }, - { "TFL", 6+I_2, 0 }, { "BTFL", 7+I_2, 0 }, - { "FSR", 8+I_2, 0 }, { "FDIV", 9+I_2, 0 }, - { "BTAM", 10+I_2M, 0 }, { "AM", 11+I_2M, 0 }, - { "SM", 12+I_2M, 0 }, { "MM", 13+I_2M, 0 }, - { "CM", 14+I_2M, 0 }, { "TDM", 15+I_2S, 0 }, - { "TFM", 16+I_2M, 0 }, { "BTM", 17+I_2M, 0 }, - { "LDM", 18+I_2M, 0 }, { "DM", 19+I_2M, 0 }, - { "BTA", 20+I_2, 0 }, { "A", 21+I_2, 0 }, - { "S", 22+I_2, 0 }, { "M", 23+I_2, 0 }, - { "C", 24+I_2, 0 }, { "TD", 25+I_2, 0 }, - { "TF", 26+I_2, 0 }, { "BT", 27+I_2, 0 }, - { "LD", 28+I_2, 0 }, { "D", 29+I_2, 0 }, - { "TRNM", 30+I_2, 0 }, { "TR", 31+I_2, 0 }, - { "SF", 32+I_1, 0 }, { "CF", 33+I_1, 0 }, - { "K", 34+I_2S, 0 }, { "DN", 35+I_2S, 0 }, - { "RN", 36+I_2S, 0 }, { "RA", 37+I_2S, 0 }, - { "WN", 38+I_2S, 0 }, { "WA", 39+I_2S, 0 }, - { "NOP", 41+I_0, 0 }, { "BB", 42+I_0, 0 }, - { "BD", 43+I_2, 0 }, { "BNF", 44+I_2, 0 }, - { "BNR", 45+I_2, 0 }, { "BI", 46+I_2S, 0 }, - { "BNI", 47+I_2S, 0 }, { "H", 48+I_0, 0 }, - { "B", 49+I_1, 0 }, { "BNG", 55+I_2, 0 }, - { "BS", 60+I_2S, 0 }, { "BX", 61+I_2, 0 }, - { "BXM", 62+I_2X, 0 }, { "BCX", 63+I_2, 0 }, - { "BCXM", 64+I_2X, 0 }, { "BLX", 65+I_2, 0 }, - { "BLXM", 66+I_2X, 0 }, { "BSX", 67+I_2, 0 }, - { "MA", 70+I_2, 0 }, { "MF", 71+I_2, 0 }, - { "TNS", 72+I_2, 0 }, { "TNF", 73+I_2, 0 }, - { "BBT", 90+I_2, 0 }, { "BMK", 91+I_2, 0 }, - { "ORF", 92+I_2, 0 }, { "ANDF", 93+I_2, 0 }, - { "CPFL", 94+I_2, 0 }, { "EORF", 95+I_2, 0 }, - { "OTD", 96+I_2, 0 }, { "DTO", 97+I_2, 0 }, - { NULL, 0, 0 } }; - -/* Print an address from five characters */ - -void fprint_addr (FILE *of, int32 spc, t_value *dig, t_bool flg) -{ -int32 i, idx; - -fputc (spc, of); /* spacer */ -if (dig[ADDR_LEN - 1] & FLAG) { /* signed? */ - fputc ('-', of); /* print minus */ - dig[ADDR_LEN - 1] = dig[ADDR_LEN - 1] & ~FLAG; } -for (i = 0; i < ADDR_LEN; i++) /* print digits */ - fprintf (of, "%X", dig[i] & DIGIT); -if ((cpu_unit.flags & IF_IDX) && flg) { /* indexing? */ - for (i = idx = 0; i < ADDR_LEN - 2; i++) { /* get index reg */ - if (dig[ADDR_LEN - 2 - i] & FLAG) - idx = idx | (1 << i); - dig[ADDR_LEN - 2 - i] = dig[ADDR_LEN - 2 - i] & ~FLAG; } - if (idx) fprintf (of, "(%d)", idx); } /* print */ -return; -} - -/* Symbolic decode - - Inputs: - *of = output stream - addr = current address - *val = values to decode - *uptr = pointer to unit - sw = switches - Outputs: - return = if >= 0, error code - if < 0, number of extra words retired -*/ - -#define FMTASC(x) ((x) < 040)? "<%03o>": "%c", (x) - -t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, - UNIT *uptr, int32 sw) -{ -int32 pmp, qmp, i, c, d, any; -uint32 op, qv, opfl; - -if (uptr == NULL) uptr = &cpu_unit; -if (sw & SWMASK ('C')) { /* character? */ - if (uptr->flags & UNIT_BCD) { - if (addr & 1) return SCPE_ARG; /* must be even */ - c = ((val[0] & DIGIT) << 4) | (val[1] & DIGIT); - if (alp_to_cdp[c] > 0) - fprintf (of, "%c", alp_to_cdp[c]); - else fprintf (of, "<%02x>", c); - return -1; } - else fprintf (of, FMTASC (val[0] & 0177)); - return SCPE_OK; } -if ((uptr->flags & UNIT_BCD) == 0) return SCPE_ARG; /* CPU or disk? */ -if (sw & SWMASK ('D')) { /* dump? */ - for (i = d = 0; i < LINE_LNT; i++) d = d | val[i]; - if (d & FLAG) { /* any flags? */ - for (i = 0; i < LINE_LNT; i++) /* print flags */ - fprintf (of, (val[i] & FLAG)? "_": " "); - fprintf (of, "\n\t"); } - for (i = 0; i < LINE_LNT; i++) /* print digits */ - fprintf (of, "%X", val[i] & DIGIT) ; - return -(i - 1); } -if (sw & SWMASK ('S')) { /* string? */ - if (addr & 1) return SCPE_ARG; /* must be even */ - for (i = 0; i < LINE_LNT; i = i + 2) { - c = ((val[i] & DIGIT) << 4) | (val[i + 1] & DIGIT); - if (alp_to_cdp[c] < 0) break; - fprintf (of, "%c", alp_to_cdp[c]); } - if (i == 0) { - fprintf (of, "<%02X>", c); - return -1; } - return -(i - 1); } -if ((sw & SWMASK ('M')) == 0) return SCPE_ARG; - -if (addr & 1) return SCPE_ARG; /* must be even */ -op = ((val[0] & DIGIT) * 10) + (val[1] & DIGIT); /* get opcode */ -for (i = qv = pmp = qmp = 0; i < ADDR_LEN; i++) { /* test addr */ - if (val[I_P + i]) pmp = 1; - if (val[I_Q + i]) qmp = 1; - qv = (qv * 10) + (val[I_Q + i] & DIGIT); } -if ((val[0] | val[1]) & FLAG) pmp = qmp = 1; /* flags force */ -for (i = 0; opcode[i].str != NULL; i++) { /* find opcode */ - opfl = opcode[i].opv & 0xFF0000; - if ((op == (opcode[i].opv & 0xFF)) && - ((qv == opcode[i].qv) || - ((opfl != I_1E) && (opfl != I_0E)))) break; } -if (opcode[i].str == NULL) return SCPE_ARG; -if (I_GETQP (opfl) == I_M_QNP) qmp = 0; /* Q no print? */ - -fprintf (of, opcode[i].str); /* print opcode */ -if (I_GETPP (opfl) == I_M_PP) /* P required? */ - fprint_addr (of, ' ', &val[I_P], I_M_QX); -else if ((I_GETPP (opfl) == I_M_PCP) && (pmp || qmp)) /* P opt & needed? */ - fprint_addr (of, ' ', &val[I_P], 0); -if (I_GETQP (opfl) == I_M_QP) { /* Q required? */ - fprint_addr (of, ',', &val[I_Q], I_GETQF (opfl)); - if (I_GETQF (opfl) & I_M_QM) /* immediate? */ - val[I_Q] = val[I_Q] & ~FLAG; } /* clr hi Q flag */ -else if ((I_GETQP (opfl) == I_M_QCP) && (pmp || qmp)) /* Q opt & needed? */ - fprint_addr (of, ',', &val[I_Q], 0); -for (i = any = 0; i < INST_LEN; i++) { /* print rem flags */ - if (val[i] & FLAG) { - if (!any) fputc (',', of); - any = 1; - fprintf (of, "%d", i); } } -return -(INST_LEN - 1); -} - -/* parse_addr - get sign + address + index */ - -t_stat parse_addr (char *cptr, t_value *val, int32 flg) -{ -int32 i, sign = 0, addr, index; -static int32 idx_tst[ADDR_LEN] = { 0, 4, 2, 1, 0 }; -char *tptr; - -if (*cptr == '+') cptr++; /* +? skip */ -else if (*cptr == '-') { /* -? skip, flag */ - sign = 1; - cptr++; } -errno = 0; /* get address */ -addr = strtoul (cptr, &tptr, 16); -if (errno || (cptr == tptr) || (addr > 0xFFFFF)) /* err or too big? */ - return SCPE_ARG; -if ((cpu_unit.flags & IF_IDX) && (flg & I_M_QX) && /* index allowed? */ - (*tptr == '(')) { /* index specified */ - errno = 0; - index = strtoul (cptr = tptr + 1, &tptr, 10); /* get index */ - if (errno || (cptr == tptr) || (index > 7)) /* err or too big? */ - return SCPE_ARG; - if (*tptr++ != ')') return SCPE_ARG; } -else index = 0; -if (*tptr != 0) return SCPE_ARG; /* all done? */ -for (i = ADDR_LEN - 1; i >= 0; i--) { /* cvt addr to dig */ - val[i] = (addr & 0xF) | ((index & idx_tst[i])? FLAG: 0); - addr = addr >> 4; } -if (sign) val[ADDR_LEN - 1] = val[ADDR_LEN - 1] | FLAG; /* set sign */ -if (flg & I_M_QM) val[0] = val[0] | FLAG; /* set immediate */ -return SCPE_OK; -} - -/* Symbolic input - - Inputs: - *cptr = pointer to input string - addr = current PC - *uptr = pointer to unit - *val = pointer to output values - sw = switches - Outputs: - status = > 0 error code - <= 0 -number of extra words -*/ - -t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw) -{ -int32 i, qv, opfl, last; -char t, la, *fptr, gbuf[CBUFSIZE]; - -while (isspace (*cptr)) cptr++; /* absorb spaces */ -if ((sw & SWMASK ('C')) || ((*cptr == '\'') && cptr++)) { /* character? */ - if ((t = *cptr & 0x7F) == 0) return SCPE_ARG; /* get char */ - if (uptr->flags & UNIT_BCD) { /* BCD? */ - if (addr & 1) return SCPE_ARG; - t = cdr_to_alp[t]; /* convert */ - if (t < 0) return SCPE_ARG; /* invalid? */ - val[0] = (t >> 4) & DIGIT; /* store */ - val[1] = t & DIGIT; - return -1; } - else val[0] = t; /* store ASCII */ - return SCPE_OK; } - -if ((uptr->flags & UNIT_BCD) == 0) return SCPE_ARG; /* CPU or disk? */ -if ((sw & SWMASK ('S')) || ((*cptr == '"') && cptr++)) { /* string? */ - if (addr & 1) return SCPE_ARG; /* must be even */ - for (i = 0; (i < sim_emax) && (*cptr != 0); i = i + 2) { - t = *cptr++ & 0x7F; /* get character */ - t = cdr_to_alp[t]; /* convert */ - if (t < 0) return SCPE_ARG; /* invalid? */ - val[i] = (t >> 4) & DIGIT; /* store */ - val[i + 1] = t & DIGIT; } - if (i == 0) return SCPE_ARG; /* final check */ - return -(i - 1); } - -if (addr & 1) return SCPE_ARG; /* even addr? */ -cptr = get_glyph (cptr, gbuf, 0); /* get opcode */ -for (i = 0; opcode[i].str != NULL; i++) { /* look it up */ - if (strcmp (gbuf, opcode[i].str) == 0) break; } -if (opcode[i].str == NULL) return SCPE_ARG; /* successful? */ -opfl = opcode[i].opv & 0xFF0000; /* get flags */ -val[0] = (opcode[i].opv & 0xFF) / 10; /* store opcode */ -val[1] = (opcode[i].opv & 0xFF) % 10; -qv = opcode[i].qv; -for (i = ADDR_LEN - 1; i >= 0; i--) { /* set P,Q fields */ - val[I_P + i] = 0; - val[I_Q + i] = qv % 10; - qv = qv /10; } - -cptr = get_glyph (cptr, gbuf, ','); /* get P field */ -if (gbuf[0]) { /* any? */ - if (parse_addr (gbuf, &val[I_P], (I_GETPP (opfl)? - I_M_QX: 0))) return SCPE_ARG; } -else if (I_GETPP (opfl) == I_M_PP) return SCPE_ARG; - -if (I_GETQP (opfl) != I_M_QNP) { /* Q field allowed? */ - cptr = get_glyph (cptr, gbuf, ','); /* get Q field */ - if (gbuf[0]) { /* any? */ - if (parse_addr (gbuf, &val[I_Q], I_GETQF (opfl))) - return SCPE_ARG; } - else if (I_GETQP (opfl) == I_M_QP) return SCPE_ARG; } - -cptr = get_glyph (cptr, fptr = gbuf, ' '); /* get flag field */ -last = -1; /* none yet */ -while (t = *fptr++) { /* loop through */ - if ((t < '0') || (t > '9')) return SCPE_ARG; /* must be digit */ - t = t - '0'; /* convert */ - if (t == 1) { /* ambiguous? */ - la = *fptr++; /* get next */ - if (la == '0') t = 10; /* 10? */ - else if ((la == '1') && (*fptr == 0)) t = 11; /* 11 & end field? */ - else --fptr; } /* dont lookahead */ - if (t <= last) return SCPE_ARG; /* in order? */ - val[t] = val[t] | FLAG; /* set flag */ - last = t; } /* continue */ - -if (*cptr != 0) return SCPE_ARG; -return -(INST_LEN - 1); -} diff --git a/I1620/i1620_tty.c b/I1620/i1620_tty.c deleted file mode 100644 index 47f20906..00000000 --- a/I1620/i1620_tty.c +++ /dev/null @@ -1,347 +0,0 @@ -/* i1620_tty.c: IBM 1620 typewriter - - 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"), - 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. - - tty console typewriter - - 22-Dec-02 RMS Added break test -*/ - -#include "i1620_defs.h" - -#define TTO_COLMAX 80 - -int32 tto_col = 0; - -extern uint8 M[MAXMEMSIZE]; -extern uint8 ind[NUM_IND]; -extern UNIT cpu_unit; -extern uint32 io_stop; - -void tti_unlock (void); -t_stat tti_rnum (int8 *c); -t_stat tti_ralp (int8 *c); -t_stat tti_read (int8 *c); -t_stat tto_num (uint32 pa, uint32 len); -t_stat tto_write (uint32 c); -t_stat tty_svc (UNIT *uptr); -t_stat tty_reset (DEVICE *dptr); - -/* TTY data structures - - tty_dev TTY device descriptor - tty_unit TTY unit descriptor - tty_reg TTY register list -*/ - -UNIT tty_unit = { UDATA (&tty_svc, 0, 0), KBD_POLL_WAIT }; - -REG tty_reg[] = { - { DRDATA (COL, tto_col, 7) }, - { DRDATA (TIME, tty_unit.wait, 24), REG_NZ + PV_LEFT }, - { NULL } }; - -DEVICE tty_dev = { - "TTY", &tty_unit, tty_reg, NULL, - 1, 10, 31, 1, 8, 7, - NULL, NULL, &tty_reset, - NULL, NULL, NULL }; - -/* Data tables */ - -/* Keyboard to numeric */ - -const char *tti_to_num = "0123456789'=@:;\""; - -/* Keyboard to alphameric (digit pair) - translates LC to UC */ - -const int8 tti_to_alp[128] = { - -1, -1, -1, -1, -1, -1, -1, -1, /* 00 */ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, /* 10 */ - -1, -1, -1, -1, -1, -1, -1, -1, - 0x00, 0x02, 0x0F, -1, 0x13, -1, -1, -1, /* !"#$%&' */ - 0x24, 0x04, 0x14, 0x10, 0x23, 0x20, 0x03, 0x21, /* ()*+,-./ */ - 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 01234567 */ - 0x78, 0x79, -1, -1, -1, 0x33, -1, -1, /* 89:;<=>? */ - 0x34, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* @ABCDEFG */ - 0x48, 0x49, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, /* HIJKLMNO */ - 0x57, 0x58, 0x59, 0x62, 0x63, 0x64, 0x65, 0x66, /* PQRSTUVW */ - 0x67, 0x68, 0x69, -1, -1, -1, -1, -1, /* XYZ[\]^_ */ - -1, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* abcdefg */ - 0x48, 0x49, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, /* hijklmno */ - 0x57, 0x58, 0x59, 0x62, 0x63, 0x64, 0x65, 0x66, /* pqrstuvw */ - 0x67, 0x68, 0x69, -1, -1, -1, -1, -1 }; /* xyz */ - -/* Numeric (digit) to typewriter */ - -const char num_to_tto[16] = { - '0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', '\'', '=', '@', ':', ';', '"' }; - -/* Alphameric (digit pair) to typewriter */ - -const char alp_to_tto[256] = { - ' ', -1, '?', '.', ')', -1, -1, -1, /* 00 */ - -1, -1, -1, -1, -1, -1, -1, -1, - '+', -1, '!', '$', '*', ' ', -1, -1, /* 10 */ - -1, -1, -1, -1, -1, -1, -1, -1, - '-', '/', '\'', ',', '(', -1, -1, -1, /* 20 */ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, '0', '=', '@', ':', -1, -1, /* 30 */ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 'A', 'B', 'C', 'D', 'E', 'F', 'G', /* 40 */ - 'H', 'I', -1, -1, -1, -1, -1, -1, - '-', 'J', 'K', 'L', 'M', 'N', 'O', 'P', /* 50 */ - 'Q', 'R', -1, -1, -1, -1, -1, -1, - -1, '/', 'S', 'T', 'U', 'V', 'W', 'X', /* 60 */ - 'Y', 'Z', -1, -1, -1, -1, -1, -1, - '0', '1', '2', '3', '4', '5', '6', '7', /* 70 */ - '8', '9', -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, /* 80 */ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, /* 90 */ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, /* A0 */ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, /* B0 */ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, /* C0 */ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, /* D0 */ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, /* E0 */ - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, /* F0 */ - -1, -1, -1, -1, -1, -1, -1, -1 }; - -/* Terminal IO - - - On input, parity errors cannot occur. - - On input, release-start does NOT cause a record mark to be stored. - - On output, invalid characters type an invalid character and set WRCHK. - If IO stop is set, the system halts at the end of the operation. -*/ - -t_stat tty (uint32 op, uint32 pa, uint32 f0, uint32 f1) -{ -t_addr i; -uint8 d; -int8 ttc; -t_stat r, inv = SCPE_OK; - -switch (op) { /* case on op */ -case OP_K: /* control */ - switch (f1) { /* case on control */ - case 1: /* space */ - tto_write (' '); - break; - case 2: /* return */ - tto_write ('\r'); - break; - case 3: /* backspace */ - 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; - case 8: /* tab */ - tto_write ('\t'); - break; - default: - 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 */ - 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 */ - break; -case OP_DN: - return tto_num (pa, 20000 - (pa % 20000)); /* dump numeric */ -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 */ - break; -default: /* invalid function */ - return STOP_INVFNC; } -return STOP_RWRAP; -} - -/* Read numerically - cannot generate parity errors */ - -t_stat tti_rnum (int8 *c) -{ -int8 flg = 0; -char *cp, raw; -t_stat r; - -*c = -1; /* no char yet */ -do { r = tti_read (&raw); /* get char */ - if (r != SCPE_OK) return r; /* error? */ - if (raw == '\r') *c = 0x7F; /* return? mark */ - else if (raw == '~') flg = FLAG; /* flag? mark */ - else if (cp = strchr (tti_to_num, raw)) /* legal? */ - *c = ((int8) (cp - tti_to_num)) | flg; /* assemble char */ - else raw = 007; /* beep! */ - tto_write (raw); } /* echo */ -while (*c == -1); -return SCPE_OK; -} - -/* Read alphamerically - cannot generate parity errors */ - -t_stat tti_ralp (int8 *c) -{ -char raw; -t_stat r; - -*c = -1; /* no char yet */ -do { r = tti_read (&raw); /* get char */ - if (r != SCPE_OK) return r; /* error? */ - if (raw == '\r') *c = 0x7F; /* return? mark */ - else if (tti_to_alp[raw] >= 0) /* legal char? */ - *c = tti_to_alp[raw]; /* xlate */ - else raw = 007; /* beep! */ - tto_write (raw); } /* echo */ -while (*c == -1); -return SCPE_OK; -} - -/* Read from keyboard */ - -t_stat tti_read (int8 *c) -{ -int32 t; - -do { t = sim_poll_kbd (); } /* get character */ -while ((t == SCPE_OK) || (t & SCPE_BREAK)); /* ignore break */ -if (t < SCPE_KFLAG) return t; /* error? */ -*c = t & 0177; /* store character */ -return SCPE_OK; -} - -/* Write numerically - cannot generate parity errors */ - -t_stat tto_num (uint32 pa, uint32 len) -{ -t_stat r; -uint8 d; -uint32 i, end; - -end = pa + len; -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 */ - if (d & FLAG) tto_write ('~'); /* flag? */ - r = tto_write (num_to_tto[d & DIGIT]); /* write */ - if (r != SCPE_OK) return r; /* error? */ - PP (pa); } /* incr mem addr */ -return STOP_RWRAP; -} - -/* Write, maintaining position */ - -t_stat tto_write (uint32 c) -{ -int32 rpt; - -if (c == '\t') { /* tab? */ - rpt = 8 - (tto_col % 8); /* distance to next */ - tto_col = tto_col + rpt; /* tab over */ - while (rpt-- > 0) sim_putchar (' '); /* use spaces */ - return SCPE_OK; } -if (c == '\r') { /* return? */ - sim_putchar ('\r'); /* crlf */ - sim_putchar ('\n'); - tto_col = 0; /* clear colcnt */ - return SCPE_OK; } -if ((c == '\n') || (c == 007)) { /* non-spacing? */ - sim_putchar (c); - return SCPE_OK; } -if (c == '\b') tto_col = tto_col? tto_col - 1: 0; /* backspace? */ -else tto_col++; /* normal */ -if (tto_col > TTO_COLMAX) { /* line wrap? */ - sim_putchar ('\r'); - sim_putchar ('\n'); - tto_col = 0; } -sim_putchar (c); -return SCPE_OK; -} - -/* Unit service - polls for WRU */ - -t_stat tty_svc (UNIT *uptr) -{ -int32 temp; - -sim_activate (&tty_unit, tty_unit.wait); /* continue poll */ -if ((temp = sim_poll_kbd ()) < SCPE_KFLAG) return temp; /* no char or error? */ -return SCPE_OK; -} - -/* Reset routine */ - -t_stat tty_reset (DEVICE *dptr) -{ -sim_activate (&tty_unit, tty_unit.wait); /* activate poll */ -tto_col = 0; -return SCPE_OK; -} - -/* TTI unlock - signals that we are ready for keyboard input */ - -void tti_unlock (void) -{ -tto_write ('`'); -return; -} diff --git a/Ibm1130/1130consoleblank.bmp b/Ibm1130/1130consoleblank.bmp deleted file mode 100644 index 9b6c7780..00000000 Binary files a/Ibm1130/1130consoleblank.bmp and /dev/null differ diff --git a/Ibm1130/HAND.CUR b/Ibm1130/HAND.CUR deleted file mode 100644 index eb0796dd..00000000 Binary files a/Ibm1130/HAND.CUR and /dev/null differ diff --git a/Ibm1130/dmsr2v12phases.h b/Ibm1130/dmsr2v12phases.h deleted file mode 100644 index 47fbb2d9..00000000 --- a/Ibm1130/dmsr2v12phases.h +++ /dev/null @@ -1,171 +0,0 @@ -0x01, "DUP - COMMON SUBROUTINES", -0x02, "DUP - CTRL RECORD PROCESSOR", -0x03, "DUP - STORE PHASE", -0x04, "DUP - *FILES, *LOCAL, *NOCAL PHASE", -0x05, "DUP - DUMP PHASE", -0x06, "DUP - DUMP LET/FLET PHASE", -0x07, "DUP - DELETE PHASE", -0x08, "DUP - DEFINE PHASE", -0x09, "DUP - EXIT PHASE", -0x0A, "DUP - CARD I/O INTERFACE", -0x0B, "DUP - KEYBOARD INPUT INTERFACE", -0x0C, "DUP - PAPER TAPE I/O INTERFACE", -0x0D, "DUP - SAVED UPCOR PHASE", -0x0E, "DUP - PRINCIPAL I/O DUMMY PHASE", -0x0F, "DUP - PRINCIPAL I/O (W/O KB) DUMMY PHASE", -0x10, "DUP - PAPER TAPE I/O DUMMY PHASE", -0x11, "DUP - MOVE DCI PROGRAMS TO UA OR FXA", -0x12, "DUP - EXIT TO MODIF DUMMY PHASE", - -0x1F, "FOR - INPUT PHASE", -0x20, "FOR - CLASSIFIERPHASE", -0x21, "FOR - CHECK ORDER/ST NO PHASE", -0x22, "FOR - COMMON SUBR OR FUNCTION PHASE", -0x23, "FOR - DIMENSION/REAL/INTEGER PHASE", -0x24, "FOR - REAL CONSTANT PHASE", -0x25, "FOR - DEFINE FILE, CALL LINK/EXIT PHASE", -0x26, "FOR - VARIABLE, STMT FUNC PHASE", -0x27, "FOR - DATA STATEMENT PHASE", -0x28, "FOR - FORMAT STATEMENT PHASE", -0x29, "FOR - SUBTRACT DECOMPOSITION PHASE", -0x2A, "FOR - ASCAN I PHASE", -0x2B, "FOR - ASCAN II PHASE", -0x2C, "FOR - DO/CONTINUE/ETC PHASE", -0x2D, "FOR - SUBSCRIPT OPTIMIZATION PHASE", -0x2E, "FOR - SCAN PHASE", -0x2F, "FOR - EXPANDER I PHASE", -0x30, "FOR - EXPANDER II PHASE", -0x31, "FOR - DATA ALLOCATION PHASE", -0x32, "FOR - COMPILATION ERROR PHASE", -0x33, "FOR - STATEMENT ALLOCATION PHASE", -0x34, "FOR - LIST STATEMENT PHASE", -0x35, "FOR - LIST SYMBOL TABLE PHASE", -0x36, "FOR - LIST CONSTANTS PHASE", -0x37, "FOR - OUTPUT I PHASE", -0x38, "FOR - OUTPUT II PHASE", -0x39, "FOR - RECOVERY/EXIT PHASE", - -0X51, "COBOL 51", -0X52, "COBOL 52", -0X53, "COBOL 53", -0X54, "COBOL 54", -0X55, "COBOL 55", -0X56, "COBOL 56", -0X57, "COBOL 57", -0X58, "COBOL 58", -0X59, "COBOL 59", -0X5A, "COBOL 5A", -0X5B, "COBOL 5B", -0X5C, "COBOL 5C", - -0X6E, "SUP PHASE 1 - MONITOR CONTROL RECORD ANALYZER", -0x6F, "SUP PHASE 2 - JOB PROCESSING", -0x70, "SUP PHASE 3 - DELETE TEMPORARY LET", -0x71, "SUP PHASE 4 - XEQ PROCESSING", -0x72, "SUP PHASE 5 - SUPV CONTROL REC PROCESSING", -0X73, "SYSTEM DUMP-CORE-TO-PRINTER", -0X74, "AUXILIARY SUPERVISOR", -0X78, "CORE LOAD BUILDER, PHASE 1", -0x79, "CORE LOAD BUILDER, PHASE 2", -0x7A, "CORE LOAD BUILDER, PHASE 3", -0x7B, "CORE LOAD BUILDER, PHASE 4", -0x7C, "CORE LOAD BUILDER, PHASE 5", -0x7D, "CORE LOAD BUILDER, PHASE 6", -0x7E, "CORE LOAD BUILDER, PHASE 7", -0x7F, "CORE LOAD BUILDER, PHASE 8", -0x80, "CORE LOAD BUILDER, PHASE 9", -0x81, "CORE LOAD BUILDER, PHASE 10", -0x82, "CORE LOAD BUILDER, PHASE 11", -0x83, "CORE LOAD BUILDER, PHASE 12", -0x84, "CORE LOAD BUILDER, PHASE 13", - -0X8C, "SYS 1403 READER", -0x8D, "SYS 1132 PRINTER", -0x8E, "SYS CONSOLE PRINTER", -0x8F, "SYS 2501/1442 READER", -0x90, "SYS 1442/1442 READER", -0x91, "SYS 1134/1055 PAPER TAPE IO", -0x92, "SYS KEYBOARD", -0x93, "SYS 2501/1442 CONVERSION", -0x94, "SYS 1134/1055 CONVERSION", -0x95, "SYS KEYBOARD CONVERSION", -0x96, "DISKZ", -0x97, "SYS DISK1", -0x98, "SYS DISKN", - -0xA0, "CIL CORE IMAGE LOADER - PHASE 1", -0xA1, "CIL CORE IMAGE LOADER - PHASE 2", - -0XB0, "RPG B0", -0XB1, "RPG B1", -0XB2, "RPG B2", -0XB3, "RPG B3", -0XB4, "RPG B4", -0XB5, "RPG B5", -0XB6, "RPG B6", -0XB7, "RPG B7", -0XB8, "RPG B8", -0XB9, "RPG B9", -0XBA, "RPG BA", -0XBB, "RPG BB", -0XBC, "RPG BC", -0XBD, "RPG BD", -0XBE, "RPG BE", -0XBF, "RPG BF", -0XC0, "RPG C0", -0XC1, "RPG C1", -0XC2, "RPG C2", -0XC3, "RPG C3", -0XC4, "RPG C4", -0XC5, "RPG C5", -0XC6, "RPG C6", -0XC7, "RPG C7", -0XC8, "RPG C8", -0XC9, "RPG C9", -0XCA, "RPG CA", -0XCB, "RPG CB", -0XCC, "RPG CC", - -0XCD, "DUP PART 2 - CTRL", -0XCE, "DUP PART 2 - MACRO UPDATE", - -0XCF, "ASM INITIALIZATION PHASE", -0xD0, "ASM CARD CONVERSION PHASE", -0xD1, "ASM DSF OUTPUT PHASE", -0xD2, "ASM INTERMEDIATE INPUT PHASE", -0xD3, "ASM END STATEMENT PHASE", -0xD4, "ASM ASSEMBLY ERROR PHASE", -0xD5, "ASM CONTROL CARDS I", -0xD6, "ASM CONTROL CARDS 2", -0xD7, "ASM DUMMY SYST SYMBOL TBL", -0xD8, "ASM SYMBOL TABLE OPTIONS PHASE", -0xD9, "ASM EXIT PHASE", -0xDA, "ASM PROG HEADER MNEMONICS PH", -0xDB, "ASM FILE STATEMENT PHASE", -0xDC, "ASM COMMON SUBROUTINES,ASCOM", -0xE4, "ASM INTERMEDIATE I/O", -0xE5, "ASM SYMBOL TABLE OVERFLOW", -0xDD, "ASM PROG CONTROL MNEMONICS PH", -0xDE, "ASM IMPERATIVE STATEMENTS PH", -0xDF, "ASM DECML,XFLC PROCESSING PH", -0xE0, "ASM DECIMAL CONVERSION PH", -0xE1, "ASM PROG LINKAGE PHASE", -0xE2, "ASM DMES PROCESSING PHASE", -0xE3, "ASM PUNCH CONVERSION PHASE", -0xE6, "ASM GRAPHIC ORDER PHASE", -0xE8, "ASM CONTROL CARDS III", -0xE9, "ASM MACRO PH 1 - SPECIAL OP AND PREPROCESSI", -0xEA, "MACRO PHASE 1A - SPECIAL PSEUDO OPS", -0xEB, "MACRO PHASE 1B - CONDITIONAL ASM PSEUDO OPS", -0xEC, "ASM MACRO PHASE 2 - MACRO DEFINITION", -0xED, "MACRO PHASE 2A - MACRO DEFINITION", -0xEE, "MACRO PHASE 2B - MACRO DEFINITION", -0xEF, "MACRO PHASE 3 - MACRO EXPANSION", -0xF0, "MACRO PHASE 3A - MACRO EXPANSION", -0xF1, "MACRO PHASE 3B - MACRO EXPANSION", -0xE7, "ASM DIVISION OPERATOR", -0xF2, "ASM CROSS-REFERENCE PART I", -0xF3, "ASM CROSS-REFERENCE PART 2A", -0xF4, "ASM CROSS-REFERENCE PART 2B", -0xF5, "ASM CROSS-REFERENCE PART 2C", -0xF6, "ASM CROSS-REFERENCE PART III", diff --git a/Ibm1130/dmsr2v12slet.h b/Ibm1130/dmsr2v12slet.h deleted file mode 100644 index 326baa06..00000000 --- a/Ibm1130/dmsr2v12slet.h +++ /dev/null @@ -1,129 +0,0 @@ -// DMS R2V12 SLET without RPG, for debugging only - -0x0001, 0x7c50, 0x032f, 0x0008, -0x0002, 0x11de, 0x05a2, 0x000b, -0x0003, 0x21de, 0x05a2, 0x0010, -0x0004, 0x01de, 0x03c0, 0x0015, -0x0005, 0x41de, 0x0550, 0x0018, -0x0006, 0x01de, 0x03c0, 0x001d, -0x0007, 0x01de, 0x05a2, 0x0020, -0x0008, 0x01de, 0x05a2, 0x0025, -0x0009, 0x01de, 0x0500, 0x002a, -0x000a, 0x7a06, 0x00db, 0x002e, -0x000b, 0x7a06, 0x0035, 0x002f, -0x000c, 0x7a06, 0x00d8, 0x0030, -0x000d, 0x7782, 0x087c, 0x0031, -0x000e, 0x7a06, 0x0248, 0x0038, -0x000f, 0x7a06, 0x0248, 0x003a, -0x0010, 0x7a06, 0x0248, 0x003c, -0x0011, 0x01de, 0x0280, 0x003e, -0x0012, 0x0e6e, 0x0140, 0x0040, -0x001f, 0x760c, 0x09f1, 0x0041, -0x0020, 0x7a34, 0x0500, 0x0049, -0x0021, 0x7a34, 0x0280, 0x004d, -0x0022, 0x7a34, 0x03c0, 0x004f, -0x0023, 0x7a34, 0x0500, 0x0052, -0x0024, 0x7a34, 0x03c0, 0x0056, -0x0025, 0x7a34, 0x0280, 0x0059, -0x0026, 0x7a34, 0x0500, 0x005b, -0x0027, 0x7a34, 0x03f0, 0x005f, -0x0028, 0x7a34, 0x03c0, 0x0063, -0x0029, 0x7a34, 0x03c0, 0x0066, -0x002a, 0x7a34, 0x03c0, 0x0069, -0x002b, 0x7a34, 0x03c0, 0x006c, -0x002c, 0x7a34, 0x0500, 0x006f, -0x002d, 0x7a34, 0x0500, 0x0073, -0x002e, 0x7a34, 0x0500, 0x0077, -0x002f, 0x7a34, 0x0500, 0x007b, -0x0030, 0x7a34, 0x0500, 0x007f, -0x0031, 0x7a34, 0x0404, 0x0083, -0x0032, 0x7a34, 0x03c0, 0x0087, -0x0033, 0x7a34, 0x03c0, 0x008a, -0x0034, 0x7a34, 0x0280, 0x008d, -0x0035, 0x7a34, 0x03c0, 0x008f, -0x0036, 0x7a34, 0x03c0, 0x0092, -0x0037, 0x7a34, 0x0500, 0x0095, -0x0038, 0x7b96, 0x03c0, 0x0099, -0x0039, 0x766e, 0x013e, 0x009c, -0x006e, 0x04fe, 0x02fe, 0x009d, -0x006f, 0x07fe, 0x052b, 0x00a0, -0x0070, 0x07fe, 0x0280, 0x00a5, -0x0071, 0x07fe, 0x0280, 0x00a7, -0x0072, 0x07fe, 0x03ea, 0x00a9, -0x0073, 0x0506, 0x04f8, 0x00ad, -0x0074, 0x0400, 0x0189, 0x00b1, -0x0078, 0x01e0, 0x0782, 0x00b3, -0x0079, 0x05bc, 0x04dd, 0x00ba, -0x007a, 0x08b6, 0x01e8, 0x00be, -0x007b, 0x08b6, 0x01e8, 0x00c0, -0x007c, 0x08b6, 0x01e8, 0x00c2, -0x007d, 0x08b6, 0x01e8, 0x00c4, -0x007e, 0x0aa0, 0x0140, 0x00c6, -0x007f, 0x0aa0, 0x0140, 0x00c7, -0x0080, 0x0aa0, 0x0140, 0x00c8, -0x0081, 0x0aa0, 0x0140, 0x00c9, -0x0082, 0x0be2, 0x0140, 0x00ca, -0x0083, 0x08b6, 0x01e8, 0x00cb, -0x0084, 0x0aa0, 0x0140, 0x00cd, -0x008c, 0x0000, 0x0134, 0x80ceU, -0x008d, 0x0000, 0x0113, 0x00cf, -0x008e, 0x0000, 0x011f, 0x00d0, -0x008f, 0x0000, 0x009c, 0x80d1U, -0x0090, 0x0000, 0x00ab, 0x00d2, -0x0091, 0x0000, 0x016c, 0x80d3U, -0x0092, 0x0000, 0x0174, 0x00d5, -0x0093, 0x0000, 0x00b9, 0x00d7, -0x0094, 0x0000, 0x0003, 0x80d8U, -0x0095, 0x0000, 0x0003, 0x00d9, -0x0096, 0x00f0, 0x00ec, 0x00da, -0x0097, 0x00f0, 0x01a2, 0x00db, -0x0098, 0x00f0, 0x02b0, 0x00dd, -0x0099, 0x0000, 0x0113, 0x00cf, -0x009a, 0x0000, 0x00ab, 0x00d2, -0x009b, 0x0000, 0x00ab, 0x00d2, -0x009c, 0x0000, 0x00b9, 0x00d7, -0x009d, 0x0000, 0x00b9, 0x00d7, -0x00a0, 0x0000, 0x016c, 0x00e0, -0x00a1, 0x0000, 0x01c0, 0x00e2, -0x00cd, 0x11de, 0x0280, 0x00e4, -0x00ce, 0x01de, 0x11df, 0x00e6, -0x00cf, 0x01e0, 0x026b, 0x00f5, -0x00d0, 0x01e8, 0x00bb, 0x00f7, -0x00d1, 0x01e8, 0x005f, 0x00f8, -0x00d2, 0x01e8, 0x005f, 0x00f9, -0x00d3, 0x0280, 0x01d5, 0x00fa, -0x00d4, 0x0ad0, 0x0145, 0x00fc, -0x00d5, 0x0280, 0x01d6, 0x00fe, -0x00d6, 0x0280, 0x0113, 0x0100, -0x00d7, 0x0000, 0x0130, 0x0101, -0x00d8, 0x07a8, 0x0254, 0x0102, -0x00d9, 0x0280, 0x01d7, 0x0104, -0x00da, 0x0280, 0x01a0, 0x0106, -0x00db, 0x0282, 0x00a3, 0x0108, -0x00dc, 0x0458, 0x05a7, 0x0109, -0x00dd, 0x0280, 0x01d5, 0x010e, -0x00de, 0x0280, 0x01d6, 0x0110, -0x00df, 0x0280, 0x017c, 0x0112, -0x00e0, 0x0282, 0x0127, 0x0114, -0x00e1, 0x0280, 0x0196, 0x0115, -0x00e2, 0x0280, 0x01d8, 0x0117, -0x00e3, 0x0280, 0x0099, 0x0119, -0x00e4, 0x098a, 0x005f, 0x011a, -0x00e5, 0x098a, 0x0062, 0x011b, -0x00e6, 0x0eca, 0x03c1, 0x011c, -0x00e7, 0x0280, 0x00b8, 0x0120, -0x00e8, 0x0280, 0x017f, 0x0121, -0x00e9, 0x0280, 0x01d6, 0x0123, -0x00ea, 0x0280, 0x01d9, 0x0125, -0x00eb, 0x0280, 0x01d9, 0x0127, -0x00ec, 0x0280, 0x01ca, 0x0129, -0x00ed, 0x0280, 0x01c2, 0x012b, -0x00ee, 0x05dc, 0x0158, 0x012d, -0x00ef, 0x07ac, 0x0051, 0x012f, -0x00f0, 0x0280, 0x01af, 0x0130, -0x00f1, 0x12f4, 0x027f, 0x0132, -0x00f2, 0x0280, 0x01c7, 0x0134, -0x00f3, 0x07a8, 0x0052, 0x0136, -0x00f4, 0x0924, 0x005b, 0x0137, -0x00f5, 0x0886, 0x003d, 0x0138, -0x00f6, 0x0eca, 0x03b2, 0x0139, diff --git a/Ibm1130/ibm1130.mak b/Ibm1130/ibm1130.mak deleted file mode 100644 index aaf8e0fb..00000000 --- a/Ibm1130/ibm1130.mak +++ /dev/null @@ -1,372 +0,0 @@ -# Microsoft Visual C++ Generated NMAKE File, Format Version 2.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Console Application" 0x0103 - -!IF "$(CFG)" == "" -CFG=Win32 Debug -!MESSAGE No configuration specified. Defaulting to Win32 Debug. -!ENDIF - -!IF "$(CFG)" != "Win32 Release" && "$(CFG)" != "Win32 Debug" -!MESSAGE Invalid configuration "$(CFG)" specified. -!MESSAGE You can specify a configuration when running NMAKE on this makefile -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "ibm1130.mak" CFG="Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "Win32 Release" (based on "Win32 (x86) Console Application") -!MESSAGE "Win32 Debug" (based on "Win32 (x86) Console Application") -!MESSAGE -!ERROR An invalid configuration is specified. -!ENDIF - -################################################################################ -# Begin Project -# PROP Target_Last_Scanned "Win32 Debug" -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "WinRel" -# PROP BASE Intermediate_Dir "WinRel" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "WinRel" -# PROP Intermediate_Dir "WinRel" -OUTDIR=.\WinRel -INTDIR=.\WinRel - -ALL : $(OUTDIR)/ibm1130.exe $(OUTDIR)/ibm1130.bsc - -$(OUTDIR) : - if not exist $(OUTDIR)/nul mkdir $(OUTDIR) - -# ADD BASE CPP /nologo /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /FR /c -# ADD CPP /nologo /W3 /GX /YX /O2 /I "c:\pdp11\supnik" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "GUI_SUPPORT" /U "VMS" /FR /c -CPP_PROJ=/nologo /W3 /GX /YX /O2 /I "c:\pdp11\supnik" /D "NDEBUG" /D "WIN32" /D\ - "_CONSOLE" /D "GUI_SUPPORT" /U "VMS" /FR$(INTDIR)/ /Fp$(OUTDIR)/"ibm1130.pch"\ - /Fo$(INTDIR)/ /c -CPP_OBJS=.\WinRel/ -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -RSC_PROJ=/l 0x409 /fo$(INTDIR)/"ibm1130.res" /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -BSC32_FLAGS=/nologo /o$(OUTDIR)/"ibm1130.bsc" -BSC32_SBRS= \ - $(INTDIR)/ibm1130_cpu.sbr \ - $(INTDIR)/ibm1130_sys.sbr \ - $(INTDIR)/ibm1130_cr.sbr \ - $(INTDIR)/ibm1130_stddev.sbr \ - $(INTDIR)/ibm1130_disk.sbr \ - $(INTDIR)/ibm1130_gdu.sbr \ - $(INTDIR)/ibm1130_gui.sbr \ - $(INTDIR)/ibm1130_prt.sbr \ - $(INTDIR)/scp.sbr \ - $(INTDIR)/scp_tty.sbr \ - $(INTDIR)/sim_tmxr.sbr \ - $(INTDIR)/sim_sock.sbr \ - $(INTDIR)/ibm1130_fmt.sbr - -$(OUTDIR)/ibm1130.bsc : $(OUTDIR) $(BSC32_SBRS) - $(BSC32) @<< - $(BSC32_FLAGS) $(BSC32_SBRS) -<< - -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NOLOGO /SUBSYSTEM:console /MACHINE:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib comdlg32.lib advapi32.lib wsock32.lib /NOLOGO /SUBSYSTEM:console /MACHINE:I386 -LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib comdlg32.lib advapi32.lib\ - wsock32.lib /NOLOGO /SUBSYSTEM:console /INCREMENTAL:no\ - /PDB:$(OUTDIR)/"ibm1130.pdb" /MACHINE:I386 /OUT:$(OUTDIR)/"ibm1130.exe" -DEF_FILE= -LINK32_OBJS= \ - $(INTDIR)/ibm1130_cpu.obj \ - $(INTDIR)/ibm1130_sys.obj \ - $(INTDIR)/ibm1130_cr.obj \ - $(INTDIR)/ibm1130_stddev.obj \ - $(INTDIR)/ibm1130.res \ - $(INTDIR)/ibm1130_disk.obj \ - $(INTDIR)/ibm1130_gdu.obj \ - $(INTDIR)/ibm1130_gui.obj \ - $(INTDIR)/ibm1130_prt.obj \ - $(INTDIR)/scp.obj \ - $(INTDIR)/scp_tty.obj \ - $(INTDIR)/sim_tmxr.obj \ - $(INTDIR)/sim_sock.obj \ - $(INTDIR)/ibm1130_fmt.obj - -$(OUTDIR)/ibm1130.exe : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS) - $(LINK32) @<< - $(LINK32_FLAGS) $(LINK32_OBJS) -<< - -!ELSEIF "$(CFG)" == "Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "WinDebug" -# PROP BASE Intermediate_Dir "WinDebug" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "WinDebug" -# PROP Intermediate_Dir "WinDebug" -OUTDIR=.\WinDebug -INTDIR=.\WinDebug - -ALL : $(OUTDIR)/ibm1130.exe $(OUTDIR)/ibm1130.bsc - -$(OUTDIR) : - if not exist $(OUTDIR)/nul mkdir $(OUTDIR) - -# ADD BASE CPP /nologo /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /FR /c -# ADD CPP /nologo /W3 /GX /Zi /YX /Od /I "c:\pdp11\supnik" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "GUI_SUPPORT" /U "VMS" /FR /c -CPP_PROJ=/nologo /W3 /GX /Zi /YX /Od /I "c:\pdp11\supnik" /D "_DEBUG" /D\ - "WIN32" /D "_CONSOLE" /D "GUI_SUPPORT" /U "VMS" /FR$(INTDIR)/\ - /Fp$(OUTDIR)/"ibm1130.pch" /Fo$(INTDIR)/ /Fd$(OUTDIR)/"ibm1130.pdb" /c -CPP_OBJS=.\WinDebug/ -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -RSC_PROJ=/l 0x409 /fo$(INTDIR)/"ibm1130.res" /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -BSC32_FLAGS=/nologo /o$(OUTDIR)/"ibm1130.bsc" -BSC32_SBRS= \ - $(INTDIR)/ibm1130_cpu.sbr \ - $(INTDIR)/ibm1130_sys.sbr \ - $(INTDIR)/ibm1130_cr.sbr \ - $(INTDIR)/ibm1130_stddev.sbr \ - $(INTDIR)/ibm1130_disk.sbr \ - $(INTDIR)/ibm1130_gdu.sbr \ - $(INTDIR)/ibm1130_gui.sbr \ - $(INTDIR)/ibm1130_prt.sbr \ - $(INTDIR)/scp.sbr \ - $(INTDIR)/scp_tty.sbr \ - $(INTDIR)/sim_tmxr.sbr \ - $(INTDIR)/sim_sock.sbr \ - $(INTDIR)/ibm1130_fmt.sbr - -$(OUTDIR)/ibm1130.bsc : $(OUTDIR) $(BSC32_SBRS) - $(BSC32) @<< - $(BSC32_FLAGS) $(BSC32_SBRS) -<< - -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NOLOGO /SUBSYSTEM:console /DEBUG /MACHINE:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib comdlg32.lib advapi32.lib wsock32.lib /NOLOGO /SUBSYSTEM:console /DEBUG /MACHINE:I386 -LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib comdlg32.lib advapi32.lib\ - wsock32.lib /NOLOGO /SUBSYSTEM:console /INCREMENTAL:yes\ - /PDB:$(OUTDIR)/"ibm1130.pdb" /DEBUG /MACHINE:I386 /OUT:$(OUTDIR)/"ibm1130.exe" -DEF_FILE= -LINK32_OBJS= \ - $(INTDIR)/ibm1130_cpu.obj \ - $(INTDIR)/ibm1130_sys.obj \ - $(INTDIR)/ibm1130_cr.obj \ - $(INTDIR)/ibm1130_stddev.obj \ - $(INTDIR)/ibm1130.res \ - $(INTDIR)/ibm1130_disk.obj \ - $(INTDIR)/ibm1130_gdu.obj \ - $(INTDIR)/ibm1130_gui.obj \ - $(INTDIR)/ibm1130_prt.obj \ - $(INTDIR)/scp.obj \ - $(INTDIR)/scp_tty.obj \ - $(INTDIR)/sim_tmxr.obj \ - $(INTDIR)/sim_sock.obj \ - $(INTDIR)/ibm1130_fmt.obj - -$(OUTDIR)/ibm1130.exe : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS) - $(LINK32) @<< - $(LINK32_FLAGS) $(LINK32_OBJS) -<< - -!ENDIF - -.c{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -.cpp{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -.cxx{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -################################################################################ -# Begin Group "Source Files" - -################################################################################ -# Begin Source File - -SOURCE=.\ibm1130_cpu.c -DEP_IBM11=\ - .\ibm1130_defs.h\ - ..\sim_defs.h - -$(INTDIR)/ibm1130_cpu.obj : $(SOURCE) $(DEP_IBM11) $(INTDIR) - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\ibm1130_sys.c -DEP_IBM113=\ - .\ibm1130_defs.h\ - ..\sim_defs.h - -$(INTDIR)/ibm1130_sys.obj : $(SOURCE) $(DEP_IBM113) $(INTDIR) - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\ibm1130_cr.c -DEP_IBM1130=\ - .\ibm1130_defs.h\ - ..\sim_defs.h - -$(INTDIR)/ibm1130_cr.obj : $(SOURCE) $(DEP_IBM1130) $(INTDIR) - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\ibm1130_stddev.c -DEP_IBM1130_=\ - .\ibm1130_defs.h\ - .\ibm1130_conout.h\ - .\ibm1130_conin.h\ - ..\sim_defs.h - -$(INTDIR)/ibm1130_stddev.obj : $(SOURCE) $(DEP_IBM1130_) $(INTDIR) - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\ibm1130.rc -DEP_IBM1130_R=\ - .\1130consoleblank.bmp\ - .\hand.cur - -$(INTDIR)/ibm1130.res : $(SOURCE) $(DEP_IBM1130_R) $(INTDIR) - $(RSC) $(RSC_PROJ) $(SOURCE) - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\ibm1130_disk.c -DEP_IBM1130_D=\ - .\ibm1130_defs.h\ - .\dmsr2v12phases.h\ - .\dmsr2v12slet.h\ - ..\sim_defs.h - -$(INTDIR)/ibm1130_disk.obj : $(SOURCE) $(DEP_IBM1130_D) $(INTDIR) - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\ibm1130_gdu.c -DEP_IBM1130_G=\ - .\ibm1130_defs.h\ - ..\sim_defs.h - -$(INTDIR)/ibm1130_gdu.obj : $(SOURCE) $(DEP_IBM1130_G) $(INTDIR) - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\ibm1130_gui.c -DEP_IBM1130_GU=\ - .\ibm1130_defs.h\ - ..\sim_defs.h - -$(INTDIR)/ibm1130_gui.obj : $(SOURCE) $(DEP_IBM1130_GU) $(INTDIR) - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\ibm1130_prt.c -DEP_IBM1130_P=\ - .\ibm1130_defs.h\ - .\ibm1130_prtwheel.h\ - ..\sim_defs.h - -$(INTDIR)/ibm1130_prt.obj : $(SOURCE) $(DEP_IBM1130_P) $(INTDIR) - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=\pdp11\supnik\scp.c -DEP_SCP_C=\ - ..\sim_defs.h\ - \pdp11\supnik\sim_rev.h\ - \pdp11\supnik\sim_sock.h\ - \pdp11\supnik\sim_tmxr.h\ - \MSVC20\INCLUDE\sys\TYPES.H - -$(INTDIR)/scp.obj : $(SOURCE) $(DEP_SCP_C) $(INTDIR) - $(CPP) $(CPP_PROJ) $(SOURCE) - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=..\scp_tty.c -DEP_SCP_T=\ - ..\sim_defs.h - -$(INTDIR)/scp_tty.obj : $(SOURCE) $(DEP_SCP_T) $(INTDIR) - $(CPP) $(CPP_PROJ) $(SOURCE) - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=\pdp11\supnik\sim_tmxr.c -DEP_SIM_T=\ - ..\sim_defs.h\ - \pdp11\supnik\sim_sock.h\ - \pdp11\supnik\sim_tmxr.h\ - \MSVC20\INCLUDE\sys\TYPES.H - -$(INTDIR)/sim_tmxr.obj : $(SOURCE) $(DEP_SIM_T) $(INTDIR) - $(CPP) $(CPP_PROJ) $(SOURCE) - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=\pdp11\supnik\sim_sock.c -DEP_SIM_S=\ - ..\sim_defs.h\ - \pdp11\supnik\sim_sock.h\ - \MSVC20\INCLUDE\sys\TYPES.H - -$(INTDIR)/sim_sock.obj : $(SOURCE) $(DEP_SIM_S) $(INTDIR) - $(CPP) $(CPP_PROJ) $(SOURCE) - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\ibm1130_fmt.c - -$(INTDIR)/ibm1130_fmt.obj : $(SOURCE) $(INTDIR) - -# End Source File -# End Group -# End Project -################################################################################ diff --git a/Ibm1130/ibm1130.rc b/Ibm1130/ibm1130.rc deleted file mode 100644 index 64f9da0d..00000000 --- a/Ibm1130/ibm1130.rc +++ /dev/null @@ -1,61 +0,0 @@ -//Microsoft Visual C++ generated resource script. -// -#include "ibm1130res.h" - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// -#include - -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE DISCARDABLE -BEGIN - "ibm1130res.h\0" -END - -2 TEXTINCLUDE DISCARDABLE -BEGIN - "#include \r\n" - "\0" -END - -3 TEXTINCLUDE DISCARDABLE -BEGIN - "\r\n" - "\0" -END - -///////////////////////////////////////////////////////////////////////////// -#endif // APSTUDIO_INVOKED - - -///////////////////////////////////////////////////////////////////////////// -// -// Bitmap -// - -IDB_CONSOLE BITMAP DISCARDABLE "1130consoleblank.bmp" - -IDC_HAND CURSOR DISCARDABLE "HAND.CUR" - -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 3 resource. -// - - -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED - diff --git a/Ibm1130/ibm1130_conin.h b/Ibm1130/ibm1130_conin.h deleted file mode 100644 index 108e4917..00000000 --- a/Ibm1130/ibm1130_conin.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * (C) Copyright 2002, Brian Knittel. - * You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN - * RISK basis, there is no warranty of fitness for any purpose, and the rest of the - * usual yada-yada. Please keep this notice and the copyright in any distributions - * or modifications. - * - * This is not a supported product, but I welcome bug reports and fixes. - * Mail to sim@ibm1130.org - */ - -// 03 ctrl-C => Program stop (not handled here) -// 05 ctrl-E => Simulator stop (not handled here) -// 08 ctrl-H => Backspace -// 0D ctrl-M (Enter) => EOF -// 11 ctrl-Q => Interrupt request (not handled here) -// 12 ctrl-R => "cent" (R because that's where cent is on the 1130 keyboard) -// 15 ctrl-U => Erase Field -// 7E ~ => "not" -// FF Del => Backspace again - -static uint16 ascii_to_conin[] = /* ASCII to ((hollerith << 4) | special key flags) */ -{ - /* 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F */ - /* 00 */ 0, 0, 0, 0, 0, 0, 0, 0,0x0004, 0, 0, 0, 0,0x0008, 0, 0, - /* 10 */ 0, 0,0x8820, 0, 0,0x0002, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 20 */ 0x0001,0x4820,0x0060,0x0420,0x4420,0x2220,0x8000,0x0120,0x8120,0x4120,0x4220,0x80a0,0x2420,0x4000,0x8420,0x3000, - /* 30 */ 0x2000,0x1000,0x0800,0x0400,0x0200,0x0100,0x0080,0x0040,0x0020,0x0010,0x0820,0x40a0,0x8220,0x00a0,0x20a0,0x2060, - /* 40 */ 0x0220,0x9000,0x8800,0x8400,0x8200,0x8100,0x8080,0x8040,0x8020,0x8010,0x5000,0x4800,0x4400,0x4200,0x4100,0x4080, - /* 50 */ 0x4040,0x4020,0x4010,0x2800,0x2400,0x2200,0x2100,0x2080,0x2040,0x2020,0x2010, 0, 0, 0, 0,0x2120, - /* 60 */ 0,0x9000,0x8800,0x8400,0x8200,0x8100,0x8080,0x8040,0x8020,0x8010,0x5000,0x4800,0x4400,0x4200,0x4100,0x4080, - /* 70 */ 0x4040,0x4020,0x4010,0x2800,0x2400,0x2200,0x2100,0x2080,0x2040,0x2020,0x2010, 0,0xB060, 0, 0,0x0004, - /* 80 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 90 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* a0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* b0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* c0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* d0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* e0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* f0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0x0004, -}; diff --git a/Ibm1130/ibm1130_conout.h b/Ibm1130/ibm1130_conout.h deleted file mode 100644 index 478e005d..00000000 --- a/Ibm1130/ibm1130_conout.h +++ /dev/null @@ -1,58 +0,0 @@ -/* IBM1130 CONSOLE OUTPUT TO ASCII CONVERSION TABLE - * - * (C) Copyright 2002, Brian Knittel. - * You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN - * RISK basis, there is no warranty of fitness for any purpose, and the rest of the - * usual yada-yada. Please keep this notice and the copyright in any distributions - * or modifications. - * - * This is not a supported product, but I welcome bug reports and fixes. - * Mail to sim@ibm1130.org - */ - -#define _0_ '\0' - -#define CENT_ '\xA2' /* cent and not: standard DOS mapping */ -#define NOT_ '\xAC' -#define IGNR_ '\xFF' -#define CRLF_ '\r' - -#define COUT_IS_CTRL 0x01 /* conout characters with bit 1 set are controls: */ - -#define COUT_CTRL_BLACK 0x04 /* none or one of these bits */ -#define COUT_CTRL_RED 0x08 - -#define COUT_CTRL_LINEFEED 0x02 /* plus none or one of these bits */ -#define COUT_CTRL_BACKSPACE 0x10 -#define COUT_CTRL_SPACE 0x20 -#define COUT_CTRL_TAB 0x40 -#define COUT_CTRL_RETURN 0x80 - -#ifdef _MSC_VER -# pragma warning(disable:4245) /* enable int->char demotion warning caused by characters with high-bit set */ -#endif - -static unsigned char conout_to_ascii[] = /* console output code to ASCII */ -{ - /* 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F */ - /* 00 */ '.', IGNR_,CENT_, '\n', '@', IGNR_,'%', _0_, _0_, IGNR_,_0_, _0_, _0_, _0_, _0_, _0_, - /* 10 */ 'F', '\b', 'f', _0_, 'G', _0_, 'g', _0_, 'B', _0_, 'b', _0_, 'C', _0_, 'c', _0_, - /* 20 */ 'I', ' ', 'i', _0_, 'H', _0_, 'h', _0_, _0_, _0_, _0_, _0_, _0_, _0_, _0_, _0_, - /* 30 */ 'D', _0_, 'd', _0_, 'E', _0_, 'e', _0_, _0_, _0_, _0_, _0_, 'A', _0_, 'a', _0_, - /* 40 */ '$', '\t', '!', _0_, '&', _0_, '>', _0_, _0_, _0_, _0_, _0_, _0_, _0_, _0_, _0_, - /* 50 */ 'O', _0_, 'o', _0_, 'P', _0_, 'o', _0_, 'K', _0_, 'k', _0_, 'L', _0_, 'l', _0_, - /* 60 */ 'R', _0_, 'r', _0_, 'Q', _0_, 'q', _0_, _0_, _0_, _0_, _0_, _0_, _0_, _0_, _0_, - /* 70 */ 'M', _0_, 'm', _0_, 'N', _0_, 'n', _0_, _0_, _0_, _0_, _0_, 'J', _0_, 'j', _0_, - /* 80 */ ',', CRLF_, ':', _0_, '-', _0_, '?', _0_, _0_, _0_, _0_, _0_, _0_, _0_, _0_, _0_, - /* 90 */ 'W', _0_, 'w', _0_, 'X', _0_, 'x', _0_, 'S', _0_, 's', _0_, 'T', _0_, 't', _0_, - /* A0 */ 'Z', _0_, 'z', _0_, 'Y', _0_, 'y', _0_, _0_, _0_, _0_, _0_, _0_, _0_, _0_, _0_, - /* B0 */ 'U', _0_, 'u', _0_, 'V', _0_, 'v', _0_, _0_, _0_, _0_, _0_, '/', _0_, '_', _0_, - /* C0 */ '#', _0_, '=', _0_, '0', _0_, '|', _0_, _0_, _0_, _0_, _0_, 'J', _0_, 'j', _0_, - /* D0 */ '6', _0_, ';', _0_, '7', _0_, '*', _0_, '2', _0_, '+', _0_, '3', _0_, '<', _0_, - /* E0 */ '9', _0_, '"', _0_, '8', _0_, '\'', _0_, _0_, _0_, _0_, _0_, _0_, _0_, _0_, _0_, - /* F0 */ '4', _0_, NOT_, _0_, '5', _0_, ')', _0_, _0_, _0_, _0_, _0_, '1', _0_, '(', _0_, -}; - -#ifdef _MSC_VER -# pragma warning(default:4245) /* enable int->char demotion warning */ -#endif diff --git a/Ibm1130/ibm1130_cpu.c b/Ibm1130/ibm1130_cpu.c deleted file mode 100644 index f258bda8..00000000 --- a/Ibm1130/ibm1130_cpu.c +++ /dev/null @@ -1,1872 +0,0 @@ -/* ibm1130_cpu.c: IBM 1130 CPU simulator - - Based on the SIMH package written by Robert M Supnik - - * (C) Copyright 2002, Brian Knittel. - * You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN - * RISK basis, there is no warranty of fitness for any purpose, and the rest of the - * usual yada-yada. Please keep this notice and the copyright in any distributions - * or modifications. - * - * This is not a supported product, but I welcome bug reports and fixes. - * Mail to simh@ibm1130.org - - 25-Jun-01 BLK Written - 10-May-02 BLK Fixed bug in MDX instruction - 27-Mar-02 BLK Made BOSC work even in short form - 16-Aug-02 BLK Fixed bug in multiply instruction; didn't work with negative values - 18-Mar-03 BLK Fixed bug in divide instruction; didn't work with negative values - 23-Jul-03 BLK Prevented tti polling in CGI mode - - The register state for the IBM 1130 CPU is: - - IAR instruction address register - ACC accumulator - EXT accumulator extension - Oflow overflow bit - Carry carry bit - CES console entry switches - ipl current interrupt level, -1 = non interrupt - iplpending bitmap of pending interrupts - wait_state current CPU state: running or waiting - DSW console run/stop switch device status word - RUNMODE processor step/run mode (may also imply IntRun) - BREAK breakpoint address - WRU simulator-break character - IntRun Int Run flag (causes level 5 interrupt after every instruction) - ILSW0..5 interrupt level status words - - The SAR (storage address register) and SBR (storage buffer register) are updated - but not saved in the CPU state; they matter only to the GUI. - - Interrupt handling: interrupts occur when any device on any level has an - active interrupt. XIO commands can clear specific IRQ bits. When this - happens, we have to evaluate all devices on the same IRQ level for remaining - indicators. The flag int_req is set with a bit corresponding to the IRQ level - when any interrupt indicator is activated. - - The 1130 console has a switch that controls several run modes: SS (single processor - step), SCLK (single clock step), SINST (single instruction step), INT_RUN - (IRQ 5 after each non interrupt-handler instruction) and RUN (normal operation). - This simulator does not implement SS and SCLK. The simulator GUI console handles - SINST, so we only have to worry about INT_RUN. The console command SET CPU IntRun sets - the tmode (trace mode) flag; this causes a level 5 interrupt after each - instruction. - - The IBM 1130 instruction formats are - - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | opcode | F| T | | general format - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | opcode | 0| T | DISPLACEMENT | short instruction - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | opcode | 1| T | I| MODIFIER | long instruction - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | ADDRESS | - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - opcode in MSBits - - F = format. 0 = short (1 word), 1 = long (2 word) instruction - - T = Tag 00 = no index register (e.g. IAR relative) - 01 = use index register 1 (e.g. core address 1 = M[1]) - 02 = use index register 2 (e.g. core address 2 = M[2]) - 03 = use index register 3 (e.g. core address 3 = M[3]) - - DISPLACEMENT = two's complement (must be sign-extended) - - I = Indirect - - Note that IAR = instruction address+1 when instruction is being decoded. - - In normal addressing mode, effective address (EA) is computed as follows: - - F = 0 T = 0 EA = IAR + DISPLACEMENT - 0 1 IAR + DISPLACEMENT + M[1] - 0 2 IAR + DISPLACEMENT + M[2] - 0 3 IAR + DISPLACEMENT + M[3] - - F = 1 T = 0 I = 0 EA = ADDRESS - 1 1 0 ADDRESS + M[1] - 1 2 0 ADDRESS + M[2] - 1 3 0 ADDRESS + M[3] - 1 0 1 M[ADDRESS] - 1 1 1 M[ADDRESS + M[1]] - 1 2 1 M[ADDRESS + M[2]] - 1 3 1 M[ADDRESS + M[3]] - - Loads or stores are then made to/from MEM[EA]. Some instructions have special - weird addressing modes. Simulator code precomputes standard addressing for - all instructions though it's not always used. - - General notes: - - Adding I/O devices requires modifications to three modules: - - ibm1130_defs.h add interrupt request definitions - ibm1130_cpu.c add XIO command linkages - ibm1130_sys.c add to sim_devices -*/ - -/* ------------------------------------------------------------------------ - * Definitions - * ------------------------------------------------------------------------ */ - -#include - -#include "ibm1130_defs.h" - -#define save_ibkpt (cpu_unit.u3) /* will be SAVEd */ - -#define UPDATE_BY_TIMER -#define ENABLE_BACKTRACE -#define CGI_SUPPORT - -static void cgi_start(void); -static void cgi_stop(t_stat reason); - -// hook pointers from scp.c -void (*sim_vm_init) (void) = &sim_init; -extern char* (*sim_vm_read) (char *ptr, int32 size, FILE *stream); -extern void (*sim_vm_post) (t_bool from_scp); -extern CTAB *sim_vm_cmd; - -// space to store extra simulator-specific commands -#define MAX_EXTRA_COMMANDS 10 -CTAB x_cmds[MAX_EXTRA_COMMANDS]; - -#ifdef WIN32 -# define CRLF "\r\n" -#else -# define CRLF "\n" -#endif - -/* ------------------------------------------------------------------------ - * initializers for globals - * ------------------------------------------------------------------------ */ - -#define SIGN_BIT(v) ((v) & 0x8000) -#define DWSIGN_BIT(v) ((v) & 0x80000000) - -uint16 M[MAXMEMSIZE]; /* core memory, up to 32Kwords (note: don't even think about trying 64K) */ -uint16 ILSW[6] = {0,0,0,0,0,0}; /* interrupt level status words */ -int32 IAR; /* instruction address register */ -int32 prev_IAR; /* instruction address register at start of current instruction */ -int32 SAR, SBR; /* storage address/buffer registers */ -int32 OP, TAG, CCC; /* instruction decoded pieces */ -int32 CES; /* console entry switches */ -int32 ACC, EXT; /* accumulator and extension */ -int32 RUNMODE; /* processor run/step mode */ -int32 ipl = -1; /* current interrupt level (-1 = not handling irq) */ -int32 iplpending = 0; /* interrupted IPL's */ -int32 tbit = 0; /* trace flag (causes level 5 IRQ after each instr) */ -int32 V = 0, C = 0; /* condition codes */ -int32 wait_state = 0; /* wait state (waiting for an IRQ) */ -int32 wait_lamp = TRUE; /* alternate indicator to light the wait lamp on the GUI */ -int32 int_req = 0; /* sum of interrupt request levels active */ -int32 int_lamps = 0; /* accumulated version of int_req - gives lamp persistence */ -int32 int_mask; /* current active interrupt mask (ipl sensitive) */ -int32 mem_mask; -int32 cpu_dsw = 0; /* CPU device status word */ -int32 ibkpt_addr = -1; /* breakpoint addr */ -int32 sim_gui = TRUE; /* enable gui */ -t_bool running = FALSE; /* TRUE if CPU is running */ -t_bool power = TRUE; /* TRUE if CPU power is on */ -t_bool cgi = FALSE; /* TRUE if we are running as a CGI program */ -t_stat reason; /* CPU execution loop control */ - -static int32 int_masks[6] = { - 0x00, 0x20, 0x30, 0x38, 0x3C, 0x3E /* IPL 0 is highest prio (sees no other interrupts) */ -}; - -/* ------------------------------------------------------------------------ - * Function declarations - * ------------------------------------------------------------------------ */ - -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, char *cptr, void *desc); -void calc_ints (void); - -extern t_stat ts_wr (int32 data, int32 addr, int32 access); -extern t_stat detach_cmd (int flags, char *cptr); -extern UNIT cr_unit; -extern int32 sim_switches; - -#ifdef ENABLE_BACKTRACE - static void archive_backtrace(char *inst); - static void reset_backtrace (void); - static void show_backtrace (int nshow); - static t_stat backtrace_cmd (int flag, char *cptr); -#else - #define archive_backtrace(inst) - #define reset_backtrace() - #define show_backtrace(ntrace) -#endif - -static void init_console_window (void); -static void destroy_console_window (void); -static t_stat view_cmd (int flag, char *cptr); -static t_stat cgi_cmd (int flag, char *cptr); -static t_stat cpu_attach (UNIT *uptr, char *cptr); -static t_bool bsctest (int32 DSPLC, t_bool reset_V); -static void exit_irq (void); -static void trace_instruction (void); - -/* ------------------------------------------------------------------------ - * CPU data structures: - * cpu_dev CPU device descriptor - * cpu_unit CPU unit descriptor - * cpu_reg CPU register list - * cpu_mod CPU modifier list - * ------------------------------------------------------------------------ */ - -UNIT cpu_unit = { UDATA (&cpu_svc, UNIT_FIX | UNIT_BINK | UNIT_ATTABLE | UNIT_SEQ, INIMEMSIZE) }; - -REG cpu_reg[] = { - { HRDATA (IAR, IAR, 32) }, - { HRDATA (ACC, ACC, 32) }, - { HRDATA (EXT, EXT, 32) }, - { FLDATA (Oflow, V, 1) }, - { FLDATA (Carry, C, 1) }, - { HRDATA (CES, CES, 32) }, - { HRDATA (ipl, ipl, 32), REG_RO }, - { HRDATA (iplpending, iplpending, 32), REG_RO }, - { HRDATA (wait_state, wait_state, 32)}, - { HRDATA (DSW, cpu_dsw, 32), REG_RO }, - { HRDATA (RUNMODE, RUNMODE, 32) }, - { HRDATA (BREAK, ibkpt_addr, 32) }, - { ORDATA (WRU, sim_int_char, 8) }, - { FLDATA (IntRun, tbit, 1) }, - - { HRDATA (ILSW0, ILSW[0], 32), REG_RO }, - { HRDATA (ILSW1, ILSW[1], 32), REG_RO }, - { HRDATA (ILSW2, ILSW[2], 32), REG_RO }, - { HRDATA (ILSW3, ILSW[3], 32), REG_RO }, - { HRDATA (ILSW4, ILSW[4], 32), REG_RO }, - { HRDATA (ILSW5, ILSW[5], 32), REG_RO }, - - { NULL} -}; - -MTAB cpu_mod[] = { - { UNIT_MSIZE, 4096, NULL, "4KW", &cpu_set_size}, - { UNIT_MSIZE, 8192, NULL, "8KW", &cpu_set_size}, - { UNIT_MSIZE, 16384, NULL, "16KW", &cpu_set_size}, - { UNIT_MSIZE, 32768, NULL, "32KW", &cpu_set_size}, - { 0 } }; - -DEVICE cpu_dev = { - "CPU", &cpu_unit, cpu_reg, cpu_mod, - 1, 16, 16, 1, 16, 16, - &cpu_ex, &cpu_dep, &cpu_reset, - NULL, cpu_attach, NULL}; // attaching to CPU creates cpu log file - -/* ------------------------------------------------------------------------ - Memory read/write -- save SAR and SBR on the way in and out - * ------------------------------------------------------------------------ */ - -int32 ReadW (int32 a) -{ - SAR = a; - SBR = (int32) M[(a) & mem_mask]; - return SBR; -} - -void WriteW (int32 a, int32 d) -{ - SAR = a; - SBR = d; - M[a & mem_mask] = (int16) d; -} - -/* ------------------------------------------------------------------------ - * upcase - force a string to uppercase (ASCII) - * ------------------------------------------------------------------------ */ - -char *upcase (char *str) -{ - char *s; - - for (s = str; *s; s++) { - if (*s >= 'a' && *s <= 'z') - *s -= 32; - } - - return str; -} - -/* ------------------------------------------------------------------------ - * calc_ints - set appropriate bits in int_req if any interrupts are pending on given levels - * - * int_req: - * bit 5 4 3 2 1 0 - * \ \ \ \ \ \ - * \ \ \ \ \ interrupt level 5 pending (lowest priority) - * \ . . . - * interrupt level 0 pending (highest priority) - * - * int_mask is set according to current interrupt level (ipl) - * - * 0 0 0 0 0 0 ipl = 0 (currently servicing highest priority interrupt) - * 1 0 0 0 0 0 1 - * 1 1 0 0 0 0 2 - * 1 1 1 0 0 0 3 - * 1 1 1 1 0 0 4 - * 1 1 1 1 1 0 5 (currently servicing lowest priority interrupt) - * 1 1 1 1 1 1 -1 (not servicing an interrupt) - * ------------------------------------------------------------------------ */ - -void calc_ints (void) -{ - register int i; - register int32 newbits = 0; - - GUI_BEGIN_CRITICAL_SECTION // using critical section here so we don't mislead the GUI thread - - for (i = 6; --i >= 0; ) { - newbits >>= 1; - if (ILSW[i]) - newbits |= 0x20; - } - - int_req = newbits; - int_lamps |= int_req; - int_mask = (ipl < 0) ? 0xFFFF : int_masks[ipl]; /* be sure this is set correctly */ - - GUI_END_CRITICAL_SECTION -} - -/* ------------------------------------------------------------------------ - * instruction processor - * ------------------------------------------------------------------------ */ - -#define INCREMENT_IAR IAR = (IAR + 1) & mem_mask -#define DECREMENT_IAR IAR = (IAR - 1) & mem_mask - -void bail (char *msg) -{ - printf("%s\n", msg); - exit(1); -} - -static void weirdop (char *msg, int offset) -{ - printf("Weird opcode: %s at %04x\n", msg, IAR+offset); -} - -static char *xio_devs[] = { - "0?", "console", "1142card", "1134papertape", - "dsk0", "1627plot", "1132print", "switches", - "1231omr", "2501card", "comm", "b?", - "sys7", "d?", "e?", "f?", - "10?", "dsk1", "dsk2", "dsk3", - "dsk4", "dsk5", "dsk6", "dsk7+", - "18?", "2250disp", "1a?", "1b", - "1c?", "1d?", "1e?", "1f?" -}; - -static char *xio_funcs[] = { - "0?", "write", "read", "sense_irq", - "control", "initw", "initr", "sense" -}; - -t_stat sim_instr (void) -{ - extern int32 sim_interval; - extern UNIT *sim_clock_queue; - int32 i, eaddr, INDIR, IR, F, DSPLC, word2, oldval, newval, src, src2, dst, abit, xbit; - int32 iocc_addr, iocc_op, iocc_dev, iocc_func, iocc_mod; - char msg[50]; - int cwincount = 0, status; - static long ninstr = 0; - static char *intlabel[] = {"INT0","INT1","INT2","INT3","INT4","INT5"}; - -#ifdef CGI_SUPPORT - if (cgi) - cgi_start(); -#endif - - if (running) /* this is definitely not reentrant */ - return -1; - - if (! power) /* this matters only to the GUI */ - return STOP_POWER_OFF; - - running = TRUE; - - mem_mask = MEMSIZE - 1; /* set other useful variables */ - calc_ints(); - - /* Main instruction fetch/decode loop */ - - reason = 0; - wait_lamp = 0; /* release lock on wait lamp */ - -#ifdef GUI_SUPPORT - update_gui(TRUE); - gui_run(TRUE); -#endif - - while (reason == 0) { - IAR &= mem_mask; - -#ifdef GUI_SUPPORT -#ifndef UPDATE_BY_TIMER -#if (UPDATE_INTERVAL > 0) - if (--cwincount <= 0) { - update_gui(FALSE); /* update console lamps only every so many instructions */ - cwincount = UPDATE_INTERVAL + (rand() % MIN(UPDATE_INTERVAL, 32)); - } -#else - update_gui(FALSE); -#endif // ifdef UPDATE_INTERVAL -#endif // ifndef UPDATE_BY_TIMER -#endif // ifdef GUI_SUPPORT - - if (sim_interval <= 0) { /* any events timed out? */ - if (sim_clock_queue != NULL) { - if ((status = sim_process_event()) != 0) - reason = status; - calc_ints(); - continue; - } - } - - if (int_req & int_mask) { /* any pending interrupts? */ - for (i = 0; i <= 5; i++) /* find highest pending interrupt */ - if ((int_req & int_mask) & (0x20 >> i)) - break; - - if (i >= 6) { /* nothing to do? */ - calc_ints(); /* weird. recalculate */ - continue; /* back to fetch */ - } - - GUI_BEGIN_CRITICAL_SECTION - - if (ipl >= 0) /* save previous IPL in bit stack */ - iplpending |= (0x20 >> ipl); - - ipl = i; /* set new interrupt level */ - int_mask = int_masks[i]; /* set appropriate mask */ - - GUI_END_CRITICAL_SECTION - - wait_state = 0; /* exit wait state */ - eaddr = ReadW(8+i); /* get IRQ vector */ - archive_backtrace(intlabel[i]); - WriteW(eaddr, IAR); /* save IAR */ - IAR = (eaddr+1) & mem_mask; /* go to next address */ - continue; /* now continue processing */ - } /* end if int_req */ - - if (wait_state) { /* waiting? */ - sim_interval = 0; /* run the clock out */ - - if (sim_qcount() <= (cgi ? 0 : 1)) { /* one routine queued? we're waiting for keyboard only */ - if (keyboard_is_busy()) { /* we are actually waiting for a keystroke */ - if ((status = sim_process_event()) != 0) /* get it with wait_state still set */ - reason = status; - } - else { /* CPU is not expecting a keystroke (keyboard interrupt) */ - if (wait_state == WAIT_OP) - reason = STOP_WAIT; /* end the simulation */ - else - reason = STOP_INVALID_INSTR; - } - } - - if (gdu_active()) /* but don't stop simulator if 2250 GDU is running */ - reason = 0; - - continue; - } - - if (IAR == ibkpt_addr) { /* simulator breakpoint? */ - save_ibkpt = ibkpt_addr; /* save bkpt */ - ibkpt_addr = ibkpt_addr | ILL_ADR_FLAG; /* disable */ - sim_activate(&cpu_unit, 1); /* sched re-enable after next instruction */ - reason = STOP_IBKPT; /* stop simulation */ - cwincount = 0; - continue; - } - - ninstr++; - if (cpu_unit.flags & UNIT_ATT) - trace_instruction(); /* log CPU details if logging is enabled */ - - prev_IAR = IAR; /* save IAR before incrementing it */ - - IR = ReadW(IAR); /* fetch 1st word of instruction */ - INCREMENT_IAR; - sim_interval = sim_interval - 1; /* this constitutes one tick of the simulation clock */ - - OP = (IR >> 11) & 0x1F; /* opcode */ - F = IR & 0x0400; /* format bit: 1 = long instr */ - TAG = IR & 0x0300; /* tag bits: index reg x */ - if (TAG) - TAG >>= 8; - - // here I compute the usual effective address on the assumption that the instruction will need it. Some don't. - - if (F) { /* long instruction, ASSUME it's valid (have to decrement IAR if not) */ - INDIR = IR & 0x0080; /* indirect bit */ - DSPLC = IR & 0x007F; /* displacement or modifier */ - if (DSPLC & 0x0040) - DSPLC |= ~ 0x7F; /* sign extend */ - - word2 = ReadW(IAR); /* get reference address */ - INCREMENT_IAR; /* bump the instruction address register */ - - eaddr = word2; /* assume standard addressing & compute effective address */ - if (TAG) /* if indexed */ - eaddr += ReadW(TAG); /* add index register value (stored in core) */ - if (INDIR) /* if indirect addressing */ - eaddr = ReadW(eaddr); /* pick up referenced address */ - } - else { /* short instruction, use displacement */ - INDIR = 0; /* never indirect */ - DSPLC = IR & 0x00FF; /* get displacement */ - if (DSPLC & 0x0080) - DSPLC |= ~ 0xFF; - - if (TAG) /* if indexed */ - eaddr = ReadW(TAG) + DSPLC; /* add index register value (stored in core) */ - else - eaddr = IAR + DSPLC; /* otherwise relative to IAR after fetch */ - } - - switch (OP) { /* decode instruction */ - case 0x01: /* --- XIO --- */ - iocc_addr = ReadW(eaddr); /* get IOCC packet */ - iocc_op = ReadW(eaddr|1); /* note 'or' not plus, address must be even for proper operation */ - - iocc_dev = (iocc_op >> 11) & 0x001F; - iocc_func = (iocc_op >> 8) & 0x0007; - iocc_mod = iocc_op & 0x00FF; - - if (cpu_unit.flags & UNIT_ATT) - trace_io("* XIO %s %s mod %02x addr %04x", xio_funcs[iocc_func], xio_devs[iocc_dev], iocc_mod, iocc_addr); - - ACC = 0; /* ACC is destroyed, and default XIO_SENSE_DEV result is 0 */ - - switch (iocc_func) { - case XIO_UNUSED: - sprintf(msg, "Unknown op %x on device %02x", iocc_func, iocc_dev); - xio_error(msg); - break; - - case XIO_SENSE_IRQ: /* examine current Interrupt Level Status Word */ - ACC = (ipl >= 0) ? ILSW[ipl] : 0; - break; - - default: /* perform device-specific operation */ - switch (iocc_dev) { - case 0x01: /* console keyboard and printer */ - xio_1131_console(iocc_addr, iocc_func, iocc_mod); - break; - case 0x02: /* 1142 card reader/punch */ - xio_1142_card(iocc_addr, iocc_func, iocc_mod); - break; - case 0x03: /* 1134 paper tape reader/punch */ - xio_1134_papertape(iocc_addr, iocc_func, iocc_mod); - break; - case 0x04: /* CPU disk storage */ - xio_disk(iocc_addr, iocc_func, iocc_mod, 0); - break; - case 0x05: /* 1627 plotter */ - xio_1627_plotter(iocc_addr, iocc_func, iocc_mod); - break; - case 0x06: /* 1132 Printer */ - xio_1132_printer(iocc_addr, iocc_func, iocc_mod); - break; - case 0x07: /* console switches, stop key, run mode */ - xio_1131_switches(iocc_addr, iocc_func, iocc_mod); - break; - case 0x08: /* 1231 optical mark reader */ - xio_1231_optical(iocc_addr, iocc_func, iocc_mod); - break; - case 0x09: /* 2501 card reader */ - xio_2501_card(iocc_addr, iocc_func, iocc_mod); - break; - case 0x0a: /* synchronous comm adapter */ - xio_1131_synch(iocc_addr, iocc_func, iocc_mod); - break; - case 0x0c: /* IBM System/7 interprocessor link */ - xio_system7(iocc_addr, iocc_func, iocc_mod); - break; - case 0x11: /* 2310 Disk Storage, Drive 1, or 2311 Disk Storage Drive. Drive 1, Disk 1 */ - xio_disk(iocc_addr, iocc_func, iocc_mod, 1); - break; - case 0x12: /* 2310 Disk Storage, Drive 2, or 2311 Disk Storage Drive. Drive 1, Disk 2 */ - xio_disk(iocc_addr, iocc_func, iocc_mod, 2); - break; - case 0x13: /* 2310 Disk Storage, Drive 3, or 2311 Disk Storage Drive. Drive 1, Disk 3 */ - xio_disk(iocc_addr, iocc_func, iocc_mod, 3); - break; - case 0x14: /* 2310 Disk Storage, Drive 4, or 2311 Disk Storage Drive. Drive 1, Disk 4 */ - xio_disk(iocc_addr, iocc_func, iocc_mod, 4); - break; - case 0x15: /* 1403 Printer */ - xio_1403_printer(iocc_addr, iocc_func, iocc_mod); - break; - case 0x16: /* 2311 Disk Storage Drive. Drive 1, Disk 5 */ - xio_disk(iocc_addr, iocc_func, iocc_mod, -1); - break; - case 0x17: /* 2311 Disk Storage Drive, Drive 2, Disk 1 through 5 */ - xio_disk(iocc_addr, iocc_func, iocc_mod, -1); - break; - case 0x19: /* 2250 Display Unit */ - xio_2250_display(iocc_addr, iocc_func, iocc_mod); - break; - default: - sprintf(msg, "unknown device %02x", iocc_dev); - xio_error(msg); - break; - } - } - - calc_ints(); /* after every XIO, reset int_mask just in case */ - break; - - case 0x02: /* --- SLA,SLT,SLC,SLCA,NOP - Shift Left family --- */ - if (F) { - weirdop("Long Left Shift", -2); - DECREMENT_IAR; - } - - CCC = ((TAG == 0) ? DSPLC : ReadW(TAG)) & 0x003F; - if (CCC == 0) - break; /* shift of zero is a NOP */ - - switch (IR & 0x00C0) { - case 0x0040: /* SLCA */ - if (TAG) { - while (CCC > 0 && (ACC & 0x8000) == 0) { - ACC <<= 1; - CCC--; - } - C = (CCC != 0); - WriteW(TAG, ReadW(TAG) & 0xFF00 | CCC); /* put low 6 bits back into index register and zero bits 8 and 9 */ - break; - } - /* if TAG == 0, fall through and treat like normal shift SLA */ - - case 0x0000: /* SLA */ - while (CCC > 0) { - C = (ACC & 0x8000); - ACC = (ACC << 1) & 0xFFFF; - CCC--; - } - break; - - case 0x00C0: /* SLC */ - if (TAG) { - while (CCC > 0 && (ACC & 0x8000) == 0) { - abit = (EXT & 0x8000) >> 15; - ACC = ((ACC << 1) & 0xFFFF) | abit; - EXT = (EXT << 1); - CCC--; - } - C = (CCC != 0); - WriteW(TAG, ReadW(TAG) & 0xFF00 | CCC); /* put 6 bits back into low byte of index register */ - break; - } - /* if TAG == 0, fall through and treat like normal shift SLT */ - - case 0x0080: /* SLT */ - while (CCC > 0) { - C = (ACC & 0x8000); - abit = (EXT & 0x8000) >> 15; - ACC = ((ACC << 1) & 0xFFFF) | abit; - EXT = (EXT << 1) & 0xFFFF; - CCC--; - } - break; - - default: - bail("SLA switch, can't happen"); - break; - } - break; - - case 0x03: /* --- SRA, SRT, RTE - Shift Right family --- */ - if (F) { - weirdop("Long Right Shift", -2); - DECREMENT_IAR; - } - - CCC = ((TAG == 0) ? DSPLC : ReadW(TAG)) & 0x3F; - if (CCC == 0) - break; /* NOP */ - - switch (IR & 0x00C0) { - case 0x0000: /* SRA */ - ACC = (CCC < 16) ? ((ACC & 0xFFFF) >> CCC) : 0; - CCC = 0; - break; - - case 0x0040: /* invalid */ - wait_state = WAIT_INVALID_OP; - break; - - case 0x0080: /* SRT */ - while (CCC > 0) { - xbit = (ACC & 0x0001) << 15; - abit = (ACC & 0x8000); - ACC = (ACC >> 1) & 0x7FFF | abit; - EXT = (EXT >> 1) & 0x7FFF | xbit; - CCC--; - } - break; - - case 0x00C0: /* RTE */ - while (CCC > 0) { - abit = (EXT & 0x0001) << 15; - xbit = (ACC & 0x0001) << 15; - ACC = (ACC >> 1) & 0x7FFF | abit; - EXT = (EXT >> 1) & 0x7FFF | xbit; - CCC--; - } - break; - - default: - bail("SRA switch, can't happen"); - break; - } - break; - - case 0x04: /* --- LDS - Load Status --- */ - if (F) { /* never fetches second word */ - weirdop("Long LDS", -2); - DECREMENT_IAR; - } - - V = (DSPLC & 1); - C = (DSPLC & 2) >> 1; - break; - - case 0x05: /* --- STS - Store Status --- */ - newval = ReadW(eaddr) & 0xFF00; - if (C) - newval |= 2; - if (V) - newval |= 1; - - WriteW(eaddr, newval); - C = V = 0; /* clear flags after storing */ - break; - - case 0x06: /* --- WAIT --- */ - wait_state = WAIT_OP; - /* note: not valid in long mode, but what happens if we try? */ - if (F) { - weirdop("Long WAIT", -2); - DECREMENT_IAR; /* assume it wouldn't have fetched 2nd word */ - } - break; - - case 0x08: /* --- BSI - Branch and store IAR --- */ - if (F) { - if (bsctest(IR, F)) /* do standard BSC long format testing */ - break; /* if any condition is true, do nothing */ - } - WriteW(eaddr, IAR); /* do subroutine call */ - archive_backtrace("BSI"); /* save info in back-trace buffer */ - IAR = (eaddr + 1) & mem_mask; - break; - - case 0x09: /* --- BSC - Branch and skip on Condition --- */ - if (F) { - if (bsctest(IR, F)) /* long format; any indicator cancels branch */ - break; - - archive_backtrace((DSPLC & 0x40) ? "BOSC" : "BSC"); /* save info in back-trace buffer */ - IAR = eaddr; /* no indicator means branch taken */ - } - else { /* short format: skip if any indicator hits */ - if (bsctest(IR, F)) { - archive_backtrace((DSPLC & 0x40) ? "BOSC" : "BSC"); /* save info in back-trace buffer */ - INCREMENT_IAR; - } - } -// 27Mar02: moved this test out of the (F) condition; BOSC works even in the -// short form. The displacement field in this instruction is always the set of -// condition bits, and the interrupt clear bit doesn't collide. - if (DSPLC & 0x40) { /* BOSC = exit from interrupt handler */ - exit_irq(); - cwincount = 0; - } - break; - - case 0x0c: /* --- LDX - Load Index --- */ - if (F) - eaddr = (INDIR) ? ReadW(word2) : word2; - else - eaddr = DSPLC; - - if (TAG) - WriteW(TAG, eaddr); - else { - archive_backtrace("LDX"); /* save info in back-trace buffer */ - IAR = eaddr; /* what happens in short form? can onlyjump to low addresses? */ - } - break; - - case 0x0d: /* --- STX - Store Index --- */ - if (F) { /* compute EA without any indexing */ - eaddr = (INDIR) ? ReadW(word2) : word2; - } - else { - eaddr = IAR + DSPLC; - } - WriteW(eaddr, TAG ? ReadW(TAG) : IAR); - break; - - case 0x0e: /* --- MDX - Modify Index and Skip --- */ - if (F) { /* long mode: adjust memory location */ - if (TAG) { - oldval = ReadW(TAG); /* add word2 to index */ - newval = oldval + (INDIR ? ReadW(word2) : word2); - WriteW(TAG, newval); - } - else { - oldval = ReadW(word2); - DSPLC = IR & 0x00FF; /* use extended displacement (includes INDIR bit) */ - if (DSPLC & 0x0080) - DSPLC |= ~ 0xFF; - newval = oldval + DSPLC; /* add modifier to @word2 */ - WriteW(word2, newval); - } - } - else { /* short mode: adust IAR or index */ - if (TAG) { - oldval = ReadW(TAG);/* add displacement to index */ - newval = oldval + DSPLC; - WriteW(TAG, newval); - } - else { - oldval = IAR; /* add displacement to IAR */ - newval = IAR + DSPLC; - archive_backtrace("MDX"); - IAR = newval & mem_mask; - } - } - - if ((F || TAG) && (((newval & 0xFFFF) == 0) || ((oldval & 0x8000) != (newval & 0x8000)))) { - archive_backtrace("SKP"); - INCREMENT_IAR; /* skip if index sign change or zero */ - } - break; - - case 0x10: /* --- A - Add --- */ - /* in adds and subtracts, carry is set or cleared, overflow is set only */ - src = ReadW(eaddr); - src2 = ACC; - ACC = (ACC + src) & 0xFFFF; - - C = ACC < src; - if (! V) - V = SIGN_BIT((~src ^ src2) & (src ^ ACC)); - break; - - case 0x11: /* --- AD - Add Double --- */ - src = ((ACC << 16) | (EXT & 0xFFFF)); - src2 = (ReadW(eaddr) << 16) + ReadW(eaddr|1); - dst = src + src2; - ACC = (dst >> 16) & 0xFFFF; - EXT = dst & 0xFFFF; - - C = (unsigned int32) dst < (unsigned int32) src; - if (! V) - V = DWSIGN_BIT((~src ^ src2) & (src ^ dst)); - break; - - case 0x12: /* --- S - Subtract --- */ - src = ACC; - src2 = ReadW(eaddr); - ACC = (ACC-src2) & 0xFFFF; - - C = src2 < src; - if (! V) - V = SIGN_BIT((src ^ src2) & (src ^ ACC)); - break; - - case 0x13: /* --- SD - Subtract Double --- */ - src = ((ACC << 16) | (EXT & 0xFFFF)); - src2 = (ReadW(eaddr) << 16) + ReadW(eaddr|1); - dst = src - src2; - ACC = (dst >> 16) & 0xFFFF; - EXT = dst & 0xFFFF; - - C = (unsigned int32) src2 < (unsigned int32) src; - if (! V) - V = DWSIGN_BIT((src ^ src2) & (src ^ dst)); - break; - - case 0x14: /* --- M - Multiply --- */ - if ((src = ACC & 0xFFFF) & 0x8000) /* sign extend the values */ - src |= ~0xFFFF; - if ((src2 = ReadW(eaddr)) & 0x8000) - src2 |= ~0xFFFF; - - dst = src * src2; - ACC = (dst >> 16) & 0xFFFF; /* split the results */ - EXT = dst & 0xFFFF; - break; - - case 0x15: /* --- D - Divide --- */ - src = ((ACC << 16) | (EXT & 0xFFFF)); - if ((src2 = ReadW(eaddr)) & 0x8000) - src2 |= ~0xFFFF; /* oops: sign extend was missing, fixed 18Mar03 */ - - if (src2 == 0) - V = 1; /* divide by zero just sets overflow, ACC & EXT are undefined */ - else { - ACC = (src / src2) & 0xFFFF; - EXT = (src % src2) & 0xFFFF; - } - break; - - case 0x18: /* --- LD - Load ACC --- */ - ACC = ReadW(eaddr); - break; - - case 0x19: /* --- LDD - Load Double --- */ - ACC = ReadW(eaddr); - EXT = ReadW(eaddr|1); /* notice address is |1 not +1 */ - break; - - case 0x1a: /* --- STO - Store ACC --- */ - WriteW(eaddr, ACC); - break; - - case 0x1b: /* --- STD - Store Double --- */ - WriteW(eaddr|1, EXT); - WriteW(eaddr, ACC); /* order is important: if odd addr, only ACC is stored */ - break; - - case 0x1c: /* --- AND - Logical AND --- */ - ACC &= ReadW(eaddr); - break; - - case 0x1d: /* --- OR - Logical OR --- */ - ACC |= ReadW(eaddr); - break; - - case 0x1e: /* --- EOR - Logical Excl OR --- */ - ACC ^= ReadW(eaddr); - break; - - default: -/* all invalid instructions act like waits */ -/* case 0x00: */ -/* case 0x07: */ -/* case 0x0a: */ -/* case 0x0b: */ -/* case 0x0e: */ -/* case 0x0f: */ -/* case 0x16: */ -/* case 0x17: */ -/* case 0x1f: */ - wait_state = WAIT_INVALID_OP; - if (F) - DECREMENT_IAR; /* assume it wouldn't have fetched 2nd word? */ - - break; - } /* end instruction decode switch */ - - if (RUNMODE != MODE_RUN && RUNMODE != MODE_INT_RUN) - reason = STOP_WAIT; - - if (tbit && (ipl < 0)) { /* if INT_RUN mode, set IRQ5 after this instr */ - GUI_BEGIN_CRITICAL_SECTION - SETBIT(cpu_dsw, CPU_DSW_INT_RUN); - SETBIT(ILSW[5], ILSW_5_INT_RUN); - int_req |= INT_REQ_5; - GUI_END_CRITICAL_SECTION - } - } /* end main loop */ - -#ifdef GUI_SUPPORT - gui_run(FALSE); -#endif - - running = FALSE; - int_lamps = 0; /* display only currently active interrupts while halted */ - - if (reason == STOP_WAIT || reason == STOP_INVALID_INSTR) { - wait_state = 0; // on resume, don't wait - wait_lamp = TRUE; // but keep the lamp lit on the GUI - } - -#ifdef CGI_SUPPORT - if (cgi) - cgi_stop(reason); -#endif - - return reason; -} - -/* ------------------------------------------------------------------------ - * bsctest - perform standard set of condition tests. We return TRUE if any - * of the condition bits specified in DSPLC test positive, FALSE if none are true. - * If reset_V is TRUE, we reset the oVerflow flag after testing it. - * ------------------------------------------------------------------------ */ - -static t_bool bsctest (int32 DSPLC, t_bool reset_V) -{ - if (DSPLC & 0x01) { /* Overflow off (note inverted sense) */ - if (! V) - return TRUE; - else if (reset_V) /* reset after testing */ - V = 0; - } - - if (DSPLC & 0x02) { /* Carry off (note inverted sense) */ - if (! C) - return TRUE; - } - - if (DSPLC & 0x04) /* Even */ - if ((ACC & 1) == 0) - return TRUE; - - if (DSPLC & 0x08) /* Positive */ - if ((ACC & 0x8000) == 0 && ACC != 0) - return TRUE; - - if (DSPLC & 0x10) /* Negative */ - if (ACC & 0x8000) - return TRUE; - - if (DSPLC & 0x20) /* Zero */ - if ((ACC & 0xFFFF) == 0) - return TRUE; - - return FALSE; -} - -/* ------------------------------------------------------------------------ - * exit_irq - pop interrupt stack as part of return from subroutine (BOSC) - * ------------------------------------------------------------------------ */ - -static void exit_irq (void) -{ - int i, bit; - - GUI_BEGIN_CRITICAL_SECTION - - ipl = -1; /* default: return to main processor level */ - int_mask = 0xFFFF; - - if (iplpending) { /* restore previous interrupt status */ - for (i = 0, bit = 0x20; i < 6; i++, bit >>= 1) { - if (iplpending & bit) { - iplpending &= ~bit; - ipl = i; - int_mask = int_masks[i]; - break; - } - } - } - GUI_END_CRITICAL_SECTION - - calc_ints(); /* recompute pending interrupt mask */ -} /* because we probably cleared some ILSW bits before this instruction */ - -/* let a device halt the simulation */ - -void break_simulation (t_stat stopreason) -{ - reason = stopreason; -} - -/* ------------------------------------------------------------------------ - * SIMH required routines - * ------------------------------------------------------------------------ */ - -/* ------------------------------------------------------------------------ - * Reset routine - * ------------------------------------------------------------------------ */ - -t_stat cpu_reset (DEVICE *dptr) -{ - wait_state = 0; /* cancel wait */ - wait_lamp = TRUE; /* but keep the wait lamp lit on the GUI */ - - if (cpu_unit.flags & UNIT_ATT) { /* record reset in CPU log */ - fseek(cpu_unit.fileref, 0, SEEK_END); - fprintf(cpu_unit.fileref, "---RESET---" CRLF); - } - - GUI_BEGIN_CRITICAL_SECTION - - reset_backtrace(); - - ipl = -1; - int_mask = 0xFFFF; - int_req = 0; /* hmmm, it SHOULD reset the int req, right? */ - int_lamps = 0; - iplpending = 0; - memset(ILSW, 0, sizeof(ILSW)); - - cpu_dsw = 0; /* clear int req and prot stop bits */ - tbit = 0; /* cancel INT_RUN mode */ - - C = V = 0; /* clear processor flags */ - IAR = SAR = SBR = 0; /* clear IAR and other registers */ - ACC = EXT = OP = TAG = CCC = C = V = 0; - - mem_mask = MEMSIZE - 1; /* wraparound mask */ - - GUI_END_CRITICAL_SECTION - - return cpu_svc(&cpu_unit); /* reset breakpoint */ -} - -/* ------------------------------------------------------------------------ - * Memory examine - * ------------------------------------------------------------------------ */ - -t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) -{ - if (vptr == NULL) return SCPE_ARG; - - /* check this out -- save command hits it in weird way */ - /* I wish I remembered what I meant when I wrote that */ - if (addr < MEMSIZE) { - *vptr = M[addr] & 0xFFFF; - return SCPE_OK; - } - return SCPE_NXM; -} - -/* ------------------------------------------------------------------------ - * Memory deposit - * ------------------------------------------------------------------------ */ - -t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw) -{ - if (addr < MEMSIZE) { - M[addr] = val & 0xFFFF; - return SCPE_OK; - } - return SCPE_NXM; -} - -/* ------------------------------------------------------------------------ - * Breakpoint service - * ------------------------------------------------------------------------ */ - -t_stat cpu_svc (UNIT *uptr) -{ - if ((ibkpt_addr & ~ILL_ADR_FLAG) == save_ibkpt) - ibkpt_addr = save_ibkpt; - - save_ibkpt = -1; - return SCPE_OK; -} - -/* ------------------------------------------------------------------------ - * Memory allocation - * ------------------------------------------------------------------------ */ - -t_stat cpu_set_size (UNIT *uptr, int32 value, char *cptr, void *desc) -{ - t_bool used; - int32 i; - - if ((value <= 0) || (value > MAXMEMSIZE) || ((value & 0xFFF) != 0)) - return SCPE_ARG; - - for (i = value, used = FALSE; i < (int32) MEMSIZE; i++) { - if (M[i] != 0) { - used = TRUE; - break; - } - } - - if (used && ! get_yn ("Really truncate memory [N]?", FALSE)) - return SCPE_OK; - - for (i = MEMSIZE; i < value; i++) /* clear expanded area */ - M[i] = 0; - - MEMSIZE = value; - mem_mask = MEMSIZE - 1; - - return SCPE_OK; -} - -/* ------------------------------------------------------------------------ - * IO function for console switches - * ------------------------------------------------------------------------ */ - -void xio_1131_switches (int32 addr, int32 func, int32 modify) -{ - char msg[80]; - - switch (func) { - case XIO_READ: - WriteW(addr, CES); - break; - - case XIO_SENSE_DEV: - ACC = cpu_dsw; - if (modify & 0x01) { /* reset interrupts */ - CLRBIT(cpu_dsw, CPU_DSW_PROGRAM_STOP|CPU_DSW_INT_RUN); - CLRBIT(ILSW[5], ILSW_5_INT_RUN); /* (these bits are set in the keyboard handler in 1130_stddev.c) */ - } - break; - - default: - sprintf(msg, "Invalid console switch function %x", func); - xio_error(msg); - } -} - -/* ------------------------------------------------------------------------ - * Illegal IO operation. Not yet sure what the actual CPU does in this case - * ------------------------------------------------------------------------ */ - -void xio_error (char *msg) -{ - printf("*** XIO error at %04x: %s\n", prev_IAR, msg); - if (cgi) - break_simulation(STOP_CRASH); -} - -/* ------------------------------------------------------------------------ - * register_cmd - add a command to the extensible command table - * ------------------------------------------------------------------------ */ - -t_stat register_cmd (char *name, t_stat (*action)(int32 flag, char *ptr), int arg, char *help) -{ - int i; - - for (i = 0; i < MAX_EXTRA_COMMANDS; i++) { // find end of command table - if (x_cmds[i].action == action) - return SCPE_OK; // command is already there, just return - if (x_cmds[i].name == NULL) - break; - } - - if (i >= (MAX_EXTRA_COMMANDS-1)) { // no more room (we need room for the NULL) - fprintf(stderr, "The command table is full - rebuild the simulator with more free slots\n"); - return SCPE_ARG; - } - - x_cmds[i].action = action; // add new command - x_cmds[i].name = name; - x_cmds[i].arg = arg; - x_cmds[i].help = help; - - i++; - x_cmds[i].action = NULL; // move the NULL terminator - x_cmds[i].name = NULL; - - return SCPE_OK; -} - -/* ------------------------------------------------------------------------ - * echo_cmd - just echo the command line - * ------------------------------------------------------------------------ */ - -static t_stat echo_cmd (int flag, char *cptr) -{ - printf("%s\n", cptr); - return SCPE_OK; -} - -/* ------------------------------------------------------------------------ - * sim_init - initialize simulator upon startup of scp, before reset - * ------------------------------------------------------------------------ */ - -void sim_init (void) -{ - sim_gui = ! (sim_switches & SWMASK('G')); /* -g means no GUI */ - - sim_vm_cmd = x_cmds; /* provide list of additional commands */ - -#ifdef GUI_SUPPORT - // set hook routines for GUI command processing - if (sim_gui) { - sim_vm_read = &read_cmdline; - sim_vm_post = &update_gui; - } -#endif - -#ifdef ENABLE_BACKTRACE - // add the BACKTRACE command - register_cmd("BACKTRACE", &backtrace_cmd, 0, "ba{cktrace} {n} list last n branches/skips/interrupts\n"); -#endif - - register_cmd("VIEW", &view_cmd, 0, "v{iew} filename view a text file with notepad\n"); - -#ifdef CGI_SUPPORT - register_cmd("CGI", &cgi_cmd, 0, "cgi run simulator in CGI mode\n"); -#endif - - register_cmd("ECHO", &echo_cmd, 0, "echo args... echo arguments passed to command\n"); -} - -/* ------------------------------------------------------------------------ - * archive_backtrace - record a jump, skip, branch or whatever - * ------------------------------------------------------------------------ */ - -#ifdef ENABLE_BACKTRACE - -#define MAXARCHIVE 16 - -static struct tag_arch { - int iar; - char *inst; -} arch[MAXARCHIVE]; -int narchived = 0, archind = 0; - -static void archive_backtrace (char *inst) -{ - static int prevind; - - if (narchived < MAXARCHIVE) - narchived++; - - if (narchived > 0 && arch[prevind].iar == prev_IAR) - return; - - arch[archind].iar = prev_IAR; - arch[archind].inst = inst; - - prevind = archind; - archind = (archind+1) % MAXARCHIVE; -} - -static void reset_backtrace (void) -{ - narchived = 0; - archind = 0; -} - -void void_backtrace (int afrom, int ato) -{ - int i; - - afrom &= mem_mask; - ato &= mem_mask; - - for (i = 0; i < narchived; i++) - if (arch[i].iar >= afrom && arch[i].iar <= ato) - arch[i].inst = "OVERWRITTEN"; -} - -static void show_backtrace (int nshow) -{ - int n = narchived, i = archind; - - if (n > nshow) n = nshow; - - while (--n >= 0) { - i = (i > 0) ? (i-1) : (MAXARCHIVE-1); - printf("from %04x (%s) ", arch[i].iar, arch[i].inst); - } - - if (narchived) - putchar('\n'); -} - -static t_stat backtrace_cmd (int flag, char *cptr) -{ - int n; - - if ((n = atoi(cptr)) <= 0) - n = 6; - - show_backtrace(n); - return SCPE_OK; -} -#else - -// stub this for the disk routine - -void void_backtrace (int afrom, int ato) -{ -} - -#endif - -// CPU log routines -- attaching a file to the CPU creates a trace of instructions and register values -// -// Syntax is WEIRD: -// -// attach cpu logfile log instructions and registers to file "logfile" -// attach -f cpu cpu.log log instructions, registers and floating point acc -// attach -m cpu mapfile logfile read addresses from "mapfile", log instructions to "logfile" -// attach -f -m cpu mapfile logfile same and log floating point stuff too -// -// mapfile if specified is a list of symbols and addresses of the form: -// symbol hexval -// -// e.g. -// FSIN 082E -// FARC 09D4 -// FMPY 09A4 -// NORM 0976 -// XMDS 095A -// START 021A -// -// These values are easily obtained from a load map created by -// XEQ L -// -// The log output is of the form -// -// IAR ACC EXT (flt) XR1 XR2 XR3 CVI FAC OPERATION -// --------------- ---- ---- -------- ---- ---- ---- --- ------------- ----------------------- -// 002a 002a 1234 5381 0.14222 00b3 0236 3f7e CV 1.04720e+000 4c80 BSC I ,0028 -// 081d PAUSE+000d 1234 5381 0.14222 00b3 0236 3f7e CV 1.04720e+000 7400 MDM L 00f0,0 (0) -// 0820 PAUSE+0010 1234 5381 0.14222 00b3 0236 3f7e CV 1.04720e+000 7201 MDX 2 0001 -// 0821 PAUSE+0011 1234 5381 0.14222 00b3 0237 3f7e CV 1.04720e+000 6a03 STX 2 0003 -// 0822 PAUSE+0012 1234 5381 0.14222 00b3 0237 3f7e CV 1.04720e+000 6600 LDX L2 0231 -// 0824 PAUSE+0014 1234 5381 0.14222 00b3 0231 3f7e CV 1.04720e+000 4c00 BSC L ,0237 -// 0237 START+001d 1234 5381 0.14222 00b3 0231 3f7e CV 1.04720e+000 4480 BSI I ,3fff -// 082f FSIN +0001 1234 5381 0.14222 00b3 0231 3f7e CV 1.04720e+000 4356 BSI 3 0056 -// 3fd5 ILS01+35dd 1234 5381 0.14222 00b3 0231 3f7e CV 1.04720e+000 4c00 BSC L ,08de -// -// IAR - instruction address register value, optionally including symbol and offset -// ACC - accumulator -// EXT - extension -// flt - ACC+EXT interpreted as the mantissa of a floating pt number (value 0.5 -> 1) -// XR* - index registers -// CVI - carry, overflow and interrupt indicators -// FAC - floating point accumulator (exponent at 125+XR3, mantissa at 126+XR3 and 127+XR3) -// OP - opcode value and crude disassembly -// -// flt and FAC are displayed only when the -f flag is specified in the attach command -// The label and offset and displayed only when the -m flag is specified in the attach command -// -// The register values shown are the values BEFORE the instruction is executed. -// - -t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, UNIT *uptr, int32 sw); - -typedef struct tag_symentry { - struct tag_symentry *next; - int addr; - char sym[6]; -} SYMENTRY, *PSYMENTRY; - -static PSYMENTRY syms = NULL; -static t_bool new_log, log_fac; - -static t_stat cpu_attach (UNIT *uptr, char *cptr) -{ - char mapfile[200], buf[200], sym[100]; - int addr; - PSYMENTRY n, prv, s; - FILE *fd; - - unlink(cptr); // delete old log file, if present - new_log = TRUE; - log_fac = sim_switches & SWMASK ('F'); // display the FAC and the ACC/EXT as fixed point. - - for (s = syms; s != NULL; s = n) { // free any old map entries - n = s->next; - free(s); - } - syms = NULL; - - if (sim_switches & SWMASK('M')) { // use a map file to display relative addresses - cptr = get_glyph(cptr, mapfile, 0); - if (! *mapfile) { - printf("/m must be followed by a filename\n"); - return SCPE_ARG; - } - if ((fd = fopen(mapfile, "r")) == NULL) { - perror(mapfile); - return SCPE_OPENERR; - } - - while (fgets(buf, sizeof(buf), fd) != NULL) { // read symbols & addresses, link in descending address order - if (sscanf(buf, "%s %x", sym, &addr) != 2) - continue; - if (*buf == ';') - continue; - - for (prv = NULL, s = syms; s != NULL; prv = s, s = s->next) { - if (s->addr < addr) - break; - } - - if ((n = malloc(sizeof(SYMENTRY))) == NULL) { - printf("out of memory reading map!\n"); - break; - } - - sym[5] = '\0'; - strcpy(n->sym, sym); - upcase(n->sym); - n->addr = addr; - - if (prv == NULL) { - n->next = syms; - syms = n; - } - else { - n->next = prv->next; - prv ->next = n; - } - } - fclose(fd); - } - - return attach_unit(uptr, cptr); -} - -static void trace_instruction (void) -{ - t_value v[2]; - float fac; - short exp; - int addr; - PSYMENTRY s; - long mant, sign; - char facstr[20], fltstr[20]; - - if ((cpu_unit.flags & UNIT_ATT) == 0) - return; - - if (new_log) { - fseek(cpu_unit.fileref, 0, SEEK_END); - new_log = FALSE; - - fprintf(cpu_unit.fileref, " IAR%s ACC EXT %s XR1 XR2 XR3 CVI %sOPERATION" CRLF, - syms ? " " : "", log_fac ? " (flt) " : "", log_fac ? " FAC " : ""); - fprintf(cpu_unit.fileref, "----%s ---- ---- %s---- ---- ---- --- %s-----------------------" CRLF, - syms ? "-----------" : "", log_fac ? "-------- " : "", log_fac ? "------------- " : ""); - } - - if (! log_fac) - facstr[0] = fltstr[0] = '\0'; - else { - mant = ((ACC & 0xFFFF) << 16) | (EXT & 0xFFFF); - if (mant == 0x80000000) { - sign = TRUE; - fac = 1.f; - } - else { - if ((sign = mant & 0x80000000)) - mant = -mant; - fac = (float) mant * ((float) 1./ (float) (unsigned long) 0x80000000); - } - sprintf(fltstr, "%c%.5f ", sign ? '-' : ' ', fac); - - if (BETWEEN(M[3], 0x300, MEMSIZE-128)) { - exp = (M[M[3]+125] & 0xFF) - 128; - mant = (M[M[3]+126] << 8) | ((M[M[3]+127] >> 8) & 0xFF); - if ((sign = (mant & 0x00800000))) - mant = (-mant) & 0x00FFFFFF; - - fac = (float) mant * ((float) 1. / (float) 0x00800000); - - if (exp > 30) { - fac *= (float) (1 << 30); - exp -= 30; - while (exp > 0) - fac *= 2; - } - else if (exp > 0) - fac *= (float) (1 << exp); - else if (exp < -30) { - fac /= (float) (1 << 30); - exp += 30; - while (exp < 0) - fac /= 2; - } - else if (exp < 0) - fac /= (float) (1 << -exp); - - sprintf(facstr, "%c%.5e ", sign ? '-' : ' ', fac); - } - else - strcpy(facstr, " "); - } - - addr = IAR & 0xFFFF; - fprintf(cpu_unit.fileref, "%04x ", addr); - - if (syms) { - for (s = syms; s != NULL; s = s->next) - if (s->addr <= addr) - break; - - if (s == NULL) - fprintf(cpu_unit.fileref, " %04x ", addr); - else - fprintf(cpu_unit.fileref, "%-5s+%04x ", s->sym, addr - s->addr); - } - - fprintf(cpu_unit.fileref, "%04x %04x %s%04x %04x %04x %c%c%c %s", - ACC & 0xFFFF, EXT & 0xFFFF, fltstr, M[1] & 0xFFFF, M[2] & 0xFFFF, M[3] & 0xFFFF, - C ? 'C' : ' ', V ? 'V' : ' ', (ipl < 0) ? ' ' : (ipl+'0'), facstr); - - v[0] = M[ IAR & mem_mask]; - v[1] = M[(IAR+1) & mem_mask]; - fprint_sym(cpu_unit.fileref, IAR & mem_mask, v, NULL, SWMASK('M')); /* disassemble instruction */ - - fputs(CRLF, cpu_unit.fileref); -} - -void trace_io (char *fmt, ...) -{ - va_list args; - - if ((cpu_unit.flags & UNIT_ATT) == 0) - return; - - va_start(args, fmt); // get pointer to argument list - vfprintf(cpu_unit.fileref, fmt, args); // write errors to terminal (stderr) - va_end(args); - - fputs(CRLF, cpu_unit.fileref); -} - -/* debugging */ - -void debug_print (char *fmt, ...) -{ - va_list args; - - va_start(args, fmt); - vprintf(fmt, args); - if (cpu_unit.flags & UNIT_ATT) - vfprintf(cpu_unit.fileref, fmt, args); - va_end(args); - - if (strchr(fmt, '\n') == NULL) { // be sure to emit a newline - putchar('\n'); - if (cpu_unit.flags & UNIT_ATT) - putc('\n', cpu_unit.fileref); - } -} - -#ifdef WIN32 -#include -#endif - -// view_cmd - let user view and/or edit a file (e.g. a printer output file, script, or source deck) - -static t_stat view_cmd (int flag, char *cptr) -{ -#ifdef WIN32 - char cmdline[256]; - - sprintf(cmdline, "notepad %s", cptr); - WinExec(cmdline, SW_SHOWNORMAL); -#endif - return SCPE_OK; -} - -#ifdef CGI_SUPPORT - -int cgi_maxsec = 0; // default run time limit - -// cgi_cmd - enable cgi mode. Specify time limit on command line if desired - -static t_stat cgi_cmd (int flag, char *cptr) -{ - cgi = TRUE; // set CGI flag - - while (*cptr && *cptr <= ' ') - cptr++; - - if (*cptr) - cgi_maxsec = atoi(cptr); // set time limit, if specified - - return SCPE_OK; -} - -// cgi_timeout - called when timer runs out - -static void cgi_timeout (int dummy) -{ - break_simulation(STOP_TIMED_OUT); // stop the simulator -} - -// cgi_clockfail - report failure to set alarm - -static void cgi_clockfail (void) -{ - printf("Set CGI time limit failed!"); -} - -// cgi_start_timer - OS dependent routine to set things up so that -// cgi_timeout() will be called after cgi_maxsec seconds. - -#if defined(WIN32) - static DWORD WINAPI cgi_timer_thread (LPVOID arg) - { - Sleep(cgi_maxsec*1000); // timer thread -- wait, then call timeout routine - cgi_timeout(0); - return 0; - } - - static void cgi_start_timer (void) - { - DWORD dwThreadID; - - if (CreateThread(NULL, 0, cgi_timer_thread, NULL, 0, &dwThreadID) == NULL) - cgi_clockfail(); - } -#else - #include - - #if defined(SIGVTALRM) && defined(ITMER_VIRTUAL) - - // setitimer counts actual runtime CPU seconds, so is insensitive to - // system load and is a better timer to use. Be sure to check, though, - // that it actually works on your OS. Note that time spent performing - // I/O does not count -- this counts user mode CPU time only, so - // the elapsed time it allows could be much larger, especially if - // the job is spewing output. - - #include - - static void cgi_start_timer (void) - { - struct itimerval rtime, otime; - - rtime.it_value.tv_sec = cgi_maxsec; - rtime.it_value.tv_usec = 0; - rtime.it_interval.tv_sec = cgi_maxsec; - rtime.it_interval.tv_usec = 0; - - if (signal(SIGVTALRM, cgi_timeout) == SIG_ERR) // set alarm handler - cgi_clockfail(); - else if (setitimer(ITIMER_VIRTUAL, &rtime, &otime)) // start timer - cgi_clockfail(); - } - - #elif defined(SIGALRM) - #include - - // if it's all we have, standard POSIX alarm will do the trick too - - static void cgi_start_timer (void) - { - if (signal(SIGALRM, cgi_timeout) == SIG_ERR) // set alarm handler - cgi_clockfail(); - else if (alarm(cgi_maxsec)) // start timer - cgi_clockfail(); - } - - #else - // don't seem to have a clock available. Better say so. - - static void cgi_start_timer (void) - { - printf("CGI time limit is not supported by this build\n"); - } - - #endif -#endif - -static void cgi_start(void) -{ - if (cgi_maxsec > 0) // if time limit was specified, set timer now - cgi_start_timer(); - -// printf("Content-type: text/html\n\n\n\n IBM 1130 Simulation Results\n\n\n

");
-}
-
-static void cgi_stop(t_stat reason)
-{
-	typedef enum {O_END, O_FORTRAN, O_MONITOR} ORIGIN;
-	char *errmsg = "";
-	static struct tag_pretstop {
-		int acc;
-		ORIGIN orig;
-		char *msg;
-	} pretstop[] = {
-		0xF000, O_FORTRAN, "No *IOCS was specified but I/O was attempted",
-		0xF001, O_FORTRAN, "Local unit defined incorrectly, or no *IOCS for specified device",
-		0xF002, O_FORTRAN, "Requested record exceeds buffer size",
-		0xF003, O_FORTRAN, "Illegal character encountered in input record",
-		0xF004, O_FORTRAN, "Exponent too large or too small in input",
-		0xF005, O_FORTRAN, "More than one exponent encountered in input",
-		0xF006, O_FORTRAN, "More than one sign encountered in input",
-		0xF007, O_FORTRAN, "More than one decimal point encountered in input",
-		0xF008, O_FORTRAN, "Read of output-only device, or write to input-only device",
-		0xF009, O_FORTRAN, "Real variable transmitted with I format or integer transmitted with E or F",
-		0xF020, O_FORTRAN, "Illegal unit reference",
-		0xF021, O_FORTRAN, "Read list exceeds length of write list",
-		0xF022, O_FORTRAN, "Record does not exist in read list",
-		0xF023, O_FORTRAN, "Maximum length of $$$$$ area on disk has been exceeded",
-		0xF024, O_FORTRAN, "*IOCS (UDISK) was not specified",
-		0xF100, O_FORTRAN, "File not defined by DEFINE FILE statement",
-		0xF101, O_FORTRAN, "File record number too large, zero or negative",
-		0xF103, O_FORTRAN, "*IOCS(DISK) was not specified",
-		0xF105, O_FORTRAN, "Length of a list element exceeds record length in DEFINE FILE",
-		0xF107, O_FORTRAN, "Attempt to read or write an invalid sector address (may occur if a core image program is run with too little room in working storage)",
-		0xF10A, O_FORTRAN, "Define file table and/or core image header corrupted, probably by an out-of-bounds array subscript",
-		0x1000, O_MONITOR, "1442 card read/punch or 1442 punch: not ready or hopper empty. [emulator: attach a file to CR or CP and go]",
-		0x1001, O_MONITOR, "Illegal device, function or word count",
-		0x100F, O_MONITOR, "Occurs in a DUP operation after DUP error D112",
-		0x2000, O_MONITOR, "Keyboard/Console Printer not ready",
-		0x2001, O_MONITOR, "Illegal device, function or word count",
-		0x3000, O_MONITOR, "1134/1055 Paper Tape not ready",
-		0x3001, O_MONITOR, "Illegal device, function or word count, or invalid check digit",
-		0x4000, O_MONITOR, "2501 Card Reader not ready",
-		0x4001, O_MONITOR, "Illegal device, function or word count",
-		0x5000, O_MONITOR, "Disk not ready",
-		0x5001, O_MONITOR, "Illegal device, function or word count, or attempt to write in protected area",
-		0x5002, O_MONITOR, "Write select or power unsafe",
-		0x5003, O_MONITOR, "Read/write/seek failure after 16 attempts or disk overflow. Extension may display logical drive number in bits 0..3 and working storage address in bits 4..15. Program Start retries 16 more times.",
-		0x5004, O_MONITOR, "Same as above from routine DISK1 and DISKN, or, an uninitialized cartridge is online during a cold start.",
-		0x6000, O_MONITOR, "1132 Printer not ready or out of paper",
-		0x6001, O_MONITOR, "Illegal device, function or word count",
-		0x7000, O_MONITOR, "1627 Plotter not ready",
-		0x7001, O_MONITOR, "Illegal device, function or word count",
-		0x8001, O_MONITOR, "SCA error: Illegal function or word count",
-		0x8002, O_MONITOR, "SCA error: if STR mode, receive or transmit operation not completed;\n"
-						   "if BSC mode, invalid start characters in the I/O area for a transmit operation",
-		0x8003, O_MONITOR, "SCA error: if STR mode, failed to synchronize before attempt to read or write, or, attempted to receive before receiving INQ sequence;\n"
-						   "if BSC mode, invalid number of identification characters for an identification specification operation",
-		0x9000, O_MONITOR, "1403 printer no ready or out of paper",
-		0x9001, O_MONITOR, "Illegal device, function or word count",
-		0x9002, O_MONITOR, "Parity check, scan check or ring check",
-		0xA000, O_MONITOR, "1231 Optical Mark Reader not ready",
-		0xA001, O_MONITOR, "Illegal device, function or word count",
-		0xA002, O_MONITOR, "Feed check, last document was processed. Clear jam, do not refeed",
-		0xA003, O_MONITOR, "Feed check, last document not  processed. Clear jam and refeed",
-		0,      O_END, 	   NULL
-	};
-	int i;
-
-	detach_cmd(0, "prt");		/* flush last print line */
-
-	if (reason == STOP_TIMED_OUT)
-		printf("\n
Sorry, emulation run time exceeded %d second%s\n", cgi_maxsec, (cgi_maxsec == 1) ? "" : "s"); - else if (IAR != 0x2a || ACC != 0x1000) { - ACC &= 0xFFFF; - for (i = 0; pretstop[i].orig != O_END; i++) { - if (pretstop[i].acc == ACC) { - errmsg = pretstop[i].msg; - break; - } - } - printf("\n
Abnormal exit: %s\nIAR = %04x, ACC = %04x\n", errmsg, IAR, ACC); - } - -// printf("
\n\n\n"); - exit(0); /* save w/o writing disk image */ -} - -#endif // ifdef CGI_SUPPORT diff --git a/Ibm1130/ibm1130_cr.c b/Ibm1130/ibm1130_cr.c deleted file mode 100644 index 283d107c..00000000 --- a/Ibm1130/ibm1130_cr.c +++ /dev/null @@ -1,2079 +0,0 @@ -#include "ibm1130_defs.h" -#include "ibm1130_fmt.h" - -/* ibm1130_cr.c: IBM 1130 1442 Card Reader simulator - - Based on the SIMH package written by Robert M Supnik - - * (C) Copyright 2002, Brian Knittel. - * You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN - * RISK basis, there is no warranty of fitness for any purpose, and the rest of the - * usual yada-yada. Please keep this notice and the copyright in any distributions - * or modifications. - * - * This is not a supported product, but I welcome bug reports and fixes. - * Mail to simh@ibm1130.org - - * Update 2003-07-23: Added autodetect for card decks (029 vs binary), - made this the default. - - * Update 2003-06-21: Fixed bug in XIO_SENSE: op_complete and response - bits were being cleared before the DSW was saved in ACC. Somehow DMS - worked with this, but APL didn't. - - * Update 2002-02-29: Added deck-list option. - - * Update 2003-02-08: Fixed error in declaration of array list_save, pointed - out by Ray Comas. - -* ----------------------------------------------------------------------- -* USAGE NOTES -* ----------------------------------------------------------------------- - -* Attach switches: - - The ATTACH CR command accepts several command-line switches - - -q quiet mode, the simulator will not print the name of each file it opens - while processing deck files (which are discussed below). For example, - - ATTACH -q @deckfile - - -l makes the simulator convert lower case letters in text decks - to the IBM lower-case Hollerith character codes. Normally, the simulator - converts lower case input to the uppercase Hollerith character codes. - (Lowercase codes are used in APL\1130 save decks). - - -d prints a lot of simulator debugging information - - -f converts tabs in an ascii file to spaces according to Fortran column conventions - -a converts tabs in an ascii file to spaces according to 1130 Assembler column conventions - -t converts tabs in an ascii file to spaces, with tab settings every 8 columns - - (See below for a discussion of tab formatting) - - The ATTACH CP command accepts the -d switch. - -* Deck lists - If you issue an attach command and specify the filename as - "@filename", the file is interpreted as a list of filenames to - be read in sequence; the effect is that the reader sees the concatenation - of all of the files listed. The simulator "reset" does NOT rewind the deck list. - - Filenames may be quoted if they contain spaces. - - The strings %1, %2, etc, if they appear, are replaced with arguments passed - on the attach command line after the name of the deckfile. These can be the - arguments to ibm1130, or to the "do" command if a "do" script is executing, if the - attach command is constructed this way: - - attach @deckfile %1 %2 %3 - - This will pass the ibm1130 or do script arguments to attach, which will make - them available in the deckfile. Then, for instance the line - - %1.for - - would be substituted accordingly. - - Blank lines and lines starting with ; # or * are ignored as comments. - - Filenames may be followed by whitespace and one or more mode options: - The mode options are: - - b forces interpration as raw binary - a forces conversion from ascii to 029 coding, tabs are left alone - af forces 029 ascii conversion, and interprets tabs in Fortran mode - aa forces 029 ascii conversion, and interprets tabs in 1130 Assembler mode - at forces 029 ascii conversion, and interprets tabs with settings every 8 spaces - - If "a" or "b" mode is not specified, the device mode setting is used. In this case, - if the mode is "auto", the simulator will select binary or 029 by inspecting each - file in turn. - - If a tab mode is not specified, tabs are left unmolested (and are treated as invalid characters) - - Example: - - attach cr @decklist - - reads filenames from file "decklist," which might contain: - - file01.for xf - file02.dat a - file03 bin b - file04 bin - - ('a' means 029, so, if you need 026 coding, specify the - device default as the correct 026 code and omit the 'a' on the text files lines). - - Literal text cards can be entered in deck files by preceding an input - line with an exclamation point. For example, - - !// JOB - !// FOR - program.for - !// XEQ - program.dat - - looks like two literal supervisor control cards, followed by the contents - of file program.for, followed by an // XEQ card, followed by the contents - of file program.dat. - - %n tokens are not replaced in literal cards. - - The line - - !BREAK - - has a special meaning: when read from a deck file, it stops the - emulator as if "IMMEDIATE STOP" was pressed. This returns control to - the command interpreter or to the current DO command script. - -* Card image format. - Card files can be ascii text or binary. There are several ASCII modes: - CODE_029, CODE_26F, etc, corresponding to different code sets. - Punch and reader modes can be set independently using - - set cr binary set cp binary * - set cr 029 set cp 029 - set cr 026f set cp 026f - set cr 026c set cp 026c - set cr auto * - - (* = default mode) - - In "auto" mode, the card reader will examine the first 160 bytes of - the deck and guess whether the card is binary or 029 text encoded. - When a deck file is used with auto mode, the simulator guesses for - each file named in the deck file. - -* Tab formatting. The attach command and deckfile entries can indicate - that tabs are to be converted to spaces, to help let you write free-form - source files. There are three tab conversion modes, which are set - with the attach command or in a decklist, as discussed earlier - - Fortran mode: - Input lines of the form - - [label]statement - - or - - [label]+continuation - - (where + is any nonalphabetic character) are rearranged in the - appropriate manner: - - 1 2 - 12345678901234567890... - ------------------------ - label statement - label+continuation - - However, you must take care that you don't end up with statement text after column 72. - - Input lines with * or C in column 1 (comments and directives) and lines without tabs - are left alone. - - (The ! escape is not used before Fortran directives as before Assembler directives) - - Assembler mode: - Input lines of the form - - [label][opcode][tag][L][argument] - - are rearranged so that the input fields are placed in the appropriate columns - - The label must start on the first character of the line. If there is no label, - the first character(s) before the opcode must be whitespace. Following the opcode, there - MUST be a tab character, followed by the format and tag. Following the format and tag - may be exactly one whitespace character, and then starts the argument. - - Input lines with * in column 1 and blank lines are turned into Assembler comments, - with the * in the Opcode field. - - Assembler directive lines at the beginning of the deck must be preceded by - ! to indicate that they are not comments. For example, - - !*LIST - * This is a comment - - Plain Tab mode: - Tabs are replaced with spaces. Tab settings are assumed to be eight characters wide, - as is standard for vi, notepad, etc. - -* CGI mode note: The command - - attach cr - - - will attach the card reader to stdin. However, this is not compatible - with the default encoding autodetect feature, so the command must be - preceded with - - set cr 029 - -* ----------------------------------------------------------------------- -* PROGRAMMING NOTES -* ----------------------------------------------------------------------- - -NOTE - there is a problem with this code. The Device Status Word (DSW) is -computed from current conditions when requested by an XIO load status -command; the value of DSW available to the simulator's examine & save -commands may NOT be accurate. This should probably be fixed. (I think there's -a way to have the expression evaluator call a routine? That would be one -way to solve the problem, the other is to keep DSW up-to-date all the time). - - The 1442 card read/punch has several cycles: - - feed cycle: moves card from hopper to read station - card from read station to punch station - card from punch station to stacker - - read or punch: operates on card at read or punch station (but not both). - - The simulator requires input cards to be read from the file attached - to the card reader unit. A feed cycle reads one line (text mode) or - 160 bytes (binary mode) from the input file to the read station buffer, - copies the read station buffer to the punch station buffer, and if - the punch unit is attached to a file, writes the punch station buffer to - the output file. - - The read and punch cycles operate on the appropriate card buffer. - - Detaching the card punch flushes the punch station buffer if necessary. - - As does the 1442, a read or punch cycle w/o a feed cycle causes a - feed cycle first. - - A feed cycle on an empty deck (reader unattaced or at EOF) clears - the appropriate buffer, so you can punch w/o attaching a deck to - the card reader. - --- -- this may need changing depending on how things work in hardware. TBD. -|| A read cycle on an empty deck causes an error. -|| Hmmm -- what takes the place of the Start button on --- the card reader? - - Binary format is stored using fxwrite of short ints, in this format: - - 1 1 - 2 2 0 1 2 3 4 5 6 7 8 9 - * * * * * * * * * * * * 0 0 0 0 - - MSB LSB - byte 0 [ 6] [ 7] [ 8] [ 9] 0 0 0 0 - byte 1 [12] [11] [ 0] [ 1] [ 2] [ 3] [ 4] [ 5] - - This means we can read words (little endian) and get this in memory: - - 12 11 0 1 2 3 4 5 6 7 8 9 - - - - - - which is what the 1130 sees. - - ASCII can be read in blocks of 80 characters but can be terminated by newline prematurely. - - Booting: card reader IPL loads 80 columns (1 card) into memory starting - at location 0 in a split fashion: - - ________________ _ _ _ - / - 12 | - 11 | - 0 | - 1 | - 2 | - 3 | Punched card - 4 | - 5 | - 6 | - 7 | - 8 | - 9 | - +------------------ - - - - - 12 11 0 1 2 3 4 5 6 7 8 9 <- columns of cold start card - | | | | | 0 0 0 / \ | | | | | | - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | 0| 1| 2| 3| 4| 5| 6| 7| 8| 9|10|11|12|13|14|15| - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | OPCODE | F| Tag | DISPLACEMENT | - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - The zeros mean that all IPL instructions are short form, - nonindexed. The 3 column is repeated in bits 8 and 9 so - it's a sign bit. - - Boot command on a binary deck does this. Boot on an unattached - reader loads one of the built-in boot card images. Boot with an ASCII - deck isn't allowed. -*/ - -#define READ_DELAY 35 // see how small a number we can get away with -#define PUNCH_DELAY 35 -#define FEED_DELAY 25 - -// umm, this is a weird little future project of mine. -// #define ENABLE_PHYSICAL_CARD_READER_SUPPORT - -// #define IS_ONLINE(u) (((u)->flags & (UNIT_ATT|UNIT_DIS)) == UNIT_ATT) - -extern int32 sim_switches; -extern UNIT cpu_unit; - -static t_stat cr_svc (UNIT *uptr); -static t_stat cr_reset (DEVICE *dptr); -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 int32 guess_cr_code (void); - -static t_stat cp_reset (DEVICE *dptr); -static t_stat cp_set_code (UNIT *uptr, int32 match, char *cptr, void *desc); -static t_stat cp_attach (UNIT *uptr, char *cptr); -static t_stat cp_detach (UNIT *uptr); - -static int16 cr_dsw = 0; /* device status word */ -static int32 cr_wait = READ_DELAY; /* read per-column wait */ -static int32 cf_wait = PUNCH_DELAY; /* punch per-column wait */ -static int32 cp_wait = FEED_DELAY; /* feed op wait */ -static int32 cr_count= 0; /* read and punch card count */ -static int32 cp_count= 0; - -#define UNIT_V_OPERATION (UNIT_V_UF + 0) /* operation in progress */ -#define UNIT_V_CODE (UNIT_V_UF + 2) /* three bits */ -#define UNIT_V_EMPTY (UNIT_V_UF + 5) -#define UNIT_V_SCRATCH (UNIT_V_UF + 6) -#define UNIT_V_QUIET (UNIT_V_UF + 7) -#define UNIT_V_DEBUG (UNIT_V_UF + 8) -#define UNIT_V_PHYSICAL (UNIT_V_UF + 9) -#define UNIT_V_LASTPUNCH (UNIT_V_UF + 10) /* used in unit_cp only */ -#define UNIT_V_LOWERCASE (UNIT_V_UF + 10) /* used in unit_cr only */ -#define UNIT_V_ACTCODE (UNIT_V_UF + 11) /* used in unit_cr only, 3 bits */ - -#define UNIT_OP (3u << UNIT_V_OPERATION) /* two bits */ -#define UNIT_CODE (7u << UNIT_V_CODE) /* three bits */ -#define UNIT_EMPTY (1u << UNIT_V_EMPTY) -#define UNIT_SCRATCH (1u << UNIT_V_SCRATCH) /* temp file */ -#define UNIT_QUIET (1u << UNIT_V_QUIET) -#define UNIT_DEBUG (1u << UNIT_V_DEBUG) -#define UNIT_PHYSICAL (1u << UNIT_V_PHYSICAL) -#define UNIT_LASTPUNCH (1u << UNIT_V_LASTPUNCH) -#define UNIT_LOWERCASE (1u << UNIT_V_LOWERCASE) /* permit lowercase input (needed for APL) */ -#define UNIT_ACTCODE (7u << UNIT_V_ACTCODE) - -#define OP_IDLE (0u << UNIT_V_OPERATION) -#define OP_READING (1u << UNIT_V_OPERATION) -#define OP_PUNCHING (2u << UNIT_V_OPERATION) -#define OP_FEEDING (3u << UNIT_V_OPERATION) - -#define SET_OP(op) {cr_unit.flags &= ~UNIT_OP; cr_unit.flags |= (op);} -#define CURRENT_OP (cr_unit.flags & UNIT_OP) - -#define CODE_AUTO (0u << UNIT_V_CODE) -#define CODE_029 (1u << UNIT_V_CODE) -#define CODE_026F (2u << UNIT_V_CODE) -#define CODE_026C (3u << UNIT_V_CODE) -#define CODE_BINARY (4u << UNIT_V_CODE) - -#define GET_CODE(un) (un.flags & UNIT_CODE) -#define SET_CODE(un,cd) {un.flags &= ~UNIT_CODE; un.flags |= (cd);} - -#define ACTCODE_029 (CODE_029 << (UNIT_V_ACTCODE-UNIT_V_CODE)) // these are used ONLY in MTAB. Elsewhere -#define ACTCODE_026F (CODE_026F << (UNIT_V_ACTCODE-UNIT_V_CODE)) // we use values CODE_xxx with macros -#define ACTCODE_026C (CODE_026C << (UNIT_V_ACTCODE-UNIT_V_CODE)) // GET_ACTCODE and SET_ACTCODE. -#define ACTCODE_BINARY (CODE_BINARY << (UNIT_V_ACTCODE-UNIT_V_CODE)) - - // get/set macros for actual-code field, these use values like CODE_029 meant for the UNIT_CODE field -#define GET_ACTCODE(un) ((un.flags & UNIT_ACTCODE) >> (UNIT_V_ACTCODE-UNIT_V_CODE)) -#define SET_ACTCODE(un,cd) {un.flags &= ~UNIT_ACTCODE; un.flags |= (cd) << (UNIT_V_ACTCODE-UNIT_V_CODE);} - -#define COLUMN u4 /* column field in unit record */ - -UNIT cr_unit = { UDATA (&cr_svc, UNIT_ATTABLE|UNIT_ROABLE, 0) }; -UNIT cp_unit = { UDATA (NULL, UNIT_ATTABLE, 0) }; - -MTAB cr_mod[] = { - { UNIT_CODE, CODE_029, "029", "029", &cr_set_code}, - { UNIT_CODE, CODE_026F, "026F", "026F", &cr_set_code}, - { UNIT_CODE, CODE_026C, "026C", "026C", &cr_set_code}, - { UNIT_CODE, CODE_BINARY, "BINARY", "BINARY", &cr_set_code}, - { UNIT_CODE, CODE_AUTO, "AUTO", "AUTO", &cr_set_code}, - { UNIT_ACTCODE, ACTCODE_029, "(029)", NULL, NULL}, /* display-only, shows current mode */ - { UNIT_ACTCODE, ACTCODE_026F, "(026F)", NULL, NULL}, - { UNIT_ACTCODE, ACTCODE_026C, "(026C)", NULL, NULL}, - { UNIT_ACTCODE, ACTCODE_BINARY, "(BINARY)", NULL, NULL}, - { 0 } }; - -MTAB cp_mod[] = { - { UNIT_CODE, CODE_029, "029", "029", &cp_set_code}, - { UNIT_CODE, CODE_026F, "026F", "026F", &cp_set_code}, - { UNIT_CODE, CODE_026C, "026C", "026C", &cp_set_code}, - { UNIT_CODE, CODE_BINARY, "BINARY", "BINARY", &cp_set_code}, - { 0 } }; - -REG cr_reg[] = { - { HRDATA (CRDSW, cr_dsw, 16) }, /* device status word */ - { DRDATA (CRTIME, cr_wait, 24), PV_LEFT }, /* operation wait */ - { DRDATA (CFTIME, cf_wait, 24), PV_LEFT }, /* operation wait */ - { DRDATA (CRCOUNT, cr_count, 32),PV_LEFT }, /* number of cards read since last attach cmd */ - { NULL } }; - -REG cp_reg[] = { - { DRDATA (CPTIME, cp_wait, 24), PV_LEFT }, /* operation wait */ - { DRDATA (CPCOUNT, cp_count, 32),PV_LEFT }, /* number of cards punched since last attach cmd */ - { NULL } }; - -DEVICE cr_dev = { - "CR", &cr_unit, cr_reg, cr_mod, - 1, 16, 16, 1, 16, 16, - NULL, NULL, cr_reset, - cr_boot, cr_attach, cr_detach}; - -DEVICE cp_dev = { - "CP", &cp_unit, cp_reg, cp_mod, - 1, 16, 16, 1, 16, 16, - NULL, NULL, cp_reset, - NULL, cp_attach, cp_detach}; - -#define CR_DSW_READ_RESPONSE 0x8000 /* device status word bits */ -#define CR_DSW_PUNCH_RESPONSE 0x4000 -#define CR_DSW_ERROR_CHECK 0x2000 -#define CR_DSW_LAST_CARD 0x1000 -#define CR_DSW_OP_COMPLETE 0x0800 -#define CR_DSW_FEED_CHECK 0x0100 -#define CR_DSW_BUSY 0x0002 -#define CR_DSW_NOT_READY 0x0001 - -typedef struct { - uint16 hollerith; - char ascii; -} CPCODE; - -static CPCODE cardcode_029[] = -{ - 0x0000, ' ', - 0x8000, '&', // + in 026 Fortran - 0x4000, '-', - 0x2000, '0', - 0x1000, '1', - 0x0800, '2', - 0x0400, '3', - 0x0200, '4', - 0x0100, '5', - 0x0080, '6', - 0x0040, '7', - 0x0020, '8', - 0x0010, '9', - 0x9000, 'A', - 0x8800, 'B', - 0x8400, 'C', - 0x8200, 'D', - 0x8100, 'E', - 0x8080, 'F', - 0x8040, 'G', - 0x8020, 'H', - 0x8010, 'I', - 0x5000, 'J', - 0x4800, 'K', - 0x4400, 'L', - 0x4200, 'M', - 0x4100, 'N', - 0x4080, 'O', - 0x4040, 'P', - 0x4020, 'Q', - 0x4010, 'R', - 0x3000, '/', - 0x2800, 'S', - 0x2400, 'T', - 0x2200, 'U', - 0x2100, 'V', - 0x2080, 'W', - 0x2040, 'X', - 0x2020, 'Y', - 0x2010, 'Z', - 0x0820, ':', - 0x0420, '#', // = in 026 Fortran - 0x0220, '@', // ' in 026 Fortran - 0x0120, '\'', - 0x00A0, '=', - 0x0060, '"', - 0x8820, '\xA2', // cent, in MS-DOS encoding (this is in guess_cr_code as well) - 0x8420, '.', - 0x8220, '<', // ) in 026 Fortran - 0x8120, '(', - 0x80A0, '+', - 0x8060, '|', - 0x4820, '!', - 0x4420, '$', - 0x4220, '*', - 0x4120, ')', - 0x40A0, ';', - 0x4060, '\xAC', // not, in MS-DOS encoding (this is in guess_cr_code as well) - 0x2420, ',', - 0x2220, '%', // ( in 026 Fortran - 0x2120, '_', - 0x20A0, '>', - 0xB000, 'a', - 0xA800, 'b', - 0xA400, 'c', - 0xA200, 'd', - 0xA100, 'e', - 0xA080, 'f', - 0xA040, 'g', - 0xA020, 'h', - 0xA010, 'i', - 0xD000, 'j', - 0xC800, 'k', - 0xC400, 'l', - 0xC200, 'm', - 0xC100, 'n', - 0xC080, 'o', - 0xC040, 'p', - 0xC020, 'q', - 0xC010, 'r', - 0x6800, 's', - 0x6400, 't', - 0x6200, 'u', - 0x6100, 'v', - 0x6080, 'w', - 0x6040, 'x', - 0x6020, 'y', - 0x6010, 'z', // these odd punch codes are used by APL: - 0x1010, '\001', // no corresponding ASCII using ^A - 0x0810, '\002', // SYN using ^B - 0x0410, '\003', // no corresponding ASCII using ^C - 0x0210, '\004', // PUNCH ON using ^D - 0x0110, '\005', // READER STOP using ^E - 0x0090, '\006', // UPPER CASE using ^F - 0x0050, '\013', // EOT using ^K - 0x0030, '\016', // no corresponding ASCII using ^N - 0x1030, '\017', // no corresponding ASCII using ^O - 0x0830, '\020', // no corresponding ASCII using ^P - -}; - -static CPCODE cardcode_026F[] = // 026 fortran -{ - 0x0000, ' ', - 0x8000, '+', - 0x4000, '-', - 0x2000, '0', - 0x1000, '1', - 0x0800, '2', - 0x0400, '3', - 0x0200, '4', - 0x0100, '5', - 0x0080, '6', - 0x0040, '7', - 0x0020, '8', - 0x0010, '9', - 0x9000, 'A', - 0x8800, 'B', - 0x8400, 'C', - 0x8200, 'D', - 0x8100, 'E', - 0x8080, 'F', - 0x8040, 'G', - 0x8020, 'H', - 0x8010, 'I', - 0x5000, 'J', - 0x4800, 'K', - 0x4400, 'L', - 0x4200, 'M', - 0x4100, 'N', - 0x4080, 'O', - 0x4040, 'P', - 0x4020, 'Q', - 0x4010, 'R', - 0x3000, '/', - 0x2800, 'S', - 0x2400, 'T', - 0x2200, 'U', - 0x2100, 'V', - 0x2080, 'W', - 0x2040, 'X', - 0x2020, 'Y', - 0x2010, 'Z', - 0x0420, '=', - 0x0220, '\'', // ' in 026 Fortran - 0x8420, '.', - 0x8220, ')', - 0x4420, '$', - 0x4220, '*', - 0x2420, ',', - 0x2220, '(', -}; - -static CPCODE cardcode_026C[] = // 026 commercial -{ - 0x0000, ' ', - 0x8000, '+', - 0x4000, '-', - 0x2000, '0', - 0x1000, '1', - 0x0800, '2', - 0x0400, '3', - 0x0200, '4', - 0x0100, '5', - 0x0080, '6', - 0x0040, '7', - 0x0020, '8', - 0x0010, '9', - 0x9000, 'A', - 0x8800, 'B', - 0x8400, 'C', - 0x8200, 'D', - 0x8100, 'E', - 0x8080, 'F', - 0x8040, 'G', - 0x8020, 'H', - 0x8010, 'I', - 0x5000, 'J', - 0x4800, 'K', - 0x4400, 'L', - 0x4200, 'M', - 0x4100, 'N', - 0x4080, 'O', - 0x4040, 'P', - 0x4020, 'Q', - 0x4010, 'R', - 0x3000, '/', - 0x2800, 'S', - 0x2400, 'T', - 0x2200, 'U', - 0x2100, 'V', - 0x2080, 'W', - 0x2040, 'X', - 0x2020, 'Y', - 0x2010, 'Z', - 0x0420, '=', - 0x0220, '\'', // ' in 026 Fortran - 0x8420, '.', - 0x8220, ')', - 0x4420, '$', - 0x4220, '*', - 0x2420, ',', - 0x2220, '(', -}; - -extern int cgi; -extern void sub_args (char *instr, char *tmpbuf, int32 maxstr, int32 nargs, char *arg[]); - -static int16 ascii_to_card[256]; - -static CPCODE *cardcode; -static int ncardcode; -static FILE *deckfile = NULL; -static char tempfile[128]; -static int cardnum; -static int any_punched = 0; - -#define MAXARGLEN 80 /* max length of a saved attach command argument */ -#define MAXARGS 10 /* max number of arguments to save */ -static char list_save[MAXARGS][MAXARGLEN], *list_arg[MAXARGLEN]; -static int list_nargs = 0; -static char* (*tab_proc)(char*) = NULL; /* tab reformatting routine */ - -static uint16 punchstation[80]; -static uint16 readstation[80]; -static enum {STATION_EMPTY, STATION_LOADED, STATION_READ, STATION_PUNCHED} punchstate = STATION_EMPTY, readstate = STATION_EMPTY; - -static t_bool nextdeck (void); -static void checkdeck (void); - -static t_stat pcr_attach(UNIT *uptr, char *devname); -static t_stat pcr_detach(UNIT *uptr); -static t_stat pcr_svc(UNIT *uptr); -static void pcr_xio_sense(int modify); -static void pcr_xio_feedcycle(void); -static void pcr_xio_startread(void); -static void pcr_reset(void); -static int pcr_read_data(void); - -/* lookup_codetable - use code flag setting to get code table pointer and length */ - -static t_bool lookup_codetable (int32 match, CPCODE **pcode, int *pncode) -{ - switch (match) { - case CODE_029: - *pcode = cardcode_029; - *pncode = sizeof(cardcode_029) / sizeof(CPCODE); - break; - - case CODE_026F: - *pcode = cardcode_026F; - *pncode = sizeof(cardcode_026F) / sizeof(CPCODE); - break; - - case CODE_026C: - *pcode = cardcode_026C; - *pncode = sizeof(cardcode_026C) / sizeof(CPCODE); - break; - - case CODE_BINARY: - *pcode = NULL; - *pncode = 0; - break; - - default: - printf("Eek! Undefined code table index"); - return FALSE; - } - return TRUE; -} - -t_stat set_active_cr_code (int match) -{ - CPCODE *code; - int i, ncode; - - SET_ACTCODE(cr_unit, match); - - if (! lookup_codetable(match, &code, &ncode)) - return SCPE_ARG; - - memset(ascii_to_card, 0, sizeof(ascii_to_card)); - - for (i = 0; i < ncode; i++) // set ascii to card code table - ascii_to_card[code[i].ascii] = code[i].hollerith; - - return SCPE_OK; -} - -static t_stat cr_set_code (UNIT *uptr, int32 match, char *cptr, void *desc) -{ - if (match == CODE_AUTO) - match = guess_cr_code(); - - return set_active_cr_code(match); -} - -static int32 guess_cr_code (void) -{ - int i; - long filepos; - int32 guess; - union { - uint16 w[80]; // one card image, viewed as 80 short words - char c[160]; // same, viewed as 160 characters - } line; - - // here, we can see if the attached file is binary or ascii and auto-set the - // mode. If we the file is a binary deck, we should be able to read a record of 80 short - // words, and the low 4 bits of each word must be zero. If the file was an ascii deck, - // then these low 4 bits are the low 4 bits of every other character in the first 160 - // chararacters of the file. They would all only be 0 if all of these characters were - // in the following set: {NUL ^P space 0 @ P ` p} . It seems very unlikely that - // this would happen, as even if the deck consisted of untrimmed card images and - // the first two lines were blank, the 81'st character would be a newline, and it would - // appear at one of the every-other characters seen on little-endian machines, anyway. - // So: if the code mode is AUTO, we can use this test and select either BINARY or 029. - // Might as well also check for the all-blanks and newlines case in case this is a - // big-endian machine. - - - guess = CODE_029; // assume ASCII, 029 - - if ((cr_unit.flags & UNIT_ATT) && (cr_unit.fileref != NULL)) { - filepos = ftell(cr_unit.fileref); // remember current position in file - fseek(cr_unit.fileref, 0, SEEK_SET); // go to first record of file - // read card image; if file too short, leave guess set to 029 - if (fxread(line.w, sizeof(line.w[0]), 80, cr_unit.fileref) == 80) { - guess = CODE_BINARY; // we got a card image, assume binary - - for (i = 0; i < 80; i++) { // make sure low bits are zeroes, which our binary card format promises - if (line.w[i] & 0x000F) { - guess = CODE_029; // low bits set, must be ascii text - break; - } - } - - if (guess == CODE_BINARY) { // if we saw no low bits, it could have been all spaces. - guess = CODE_029; // so now assume file is text - for (i = 0; i < 160; i++) { // ensure all 160 characters are 7-bit ASCII (or not or cent) - if ((strchr("\r\n\t\xA2\xAC", line.c[i]) == NULL) && ! BETWEEN(line.c[i], ' ', '\x7F')) { - guess = CODE_BINARY; // oops, null or weird character, it's binary after all - break; - } - } - } - } - - fseek(cr_unit.fileref, filepos, SEEK_SET); // return to original position - } - - return guess; -} - -static t_stat cp_set_code (UNIT *uptr, int32 match, char *cptr, void *desc) -{ - CPCODE *code; - int ncode; - - if (! lookup_codetable(match, &code, &ncode)) - return SCPE_ARG; - - cardcode = code; // save code table for punch output - ncardcode = ncode; - - return SCPE_OK; -} - -t_stat load_cr_boot (int drvno, int switches) -{ - int i; - char *name, msg[80]; - t_bool expand; - uint16 word, *boot; - static uint16 dms_boot_data[] = { /* DMSV2M12, already expanded to 16 bits */ - 0xc80a, 0x18c2, 0xd008, 0xc019, 0x8007, 0xd017, 0xc033, 0x100a, - 0xd031, 0x7015, 0x000c, 0xe800, 0x0020, 0x08f8, 0x4828, 0x7035, - 0x70fa, 0x4814, 0xf026, 0x2000, 0x8800, 0x9000, 0x9800, 0xa000, - 0xb000, 0xb800, 0xb810, 0xb820, 0xb830, 0xb820, 0x3000, 0x08ea, - 0xc0eb, 0x4828, 0x70fb, 0x9027, 0x4830, 0x70f8, 0x8001, 0xd000, - 0xc0f4, 0xd0d9, 0xc01d, 0x1804, 0xe8d6, 0xd0d9, 0xc8e3, 0x18d3, - 0xd017, 0x18c4, 0xd0d8, 0x9016, 0xd815, 0x90db, 0xe8cc, 0xd0ef, - 0xc016, 0x1807, 0x0035, 0x00d0, 0xc008, 0x1803, 0xe8c4, 0xd00f, - 0x080d, 0x08c4, 0x1003, 0x4810, 0x70d9, 0x3000, 0x08df, 0x3000, - 0x7010, 0x00d1, 0x0028, 0x000a, 0x70f3, 0x0000, 0x00d0, 0xa0c0 - }; - static uint16 apl_boot_data[] = { /* APLIPL, already expanded */ - 0x7021, 0x3000, 0x7038, 0xa0c0, 0x0002, 0x4808, 0x0003, 0x0026, - 0x0001, 0x0001, 0x000c, 0x0000, 0x0000, 0x0800, 0x48f8, 0x0027, - 0x7002, 0x08f2, 0x3800, 0xe0fe, 0x18cc, 0x100e, 0x10c1, 0x4802, - 0x7007, 0x4828, 0x7005, 0x4804, 0x7001, 0x70f3, 0x08e7, 0x70e1, - 0x08ed, 0x70f1, 0xc0e0, 0x1807, 0xd0de, 0xc0df, 0x1801, 0xd0dd, - 0x800d, 0xd00c, 0xc0e3, 0x1005, 0xe80a, 0xd009, 0xc0d8, 0x1008, - 0xd0d6, 0xc0dd, 0x1008, 0x80d4, 0xd0da, 0x1000, 0xb000, 0x00f6, - 0x70e7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x9000, 0x4004, 0x40c0, 0x8001, 0x4004, 0x40c0, 0x0000, 0x0000 }; - static uint16 aplp_boot_data[] = { /* APLIPL Privileged, already expanded */ - 0x7021, 0x3000, 0x7038, 0xa0c0, 0x0002, 0x4808, 0x0003, 0x0026, - 0x0001, 0x0001, 0x000c, 0x0000, 0x0000, 0x0800, 0x48f8, 0x0027, - 0x7002, 0x08f2, 0x3800, 0xe0fe, 0x18cc, 0x100e, 0x10c1, 0x4802, - 0x7007, 0x4828, 0x7005, 0x4804, 0x7001, 0x70f3, 0x08e7, 0x70e1, - 0x08ed, 0x70f1, 0xc0e0, 0x1807, 0xd0de, 0xc0df, 0x1801, 0xd0dd, - 0x800d, 0xd00c, 0xc0e3, 0x1005, 0xe80a, 0xd009, 0xc0d8, 0x1008, - 0xd0d6, 0xc0dd, 0x1008, 0x80d4, 0xd0da, 0x1002, 0xb000, 0x00f6, - 0x70e7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x9000, 0x4004, 0x40c0, 0x8001, 0x4004, 0x40c0, 0x4004, 0x4001 - }; - - if ((switches & SWMASK('A')) && (switches & SWMASK('P'))) { - boot = aplp_boot_data; - name = "APL\\1130 Privileged"; - expand = FALSE; - } - else if (switches & SWMASK('A')) { - boot = apl_boot_data; - name = "APL\\1130"; - expand = FALSE; - } - else { - boot = dms_boot_data; - name = "DMS V2M12"; - expand = FALSE; - } - - if (drvno >= 0) /* if specified, set toggle switches to disk drive no */ - CES = drvno; /* so BOOT DSK1 will work correctly (DMS boot uses this) */ - - IAR = 0; /* clear IAR */ - - for (i = 0; i < 80; i++) { /* store the boot image to core words 0..79 */ - word = boot[i]; /* expanding the 12-bit card data to 16 bits if not already expanded */ - if (expand) - word = (word & 0xF800) | ((word & 0x0400) ? 0x00C0 : 0x0000) | ((word & 0x03F0) >> 4); - - WriteW(i, word); - } - /* quiet switch or CGI mode inhibit the boot remark */ - if ((switches & SWMASK('Q') == 0) && ! cgi) { - sprintf(msg,"Loaded %s cold start card\n", name); - -#ifdef GUI_SUPPORT - remark_cmd(msg); -#else - printf(msg); -#endif - } - - return SCPE_OK; -} - -t_stat cr_boot (int unitno, DEVICE *dptr) -{ - t_stat rval; - uint16 buf[80]; - int i; - - if ((rval = reset_all(0)) != SCPE_OK) - return rval; - - if (! (cr_unit.flags & UNIT_ATT)) /* no deck; load standard boot anyway */ - return load_cr_boot(-1, 0); - - if (GET_ACTCODE(cr_unit) != CODE_BINARY) { - printf("Can only boot from card reader when set to BINARY mode"); - return SCPE_IOERR; - } - - if (cr_unit.fileref == NULL) /* this will happen if no file in deck file can be opened */ - return SCPE_IOERR; - - if (fxread(buf, sizeof(buf[0]), 80, cr_unit.fileref) != 80) - return SCPE_IOERR; - - IAR = 0; /* Program Load sets IAR = 0 */ - - for (i = 0; i < 80; i++) /* shift 12 bits into 16 */ - WriteW(i, (buf[i] & 0xF800) | ((buf[i] & 0x0400) ? 0x00C0 : 0x0000) | ((buf[i] & 0x03F0) >> 4)); - - return SCPE_OK; -} - -char card_to_ascii (uint16 hol) -{ - int i; - - for (i = 0; i < ncardcode; i++) - if (cardcode[i].hollerith == hol) - return cardcode[i].ascii; - - return '?'; -} - -// hollerith_to_ascii - provide a generic conversion for simulator debugging - -char hollerith_to_ascii (uint16 hol) -{ - int i; - - for (i = 0; i < ncardcode; i++) - if (cardcode_029[i].hollerith == hol) - return cardcode[i].ascii; - - return ' '; -} - -/* feedcycle - move cards to next station */ - -static void feedcycle (t_bool load, t_bool punching) -{ - char buf[84], *x, *result; - int i, nread, nwrite, ch; - - /* write punched card if punch is attached to a file */ - if (cp_unit.flags & UNIT_ATT) { - if (any_punched && punchstate != STATION_EMPTY) { - if (GET_CODE(cp_unit) == CODE_BINARY) { - fxwrite(punchstation, sizeof(punchstation[0]), 80, cp_unit.fileref); - } - else { - for (i = 80; --i >= 0; ) { /* find last nonblank column */ - if (punchstation[i] != 0) - break; - } - - /* i is now index of last character to output or -1 if all blank */ - - for (nwrite = 0; nwrite <= i; nwrite++) { /* convert characters */ - buf[nwrite] = card_to_ascii(punchstation[nwrite]); - } - - /* nwrite is now number of characters to output */ - -#ifdef WIN32 - buf[nwrite++] = '\r'; /* add CR before NL for microsoft */ -#endif - buf[nwrite++] = '\n'; /* append newline */ - fxwrite(buf, sizeof(char), nwrite, cp_unit.fileref); - } - } - - cp_count++; - } - - if (! load) // all we wanted to do was flush the punch - return; - - /* slide cards from reader to punch. If we know we're punching, - * generate a blank card in any case. Otherwise, it should take two feed - * cycles to get a read card from the hopper to punch station */ - - if (readstate == STATION_EMPTY) { - if (punching) { - memset(punchstation, 0, sizeof(punchstation)); - punchstate = STATION_LOADED; - } - else - punchstate = STATION_EMPTY; - } - else { - memcpy(punchstation, readstation, sizeof(punchstation)); - punchstate = STATION_LOADED; - } - - /* load card into read station */ - -again: /* jump here if we've loaded a new deck after emptying the previous one */ - - if (cr_unit.flags & UNIT_ATT) { - - memset(readstation, 0, sizeof(readstation)); /* blank out the card image */ - - if (cr_unit.fileref == NULL) - nread = 0; - - else if (GET_ACTCODE(cr_unit) == CODE_BINARY) /* binary read is straightforward */ - nread = fxread(readstation, sizeof(readstation[0]), 80, cr_unit.fileref); - - else if (fgets(buf, sizeof(buf), cr_unit.fileref) == NULL) /* read up to 80 chars */ - nread = 0; /* hmm, end of file */ - - else { /* check for newline */ - if ((x = strchr(buf, '\r')) == NULL) - x = strchr(buf, '\n'); - - if (x == NULL) { /* there were no delimiters, burn rest of line */ - while ((ch = getc(cr_unit.fileref)) != EOF) { /* get character */ - if (ch == '\n') /* newline, done */ - break; - - if (ch == '\r') { /* CR, try to take newline too */ - ch = getc(cr_unit.fileref); - if (ch != EOF && ch != '\n') /* hmm, put it back */ - ungetc(ch, cr_unit.fileref); - - break; - } - } - nread = 80; /* take just the first 80 characters */ - } - else - nread = x-buf; /* reduce length of string */ - - if (! (cr_unit.flags & UNIT_LOWERCASE)) - upcase(buf); /* force uppercase */ - - if (tab_proc != NULL) { /* apply tab editing, if specified */ - buf[nread] = '\0'; /* .. be sure string is terminated */ - result = (*tab_proc)(buf); /* .. convert tabs spaces */ - nread = strlen(result); /* .. set new read length */ - } - else - result = buf; - - for (i = 0; i < nread; i++) /* convert ascii to punch code */ - readstation[i] = ascii_to_card[result[i]]; - - nread = 80; /* even if line was blank consider it present */ - } - - if (nread <= 0) { /* set hopper flag accordingly */ - if (deckfile != NULL && nextdeck()) - goto again; - - if (punching) /* pretend we loaded a blank card */ - nread = 80; - } - - if (nread == 0) { - SETBIT(cr_unit.flags, UNIT_EMPTY); - readstate = STATION_EMPTY; - cardnum = -1; /* nix the card counter */ - } - else { - CLRBIT(cr_unit.flags, UNIT_EMPTY); - readstate = STATION_LOADED; - cardnum++; /* advance card counter */ - cr_count++; - } - } -// else -// readstate = STATION_EMPTY; - - cr_unit.COLUMN = -1; /* neither device is currently cycling */ - cp_unit.COLUMN = -1; -} - -#ifdef NO_USE_FOR_THIS_CURRENTLY - -/* this routine should probably be hooked up to the GUI somehow */ - -/* NPRO - nonprocess runout, flushes out the reader/punch */ - -static void npro (void) -{ - if (cr_unit.flags & UNIT_ATT) - fseek(cr_unit.fileref, 0, SEEK_END); /* push reader to EOF */ - if (deckfile != NULL) - fseek(deckfile, 0, SEEK_END); /* skip to end of deck list */ - - cardnum = -1; /* nix the card counter */ - - if (punchstate == STATION_PUNCHED) - feedcycle(FALSE, FALSE); /* flush out card just punched */ - - readstate = punchstate = STATION_EMPTY; - cr_unit.COLUMN = -1; /* neither device is currently cycling */ - cp_unit.COLUMN = -1; - SETBIT(cr_unit.flags, UNIT_EMPTY); /* set hopper empty */ -} - -#endif - -/* skipbl - skip leading whitespace in a string */ - -static char * skipbl (char *str) -{ - while (*str && *str <= ' ') - str++; - - return str; -} - -/* alltrim - remove all leading and trailing whitespace from a string */ - -static char * alltrim (char *str) -{ - char *s, *lastnb; - - if ((s = skipbl(str)) != str) /* slide down over leading whitespace */ - strcpy(str, s); - - for (lastnb = str-1, s = str; *s; s++) /* point to last nonblank characteter in string */ - if (*s > ' ') - lastnb = s; - - lastnb[1] = '\0'; /* clip just after it */ - - return str; -} - -/* checkdeck - set hopper empty status based on condition of current reader file */ - -static void checkdeck (void) -{ - t_bool empty; - - if (cr_unit.fileref == NULL) { /* there is no open file */ - empty = TRUE; - } - else { - fseek(cr_unit.fileref, 0, SEEK_END); /* seek to end of file */ - empty = ftell(cr_unit.fileref) <= 0; /* file is empty if there was nothing in it*/ - cardnum = 0; /* reset card counter */ - fseek(cr_unit.fileref, 0, SEEK_SET); /* rewind deck */ - } - - if (empty) { - SETBIT(cr_unit.flags, UNIT_EMPTY); - if (cr_unit.fileref != NULL) /* real file but it's empty, hmmm, try another */ - nextdeck(); - } - else { - CLRBIT(cr_unit.flags, UNIT_EMPTY); - } -} - -/* nextdeck - attempt to load a new file from the deck list into the hopper */ - -static t_bool nextdeck (void) -{ - char buf[200], tmpbuf[200], *fname, *tn, *c, quote, *mode; - int code; - long fpos; - static char white[] = " \t\r\n"; - - cardnum = 0; /* reset card counter */ - - if (deckfile == NULL) /* we can't help */ - return FALSE; - - code = GET_CODE(cr_unit); /* default code as set */ - - if (cr_unit.fileref != NULL) { /* this pulls the rug out from under scp */ - fclose(cr_unit.fileref); /* since the attach flag is still set. be careful! */ - cr_unit.fileref = NULL; - - if (cr_unit.flags & UNIT_SCRATCH) { - unlink(tempfile); - CLRBIT(cr_unit.flags, UNIT_SCRATCH); - } - } - - for (;;) { /* get a filename */ - tab_proc = NULL; /* default: no tab editing */ - - if (fgets(buf, sizeof(buf), deckfile) == NULL) - break; /* oops, no more names */ - - alltrim(buf); /* remove leading and trailing spaces */ - - if (! *buf) - continue; /* empty line */ - - if (*buf == '#' || *buf == '*' || *buf == ';') - continue; /* comment */ - - if (strnicmp(buf, "!BREAK", 6) == 0) { /* stop the simulation */ - break_simulation(STOP_DECK_BREAK); - continue; - } - - if (buf[0] == '!') { /* literal text line, make a temporary file */ - if (*tempfile == '\0') { - if ((tn = tempnam(".", "1130")) == NULL) { - printf("Cannot create temporary card file name\n"); - break_simulation(STOP_DECK_BREAK); - return 0; - } - strcpy(tempfile, tn); - strcat(tempfile, ".tmp"); - } - - if ((cr_unit.fileref = fopen(tempfile, "wb+")) == NULL) { - printf("Cannot create temporary file %s\n", tempfile); - break_simulation(STOP_DECK_BREAK); - return 0; - } - - SETBIT(cr_unit.flags, UNIT_SCRATCH); - - for (;;) { /* store literal cards into temporary file */ - upcase(buf+1); - fputs(buf+1, cr_unit.fileref); - putc('\n', cr_unit.fileref); - - if (cpu_unit.flags & UNIT_ATT) - trace_io("(Literal card %s\n)", buf+1); - if (! (cr_unit.flags & UNIT_QUIET)) - printf( "(Literal card %s)\n", buf+1); - - fpos = ftell(deckfile); - if (fgets(buf, sizeof(buf), deckfile) == NULL) - break; /* oops, end of file */ - if (buf[0] != '!' || strnicmp(buf, "!BREAK", 6) == 0) - break; - alltrim(buf); - } - fseek(deckfile, fpos, SEEK_SET); /* restore deck file to just before non-literal card */ - - fseek(cr_unit.fileref, 0, SEEK_SET); /* rewind scratch file for reading */ - code = CODE_029; /* assume literal cards use keycode 029 */ - break; - } - - sub_args(buf, tmpbuf, sizeof(buf), list_nargs, list_arg); /* substitute in stuff from the attach command line */ - - fname = c = buf; /* pick filename from string */ - - if (*c == '\'' || *c == '"') { /* quoted string */ - quote = *c; /* remember the quote type */ - strcpy(c, c+1); /* slide string down over the quote */ - while (*c && (*c != quote)) - c++; /* skip to end of quote */ - } - else { /* not quoted; look for terminating whitespace */ - while (*c && (*c > ' ')) - c++; - } - - if (*c) - *c++ = 0; /* term arg at space or closing quote & move to next character */ - - if (! *fname) /* blank line, no filename */ - continue; - - if ((cr_unit.fileref = fopen(fname, "rb")) == NULL) { - printf("File '%s' specified in deck file '%s' cannot be opened\n", fname, cr_unit.filename+1); - continue; - } - - mode = c = skipbl(c); /* skip to next token, which would be mode, if present */ - - switch (*c) { - case 'b': - case 'B': - code = CODE_BINARY; /* force code */ - c++; /* accept mode character by moving past it */ - break; - - case 'a': - case 'A': - code = CODE_029; - c++; - - switch (*c) { /* is ascii mode followed by another character? */ - case 'F': - case 'f': - tab_proc = EditToFortran; - c++; - break; - - case 'A': - case 'a': - tab_proc = EditToAsm; - c++; - break; - - case 't': - case 'T': - tab_proc = EditToWhitespace; - c++; - break; - } - } - - if (*skipbl(c)) /* there should be nothing left */ - printf("* Bad mode specifier %s after filename %s in deck file", mode, fname); - - if (code == CODE_AUTO) /* otherwise if mode is auto, guess it, otherwise use default */ - code = guess_cr_code(); - - if (cpu_unit.flags & UNIT_ATT) - trace_io("(Opened %s deck %s%s)\n", (code == CODE_BINARY) ? "binary" : "text", fname, tab_proc ? (*tab_proc)(NULL) : ""); - - if (! (cr_unit.flags & UNIT_QUIET)) - printf( "(Opened %s deck %s%s)\n", (code == CODE_BINARY) ? "binary" : "text", fname, tab_proc ? (*tab_proc)(NULL) : ""); - - break; - } - - checkdeck(); - - if (code != CODE_AUTO) /* if code was determined, set it */ - set_active_cr_code(code); /* (it may be left at CODE_AUTO when deckfile is exhausted */ - - return (cr_unit.flags & UNIT_EMPTY) == 0; /* return TRUE if a deck has been loaded */ -} - -static t_stat cr_reset (DEVICE *dptr) -{ - if (GET_ACTCODE(cr_unit) == CODE_AUTO) - SET_ACTCODE(cr_unit, CODE_029); /* if actual code is not yet set, select 029 for now*/ - - cr_set_code(&cr_unit, GET_ACTCODE(cr_unit), NULL, NULL); /* reset to specified code table */ - - readstate = STATION_EMPTY; - - cr_dsw = 0; - sim_cancel(&cr_unit); /* cancel any pending ops */ - calc_ints(); - - SET_OP(OP_IDLE); - - cr_unit.COLUMN = -1; /* neither device is currently cycling */ - - if (cr_unit.flags & UNIT_PHYSICAL) { - pcr_reset(); - return SCPE_OK; - } - - SETBIT(cr_unit.flags, UNIT_EMPTY); /* assume hopper empty */ - - if (cr_unit.flags & UNIT_ATT) { -// if (deckfile != NULL) { /* do NOT rewind the deck file */ -// fseek(deckfile, 0, SEEK_SET); -// nextdeck(); -// } -// else -// checkdeck(); - - if (cr_unit.fileref != NULL) - feedcycle(FALSE, FALSE); - } - - return SCPE_OK; -} - -static t_stat cp_reset (DEVICE *dptr) -{ - if (GET_CODE(cp_unit) == CODE_AUTO) - SET_CODE(cp_unit, CODE_BINARY); /* punch is never in auto mode; turn it to binary on startup */ - - cp_set_code(&cp_unit, GET_CODE(cp_unit), NULL, NULL); - punchstate = STATION_EMPTY; - - cp_unit.COLUMN = -1; - return SCPE_OK; -} - -static t_stat cr_attach (UNIT *uptr, char *cptr) -{ - t_stat rval; - t_bool use_decklist; - char *c, *arg, quote; - -// no - don't cancel pending read? -// sim_cancel(uptr); /* cancel pending operations */ - - CLRBIT(uptr->flags, UNIT_QUIET|UNIT_DEBUG|UNIT_PHYSICAL|UNIT_LOWERCASE); /* set options */ - - tab_proc = NULL; - - if (sim_switches & SWMASK('D')) SETBIT(uptr->flags, UNIT_DEBUG); - if (sim_switches & SWMASK('Q')) SETBIT(uptr->flags, UNIT_QUIET); - if (sim_switches & SWMASK('L')) SETBIT(uptr->flags, UNIT_LOWERCASE); - - if (sim_switches & SWMASK('F')) tab_proc = EditToFortran; - if (sim_switches & SWMASK('A')) tab_proc = EditToAsm; - if (sim_switches & SWMASK('T')) tab_proc = EditToWhitespace; - - cr_detach(uptr); /* detach file and possibly deckfile */ - CLRBIT(uptr->flags, UNIT_SCRATCH); - - c = cptr; /* extract arguments */ - for (list_nargs = 0; list_nargs < MAXARGS; list_nargs++) { - while (*c && (*c <= ' ')) /* skip blanks */ - c++; - - if (! *c) - break; /* all done */ - - arg = c; /* save start */ - while (*c && (*c > ' ')) { - if (*c == '\'' || *c == '"') { /* quoted string */ - for (quote = *c++; *c;) - if (*c++ == quote) - break; - } - else c++; - } - - if (*c) - *c++ = 0; /* term arg at space */ - - list_arg[list_nargs] = list_save[list_nargs]; /* set pointer to permanent storage location */ - strncpy(list_arg[list_nargs], arg, MAXARGLEN); /* store copy */ - } - - if (list_nargs <= 0) /* need at least 1 */ - return SCPE_2FARG; - - cardnum = 0; /* reset card counter */ - use_decklist = FALSE; - - cptr = list_arg[0]; /* filename is first argument */ - -#ifdef ENABLE_ENABLE_PHYSICAL_CARD_READER_SUPPORT - if (*cptr == '=') { /* open physical card reader device */ - if ((rval = pcr_attach(uptr, ++cptr)) != SCPE_OK) - return rval; - } -#endif - - if (*cptr == '@') { - use_decklist = TRUE; - cptr++; - } - - if (strcmp(cptr, "-") == 0 && ! use_decklist) { /* standard input */ - if (uptr -> flags & UNIT_DIS) return SCPE_UDIS; /* disabled? */ - uptr->filename = calloc(CBUFSIZE, sizeof(char)); - strcpy(uptr->filename, "(stdin)"); - uptr->fileref = stdin; - SETBIT(uptr->flags, UNIT_ATT); - uptr->pos = 0; - } - else if ((rval = attach_unit(uptr, cptr)) != SCPE_OK) - return rval; - - if (use_decklist) { /* if we skipped the '@', store the actually-specified name */ - strncpy(uptr->filename, cptr-1, CBUFSIZE); - deckfile = cr_unit.fileref; /* save the deck file stream in our local variable */ - cr_unit.fileref = NULL; - nextdeck(); - } - else { - checkdeck(); - cr_set_code(&cr_unit, GET_CODE(cr_unit), NULL, NULL); - } - - // there is a read pending. Pull the card in to make it go - if (CURRENT_OP == OP_READING || CURRENT_OP == OP_PUNCHING || CURRENT_OP == OP_FEEDING) - feedcycle(TRUE, (cp_unit.flags & UNIT_ATT) != 0); - -// no - don't reset the reader -// cr_reset(&cr_dev); /* reset the whole thing */ -// cp_reset(&cp_dev); - - return SCPE_OK; -} - -static t_stat cr_detach (UNIT *uptr) -{ - t_stat rval; - - cr_count = 0; /* clear read count */ - - if (cr_unit.flags & UNIT_PHYSICAL) - return pcr_detach(uptr); - - if (cr_unit.flags & UNIT_ATT && deckfile != NULL) { - if (cr_unit.fileref != NULL) /* close the active card deck */ - fclose(cr_unit.fileref); - - if (cr_unit.flags & UNIT_SCRATCH) { - unlink(tempfile); - CLRBIT(cr_unit.flags, UNIT_SCRATCH); - } - - cr_unit.fileref = deckfile; /* give scp a file to close */ - } - - if (uptr->fileref == stdout) { - CLRBIT(uptr->flags, UNIT_ATT); - free(uptr->filename); - uptr->filename = NULL; - rval = SCPE_OK; - } - else - rval = detach_unit(uptr); - - return rval; -} - -static t_stat cp_attach (UNIT *uptr, char *cptr) -{ - /* if -d is specified turn on debugging (bit is in card reader UNIT) */ - if (sim_switches & SWMASK('D')) SETBIT(cr_unit.flags, UNIT_DEBUG); - - return attach_unit(uptr, cptr); -} - -static t_stat cp_detach (UNIT *uptr) -{ - if (cp_unit.flags & UNIT_ATT) - if (punchstate == STATION_PUNCHED) - feedcycle(FALSE, FALSE); /* flush out card just punched */ - - any_punched = 0; /* reset punch detected */ - cp_count = 0; /* clear punch count */ - - return detach_unit(uptr); -} - -static void op_done (void) -{ - if (cr_unit.flags & UNIT_DEBUG) - DEBUG_PRINT("!CR Op Complete, card %d", cardnum); - - SET_OP(OP_IDLE); - SETBIT(cr_dsw, CR_DSW_OP_COMPLETE); - SETBIT(ILSW[4], ILSW_4_1442_CARD); - calc_ints(); -} - -static t_stat cr_svc (UNIT *uptr) -{ - if (uptr->flags & UNIT_PHYSICAL) - return pcr_svc(uptr); - - switch (CURRENT_OP) { - case OP_IDLE: - break; - - case OP_FEEDING: - op_done(); - break; - - case OP_READING: - if (readstate == STATION_EMPTY) { /* read active but no cards? hang */ - sim_activate(&cr_unit, cf_wait); - break; - } - - if (++cr_unit.COLUMN < 80) { - SETBIT(cr_dsw, CR_DSW_READ_RESPONSE); - SETBIT(ILSW[0], ILSW_0_1442_CARD); - calc_ints(); - sim_activate(&cr_unit, cr_wait); - if (cr_unit.flags & UNIT_DEBUG) - DEBUG_PRINT("!CR Read Response %d : %d", cardnum, cr_unit.COLUMN+1); - } - else { - readstate = STATION_READ; - op_done(); - } - break; - - case OP_PUNCHING: - if (punchstate == STATION_EMPTY) { /* punch active but no cards? hang */ - sim_activate(&cr_unit, cf_wait); - break; - } - - if (cp_unit.flags & UNIT_LASTPUNCH) { - punchstate = STATION_PUNCHED; - op_done(); - } - else if (++cp_unit.COLUMN < 80) { - SETBIT(cr_dsw, CR_DSW_PUNCH_RESPONSE); - SETBIT(ILSW[0], ILSW_0_1442_CARD); - calc_ints(); - sim_activate(&cr_unit, cp_wait); - if (cr_unit.flags & UNIT_DEBUG) - DEBUG_PRINT("!CR Punch Response"); - } - else { - punchstate = STATION_PUNCHED; - op_done(); - } - break; - } - - return SCPE_OK; -} - -void xio_1142_card (int32 addr, int32 func, int32 modify) -{ - char msg[80]; - int ch; - int16 wd; - t_bool lastcard; - - switch (func) { - case XIO_SENSE_DEV: - if (cr_unit.flags & UNIT_PHYSICAL) { - pcr_xio_sense(modify); - return; - } - - if (cp_unit.flags & UNIT_ATT) - lastcard = FALSE; /* if punch file is open, assume infinite blank cards in reader */ - else if ((cr_unit.flags & UNIT_ATT) == 0) - lastcard = TRUE; /* if nothing to read, hopper's empty */ - else if (readstate == STATION_LOADED) - lastcard = FALSE; - else if (cr_unit.fileref == NULL) - lastcard = TRUE; - else if ((ch = getc(cr_unit.fileref)) != EOF) { - ungetc(ch, cr_unit.fileref); /* put character back; hopper's not empty */ - lastcard = FALSE; - } - else if (deckfile != NULL && nextdeck()) - lastcard = FALSE; - else - lastcard = TRUE; /* there is nothing left to read for a next card */ - - CLRBIT(cr_dsw, CR_DSW_LAST_CARD|CR_DSW_BUSY|CR_DSW_NOT_READY); - - if (lastcard) - SETBIT(cr_dsw, CR_DSW_LAST_CARD); - - if (CURRENT_OP != OP_IDLE) - SETBIT(cr_dsw, CR_DSW_BUSY|CR_DSW_NOT_READY); - else if (readstate == STATION_EMPTY && punchstate == STATION_EMPTY && lastcard) - SETBIT(cr_dsw, CR_DSW_NOT_READY); - - ACC = cr_dsw; /* return the DSW */ - - if (cr_unit.flags & UNIT_DEBUG) - DEBUG_PRINT("#CR Sense %04x%s%s", cr_dsw & 0xFFFF, (modify & 1) ? " RESET0" : "", (modify & 2) ? " RESET4" : ""); - - if (modify & 0x01) { /* reset interrupts */ - CLRBIT(cr_dsw, CR_DSW_READ_RESPONSE|CR_DSW_PUNCH_RESPONSE); - CLRBIT(ILSW[0], ILSW_0_1442_CARD); - } - - if (modify & 0x02) { - CLRBIT(cr_dsw, CR_DSW_OP_COMPLETE); - CLRBIT(ILSW[4], ILSW_4_1442_CARD); - } - break; - - case XIO_READ: /* get card data into word pointed to in IOCC packet */ - if (cr_unit.flags & OP_READING) { - if (cr_unit.COLUMN < 0) { - xio_error("1442: Premature read!"); - } - else if (cr_unit.COLUMN < 80) { - WriteW(addr, readstation[cr_unit.COLUMN]); - if (cr_unit.flags & UNIT_DEBUG) - DEBUG_PRINT("#CR Read %03x", (readstation[cr_unit.COLUMN] >> 4)); - } - else if (cr_unit.COLUMN == 80) { - xio_error("1442: Read past column 80!"); - cr_unit.COLUMN++; // don't report it again - } - } - else { -// don't complain: APL\1130 issues both reads and writes on every interrupt -// (probably to keep the code small). Apparently it's just ignored if corresponding -// control didn't initiate a read cycle. -// xio_error("1442: Read when not in a read cycle!"); - } - break; - - case XIO_WRITE: - if (cr_unit.flags & OP_PUNCHING) { - if (cp_unit.COLUMN < 0) { - xio_error("1442: Premature write!"); - } - else if (cp_unit.flags & UNIT_LASTPUNCH) { - xio_error("1442: Punch past last-punch column!"); - cp_unit.COLUMN = 81; - } - else if (cp_unit.COLUMN < 80) { - wd = ReadW(addr); /* store one word to punch buffer */ - punchstation[cp_unit.COLUMN] = wd & 0xFFF0; - if (wd & 0x0008) /* mark this as last column to be punched */ - SETBIT(cp_unit.flags, UNIT_LASTPUNCH); - if (cr_unit.flags & UNIT_DEBUG) - DEBUG_PRINT("#CR Punch %03x%s", (wd >> 4) & 0xFFF, (wd & 8) ? " LAST" : ""); - } - else if (cp_unit.COLUMN == 80) { - xio_error("1442: Punch past column 80!"); - cp_unit.COLUMN++; // don't report it again - } - } - else { -// don't complain: APL\1130 issues both reads and writes on every interrupt -// (probably to keep the code small). Apparently it's just ignored if corresponding -// control didn't initiate a punch cycle. -// xio_error("1442: Write when not in a punch cycle!"); - } - break; - - case XIO_CONTROL: - switch (modify & 7) { - case 1: /* start punch */ - if (cr_unit.flags & UNIT_DEBUG) - DEBUG_PRINT("#CR Start Punch"); - if (punchstate != STATION_LOADED) - feedcycle(TRUE, TRUE); - - SET_OP(OP_PUNCHING); - cp_unit.COLUMN = -1; - - CLRBIT(cp_unit.flags, UNIT_LASTPUNCH); - - any_punched = 1; /* we've started punching, so enable writing to output deck file */ - - sim_cancel(&cr_unit); - sim_activate(&cr_unit, cp_wait); - break; - - case 2: /* feed cycle */ - if (cr_unit.flags & UNIT_DEBUG) - DEBUG_PRINT("#CR Feed"); - - if (cr_unit.flags & UNIT_PHYSICAL) { - pcr_xio_feedcycle(); - return; - } - feedcycle(TRUE, (cp_unit.flags & UNIT_ATT) != 0); - - SET_OP(OP_FEEDING); - - sim_cancel(&cr_unit); - sim_activate(&cr_unit, cf_wait); - break; - - case 4: /* start read */ - if (cr_unit.flags & UNIT_DEBUG) - DEBUG_PRINT("#CR Start read"); - - if (cp_unit.flags & UNIT_PHYSICAL) { - pcr_xio_startread(); - return; - } - - if (readstate != STATION_LOADED) - feedcycle(TRUE, (cp_unit.flags & UNIT_ATT) != 0); - - SET_OP(OP_READING); - cr_unit.COLUMN = -1; - - sim_cancel(&cr_unit); - sim_activate(&cr_unit, cr_wait); - break; - - case 0: - if (cr_unit.flags & UNIT_DEBUG) - DEBUG_PRINT("#CR NOP"); - break; - - default: - sprintf(msg, "1442: Multiple operations in XIO_CONTROL: %x", modify); - xio_error(msg); - return; - } - - break; - - default: - sprintf(msg, "Invalid 1442 XIO function %x", func); - xio_error(msg); - break; - } -} - -#if ! (defined(ENABLE_PHYSICAL_CARD_READER_SUPPORT) && defined(WIN32)) - - /* stub out the physical card reader routines */ - - static t_stat pcr_attach (UNIT *uptr, char *devname) {return SCPE_ARG;} - static t_stat pcr_detach (UNIT *uptr) {return detach_unit(uptr);} - static t_stat pcr_svc (UNIT *uptr) {return SCPE_OK;} - static void pcr_xio_sense (int modify) {} - static void pcr_xio_feedcycle (void) {} - static void pcr_xio_startread (void) {} - static void pcr_reset (void) {} - static int pcr_read_data (void) {return 0;} - -#else - -/* - * This code supports a physical card reader interface I built. Details - * available upon request, write to brian@ibm1130.org - - * NOTE: THIS IS NOT COMPLETE OR EVEN CLOSE, JUST SOME CODE SLAMMED INTO THE FILE - */ - -#include - -#define PCR_STATUS_READY 1 -#define PCR_STATUS_ERROR 2 -#define PCR_STATUS_HEMPTY 4 -#define PCR_STATUS_EOF 8 -#define PCR_STATUS_PICKING 16 - -static char pcr_status = '?'; -static void pcr_cmd (char cmd); - -static t_stat pcr_attach (UNIT *uptr, char *devname) -{ - HANDLE hPort; - DCB dcb; - COMMTIMEOUTS cto; - DWORD nerr; - /* open the COM port */ - hPort = CreateFile(devname, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); - if (hPort == INVALID_HANDLE_VALUE) - return SCPE_OPENERR; - - memset(&dcb, 0, sizeof(dcb)); /* set communications parameters */ - - dcb.DCBlength = sizeof(DCB); - dcb.BaudRate = CBR_115200; /* for the USB virtual com port, baud rate is irrelevant */ - dcb.fBinary = 1; - dcb.fParity = 0; - dcb.fOutxCtsFlow = 0; - dcb.fOutxDsrFlow = 0; - dcb.fDtrControl = DTR_CONTROL_ENABLE; - dcb.fDsrSensitivity = FALSE; - dcb.fTXContinueOnXoff = 0; - dcb.fOutX = 0; - dcb.fInX = 0; - dcb.fErrorChar = 0; - dcb.fNull = 0; - dcb.fRtsControl = RTS_CONTROL_ENABLE; - dcb.fAbortOnError = 0; - dcb.XonLim = 0; - dcb.XoffLim = 0; - dcb.ByteSize = 8; - dcb.Parity = NOPARITY; - dcb.StopBits = ONESTOPBIT; - dcb.XonChar = 0; - dcb.XoffChar = 0; - dcb.ErrorChar = 0; - dcb.EofChar = 0; - dcb.EvtChar = 0; - - if (! SetCommState(hPort, &dcb)) { - CloseHandle(hPort); - printf("Call to SetCommState failed\n"); - return SCPE_OPENERR; - } - - cto.ReadIntervalTimeout = 100; // stop if 100 msec elapses between two received bytes - cto.ReadTotalTimeoutMultiplier = 0; // no length sensitivity - cto.ReadTotalTimeoutConstant = 400; // allow 400 msec for a read (reset command can take a while) - - cto.WriteTotalTimeoutMultiplier = 0; - cto.WriteTotalTimeoutConstant = 200; // allow 200 msec for a write - - if (! SetCommTimeouts(hPort, &cto)) { - CloseHandle(hPort); - printf("Call to SetCommTimeouts failed\n"); - return SCPE_OPENERR; - } - - PurgeComm(hPort, PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR); - ClearCommError(hPort, &nerr, NULL); - - SETBIT(uptr->flags, UNIT_PHYSICAL|UNIT_ATT); /* mark device as attached */ - uptr->filename = calloc(strlen(devname)+1, sizeof(char)); - strcpy(uptr->filename, devname); - - uptr->fileref = (FILE *) hPort; /* store the handle in the slot for the file pointer */ - - cr_unit.COLUMN = -1; /* neither device is currently cycling */ - return SCPE_OK; -} - -static t_stat pcr_detach (UNIT *uptr) -{ - CLRBIT(cr_unit.flags, UNIT_PHYSICAL|UNIT_ATT); /* drop the attach and physical bits */ - - CloseHandle((HANDLE) (uptr->fileref)); /* close the COM port */ - uptr->fileref = NULL; - - free(uptr->filename); /* release the name copy */ - uptr->filename = NULL; - - return SCPE_OK; -} - -static void pcr_xio_sense (int modify) -{ - CLRBIT(cr_dsw, CR_DSW_LAST_CARD|CR_DSW_BUSY|CR_DSW_NOT_READY|CR_DSW_ERROR_CHECK); - - if (pcr_status & PCR_STATUS_HEMPTY) /* set 1130 status bits based on last status recv'd from */ - SETBIT(cr_dsw, CR_DSW_LAST_CARD); /* the card reader */ - - if (pcr_status & PCR_STATUS_ERROR) - SETBIT(cr_dsw, CR_DSW_ERROR_CHECK); - - if (pcr_status & PCR_STATUS_PICKING) - SETBIT(cr_dsw, CR_DSW_BUSY); - - if (! (pcr_status & PCR_STATUS_READY)) - SETBIT(cr_dsw, CR_DSW_NOT_READY); - - if (modify & 0x01) { /* reset simulated interrupts */ - CLRBIT(cr_dsw, CR_DSW_READ_RESPONSE|CR_DSW_PUNCH_RESPONSE); - CLRBIT(ILSW[0], ILSW_0_1442_CARD); - } - - if (modify & 0x02) { - CLRBIT(cr_dsw, CR_DSW_OP_COMPLETE); - CLRBIT(ILSW[4], ILSW_4_1442_CARD); - } - - ACC = cr_dsw; /* return the DSW */ - - if (cr_unit.flags & UNIT_DEBUG) - DEBUG_PRINT("#CR Sense %04x%s%s", cr_dsw, (modify & 1) ? " RESET0" : "", (modify & 2) ? " RESET4" : ""); -} - -static void pcr_xio_feedcycle (void) -{ - pcr_cmd('P'); // initiate pick - SET_OP(OP_FEEDING); -} - -static void pcr_xio_startread (void) -{ - pcr_cmd('P'); // initiate pick - SET_OP(OP_READING); -} - -static void pcr_reset (void) -{ - pcr_cmd('X'); // cancel pending pick -} - -static t_stat pcr_svc (UNIT *uptr) -{ - switch (CURRENT_OP) { - case OP_IDLE: - break; - - case OP_FEEDING: - op_done(); - break; - - case OP_READING: -/* this needs to poll the usb port for a = or ! */ - - if (readstate == STATION_EMPTY) { /* read active but no cards? hang */ - sim_activate(&cr_unit, cf_wait); - break; - } - - if (++cr_unit.COLUMN < 80) { - SETBIT(cr_dsw, CR_DSW_READ_RESPONSE); - SETBIT(ILSW[0], ILSW_0_1442_CARD); - calc_ints(); - sim_activate(&cr_unit, cr_wait); - if (cr_unit.flags & UNIT_DEBUG) - DEBUG_PRINT("!CR Read Response %d : %d", cardnum, cr_unit.COLUMN+1); - } - else { - readstate = STATION_READ; - op_done(); - } - break; - - case OP_PUNCHING: - return cr_svc(uptr); - } - - return SCPE_OK; -} - -static void pcr_cmd (char cmd) -{ - DWORD nio; - char resp; - int ntries = 10; - BOOL resend = TRUE; - - while (--ntries >= 0) { - if (resend && cmd != 0) { - if (! WriteFile((HANDLE) cr_unit.fileref, &cmd, 1, &nio, NULL)) { - printf("* Error writing to card reader interface\n"); - return; - } - } - - resend = TRUE; - - nio = 0; - ReadFile((HANDLE) cr_unit.fileref, &resp, 1, &nio, NULL); - - if (nio != 1) { - printf("* Timeout reading from card reader interface\n"); - continue; - } - - if (resp == '?') - continue; // it didn't recognize the command - - if (resp >= '@' && resp <= '_') { - pcr_status = resp; - return; - } - - if (resp == '!') { // we were expecting a response, but got a cancellation notice from pending pick - resend = FALSE; // status byte is coming - ntries++; // no penalty - } - else if (resp == '=') { // we were expecting a response, but are getting data from a pending pick - pcr_read_data(); - resend = FALSE; // status byte is coming - ntries++; // no penalty - continue; - } - // else -- just ignore it? - } - - printf("* Card reader interface failed to respond within 10 tries\n"); -} - -static int pcr_read_data (void) -{ - DWORD nio; - - ReadFile((HANDLE) cr_unit.fileref, readstation, 160, &nio, NULL); - return nio == 160; -} - -#endif diff --git a/Ibm1130/ibm1130_defs.h b/Ibm1130/ibm1130_defs.h deleted file mode 100644 index 61b75024..00000000 --- a/Ibm1130/ibm1130_defs.h +++ /dev/null @@ -1,294 +0,0 @@ -/* - * (C) Copyright 2002, Brian Knittel. - * You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN - * RISK basis, there is no warranty of fitness for any purpose, and the rest of the - * usual yada-yada. Please keep this notice and the copyright in any distributions - * or modifications. - * - * This is not a supported product, but I welcome bug reports and fixes. - * Mail to sim@ibm1130.org - */ - -/* ibm1130_defs.h: IBM-1130 simulator definitions - */ - -#include "sim_defs.h" /* main SIMH defns (include path should include .., or make a copy) */ -#include -#include - -#if defined(VMS) - # include /* to pick up 'unlink' */ -#endif - -#define MIN(a,b) (((a) <= (b)) ? (a) : (b)) -#define MAX(a,b) (((a) >= (b)) ? (a) : (b)) - -#ifndef WIN32 - int strnicmp (char *a, char *b, int n); - int strcmpi (char *a, char *b); -#endif - -// #define GUI_SUPPORT // uncomment to compile the GUI extensions. It's defined in the windows ibm1130.mak makefile - -/* ------------------------------------------------------------------------ */ -/* Architectural constants */ - -#define MAXMEMSIZE (32768) /* 32Kwords */ -#define INIMEMSIZE (16384) /* 16Kwords */ -#define MEMSIZE (cpu_unit.capac) - -#define UNIT_MSIZE (1 << (UNIT_V_UF + 7)) /* flag for memory size setting */ - -#define ILL_ADR_FLAG 0x40000000 /* an impossible 1130 address */ - -/* ------------------------------------------------------------------------ */ -/* Global state */ - -extern int cgi; // TRUE if we are running as a CGI program -extern int sim_gui; - -extern uint16 M[]; /* core memory, up to 32Kwords (note: don't even think about trying 64K) */ -extern uint16 ILSW[]; /* interrupt level status words */ -extern int32 IAR; /* instruction address register */ -extern int32 prev_IAR; /* instruction address register at start of current instruction */ -extern int32 SAR, SBR; /* storage address/buffer registers */ -extern int32 OP, TAG, CCC; /* instruction decoded pieces */ -extern int32 CES; /* console entry switches */ -extern int32 ACC, EXT; /* accumulator and extension */ -extern int32 RUNMODE; /* processor run/step mode */ -extern int32 ipl; /* current interrupt level (-1 = not handling irq) */ -extern int32 iplpending; /* interrupted IPL's */ -extern int32 tbit; /* trace flag (causes level 5 IRQ after each instr) */ -extern int32 V, C; /* condition codes */ -extern int32 wait_state; /* wait state (waiting for an IRQ) */ -extern int32 wait_lamp; /* alternate indicator to light the wait lamp on the GUI */ -extern int32 int_req; /* sum of interrupt request levels active */ -extern int32 int_lamps; /* accumulated version of int_req - gives lamp persistence */ -extern int32 int_mask; /* current active interrupt mask (ipl sensitive) */ -extern int32 mem_mask; -extern int32 cpu_dsw; /* CPU device status word */ -extern int32 sim_int_char; /* interrupt character */ -extern t_bool running; -extern t_bool power; -extern t_bool cgi; /* TRUE if we are running as a CGI program */ -extern t_stat reason; /* CPU execution loop control */ - -#define WAIT_OP 1 /* wait state causes: wait instruction, invalid instruction*/ -#define WAIT_INVALID_OP 2 - -#define MODE_SS 3 /* RUNMODE values. SS and SMC are not implemented in this simulator */ -#define MODE_SMC 2 -#define MODE_INT_RUN 1 -#define MODE_RUN 0 -#define MODE_SI -1 -#define MODE_DISP -2 -#define MODE_LOAD -3 - -/* ------------------------------------------------------------------------ */ -/* debugging */ -/* ------------------------------------------------------------------------ */ - -#define ENABLE_DEBUG_PRINT -#define ENABLE_DEBUG_TO_LOG - -#ifdef ENABLE_DEBUG_PRINT -# define DEBUG_PRINT debug_print -#else -# ifdef ENABLE_DEBUG_TO_LOG -# define DEBUG_PRINT trace_io -# else -# define DEBUG_PRINT if (0) debug_print -# endif -#endif - -void debug_print(char *fmt, ...); - -/* ------------------------------------------------------------------------ */ -/* memory IO routines */ - -int32 ReadW (int32 a); -void WriteW (int32 a, int32 d); - -/* ------------------------------------------------------------------------ */ -/* handy macros */ - -#define CLRBIT(v,b) ((v) &= ~(b)) -#define SETBIT(v,b) ((v) |= (b)) -#define BETWEEN(v,a,b) (((v) >= (a)) && ((v) <= (b))) - -/* ------------------------------------------------------------------------ */ -/* Simulator stop codes */ - -#define STOP_WAIT 1 /* wait, no events */ -#define STOP_INVALID_INSTR 2 /* bad instruction */ -#define STOP_IBKPT 3 /* simulator breakpoint */ -#define STOP_INCOMPLETE 4 /* simulator coding not complete here */ -#define STOP_POWER_OFF 5 /* no power */ -#define STOP_DECK_BREAK 6 /* !BREAK in deck file */ -#define STOP_PHASE_BREAK 7 /* phase load break */ -#define STOP_CRASH 8 /* program has crashed badly */ -#define STOP_TIMED_OUT 9 /* simulation time limit exceeded */ - -#define IORETURN(f,v) ((f)? (v): SCPE_OK) /* cond error return */ - -#define INT_REQ_0 0x01 /* bits for interrupt levels (ipl, iplpending, int_req, int_mask) */ -#define INT_REQ_1 0x02 -#define INT_REQ_2 0x04 -#define INT_REQ_3 0x08 -#define INT_REQ_4 0x10 -#define INT_REQ_5 0x20 - -#define XIO_UNUSED 0x00 /* XIO commands */ -#define XIO_WRITE 0x01 -#define XIO_READ 0x02 -#define XIO_SENSE_IRQ 0x03 -#define XIO_CONTROL 0x04 -#define XIO_INITW 0x05 -#define XIO_INITR 0x06 -#define XIO_SENSE_DEV 0x07 - -#define XIO_FAILED 0x20 /* fake function to record error */ - -/* ILSW bits - set by appropriate device whenever an interrupt is outstanding */ - -#define ILSW_0_1442_CARD 0x8000 /* ILSW 0 is not really defined on the 1130 */ - -#define ILSW_1_1132_PRINTER 0x8000 // had these backwards! -#define ILSW_1_SCA 0x4000 - -#define ILSW_2_1131_DISK 0x8000 - -#define ILSW_2_2310_DRV_1 0x4000 -#define ILSW_2_2310_DRV_2 0x2000 -#define ILSW_2_2310_DRV_3 0x1000 -#define ILSW_2_2310_DRV_4 0x0800 /* can have 2310 or 2311 */ - -#define ILSW_2_2311_DRV_1_DISK_1 0x4000 -#define ILSW_2_2311_DRV_1_DISK_2 0x2000 -#define ILSW_2_2311_DRV_1_DISK_3 0x1000 -#define ILSW_2_2311_DRV_1_DISK_4 0x0800 - -#define ILSW_2_2311_DRV_1_DISK_5 0x0400 -#define ILSW_2_2311_DRV_2_DISK_1 0x0200 -#define ILSW_2_2311_DRV_2_DISK_2 0x0100 -#define ILSW_2_2311_DRV_2_DISK_3 0x0080 -#define ILSW_2_2311_DRV_2_DISK_4 0x0040 -#define ILSW_2_2311_DRV_2_DISK_5 0x0020 - -#define ILSW_2_SAC_BIT_11 0x0010 -#define ILSW_2_SAC_BIT_12 0x0008 -#define ILSW_2_SAC_BIT_13 0x0004 -#define ILSW_2_SAC_BIT_14 0x0002 -#define ILSW_2_SAC_BIT_15 0x0001 - -#define ILSW_3_1627_PLOTTER 0x8000 -#define ILSW_3_SAC_BIT_01 0x4000 -#define ILSW_3_SAC_BIT_02 0x2000 -#define ILSW_3_SAC_BIT_03 0x1000 -#define ILSW_3_2250_DISPLAY 0x0800 -#define ILSW_3_SYSTEM7 0x0800 -#define ILSW_3_SAC_BIT_05 0x0400 -#define ILSW_3_SAC_BIT_06 0x0200 -#define ILSW_3_SAC_BIT_07 0x0100 -#define ILSW_3_SAC_BIT_08 0x0080 -#define ILSW_3_SAC_BIT_09 0x0040 -#define ILSW_3_SAC_BIT_10 0x0020 -#define ILSW_3_SAC_BIT_11 0x0010 -#define ILSW_3_SAC_BIT_12 0x0008 -#define ILSW_3_SAC_BIT_13 0x0004 -#define ILSW_3_SAC_BIT_14 0x0002 -#define ILSW_3_SAC_BIT_15 0x0001 - -#define ILSW_4_1134_TAPE 0x8000 -#define ILSW_4_1055_TAPE 0x8000 -#define ILSW_4_CONSOLE 0x4000 -#define ILSW_4_1442_CARD 0x2000 -#define ILSW_4_2501_CARD 0x1000 -#define ILSW_4_1403_PRINTER 0x0800 -#define ILSW_4_1231_MARK 0x0400 -#define ILSW_4_SAC_BIT_06 0x0200 -#define ILSW_4_SAC_BIT_07 0x0100 -#define ILSW_4_SAC_BIT_08 0x0080 -#define ILSW_4_SAC_BIT_09 0x0040 -#define ILSW_4_SAC_BIT_10 0x0020 -#define ILSW_4_SAC_BIT_11 0x0010 -#define ILSW_4_SAC_BIT_12 0x0008 -#define ILSW_4_SAC_BIT_13 0x0004 -#define ILSW_4_SAC_BIT_14 0x0002 -#define ILSW_4_SAC_BIT_15 0x0001 - -#define ILSW_5_INT_RUN 0x8000 -#define ILSW_5_PROGRAM_STOP 0x8000 -#define ILSW_5_SAC_BIT_01 0x4000 -#define ILSW_5_SAC_BIT_02 0x2000 -#define ILSW_5_SAC_BIT_03 0x1000 -#define ILSW_5_SAC_BIT_04 0x0800 -#define ILSW_5_SAC_BIT_05 0x0400 -#define ILSW_5_SAC_BIT_06 0x0200 -#define ILSW_5_SAC_BIT_07 0x0100 -#define ILSW_5_SAC_BIT_08 0x0080 -#define ILSW_5_SAC_BIT_09 0x0040 -#define ILSW_5_SAC_BIT_10 0x0020 -#define ILSW_5_SAC_BIT_11 0x0010 -#define ILSW_5_SAC_BIT_12 0x0008 -#define ILSW_5_SAC_BIT_13 0x0004 -#define ILSW_5_SAC_BIT_14 0x0002 -#define ILSW_5_SAC_BIT_15 0x0001 - -//* CPU DSW bits - -#define CPU_DSW_PROGRAM_STOP 0x8000 -#define CPU_DSW_INT_RUN 0x4000 - -/* prototypes: xio handlers */ - -void xio_1131_console (int32 addr, int32 func, int32 modify); // console keyboard and printer -void xio_1142_card (int32 addr, int32 func, int32 modify); // standard card reader/punch -void xio_1134_papertape (int32 addr, int32 func, int32 modify); // paper tape reader/punch -void xio_disk (int32 addr, int32 func, int32 modify, int drv); // internal CPU disk -void xio_1627_plotter (int32 addr, int32 func, int32 modify); // XY plotter -void xio_1132_printer (int32 addr, int32 func, int32 modify); // standard line printer -void xio_1131_switches (int32 addr, int32 func, int32 modify); // console buttons & switches -void xio_1231_optical (int32 addr, int32 func, int32 modify); // optical mark page reader -void xio_2501_card (int32 addr, int32 func, int32 modify); // alternate high-speed card reader -void xio_1131_synch (int32 addr, int32 func, int32 modify); // synchronous communications adapter -void xio_system7 (int32 addr, int32 func, int32 modify); // system/7 interprocessor IO link -void xio_1403_printer (int32 addr, int32 func, int32 modify); // alternate high-speed printer -void xio_2250_display (int32 addr, int32 func, int32 modify); // vector display processor -void xio_error (char *msg); - -void bail (char *msg); -t_stat load_cr_boot (int drv, int switches); -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 */ -char *upcase(char *str); -void break_simulation (t_stat reason); /* let a device halt the simulation */ -char hollerith_to_ascii (uint16 hol); /* for debugging use only */ -t_bool gdu_active (void); -void remark_cmd (char *remark); -void stuff_cmd (char *cmd); -void update_gui (t_bool force); -void sim_init (void); -t_stat register_cmd (char *name, t_stat (*action)(int32 flag, char *ptr), int arg, char *help); - -/* GUI interface routines */ -t_bool keyboard_is_busy (void); -void forms_check (int set); /* device notification to console lamp display */ -void print_check (int set); -void keyboard_selected (int select); -void disk_ready (int ready); -void disk_unlocked (int unlocked); -void gui_run(int running); -char *read_cmdline (char *ptr, int size, FILE *stream); - -#ifdef GUI_SUPPORT -# define GUI_BEGIN_CRITICAL_SECTION begin_critical_section(); -# define GUI_END_CRITICAL_SECTION end_critical_section(); - void begin_critical_section (void); - void end_critical_section (void); -#else -# define GUI_BEGIN_CRITICAL_SECTION -# define GUI_END_CRITICAL_SECTION -#endif diff --git a/Ibm1130/ibm1130_disk.c b/Ibm1130/ibm1130_disk.c deleted file mode 100644 index 756b2e5a..00000000 --- a/Ibm1130/ibm1130_disk.c +++ /dev/null @@ -1,875 +0,0 @@ -/* ibm1130_disk.c: IBM 1130 disk IO simulator - -NOTE - there is a problem with this code. The Device Status Word (DSW) is -computed from current conditions when requested by an XIO load status -command; the value of DSW available to the simulator's examine & save -commands may NOT be accurate. This should probably be fixed. - - Based on the SIMH package written by Robert M Supnik - - * (C) Copyright 2002, Brian Knittel. - * You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN - * RISK basis, there is no warranty of fitness for any purpose, and the rest of the - * usual yada-yada. Please keep this notice and the copyright in any distributions - * or modifications. - * - * Revision History - * 15-jun-03 moved actual read on XIO read to end of time interval, - * as the APL boot card required 2 instructions to run between the - * time read was initiated and the time the data was read (a jump and a wait) - * - * 01-sep-02 corrected treatment of -m and -r flags in dsk_attach - * in cgi mode, so that file is opened readonly but emulated - * disk is writable. - * - * This is not a supported product, but I welcome bug reports and fixes. - * Mail to simh@ibm1130.org - */ - -#include "ibm1130_defs.h" -#include "memory.h" - -#define TRACE_DMS_IO // define to enable debug of DMS phase IO - -#ifdef TRACE_DMS_IO -extern int32 sim_switches; -extern int32 sim_quiet; -static int trace_dms = 0; -static void tracesector (int iswrite, int nwords, int addr, int sector); -static t_stat where_cmd (int flag, char *ptr); -static t_stat phdebug_cmd (int flag, char *ptr); -static t_stat fdump_cmd (int flags, char *cptr); -static void enable_dms_tracing (int newsetting); -#endif - -/* Constants */ - -#define DSK_NUMWD 321 /* words/sector */ -#define DSK_NUMSC 4 /* sectors/surface */ -#define DSK_NUMSF 2 /* surfaces/cylinder */ -#define DSK_NUMCY 203 /* cylinders/drive */ -#define DSK_NUMTR (DSK_NUMCY * DSK_NUMSF) /* tracks/drive */ -#define DSK_NUMDR 5 /* drives/controller */ -#define DSK_SIZE (DSK_NUMCY * DSK_NUMSF * DSK_NUMSC * DSK_NUMWD) /* words/drive */ - -#define UNIT_V_RONLY (UNIT_V_UF + 0) /* hwre write lock */ -#define UNIT_V_OPERR (UNIT_V_UF + 1) /* operation error flag */ -#define UNIT_V_HARDERR (UNIT_V_UF + 2) /* hard error flag (reset on power down) */ -#define UNIT_RONLY (1u << UNIT_V_RONLY) -#define UNIT_OPERR (1u << UNIT_V_OPERR) -#define UNIT_HARDERR (1u << UNIT_V_HARDERR) - -#define MEM_MAPPED(uptr) (uptr->flags & UNIT_BUF) /* disk buffered in memory */ - -#define IO_NONE 0 /* last operation, used to ensure fseek between read and write */ -#define IO_READ 1 -#define IO_WRITE 2 - -#define DSK_DSW_DATA_ERROR 0x8000 /* device status word bits */ -#define DSK_DSW_OP_COMPLETE 0x4000 -#define DSK_DSW_NOT_READY 0x2000 -#define DSK_DSW_DISK_BUSY 0x1000 -#define DSK_DSW_CARRIAGE_HOME 0x0800 -#define DSK_DSW_SECTOR_MASK 0x0003 - - /* device status words */ -static int16 dsk_dsw[DSK_NUMDR] = {DSK_DSW_NOT_READY, DSK_DSW_NOT_READY, DSK_DSW_NOT_READY, DSK_DSW_NOT_READY, DSK_DSW_NOT_READY}; -static int16 dsk_sec[DSK_NUMDR] = {0}; /* next-sector-up */ -static char dsk_lastio[DSK_NUMDR]; /* last stdio operation: IO_READ or IO_WRITE */ -int32 dsk_swait = 50; /* seek time -- see how short a delay we can get away with */ -int32 dsk_rwait = 50; /* rotate time */ -static t_bool raw_disk_debug = FALSE; - -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, DEVICE *dptr); - -static void diskfail (UNIT *uptr, int errflag); - -/* DSK data structures - - dsk_dev disk device descriptor - dsk_unit unit descriptor - dsk_reg register list -*/ - -UNIT dsk_unit[] = { - { UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, DSK_SIZE) }, - { UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, DSK_SIZE) }, - { UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, DSK_SIZE) }, - { UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, DSK_SIZE) }, - { UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, DSK_SIZE) } -}; - -#define IS_ONLINE(u) (((u)->flags & (UNIT_ATT|UNIT_DIS)) == UNIT_ATT) - -/* Parameters in the unit descriptor */ - -#define CYL u3 /* current cylinder */ -#define FUNC u4 /* current function */ - -REG dsk_reg[] = { - { HRDATA (DSKDSW0, dsk_dsw[0], 16) }, - { HRDATA (DSKDSW1, dsk_dsw[1], 16) }, - { HRDATA (DSKDSW2, dsk_dsw[2], 16) }, - { HRDATA (DSKDSW3, dsk_dsw[3], 16) }, - { HRDATA (DSKDSW4, dsk_dsw[4], 16) }, - { DRDATA (STIME, dsk_swait, 24), PV_LEFT }, - { DRDATA (RTIME, dsk_rwait, 24), PV_LEFT }, - { NULL } }; - -MTAB dsk_mod[] = { - { UNIT_RONLY, 0, "write enabled", "ENABLED", NULL }, - { UNIT_RONLY, UNIT_RONLY, "write locked", "LOCKED", NULL }, - { 0 } }; - -DEVICE dsk_dev = { - "DSK", dsk_unit, dsk_reg, dsk_mod, - DSK_NUMDR, 16, 16, 1, 16, 16, - NULL, NULL, &dsk_reset, - dsk_boot, dsk_attach, dsk_detach}; - -static int32 dsk_ilswbit[DSK_NUMDR] = { /* interrupt level status word bits for the drives */ - ILSW_2_1131_DISK, - ILSW_2_2310_DRV_1, - ILSW_2_2310_DRV_2, - ILSW_2_2310_DRV_3, - ILSW_2_2310_DRV_4, -}; - -static int32 dsk_ilswlevel[DSK_NUMDR] = -{ - 2, /* interrupt levels for the drives */ - 2, 2, 2, 2 -}; - -typedef enum {DSK_FUNC_IDLE, DSK_FUNC_READ, DSK_FUNC_VERIFY, DSK_FUNC_WRITE, DSK_FUNC_SEEK, DSK_FUNC_FAILED} DSK_FUNC; - -static struct tag_dsk_action { /* stores data needed for pending IO activity */ - int32 io_address; - uint32 io_filepos; - int io_nwords; - int io_sector; -} dsk_action[DSK_NUMDR]; - -/* xio_disk - XIO command interpreter for the disk drives */ -/* - * device status word: - * - * 0 data error, occurs when: - * 1. A modulo 4 error is detected during a read, read-check, or write operation. - * 2. The disk storage is in a read or write mode at the leading edge of a sector pulse. - * 3. A seek-incomplete signal is received from the 2311. - * 4. A write select error has occurred in the disk storage drive. - * 5. The power unsafe latch is set in the attachment. - * Conditions 1, 2, and 3 are turned off by a sense device command with modifier bit 15 - * set to 1. Conditions 4 and 5 are turned off by powering the drive off and back on. - * 1 operation complete - * 2 not ready, occurs when disk not ready or busy or disabled or off-line or - * power unsafe latch set. Also included in the disk not ready is the write select error, - * which can be a result of power unsafe or write select. - * 3 disk busy - * 4 carriage home (on cyl 0) - * 15-16: number of next sector spinning into position. - */ - -extern void void_backtrace (int afrom, int ato); - -void xio_disk (int32 iocc_addr, int32 func, int32 modify, int drv) -{ - int i, rev, nsteps, newcyl, sec, nwords; - uint32 newpos; // changed from t_addr to uint32 in anticipation of simh 64-bit development - char msg[80]; - UNIT *uptr = dsk_unit+drv; - int16 buf[DSK_NUMWD]; - - if (! BETWEEN(drv, 0, DSK_NUMDR-1)) { // hmmm, invalid drive */ - if (func != XIO_SENSE_DEV) { // tried to use it, too - // just do nothing, as if the controller isn't there. NAMCRA at N0116300 tests for drives by attempting reads -// sprintf(msg, "Op %x on invalid drive number %d", func, drv); -// xio_error(msg); - } - return; - } - - CLRBIT(uptr->flags, UNIT_OPERR); /* clear pending error flag from previous op, if any */ - - switch (func) { - case XIO_INITR: - if (! IS_ONLINE(uptr)) { /* disk is offline */ - diskfail(uptr, UNIT_HARDERR); /* make error stick till reset or attach */ - break; - } - - sim_cancel(uptr); /* cancel any pending ops */ - dsk_dsw[drv] |= DSK_DSW_DISK_BUSY; /* and mark the disk as busy */ - - nwords = M[iocc_addr++ & mem_mask]; /* get word count w/o upsetting SAR/SBR */ - - if (nwords == 0) /* this is bad -- on real 1130, this locks up disk controller ! */ - break; - - if (! BETWEEN(nwords, 1, DSK_NUMWD)) { /* count bad */ - SETBIT(uptr->flags, UNIT_OPERR); /* set data error DSW bit when op complete */ - nwords = DSK_NUMWD; /* limit xfer to proper sector size */ - } - - sec = modify & 0x07; /* get sector on cylinder */ - - if ((modify & 0x0080) == 0) { /* it's a real read if it's not a read check */ - // ah. We have a problem. The APL boot card counts on there being time for at least one - // more instruction to execute between the XIO read and the time the data starts loading - // into core. So, we have to defer the actual read operation a bit. Might as well wait - // until it's time to issue the operation complete interrupt. This means saving the - // IO information, then performing the actual read in dsk_svc. - - newpos = (uptr->CYL*DSK_NUMSC*DSK_NUMSF + sec)*2*DSK_NUMWD; - - dsk_action[drv].io_address = iocc_addr; - dsk_action[drv].io_nwords = nwords; - dsk_action[drv].io_sector = sec; - dsk_action[drv].io_filepos = newpos; - - uptr->FUNC = DSK_FUNC_READ; - } - else { - trace_io("* DSK%d verify %d.%d (%x)", drv, uptr->CYL, sec, uptr->CYL*8 + sec); - - if (raw_disk_debug) - printf("* DSK%d verify %d.%d (%x)", drv, uptr->CYL, sec, uptr->CYL*8 + sec); - - uptr->FUNC = DSK_FUNC_VERIFY; - } - - sim_activate(uptr, dsk_rwait); - break; - - case XIO_INITW: - if (! IS_ONLINE(uptr)) { /* disk is offline */ - diskfail(uptr, UNIT_HARDERR); /* make error stick till reset or attach */ - break; - } - - if (uptr->flags & UNIT_RONLY) { /* oops, write to RO disk? permanent error */ - diskfail(uptr, UNIT_HARDERR); - break; - } - - sim_cancel(uptr); /* cancel any pending ops */ - dsk_dsw[drv] |= DSK_DSW_DISK_BUSY; /* and mark drive as busy */ - - nwords = M[iocc_addr++ & mem_mask]; /* get word count w/o upsetting SAR/SBR */ - - if (nwords == 0) /* this is bad -- locks up disk controller ! */ - break; - - if (! BETWEEN(nwords, 1, DSK_NUMWD)) { /* count bad */ - SETBIT(uptr->flags, UNIT_OPERR); /* set data error DSW bit when op complete */ - nwords = DSK_NUMWD; /* limit xfer to proper sector size */ - } - - sec = modify & 0x07; /* get sector on cylinder */ - newpos = (uptr->CYL*DSK_NUMSC*DSK_NUMSF + sec)*2*DSK_NUMWD; - - trace_io("* DSK%d wrote %d words from M[%04x-%04x] to %d.%d (%x, %x)", drv, nwords, iocc_addr & mem_mask, (iocc_addr + nwords - 1) & mem_mask, uptr->CYL, sec, uptr->CYL*8 + sec, newpos); - - if (raw_disk_debug) - printf("* DSK%d XIO @ %04x wrote %d words from M[%04x-%04x] to %d.%d (%x, %x)\n", drv, prev_IAR, nwords, iocc_addr & mem_mask, (iocc_addr + nwords - 1) & mem_mask, uptr->CYL, sec, uptr->CYL*8 + sec, newpos); - -#ifdef TRACE_DMS_IO - if (trace_dms) - tracesector(1, nwords, iocc_addr & mem_mask, uptr->CYL*8 + sec); -#endif - for (i = 0; i < nwords; i++) - buf[i] = M[iocc_addr++ & mem_mask]; - - for (; i < DSK_NUMWD; i++) /* rest of sector gets zeroed */ - buf[i] = 0; - - i = uptr->CYL*8 + sec; - if (buf[0] != i) - printf("*DSK writing bad sector#\n"); - - if (MEM_MAPPED(uptr)) { - memcpy((char *) uptr->filebuf + newpos, buf, 2*DSK_NUMWD); - uptr->hwmark = newpos + 2*DSK_NUMWD; - } - else { - if (uptr->pos != newpos || dsk_lastio[drv] != IO_WRITE) { - fseek(uptr->fileref, newpos, SEEK_SET); - dsk_lastio[drv] = IO_WRITE; - } - - fxwrite(buf, 2, DSK_NUMWD, uptr->fileref); - uptr->pos = newpos + 2*DSK_NUMWD; - } - - uptr->FUNC = DSK_FUNC_WRITE; - sim_activate(uptr, dsk_rwait); - break; - - case XIO_CONTROL: /* step fwd/rev */ - if (! IS_ONLINE(uptr)) { - diskfail(uptr, UNIT_HARDERR); - break; - } - - sim_cancel(uptr); - - rev = modify & 4; - nsteps = iocc_addr & 0x00FF; - if (nsteps == 0) /* 0 steps does not cause op complete interrupt */ - break; - - newcyl = uptr->CYL + (rev ? (-nsteps) : nsteps); - if (newcyl < 0) - newcyl = 0; - else if (newcyl >= DSK_NUMCY) - newcyl = DSK_NUMCY-1; - - uptr->FUNC = DSK_FUNC_SEEK; - uptr->CYL = newcyl; - sim_activate(uptr, dsk_swait); /* schedule interrupt */ - - dsk_dsw[drv] |= DSK_DSW_DISK_BUSY; - trace_io("* DSK%d at cyl %d", drv, newcyl); - break; - - case XIO_SENSE_DEV: - CLRBIT(dsk_dsw[drv], DSK_DSW_CARRIAGE_HOME|DSK_DSW_NOT_READY); - - if ((uptr->flags & UNIT_HARDERR) || (dsk_dsw[drv] & DSK_DSW_DISK_BUSY) || ! IS_ONLINE(uptr)) - SETBIT(dsk_dsw[drv], DSK_DSW_NOT_READY); - else if (uptr->CYL <= 0) { - SETBIT(dsk_dsw[drv], DSK_DSW_CARRIAGE_HOME); - uptr->CYL = 0; - } - - dsk_sec[drv] = (dsk_sec[drv] + 1) % 4; /* advance the "next sector" count every time */ - ACC = dsk_dsw[drv] | dsk_sec[drv]; - - if (modify & 0x01) { /* reset interrupts */ - CLRBIT(dsk_dsw[drv], DSK_DSW_OP_COMPLETE|DSK_DSW_DATA_ERROR); - CLRBIT(ILSW[dsk_ilswlevel[drv]], dsk_ilswbit[drv]); - } - break; - - default: - sprintf(msg, "Invalid disk XIO function %x", func); - xio_error(msg); - } -} - -/* diskfail - schedule an operation complete that sets the error bit */ - -static void diskfail (UNIT *uptr, int errflag) -{ - sim_cancel(uptr); /* cancel any pending ops */ - SETBIT(uptr->flags, errflag); /* set the error flag */ - uptr->FUNC = DSK_FUNC_FAILED; /* tell svc routine why it failed */ - sim_activate(uptr, 1); /* schedule an immediate op complete interrupt */ -} - -t_stat dsk_svc (UNIT *uptr) -{ - int drv = uptr - dsk_unit, i, nwords, sec; - int16 buf[DSK_NUMWD]; - uint32 newpos; // changed from t_addr to uint32 in anticipation of simh 64-bit development - int32 iocc_addr; - - if (uptr->FUNC == DSK_FUNC_IDLE) /* service function called with no activity? not good, but ignore */ - return SCPE_OK; - - CLRBIT(dsk_dsw[drv], DSK_DSW_DISK_BUSY); /* activate operation complete interrupt */ - SETBIT(dsk_dsw[drv], DSK_DSW_OP_COMPLETE); - - if (uptr->flags & (UNIT_OPERR|UNIT_HARDERR)) { /* word count error or data error */ - SETBIT(dsk_dsw[drv], DSK_DSW_DATA_ERROR); - CLRBIT(uptr->flags, UNIT_OPERR); /* soft error is one time occurrence; don't clear hard error */ - } - /* schedule interrupt */ - SETBIT(ILSW[dsk_ilswlevel[drv]], dsk_ilswbit[drv]); - - switch (uptr->FUNC) { /* take care of business */ - case DSK_FUNC_IDLE: - case DSK_FUNC_VERIFY: - case DSK_FUNC_WRITE: - case DSK_FUNC_SEEK: - case DSK_FUNC_FAILED: - break; - - case DSK_FUNC_READ: /* actually read the data into core */ - iocc_addr = dsk_action[drv].io_address; /* recover saved parameters */ - nwords = dsk_action[drv].io_nwords; - newpos = dsk_action[drv].io_filepos; - sec = dsk_action[drv].io_sector; - - if (MEM_MAPPED(uptr)) { - memcpy(buf, (char *) uptr->filebuf + newpos, 2*DSK_NUMWD); - } - else { - if (uptr->pos != newpos || dsk_lastio[drv] != IO_READ) { - fseek(uptr->fileref, newpos, SEEK_SET); - dsk_lastio[drv] = IO_READ; - uptr->pos = newpos; - } - fxread(buf, 2, DSK_NUMWD, uptr->fileref); // read whole sector so we're in position for next read - uptr->pos = newpos + 2*DSK_NUMWD; - } - - void_backtrace(iocc_addr, iocc_addr + nwords - 1); // mark prev instruction as altered - - trace_io("* DSK%d read %d words from %d.%d (%x, %x) to M[%04x-%04x]", drv, nwords, uptr->CYL, sec, uptr->CYL*8 + sec, newpos, iocc_addr & mem_mask, - (iocc_addr + nwords - 1) & mem_mask); - -// // this will help debug the monitor by letting me watch phase loading - if (raw_disk_debug) - printf("* DSK%d XIO @ %04x read %d words from %d.%d (%x, %x) to M[%04x-%04x]\n", drv, prev_IAR, nwords, uptr->CYL, sec, uptr->CYL*8 + sec, newpos, iocc_addr & mem_mask, - (iocc_addr + nwords - 1) & mem_mask); - - i = uptr->CYL*8 + sec; - if (buf[0] != i) - printf("*DSK read bad sector #\n"); - - for (i = 0; i < nwords; i++) - M[(iocc_addr+i) & mem_mask] = buf[i]; - -#ifdef TRACE_DMS_IO - if (trace_dms) - tracesector(0, nwords, iocc_addr & mem_mask, uptr->CYL*8 + sec); -#endif - break; - - default: - fprintf(stderr, "Unexpected FUNC %x in dsk_svc(%d)\n", uptr->FUNC, drv); - break; - - } - - uptr->FUNC = DSK_FUNC_IDLE; // we're done with this operation - - return SCPE_OK; -} - -t_stat dsk_reset (DEVICE *dptr) -{ - int drv; - UNIT *uptr; - -#ifdef TRACE_DMS_IO - // add the WHERE command. It finds the phase that was loaded at given address and indicates - // the offset in the phase - register_cmd("WHERE", &where_cmd, 0, "w{here} address find phase and offset of an address\n"); - register_cmd("PHDEBUG", &phdebug_cmd, 0, "ph{debug} off|phlo phhi break on phase load\n"); - register_cmd("FDUMP", &fdump_cmd, 0, NULL); -#endif - - for (drv = 0, uptr = dsk_dev.units; drv < DSK_NUMDR; drv++, uptr++) { - sim_cancel(uptr); - - CLRBIT(ILSW[2], dsk_ilswbit[drv]); - CLRBIT(uptr->flags, UNIT_OPERR|UNIT_HARDERR); - - uptr->CYL = 0; - uptr->FUNC = DSK_FUNC_IDLE; - dsk_dsw[drv] = (uptr->flags & UNIT_ATT) ? DSK_DSW_CARRIAGE_HOME : 0; - } - - calc_ints(); - - return SCPE_OK; -} - -static t_stat dsk_attach (UNIT *uptr, char *cptr) -{ - int drv = uptr - dsk_unit; - t_stat rval; - - sim_cancel(uptr); // cancel current IO - dsk_lastio[drv] = IO_NONE; - - if (uptr->flags & UNIT_ATT) // dismount current disk - if ((rval = dsk_detach(uptr)) != SCPE_OK) - return rval; - - uptr->CYL = 0; // reset the device - uptr->FUNC = DSK_FUNC_IDLE; - dsk_dsw[drv] = DSK_DSW_CARRIAGE_HOME; - - CLRBIT(uptr->flags, UNIT_RO|UNIT_ROABLE|UNIT_BUFABLE|UNIT_BUF|UNIT_RONLY|UNIT_OPERR|UNIT_HARDERR); - CLRBIT(ILSW[2], dsk_ilswbit[drv]); - calc_ints(); - - if (sim_switches & SWMASK('M')) // if memory mode (e.g. for CGI), buffer the file - SETBIT(uptr->flags, UNIT_BUFABLE); - - if (sim_switches & SWMASK('R')) // read lock mode - SETBIT(uptr->flags, UNIT_RO|UNIT_ROABLE|UNIT_RONLY); - - if (cgi && (sim_switches & SWMASK('M'))) { // if cgi and memory mode, - sim_switches |= SWMASK('R'); // have attach_unit open file in readonly mode - SETBIT(uptr->flags, UNIT_ROABLE|UNIT_MUSTBUF); // but don't set the UNIT_RONLY flag so DMS can write to the buffered image - } - - if ((rval = attach_unit(uptr, cptr)) != SCPE_OK) { // mount new disk - SETBIT(dsk_dsw[drv], DSK_DSW_NOT_READY); - return rval; - } - - if (drv == 0) { - disk_ready(TRUE); - disk_unlocked(FALSE); - } - - enable_dms_tracing(sim_switches & SWMASK('D')); - raw_disk_debug = sim_switches & SWMASK('G'); - - return SCPE_OK; -} - -static t_stat dsk_detach (UNIT *uptr) -{ - t_stat rval; - int drv = uptr - dsk_unit; - - sim_cancel(uptr); - - if ((rval = detach_unit (uptr)) != SCPE_OK) - return rval; - - CLRBIT(ILSW[2], dsk_ilswbit[drv]); - CLRBIT(uptr->flags, UNIT_OPERR|UNIT_HARDERR); - calc_ints(); - - uptr->CYL = 0; - uptr->FUNC = DSK_FUNC_IDLE; - dsk_dsw[drv] = DSK_DSW_NOT_READY; - - if (drv == 0) { - disk_unlocked(TRUE); - disk_ready(FALSE); - } - - return SCPE_OK; -} - -// boot routine - if they type BOOT DSK, load the standard boot card. - -static t_stat dsk_boot (int unitno, DEVICE *dptr) -{ - t_stat rval; - - if ((rval = reset_all(0)) != SCPE_OK) - return rval; - - return load_cr_boot(unitno, sim_switches); -} - -#ifdef TRACE_DMS_IO - -static struct { - int phid; - char *name; -} phase[] = { -# include "dmsr2v12phases.h" - 0xFFFF, "" -}; - -#pragma pack(2) -#define MAXSLET ((3*320)/4) -struct tag_slet { - int16 phid; - int16 addr; - int16 nwords; - int16 sector; -} slet[MAXSLET] = { -# include "dmsr2v12slet.h" // without RPG, use this info until overwritten by actual data from disk -}; - -#pragma pack() - -#define MAXMSEG 100 -struct tag_mseg { - char *name; - int addr, offset, len, phid; -} mseg[MAXMSEG]; -int nseg = 0; - -static void enable_dms_tracing (int newsetting) -{ - nseg = 0; // clear the segment map - - if ((newsetting && trace_dms) || ! (newsetting || trace_dms)) - return; - - trace_dms = newsetting; - if (! sim_quiet) - printf("DMS disk tracing is now %sabled\n", trace_dms ? "en" : "dis"); -} - -char * saywhere (int addr) -{ - int i; - static char buf[150]; - - for (i = 0; i < nseg; i++) { - if (addr >= mseg[i].addr && addr < (mseg[i].addr+mseg[i].len)) { - sprintf(buf, "/%04x = /%04x + /%x in ", addr, mseg[i].addr - mseg[i].offset, addr-mseg[i].addr + mseg[i].offset); - if (mseg[i].phid > 0) - sprintf(buf+strlen(buf), "phase %02x (%s)", mseg[i].phid, mseg[i].name); - else - sprintf(buf+strlen(buf), "%s", mseg[i].name); - - return buf; - } - } - return NULL; -} - -static int phdebug_lo = -1, phdebug_hi = -1; - -static t_stat phdebug_cmd (int flag, char *ptr) -{ - int val1, val2; - - if (strcmpi(ptr, "off") == 0) - phdebug_lo = phdebug_hi = -1; - else { - switch(sscanf(ptr, "%x%x", &val1, &val2)) { - case 1: - phdebug_lo = phdebug_hi = val1; - enable_dms_tracing(TRUE); - break; - - case 2: - phdebug_lo = val1; - phdebug_hi = val2; - enable_dms_tracing(TRUE); - break; - - default: - printf("Usage: phdebug off | phdebug phfrom [phto]\n"); - break; - } - } - return SCPE_OK; -} - -static t_stat where_cmd (int flag, char *ptr) -{ - int addr; - char *where; - - if (! trace_dms) { - printf("Tracing is disabled. To enable, attach disk with -d switch\n"); - return SCPE_OK; - } - - if (sscanf(ptr, "%x", &addr) != 1) - return SCPE_ARG; - - if ((where = saywhere(addr)) == NULL) - printf("/%04x not found\n", addr); - else - printf("%s\n", where); - - return SCPE_OK; -} - -// savesector - save info on a sector just read. THIS IS NOT YET TESTED - -static void addseg (int i) -{ - if (! trace_dms) - return; - - if (nseg >= MAXMSEG) { - printf("(Memory map full, disabling tracing)\n"); - trace_dms = 0; - nseg = -1; - return; - } - memcpy(mseg+i+1, mseg+i, (nseg-i)*sizeof(mseg[0])); - nseg++; -} - -static void delseg (int i) -{ - if (! trace_dms) - return; - - if (nseg > 0) { - nseg--; - memcpy(mseg+i, mseg+i+1, (nseg-i)*sizeof(mseg[0])); - } -} - -static void savesector (int addr, int offset, int len, int phid, char *name) -{ - int i; - - if (! trace_dms) - return; - - addr++; // first word is sector address, so account for that - len--; - - for (i = 0; i < nseg; i++) { - if (addr >= (mseg[i].addr+mseg[i].len)) // entirely after this entry - continue; - - if (mseg[i].addr < addr) { // old one starts before this. split it - addseg(i); - mseg[i].len = addr-mseg[i].addr; - i++; - mseg[i].addr = addr; - mseg[i].len -= mseg[i-1].len; - } - - break; - } - - addseg(i); // add new segment. Old one ends up after this - - if (i >= MAXMSEG) - return; - - mseg[i].addr = addr; - mseg[i].offset = offset; - mseg[i].phid = phid; - mseg[i].len = len; - mseg[i].name = name; - - i++; // delete any segments completely covered - - while (i < nseg && (mseg[i].addr+mseg[i].len) <= (addr+len)) - delseg(i); - - if (i < nseg && mseg[i].addr < (addr+len)) { // old one extends past this. Retain the end - mseg[i].len = (mseg[i].addr+mseg[i].len) - (addr+len); - mseg[i].addr = addr+len; - } -} - -static void tracesector (int iswrite, int nwords, int addr, int sector) -{ - int i, phid = 0, sletind = -1, offset = 0; - char *name = NULL; - - if (nwords < 3 || ! trace_dms) - return; - - switch (sector) { // explicitly known sector name - case 0: name = "ID/COLD START"; break; - case 1: name = "DCOM"; break; - case 2: name = "RESIDENT IMAGE"; break; - case 3: - case 4: - case 5: name = "SLET"; // save just-read or written SLET info - memmove(&slet[(320/4)*(sector-3)], &M[addr+1], nwords*2); - break; - case 6: name = "RELOAD TABLE"; break; - case 7: name = "PAGE HEADER"; break; - } - - printf("* %04x: %3d /%04x %c %3d.%d ", - prev_IAR, nwords, addr, iswrite ? '>' : '<', sector/8, sector%8); - - if (name == NULL) { // look up sector in SLET - for (i = 0; i < MAXSLET; i++) { - if (slet[i].phid == 0) // not found - goto done; - else if (slet[i].sector > sector) { - if (--i >= 0) { - if (sector >= slet[i].sector && sector <= (slet[i].sector + slet[i].nwords/320)) { - phid = slet[i].phid; - offset = (sector-slet[i].sector)*320; - break; - } - } - goto done; - } - if (slet[i].sector == sector) { - phid = slet[i].phid; // we found the starting sector - break; - } - } - - if (i >= MAXSLET) // was not found - goto done; - - name = "?"; - for (i = sizeof(phase)/sizeof(phase[0]); --i >= 0; ) { - if (phase[i].phid == phid) { // look up name - name = phase[i].name; - break; - } - } - printf("%02x %s", phid, name); - } - else - printf("%s", name); - -done: - putchar('\n'); - - if (phid >= phdebug_lo && phid <= phdebug_hi && offset == 0) - break_simulation(STOP_PHASE_BREAK); // break on read of first sector of indicated phases - - if (name != NULL && *name != '?' && ! iswrite) - savesector(addr, offset, nwords, phid, name); -} - -static t_stat fdump_cmd (int flags, char *cptr) -{ - int addr = 0x7a24; // address of next statement; - int sofst = 0x7a26, symaddr; - int cword, nwords, stype, has_stnum, strel = 1, laststno = 0; - - addr = M[addr & mem_mask] & mem_mask; // get address of first statement - sofst = M[sofst & mem_mask] & mem_mask; // get address of symbol table - - for (;;) { - cword = M[addr]; - nwords = (cword >> 2) & 0x01FF; - stype = (cword >> 1) & 0x7C00; - has_stnum = (cword & 1); - - if (has_stnum) { - laststno++; - strel = 0; - } - - printf("/%04x [%4d +%3d] %3d - %04x", addr, laststno, strel, nwords, stype); - - if (has_stnum) { - addr++; - nwords--; - symaddr = sofst - (M[addr] & 0x7FF)*3 + 3; - printf(" [%04x %04x %04x]", M[symaddr], M[symaddr+1], M[symaddr+2]); - } - - if (stype == 0x5000) { // error record - printf(" (err %d)", M[addr+1]); - } - - if (stype == 0x0800) - break; - - addr += nwords; - putchar('\n'); - - if (nwords == 0) { - printf("0 words?\n"); - break; - } - strel++; - } - - printf("\nEnd found at /%04x, EOFS = /%04x\n", addr, M[0x7a25 & mem_mask]); - return SCPE_OK; -} - -#endif // TRACE_DMS_IO diff --git a/Ibm1130/ibm1130_fmt.c b/Ibm1130/ibm1130_fmt.c deleted file mode 100644 index faccb046..00000000 --- a/Ibm1130/ibm1130_fmt.c +++ /dev/null @@ -1,303 +0,0 @@ -// ibm1130_fmt.c : interpret tabs in 1130 Assembler or Fortran source -// Bob Flanders -// ------------------------------------------------------------------------------------------- -// -// These routines are used by ibm1130_cr.c when the user has indicated -// that the input text is formatted with tabs. Input lines are edited -// into the appropriate column format. Three edit modes are recognized: -// -// Assembler mode: -// Input lines of the form -// -// [label][opcode][tag][L][argument] -// -// are rearranged so that the input fields are placed in the appropriate columns -// -// The label must start on the first character of the line. If there is no label, -// the first character(s) before the opcode must be whitespace. Following the opcode, there -// MUST be a tab character, followed by the format and tag. Following the format and tag -// may be exactly one whitespace character, and then starts the argument. -// -// Input lines with * in column 1 and blank lines are turned into Assembler comments, -// with the * in the Opcode field. -// -// Assembler directive lines at the beginning of the deck must be preceded by -// ! to indicate that they are not comments. For example, -// -// !*LIST -// * This is a comment -// -// Fortran mode: -// Input lines of the form -// -// [label]statement -// -// or -// -// [label]Xcontinuation -// -// where X is a non alphabetic contination character are rearranged in the -// appropriate manner: -// -// 1 2 -// 12345678901234567890... -// ------------------------ -// label statement -// labelXcontinuation -// -// However, you must take care that you don't end up with statement text after column 72. -// -// Input lines with * or C in column 1 are left alone (comments and directives) -// -// (The ! escape is not used before Fortran directives as before Assembler directives) -// -// Tab mode: -// Tabs are replaced with spaces. Tab settings are assumed to be eight characters wide, -// as is standard for vi, notepad, etc. -// ------------------------------------------------------------------------------------------- - -#include -#include -#include -#include -#include -#include "ibm1130_fmt.h" - -#define MAXLINE 81 // maximum output line size -#define WORKSZ 256 // size for tab work area -#define TAGOFFSET 12 // offset for tag field -#define FMTOFFSET 11 // offset for format field - -#define MIN(a,b) ((a < b) ? a : b) -#define AMSG " with Assembler Reformat" -#define FMSG " with FORTRAN Reformat" -#define AFORMAT "%20.20s%-60.60s"," " -#define ACOMMENTFMT "%20.20s%-60.60s"," " -#define ABLANKLINE "%20.20s*"," " -#define FFORMAT "%-5.5s %-74.74s" -#define FCONTFMT "%-5.5s%-75.75s" - -char gszLabel[6]; // work area for label -char gszArg[MAXLINE]; // .. argument -char gszOutput[MAXLINE]; // .. output -short gaiAsmTabs[] = {7,12,15,20,25,30,35,40,45,52,0};// tab stops for assembler - -short gaiPlainTabs[] = {9, 17, 25, 33, 41, 49, 57, 65, 73, 0};// tab stops for just plain tabs - -// /////////////// -// helper routines - -/////////////////////////////////////////////////// -// ExpandTabs: Expand tabs to spaces - -char* ExpandTabs(char* p_szInbuf, // expand tabs .. input buffer - char* p_szOutbuf, // .. output buffer - short* p_aiTabs) // .. array of tab stops (1 based) -- 0 end of array -{ -short iI, // input position - iO, // output position - iT; // next tab stop - -char cX; // character to test - - iI = 0; // init input position - iO = 0; // init output position - iT = 0; // init tab stop - - while (cX = *(p_szInbuf + iI)) // while there are characters - { - if (cX == '\t') // q. tab character? - { // a. yes .. - while ((p_aiTabs[iT] <= iO + 1) // search for next valid stop .. - && (p_aiTabs[iT] != 0)) // .. or end of table - iT++; // .. go to next tab - - if (p_aiTabs[iT] != 0) // q. end of tab array? - { // a. no .. - while (iO < (p_aiTabs[iT] - 1)) // fill to tab with blanks - *(p_szOutbuf + iO++) = ' '; // .. put in a blank - - } - else // Otherwise ... - *(p_szOutbuf + iO++) = ' '; // .. Translate to blank - } - else // Otherwise .. not tab - *(p_szOutbuf + iO++) = cX; // .. save the input char - - iI++; // next input character - } - - *(p_szOutbuf + iO) = 0; // end the string.. - return p_szOutbuf; // .. return output area addr -} - -///////////////////////////////////// -// extract next token, modify pointer - -char* GetToken(char* p_szOut, // output location - int p_iLen, // max output length - char**p_pszToken) // pointer to input token -{ -int iI; // work integer -char* pszX; // work pointer - - pszX = *p_pszToken; // get pointer to token - - for (iI = 0; *(pszX + iI) && (!isspace(*(pszX + iI)));) // while not whitespace & not end - iI++; // .. count token length - - memset(p_szOut, 0, p_iLen); // zero out output area - - if (iI > 0) // q. any chars? - strncpy(p_szOut, *p_pszToken, MIN(iI, p_iLen-1)); // a. yes.. copy max of p_iLen-1 - - *p_pszToken += iI; // point beyond token - return p_szOut; // .. return token pointer -} - -///////////////////////////////////////////////////////// -// EditToAsm - convert tab-formatted text line to 1130 Assembler format - -char *EditToAsm (char* p_pszEdit) // convert line to 1130 assembler -{ -char pszLine[MAXLINE]; // source line -char pszWork[WORKSZ]; // work buffer -char acTFWrk[2]; // tag/format work area -size_t iI; // work integer - - if (p_pszEdit == NULL) // q. null request? - return AMSG; // a. yes .. return display message - - if (*p_pszEdit == '!') // leave lines starting with ! alone - return EditToWhitespace(p_pszEdit+1); - - if (*p_pszEdit == '*') // q. comment line? - { // a. yes.. - strncpy(pszWork, EditToWhitespace(p_pszEdit), MAXLINE); // .. convert any tabs - sprintf(gszOutput, ACOMMENTFMT, pszWork); // .. put the comment out there in the opcode column - return gszOutput; // .. and return it - } - - strncpy(pszLine, p_pszEdit, MAXLINE-1); // copy the line local - - ExpandTabs(pszLine, pszWork, gaiAsmTabs); // expand the tabs - strncpy(pszLine, pszWork, MAXLINE-1); // copy the line back - - for (iI = strlen(pszLine); iI--;) // trim trailing whitespace - { - if (*(pszLine + iI) <= ' ') // q. space or less? - *(pszLine + iI) = 0; // a. yes .. remove it - else // otherwise - break; // .. done. Leave loop. - } - - if (strlen(pszLine) == 0) // q. blank line? - { // a. yes .. Assembler abhors these so - sprintf(gszOutput, ABLANKLINE); // format as comment statement - return gszOutput; // .. and return it - } - - - // TODO: Add code to process a strip switch - // comment? - - if (strlen(pszLine) > (TAGOFFSET + 1)) // q. line long enough? - { // a. yes.. reorder tag/format - memcpy(acTFWrk, pszLine + FMTOFFSET, 2); // get tag/format - memset((pszLine + FMTOFFSET), ' ', 2); // .. blank 'em out - - for (iI = 0; iI < 2; iI ++) - if (isalpha(acTFWrk[iI])) // q. alpha char? - *(pszLine + FMTOFFSET) = acTFWrk[iI]; // a. yes .. make it format - else if (isdigit(acTFWrk[iI])) // q. digit? - *(pszLine + TAGOFFSET) = acTFWrk[iI]; // a. yes .. make it the tag - } - - sprintf(gszOutput, AFORMAT, pszLine); // format the line - - return gszOutput; // return formatted line -} - -///////////////////////////////////////////////////////// -// EditToFortran - convert tab-formatted input text line to FORTRAN format -// (a la DEC Fortran) - -char *EditToFortran(char* p_pszEdit) // convert line to 1130 assembler -{ -char pszLine[MAXLINE]; // source line -char* pszWork; // work pointer -size_t iI; // work integer -char bContinue; // true if continue - - if (p_pszEdit == NULL) // q. null request? - return FMSG; // a. yes .. return display message - - if (strchr(p_pszEdit, '\t') == NULL) // q. no tab in the line? - return p_pszEdit; // a. nope, return line as is, assume it's formatted correctly - - if (*p_pszEdit == 'C' || *p_pszEdit == '*' || *p_pszEdit == '\0') // q. comment or directive or blank line? - { // a. yes.. don't restructure - return EditToWhitespace(p_pszEdit); - } - - strncpy(pszLine, p_pszEdit, MAXLINE-1); // copy the line local - - for (iI = strlen(pszLine); iI--;) // trim trailing whitespace - { - if (*(pszLine + iI) <= ' ') // q. space or less? - *(pszLine + iI) = 0; // a. yes .. remove it - else // otherwise - break; // .. done. Leave loop. - } - - // TODO: Add code to process a strip switch - // comment? - - pszWork = (char*) pszLine; // set pointer to line - GetToken(gszLabel, 6, &pszWork); // get the line, if any. - - pszWork++; // skip tab/whitespace - - // continuation... - bContinue = ((isdigit(*pszWork) && (*pszWork != '0')) // if first char non-zero digit - || (!isspace(*pszWork) && !isalpha(*pszWork))); // .. or non-alpha non-blank - - memset(gszArg, 0, MAXLINE); // .. and arguments - - strncpy(gszArg, pszWork, 75); // copy rest to argument - - sprintf(gszOutput, (bContinue) ? FCONTFMT : FFORMAT, // format the line - gszLabel, // .. statement # - gszArg); // .. code - - return gszOutput; // return formatted line -} - -///////////////////////////////////////////////////////// -// EditToWhitespace - expand tabs at 8 space intervals. - -char* EditToWhitespace(char *p_pszEdit) -{ -int iI; /* work integer */ -char pszLine[MAXLINE]; // source line -char pszWork[WORKSZ]; // work buffer - - if (p_pszEdit == NULL) // q. null request? - return AMSG; // a. yes .. return display message - - strncpy(pszLine, p_pszEdit, MAXLINE-1); // copy the line local - - ExpandTabs(pszLine, pszWork, gaiPlainTabs); // expand the tabs - strncpy(gszOutput, pszWork, MAXLINE-1); // copy the line back - - for (iI = strlen(gszOutput); iI--;) // look at each character - { - if (*(gszOutput + iI) <= ' ') // q. space or less? - *(gszOutput + iI) = 0; // a. yes .. remove it - else // otherwise - break; // .. done. Leave loop. - } - - - return gszOutput; /* ... return buffer */ -} diff --git a/Ibm1130/ibm1130_fmt.h b/Ibm1130/ibm1130_fmt.h deleted file mode 100644 index 170d1c88..00000000 --- a/Ibm1130/ibm1130_fmt.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - * (C) Copyright 2003, Bob Flander. - * You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN - * RISK basis, there is no warranty of fitness for any purpose, and the rest of the - * usual yada-yada. Please keep this notice and the copyright in any distributions - * or modifications. - * - * This is not a supported product, but I welcome bug reports and fixes. - * Mail to bob@jftr.com - */ - -/* ibm1130_asm.h: definition of routines in ibm1130_asm.c - */ - -char* EditToAsm(char*); // convert edit format to 1130 assembler format -char* EditToFortran(char*); // convert edit format to Fortran format -char* EditToWhitespace(char*); // clean white space, tabstops every 8 positions diff --git a/Ibm1130/ibm1130_gdu.c b/Ibm1130/ibm1130_gdu.c deleted file mode 100644 index a1501609..00000000 --- a/Ibm1130/ibm1130_gdu.c +++ /dev/null @@ -1,1118 +0,0 @@ -#include "ibm1130_defs.h" - -/* ibm1130_gdu.c: IBM 1130 2250 Graphical Display Unit - - (Under construction) -// stuff to fix: -// "store revert" might be backwards? -// alpha keyboard is not implemented -// pushbuttons are not implemented -// there is something about interrupts being deferred during a subroutine transition? - - Based on the SIMH package written by Robert M Supnik - - * (C) Copyright 2002, Brian Knittel. - * You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN - * RISK basis, there is no warranty of fitness for any purpose, and the rest of the - * usual yada-yada. Please keep this notice and the copyright in any distributions - * or modifications. - * - * This is not a supported product, but I welcome bug reports and fixes. - * Mail to simh@ibm1130.org - */ - -#define BLIT_MODE // normally defined, undefine when debugging generate_image() -//#define DEBUG_LIGHTPEN // normally undefined, define to visualize light-pen sensing - -#define DEFAULT_GDU_RATE 20 // default frame rate -#define DEFAULT_PEN_THRESHOLD 3 // default looseness of light-pen hit -#define INDWIDTH 32 // width of an indicator (there are two columns of these) -#define INITSIZE 512 // initial window size - -#define GDU_DSW_ORDER_CONTROLLED_INTERRUPT 0x8000 -#define GDU_DSW_KEYBOARD_INTERUPT 0x4000 -#define GDU_DSW_DETECT_INTERRUPT 0x2000 -#define GDU_DSW_CYCLE_STEAL_CHECK 0x1000 -#define GDU_DSW_DETECT_STATUS 0x0800 -#define GDU_DSW_LIGHT_PEN_SWITCH 0x0100 -#define GDU_DSW_BUSY 0x0080 -#define GDU_DSW_CHARACTER_MODE 0x0040 -#define GDU_DSW_POINT_MODE 0x0020 -#define GDU_DSW_ADDR_DISP 0x0003 - -#define GDU_FKEY_DATA_AVAILABLE 0x8000 -#define GDU_FKEY_KEY_CODE 0x1F00 -#define GDU_FKEY_OVERLAY_CODE 0x00FF - -#define GDU_AKEY_DATA_AVAILABLE 0x8000 -#define GDU_AKEY_END 0x1000 -#define GDU_AKEY_CANCEL 0x0800 -#define GDU_AKEY_ADVANCE 0x0400 -#define GDU_AKEY_BACKSPACE 0x0200 -#define GDU_AKEY_JUMP 0x0100 -#define GDU_AKEY_KEY_CODE 0x00FF - -/* -------------------------------------------------------------------------------------- */ - -#define UNIT_V_DISPLAYED (UNIT_V_UF + 0) -#define UNIT_V_DETECTS_ENABLED (UNIT_V_UF + 1) -#define UNIT_V_INTERRUPTS_DEFERRED (UNIT_V_UF + 2) -#define UNIT_V_LARGE_CHARS (UNIT_V_UF + 3) - -#define UNIT_DISPLAYED (1u << UNIT_V_DISPLAYED) /* display windows is up */ -#define UNIT_DETECTS_ENABLED (1u << UNIT_V_DETECTS_ENABLED) /* light pen detects are enabled */ -#define UNIT_INTERRUPTS_DEFERRED (1u << UNIT_V_INTERRUPTS_DEFERRED) /* light pen interrupts are deferred */ -#define UNIT_LARGE_CHARS (1u << UNIT_V_LARGE_CHARS) /* large character mode */ - -static t_stat gdu_reset (DEVICE *dptr); - -static int16 gdu_dsw = 1; /* device status word */ -static int16 gdu_ar = 0; /* address register */ -static int16 gdu_x = 0; /* X deflection */ -static int16 gdu_y = 0; /* Y deflection */ -static int16 gdu_fkey = 0; /* function keyboard register */ -static int16 gdu_akey = 0; /* alphanumeric keyboard register */ -static int16 gdu_revert = 0; /* revert address register */ -static int32 gdu_indicators = 0; /* programmed indicator lamps */ -static int32 gdu_threshold = DEFAULT_PEN_THRESHOLD; /* mouse must be within 3/1024 of line to be a hit */ -static int32 gdu_rate = DEFAULT_GDU_RATE; /* refresh rate. 0 = default */ - -UNIT gdu_unit = { UDATA (NULL, 0, 0) }; - -REG gdu_reg[] = { - { HRDATA (GDUDSW, gdu_dsw, 16) }, /* device status word */ - { HRDATA (GDUAR, gdu_ar, 16) }, /* address register */ - { HRDATA (GDUXREG, gdu_x, 16) }, /* X deflection register */ - { HRDATA (GDUYREG, gdu_y, 16) }, /* Y deflection register */ - { HRDATA (GDUFKEY, gdu_fkey, 16) }, /* function keyboard register */ - { HRDATA (GDUAKEY, gdu_akey, 16) }, /* alphanumeric keyboard register */ - { HRDATA (GDUREVERT,gdu_revert, 16) }, /* revert address register */ - { HRDATA (GDUAKEY, gdu_indicators, 32) }, /* programmed indicators */ - { DRDATA (GDUTHRESH,gdu_threshold, 32) }, /* mouse closeness threshhold */ - { DRDATA (GDURATE, gdu_rate, 32) }, /* refresh rate in frames/sec */ - { NULL } }; - -DEVICE gdu_dev = { - "GDU", &gdu_unit, gdu_reg, NULL, - 1, 16, 16, 1, 16, 16, - NULL, NULL, gdu_reset, - NULL, NULL, NULL}; - -/* -------------------------------------------------------------------------------------- */ - -#ifndef GUI_SUPPORT - -static t_stat gdu_reset (DEVICE *dptr) -{ - return SCPE_OK; -} - -void xio_2250_display (int32 addr, int32 func, int32 modify) -{ - // ignore commands to nonexistent device -} - -t_bool gdu_active (void) -{ - return 0; -} - -/* -------------------------------------------------------------------------------------- */ -#else // GUI_SUPPORT defined - -/******* PLATFORM INDEPENDENT CODE ********************************************************/ - -static int32 gdu_instaddr; // address of first word of instruction -static int xmouse, ymouse, lpen_dist, lpen_dist2; // current mouse pointer, scaled closeness threshhold, same squared -static double sfactor; // current scaling factor -static t_bool last_abs = TRUE; // last positioning instruction was absolute -static t_bool mouse_present = FALSE; // mouse is/is not in the window - -static void clear_interrupts (void); -static void set_indicators (int32 new_inds); -static void start_regeneration (void); -static void halt_regeneration (void); -static void draw_characters (void); -static void notify_window_closed (void); - -// routines that must be implemented per-platform - -static void DrawLine(int x0, int y0, int x1, int y1); -static void DrawPoint(int x, int y); -static void CheckGDUKeyboard(void); -static t_bool CreateGDUWindow(void); -static void StartGDUUpdates(void); -static void StopGDUUpdates(void); -static void GetMouseCoordinates(void); -static void UpdateGDUIndicators(void); -static void ShowPenHit (int x, int y); -static void EraseGDUScreen (void); - -/* -------------------------------------------------------------------------------------- */ - -void xio_2250_display (int32 addr, int32 func, int32 modify) -{ - switch (func) { - case XIO_SENSE_DEV: - ACC = (gdu_dsw & GDU_DSW_BUSY) ? GDU_DSW_BUSY : gdu_dsw; - if (modify & 1) - clear_interrupts(); - break; - - case XIO_READ: /* store status data into word pointed to by IOCC packet */ - if (gdu_dsw & GDU_DSW_BUSY) /* not permitted while device is busy */ - break; - - WriteW(addr, gdu_ar); /* save status information */ - WriteW(addr+1, gdu_dsw); - WriteW(addr+2, gdu_x & 0x7FF); - WriteW(addr+3, gdu_y & 0x7FF); - WriteW(addr+4, gdu_fkey); - WriteW(addr+5, gdu_akey); - gdu_ar = addr+6; /* this alters the channel address register? */ - - clear_interrupts(); /* read status clears the interrupts */ - break; - - case XIO_WRITE: - if (gdu_dsw & GDU_DSW_BUSY) /* treated as no-op if display is busy */ - break; - - if (modify & 0x80) { /* bit 8 on means set indicators, 0 means start regeneration */ - set_indicators((ReadW(addr) << 16) | ReadW(addr+1)); - } - else { - gdu_ar = addr; - gdu_fkey = 0; - gdu_akey = 0; - clear_interrupts(); - start_regeneration(); - } - break; - - case XIO_CONTROL: - if (modify & 0x80) { /* bit 8 on means reset, off is no-op */ - gdu_reset(&gdu_dev); - set_indicators((addr << 16) | addr); - } - break; - - default: /* all other commands are no-ops */ - break; - } -} - -static t_stat gdu_reset (DEVICE *dptr) -{ - halt_regeneration(); - clear_interrupts(); - set_indicators(0); - gdu_x = gdu_y = 512; - CLRBIT(gdu_unit.flags, UNIT_INTERRUPTS_DEFERRED | UNIT_DETECTS_ENABLED | UNIT_LARGE_CHARS); - gdu_dsw = 1; - return SCPE_OK; -} - -static void clear_interrupts (void) -{ - CLRBIT(gdu_dsw, GDU_DSW_ORDER_CONTROLLED_INTERRUPT | GDU_DSW_KEYBOARD_INTERUPT | GDU_DSW_DETECT_INTERRUPT); - CLRBIT(ILSW[3], ILSW_3_2250_DISPLAY); - calc_ints(); -} - -static void gdu_interrupt (int32 dswbit) -{ - SETBIT(gdu_dsw, dswbit); - SETBIT(ILSW[3], ILSW_3_2250_DISPLAY); - calc_ints(); - halt_regeneration(); -} - -static void set_indicators (int32 new_inds) -{ - gdu_indicators = new_inds; - if (gdu_unit.flags & UNIT_DISPLAYED) - UpdateGDUIndicators(); -} - -static void start_regeneration (void) -{ - SETBIT(gdu_dsw, GDU_DSW_BUSY); - - if (gdu_unit.flags & UNIT_DISPLAYED) { - StartGDUUpdates(); - } - else { - if (! CreateGDUWindow()) - return; - SETBIT(gdu_unit.flags, UNIT_DISPLAYED); - } -} - -static void halt_regeneration (void) -{ - if (gdu_dsw & GDU_DSW_BUSY) { - StopGDUUpdates(); - CLRBIT(gdu_dsw, GDU_DSW_BUSY); - } - EraseGDUScreen(); -} - -static void notify_window_closed (void) -{ - if (gdu_dsw & GDU_DSW_BUSY) { - StopGDUUpdates(); - CLRBIT(gdu_dsw, GDU_DSW_BUSY); - } - CLRBIT(gdu_unit.flags, UNIT_DISPLAYED); - gdu_reset(&gdu_dev); -} - -static int32 read_gduword (void) -{ - int32 w; - - w = M[gdu_ar++ & mem_mask]; - gdu_dsw = (gdu_dsw & ~GDU_DSW_ADDR_DISP) | ((gdu_ar - gdu_instaddr) & GDU_DSW_ADDR_DISP); - - return w; -} - -#define DIST2(x0,y0,x1,y1) (((x1)-(x0))*((x1)-(x0))+((y1)-(y0))*((y1)-(y0))) - -static void draw (int32 newx, int32 newy, t_bool beam) -{ - int xmin, xmax, ymin, ymax, xd, yd; - double s; - int hit = FALSE; - - if (beam) { - if (gdu_dsw & GDU_DSW_POINT_MODE) { - DrawPoint(newx, newy); - -#ifdef DEBUG_LIGHTPEN - if (DIST2(newx, newy, xmouse, ymouse) <= lpen_dist2) - hit = TRUE; -#else - if (gdu_unit.flags & UNIT_DETECTS_ENABLED && mouse_present) - if (DIST2(newx, newy, xmouse, ymouse) <= lpen_dist2) - hit = TRUE; -#endif - } - else { - DrawLine(gdu_x, gdu_y, newx, newy); - - // calculate proximity of light pen to the line -#ifndef DEBUG_LIGHTPEN - if (gdu_unit.flags & UNIT_DETECTS_ENABLED && mouse_present) { -#endif - if (gdu_x <= newx) - xmin = gdu_x, xmax = newx; - else - xmin = newx, xmax = gdu_x; - - if (gdu_y <= newy) - ymin = gdu_y, ymax = newy; - else - ymin = newy, ymax = gdu_y; - - if (newx == gdu_x) { - // line is vertical. Nearest point is an endpoint if the mouse is above or - // below the line segment, otherwise the segment point at the same y as the mouse - xd = gdu_x; - yd = (ymouse <= ymin) ? ymin : (ymouse >= ymax) ? ymax : ymouse; - - if (DIST2(xd, yd, xmouse, ymouse) <= lpen_dist2) - hit = TRUE; - } - else if (newy == gdu_y) { - // line is horizontal. Nearest point is an endpoint if the mouse is to the left or - // the right of the line segment, otherwise the segment point at the same x as the mouse - xd = (xmouse <= xmin) ? xmin : (xmouse >= xmax) ? xmax : xmouse; - yd = gdu_y; - - if (DIST2(xd, yd, xmouse, ymouse) <= lpen_dist2) - hit = TRUE; - } - else { - // line is diagonal. See if the mouse is inside the box lpen_dist wider than the line segment's bounding rectangle - if (xmouse >= (xmin-lpen_dist) && xmouse <= (xmax+lpen_dist) && ymouse >= (ymin-lpen_dist) || ymouse <= (ymax+lpen_dist)) { - // compute the point at the intersection of the line through the line segment and the normal - // to that line through the mouse. This is the point on the line through the line segment - // nearest the mouse - - s = (double)(newy - gdu_y) / (double)(newx - gdu_x); // slope of line segment - xd = (int) ((ymouse + xmouse/s - gdu_y + s*gdu_x) / (s + 1./s) + 0.5); - - // if intersection is beyond either end of the line segment, the nearest point to the - // mouse is nearest segment end, otherwise it's the computed intersection point - if (xd < xmin || xd > xmax) { -#ifdef DEBUG_LIGHTPEN - // if it's a hit, set xd and yd so we can display the hit - if (DIST2(gdu_x, gdu_y, xmouse, ymouse) <= lpen_dist2) { - hit = TRUE; - xd = gdu_x; - yd = gdu_y; - } - else if (DIST2(newx, newy, xmouse, ymouse) <= lpen_dist2) { - hit = TRUE; - xd = newx; - yd = newy; - } -#else - if (DIST2(gdu_x, gdu_y, xmouse, ymouse) <= lpen_dist2 || DIST2(newx, newy, xmouse, ymouse) <= lpen_dist2) - hit = TRUE; -#endif - } - else { - yd = (int) (gdu_y + s*(xd - gdu_x) + 0.5); - if (DIST2(xd, yd, xmouse, ymouse) <= lpen_dist2) - hit = TRUE; - } - } - } -#ifndef DEBUG_LIGHTPEN - } -#endif - } - } - - if (hit) { -#ifdef DEBUG_LIGHTPEN - ShowPenHit(xd, yd); - if (gdu_unit.flags & UNIT_DETECTS_ENABLED && mouse_present) - SETBIT(gdu_dsw, GDU_DSW_DETECT_STATUS); -#else - SETBIT(gdu_dsw, GDU_DSW_DETECT_STATUS); -#endif - } - - gdu_x = newx; - gdu_y = newy; -} - -static void generate_image (void) -{ - int32 instr, new_addr, newx, newy; - t_bool run = TRUE, accept; - - if (! (gdu_dsw & GDU_DSW_BUSY)) - return; - - GetMouseCoordinates(); - - lpen_dist = (int) (gdu_threshold/sfactor + 0.5); // mouse-to-line threshhold at current scaling factor - lpen_dist2 = lpen_dist * lpen_dist; - - while (run) { - if ((gdu_dsw & GDU_DSW_DETECT_STATUS) && ! (gdu_unit.flags & UNIT_INTERRUPTS_DEFERRED)) { - CLRBIT(gdu_dsw, GDU_DSW_DETECT_STATUS); // clear when interrupt is activated - gdu_interrupt(GDU_DSW_DETECT_INTERRUPT); - run = FALSE; - break; - } - - gdu_instaddr = gdu_ar; // remember address of GDU instruction - instr = read_gduword(); // fetch instruction (and we really are cycle stealing here!) - - switch ((instr >> 12) & 0xF) { // decode instruction - case 0: // short branch - case 1: - gdu_revert = gdu_ar; // save revert address & get new address - gdu_ar = read_gduword() & 0x1FFF; - if (gdu_dsw & GDU_DSW_CHARACTER_MODE) { - draw_characters(); // in character mode this means we are at character data - gdu_ar = gdu_revert; - } - break; - - case 2: // long branch/interrupt - new_addr = read_gduword(); // get next word - accept = ((instr & 1) ? (gdu_dsw & GDU_DSW_LIGHT_PEN_SWITCH) : TRUE) && ((instr & 2) ? (gdu_dsw & GDU_DSW_DETECT_STATUS) : TRUE); - - if (instr & 2) // clear after testing - CLRBIT(gdu_dsw, GDU_DSW_DETECT_STATUS); - - if (instr & 0x0400) // NOP - accept = FALSE; - - if (accept) { - if (instr & 0x0800) { // branch - gdu_revert = gdu_ar; - - if (instr & 0x0080) // indirect - new_addr = M[new_addr & mem_mask]; - - gdu_ar = new_addr; - - if (gdu_dsw & GDU_DSW_CHARACTER_MODE) { - draw_characters(); - gdu_ar = gdu_revert; - } - } - else { // interrupt - gdu_interrupt(GDU_DSW_ORDER_CONTROLLED_INTERRUPT); - run = FALSE; - } - } - break; - - case 3: // control instructions - CLRBIT(gdu_dsw, GDU_DSW_CHARACTER_MODE); - - switch ((instr >> 8) & 0xF) { - case 1: // set pen mode - if ((instr & 0xC) == 8) - SETBIT(gdu_unit.flags, UNIT_DETECTS_ENABLED); - else if ((instr & 0xC) == 4) - CLRBIT(gdu_unit.flags, UNIT_DETECTS_ENABLED); - - if ((instr & 0x3) == 2) - SETBIT(gdu_unit.flags, UNIT_INTERRUPTS_DEFERRED); - else if ((instr & 0x3) == 1) - CLRBIT(gdu_unit.flags, UNIT_INTERRUPTS_DEFERRED); - break; - - case 2: // set graphic mode - if (instr & 1) - SETBIT(gdu_dsw, GDU_DSW_POINT_MODE); - else - CLRBIT(gdu_dsw, GDU_DSW_POINT_MODE); - break; - - case 3: // set character mode - SETBIT(gdu_dsw, GDU_DSW_CHARACTER_MODE); - if (instr & 1) - SETBIT(gdu_unit.flags, UNIT_LARGE_CHARS); - else - CLRBIT(gdu_unit.flags, UNIT_LARGE_CHARS); - break; - - case 4: // start timer - run = FALSE; // (which, for us, means stop processing until next timer message) - CheckGDUKeyboard(); - break; - - case 5: // store revert - M[gdu_ar & mem_mask] = gdu_revert; - read_gduword(); // skip to next address - break; - - case 6: // revert - gdu_ar = gdu_revert; - break; - - default: // all others treated as no-ops - break; - } - break; - - case 4: // long absolute - case 5: - CLRBIT(gdu_dsw, GDU_DSW_CHARACTER_MODE); - newx = instr & 0x3FF; - newy = read_gduword() & 0x3FF; - draw(newx, newy, instr & 0x1000); - last_abs = TRUE; - break; - - case 6: // short absolute - case 7: - CLRBIT(gdu_dsw, GDU_DSW_CHARACTER_MODE); - newx = gdu_x; - newy = gdu_y; - if (instr & 0x0800) - newy = instr & 0x3FF; - else - newx = instr & 0x3FF; - draw(newx, newy, instr & 0x1000); - last_abs = TRUE; - break; - - default: // high bit set - it's a relative instruction - CLRBIT(gdu_dsw, GDU_DSW_CHARACTER_MODE); - newx = (instr >> 8) & 0x3F; - newy = instr & 0x3F; - - if (instr & 0x4000) // sign extend x - values are in 2's complement - newx |= -1 & ~0x3F; // although documentation doesn't make that clear - - if (instr & 0x0040) // sign extend y - newy |= -1 & ~0x3F; - - newx = gdu_x + newx; - newy = gdu_y + newy; - draw(newx, newy, instr & 0x0080); - last_abs = FALSE; - break; - } - } -} - -static struct charinfo { // character mode scaling info: - int dx, dy; // character and line spacing - double sx, sy; // scaling factors: character units to screen units - int xoff, yoff; // x and y offset to lower left corner of character - int suby; // subscript/superscript offset -} cx[2] = { - {14, 20, 1.7, 2.0, -6, -7, 6}, // regular - {21, 30, 2.5, 3.0, -9, -11, 9} // large -}; - -static void draw_characters (void) -{ - int32 w, x0, y0, x1, y1, yoff = 0, ninstr = 0; - t_bool dospace, didstroke = FALSE; - struct charinfo *ci; - - ci = &cx[(gdu_unit.flags & UNIT_LARGE_CHARS) ? 1 : 0]; - x0 = gdu_x + ci->xoff; // starting position - y0 = gdu_y + ci->yoff; - - do { - if (++ninstr > 29) { // too many control words - gdu_interrupt(GDU_DSW_CYCLE_STEAL_CHECK); - return; - } - - dospace = TRUE; - w = M[gdu_ar++ & mem_mask]; // get next stroke or control word - - x1 = (w >> 12) & 7; - y1 = (w >> 8) & 7; - - if (x1 == 7) { // this is a character control word - dospace = FALSE; // inhibit character spacing - - switch (y1) { - case 1: // subscript - if (yoff == 0) // (ignored if superscript is in effect) - yoff = -ci->suby; - break; - -// case 2: // no-op or null (nothing to do) -// default: // all unknowns are no-ops -// break; - - case 4: // superscript - yoff = ci->suby; - break; - - case 7: // new line - gdu_x = 0; - gdu_y -= ci->dy; - if (gdu_y < 0 && last_abs) - gdu_y = 1024 - ci->dy; // this is a guess - break; - } - } - else { // this is stroke data -- extract two strokes - x1 = gdu_x + (int) (x1*ci->sx + 0.5); - y1 = gdu_y + (int) ((y1+yoff)*ci->sy + 0.5); - - if (w & 0x0800) { - didstroke = TRUE; - DrawLine(x0, y0, x1, y1); - } - - x0 = (w >> 4) & 7; - y0 = w & 7; - - x0 = gdu_x + (int) (x0*ci->sx + 0.5); - y0 = gdu_y + (int) ((y0+yoff)*ci->sy + 0.5); - - if (w & 0x0008) { - didstroke = TRUE; - DrawLine(x1, y1, x0, y0); - } - } - - if (dospace) { - gdu_x += ci->dx; - if (gdu_x > 1023 && last_abs) { // line wrap - gdu_x = 0; - gdu_y -= ci->dy; - } - } - } while ((w & 0x0080) == 0); // repeat until we hit revert bit - - if (didstroke && mouse_present && (gdu_unit.flags & UNIT_DETECTS_ENABLED)) { - if (xmouse >= (gdu_x - ci->xoff/2) && xmouse <= (gdu_x + ci->xoff/2) && - ymouse >= (gdu_y - ci->yoff/2) && ymouse <= (gdu_y + ci->yoff/2)) - SETBIT(gdu_dsw, GDU_DSW_DETECT_STATUS); - } -} - -/******* PLATFORM SPECIFIC CODE ***********************************************************/ - -#ifdef WIN32 - -#include -#include - -#define APPCLASS "IBM2250GDU" // window class name - -#define RGB_GREEN RGB(0,255,0) // handy colors -#define RGB_RED RGB(255,0,0) - -static HINSTANCE hInstance; -static HWND hwGDU = NULL; -static HDC hdcGDU = NULL; -static HBITMAP hBmp = NULL; -static int curwid = 0; -static int curht = 0; -static BOOL wcInited = FALSE; -static int GDUPumpID = 0; -static HANDLE hGDUPump = INVALID_HANDLE_VALUE; -static HPEN hGreenPen = NULL; -static HBRUSH hRedBrush = NULL; -#ifdef DEBUG_LIGHTPEN -static HPEN hRedPen = NULL; -#endif -static HBRUSH hGrayBrush, hDarkBrush; -static HPEN hBlackPen; - -static LRESULT APIENTRY GDUWndProc (HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam); -static DWORD WINAPI GDUPump (LPVOID arg); - -static void destroy_GDU_window (void) -{ - if (hwGDU != NULL) - SendMessage(hwGDU, WM_CLOSE, 0, 0); // cross thread call is OK - - if (hGDUPump != INVALID_HANDLE_VALUE) { // this is not the most graceful way to do it - TerminateThread(hGDUPump, 0); - hGDUPump = INVALID_HANDLE_VALUE; - GDUPumpID = 0; - hwGDU = NULL; - } - - if (hdcGDU != NULL) { - DeleteDC(hdcGDU); - hdcGDU = NULL; - } - - if (hBmp != NULL) { - DeleteObject(hBmp); - hBmp = NULL; - } - - if (hGreenPen != NULL) { - DeleteObject(hGreenPen); - hGreenPen = NULL; - } - - if (hRedBrush != NULL) { - DeleteObject(hRedBrush); - hRedBrush = NULL; - } - -#ifdef DEBUG_LIGHTPEN - if (hRedPen != NULL) { - DeleteObject(hRedPen); - hRedPen = NULL; - } -#endif -} - -static t_bool CreateGDUWindow (void) -{ - static BOOL did_atexit = FALSE; - - if (hwGDU != NULL) { // window already exists - StartGDUUpdates(); - return TRUE; - } - - hInstance = GetModuleHandle(NULL); - - if (hGDUPump == INVALID_HANDLE_VALUE) - hGDUPump = CreateThread(NULL, 0, GDUPump, 0, 0, &GDUPumpID); - - if (! did_atexit) { - atexit(destroy_GDU_window); - did_atexit = TRUE; - } - - return TRUE; -} - -// windows message handlers ---------------------------------------------------- - -// close the window - -static void gdu_WM_CLOSE (HWND hWnd) -{ - DestroyWindow(hWnd); -} - -// the window is being destroyed - -static void gdu_WM_DESTROY (HWND hWnd) -{ - notify_window_closed(); - hwGDU = NULL; -} - -// adjust the min and max resizing boundaries - -static void gdu_WM_GETMINMAXINFO (HWND hWnd, LPMINMAXINFO mm) -{ - mm->ptMinTrackSize.x = 100 + 2*INDWIDTH; - mm->ptMinTrackSize.y = 100; -} - -static void PaintImage (HDC hDC, BOOL draw_indicators) -{ - HPEN hOldPen; - RECT r; - int wid, ht, x, y, dy, i, j, ycirc; - unsigned long bit; - - GetClientRect(hwGDU, &r); - wid = r.right+1 - 2*INDWIDTH; - ht = r.bottom+1; - sfactor = (double) MIN(wid,ht) / 1024.; - - if (gdu_dsw & GDU_DSW_BUSY) { -#ifdef BLIT_MODE - // if compiled for BLIT_MODE, draw the image into a memory display context, then - // blit the new image over window. This eliminates the flicker that a normal erase-and- - // repaint would cause. - - if (wid != curwid || ht != curht) { // dimensions have changed, discard old memory display context - if (hdcGDU != NULL) { - DeleteDC(hdcGDU); - hdcGDU = NULL; - } - curwid = wid; - curht = ht; - } - - if (hdcGDU == NULL) { // allocate memory display context & select a bitmap into it - hdcGDU = CreateCompatibleDC(hDC); - if (hBmp != NULL) - DeleteObject(hBmp); - hBmp = CreateCompatibleBitmap(hDC, wid, ht); - SelectObject(hdcGDU, hBmp); - } - - PatBlt(hdcGDU, 0, 0, wid, ht, BLACKNESS); // start with a black screen - - hOldPen = SelectObject(hdcGDU, hGreenPen); - - SetMapMode(hdcGDU, MM_ANISOTROPIC); - SetWindowExtEx(hdcGDU, 1024, -1024, NULL); - SetViewportExtEx(hdcGDU, wid, ht, NULL); - SetWindowOrgEx(hdcGDU, 0, 1023, NULL); - - generate_image(); // run the display program to paint the image into the memory context - - SetWindowExtEx(hdcGDU, wid, ht, NULL); // undo the scaling so the blit isn't distorted - SetViewportExtEx(hdcGDU, wid, ht, NULL); - SetWindowOrgEx(hdcGDU, 0, 0, NULL); - BitBlt(hDC, 0, 0, wid, ht, hdcGDU, 0, 0, SRCCOPY); // blit the new image over the old - - SelectObject(hdcGDU, hOldPen); -#else - // for testing purposes -- draw the image directly onto the screen. - // Compile this way when you want to single-step through the image drawing routine, - // so you can see the draws occur. - hdcGDU = hDC; - hOldPen = SelectObject(hdcGDU, hGreenPen); - - SetMapMode(hdcGDU, MM_ANISOTROPIC); - SetWindowExtEx(hdcGDU, 1024, -1024, NULL); - SetViewportExtEx(hdcGDU, wid, ht, NULL); - SetWindowOrgEx(hdcGDU, 0, 1023, NULL); - - generate_image(); - - SelectObject(hdcGDU, hOldPen); - hdcGDU = NULL; -#endif - } - - if (draw_indicators) { - x = r.right-2*INDWIDTH+1; - dy = ht / 16; - ycirc = MIN(dy-2, 8); - - r.left = x; - FillRect(hDC, &r, hGrayBrush); - SelectObject(hDC, hBlackPen); - - bit = 0x80000000L; - for (i = 0; i < 2; i++) { - MoveToEx(hDC, x, 0, NULL); - LineTo(hDC, x, r.bottom); - y = 0; - for (j = 0; j < 16; j++) { - MoveToEx(hDC, x, y, NULL); - LineTo(hDC, x+INDWIDTH, y); - - SelectObject(hDC, (gdu_indicators & bit) ? hRedBrush : hDarkBrush); - Pie(hDC, x+1, y+1, x+1+ycirc, y+1+ycirc, x+1, y+1, x+1, y+1); - - y += dy; - bit >>= 1; - } - x += INDWIDTH; - } - } -} - -// repaint the window - -static void gdu_WM_PAINT (HWND hWnd) -{ - PAINTSTRUCT ps; - HDC hDC; - // code for display - hDC = BeginPaint(hWnd, &ps); - PaintImage(hDC, TRUE); - EndPaint(hWnd, &ps); -} - -// the window has been resized - -static void gdu_WM_SIZE (HWND hWnd, UINT state, int cx, int cy) -{ - InvalidateRect(hWnd, NULL, FALSE); -} - -// tweak the sizing rectangle during a resize to guarantee a square window - -static void gdu_WM_SIZING (HWND hWnd, WPARAM fwSide, LPRECT r) -{ - switch (fwSide) { - case WMSZ_LEFT: - case WMSZ_RIGHT: - case WMSZ_BOTTOMLEFT: - case WMSZ_BOTTOMRIGHT: - r->bottom = r->right - r->left - 2*INDWIDTH + r->top; - break; - - case WMSZ_TOP: - case WMSZ_BOTTOM: - case WMSZ_TOPRIGHT: - r->right = r->bottom - r->top + r->left + 2*INDWIDTH; - break; - - case WMSZ_TOPLEFT: - r->left = r->top - r->bottom + r->right - 2*INDWIDTH; - break; - } -} - -// the refresh timer has gone off - -static void gdu_WM_TIMER (HWND hWnd, UINT id) -{ - HDC hDC; - - if (running) { // if CPU is running, update picture -#ifdef BLIT_MODE - hDC = GetDC(hWnd); // blit the new image right over the old - PaintImage(hDC, FALSE); - ReleaseDC(hWnd, hDC); -#else - InvalidateRect(hWnd, NULL, TRUE); // repaint -#endif - } -} - -// window procedure ------------------------------------------------------------ - -#define HANDLE(msg) case msg: return HANDLE_##msg(hWnd, wParam, lParam, gdu_##msg); - -#ifndef HANDLE_WM_SIZING -// void Cls_OnSizing(HWND hwnd, UINT fwSide, LPRECT r) -# define HANDLE_WM_SIZING(hwnd, wParam, lParam, fn) \ - ((fn)((hwnd), (UINT)(wParam), (LPRECT)(lParam)), 0L) -#endif - -static LRESULT APIENTRY GDUWndProc (HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam) -{ - switch (iMessage) { - HANDLE(WM_CLOSE); - HANDLE(WM_GETMINMAXINFO); - HANDLE(WM_DESTROY); - HANDLE(WM_PAINT); - HANDLE(WM_SIZE); - HANDLE(WM_SIZING); - HANDLE(WM_TIMER); - default: // any message we don't process - return DefWindowProc(hWnd, iMessage, wParam, lParam); - } - return 0L; -} - -// graphic calls ---------------------------------------------------------------- - -static void DrawLine (int x0, int y0, int x1, int y1) -{ - MoveToEx(hdcGDU, x0, y0, NULL); - LineTo(hdcGDU, x1, y1); -} - -static void DrawPoint (int x, int y) -{ - SetPixel(hdcGDU, x, y, RGB_GREEN); -} - -static void UpdateGDUIndicators(void) -{ - if (hwGDU != NULL) - InvalidateRect(hwGDU, NULL, TRUE); -} - -static void CheckGDUKeyboard (void) -{ -} - -static UINT idTimer = 0; - -static void StartGDUUpdates (void) -{ - int msec; - - if (idTimer == 0) { - msec = (gdu_rate == 0) ? (1000 / DEFAULT_GDU_RATE) : 1000/gdu_rate; - idTimer = SetTimer(hwGDU, 1, msec, NULL); - } -} - -static void StopGDUUpdates (void) -{ - if (idTimer != 0) { - KillTimer(hwGDU, 1); - idTimer = 0; - } -} - -static void GetMouseCoordinates() -{ - POINT p; - RECT r; - - GetCursorPos(&p); - GetClientRect(hwGDU, &r); - if (! ScreenToClient(hwGDU, &p)) { - xmouse = ymouse = -2000; - mouse_present = FALSE; - return; - } - - if (p.x < r.left || p.x >= r.right || p.y < r.top || p.y > r.bottom) { - mouse_present = FALSE; - return; - } - - // convert mouse coordinates to scaled coordinates - - xmouse = (int) (1024./(r.right+1.-2*INDWIDTH)*p.x + 0.5); - ymouse = 1023 - (int) (1024./(r.bottom+1.)*p.y + 0.5); - mouse_present = TRUE; -} - -t_bool gdu_active (void) -{ - return gdu_dsw & GDU_DSW_BUSY; -} - -static void EraseGDUScreen (void) -{ - if (hwGDU != NULL) /* redraw screen. it will be blank if GDU is not running */ - InvalidateRect(hwGDU, NULL, TRUE); -} - -/* GDUPump - thread responsible for creating and displaying the graphics window */ - -static DWORD WINAPI GDUPump (LPVOID arg) -{ - MSG msg; - WNDCLASS wc; - - if (! wcInited) { /* register Window class */ - memset(&wc, 0, sizeof(wc)); - wc.style = CS_NOCLOSE; - wc.lpfnWndProc = GDUWndProc; - wc.hInstance = hInstance; - wc.hCursor = LoadCursor(NULL, IDC_ARROW); - wc.hbrBackground = GetStockObject(BLACK_BRUSH); - wc.lpszClassName = APPCLASS; - - if (! RegisterClass(&wc)) { - GDUPumpID = 0; - return 0; - } - - wcInited = TRUE; - } - - if (hGreenPen == NULL) - hGreenPen = CreatePen(PS_SOLID, 1, RGB_GREEN); - -#ifdef DEBUG_LIGHTPEN - if (hRedPen == NULL) - hRedPen = CreatePen(PS_SOLID, 1, RGB_RED); -#endif - - if (hRedBrush == NULL) - hRedBrush = CreateSolidBrush(RGB_RED); - - hGrayBrush = GetStockObject(GRAY_BRUSH); - hDarkBrush = GetStockObject(DKGRAY_BRUSH); - hBlackPen = GetStockObject(BLACK_PEN); - - if (hwGDU == NULL) { /* create window */ - hwGDU = CreateWindow(APPCLASS, - "2250 Display", - WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN, - CW_USEDEFAULT, CW_USEDEFAULT, // initial x, y position - INITSIZE+2*INDWIDTH, INITSIZE, // initial width and height - NULL, // parent window handle - NULL, // use class menu - hInstance, // program instance handle - NULL); // create parameters - - if (hwGDU == NULL) { - GDUPumpID = 0; - return 0; - } - } - - ShowWindow(hwGDU, SW_SHOWNOACTIVATE); /* display it */ - UpdateWindow(hwGDU); - - StartGDUUpdates(); - - while (GetMessage(&msg, hwGDU, 0, 0)) { /* message pump - this basically loops forevermore */ - TranslateMessage(&msg); - DispatchMessage(&msg); - } - - if (hwGDU != NULL) { - DestroyWindow(hwGDU); /* but if a quit message got posted, clean up */ - hwGDU = NULL; - } - - GDUPumpID = 0; - return 0; -} - -#ifdef DEBUG_LIGHTPEN -static void ShowPenHit (int x, int y) -{ - HPEN hOldPen; - - hOldPen = SelectObject(hdcGDU, hRedPen); - DrawLine(x-10, y-10, x+10, y+10); - DrawLine(x-10, y+10, x+10, y-10); - SelectObject(hdcGDU, hOldPen); -} -#endif - -#endif // WIN32 defined -#endif // GUI_SUPPORT defined diff --git a/Ibm1130/ibm1130_gui.c b/Ibm1130/ibm1130_gui.c deleted file mode 100644 index 8a1461cb..00000000 --- a/Ibm1130/ibm1130_gui.c +++ /dev/null @@ -1,1269 +0,0 @@ -/* ibm1130_gui.c: IBM 1130 CPU simulator Console Display - * - * Based on the SIMH package written by Robert M Supnik - * - * (C) Copyright 2002, Brian Knittel. - * You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN - * RISK basis, there is no warranty of fitness for any purpose, and the rest of the - * usual yada-yada. Please keep this notice and the copyright in any distributions - * or modifications. - * - * This is not a supported product, but I welcome bug reports and fixes. - * Mail to simh@ibm1130.org - * - * 17-May-02 BLK Pulled out of ibm1130_cpu.c - */ - -/* ------------------------------------------------------------------------ - * Definitions - * ------------------------------------------------------------------------ */ - -#include -#include - -#include "ibm1130_defs.h" -#include "ibm1130res.h" - -#define UPDATE_BY_TIMER - -#ifdef UPDATE_BY_TIMER -# define UPDATE_INTERVAL 20 // set to desired number of updates/second -#else -# define UPDATE_INTERVAL 5000 // GUI: set to 100000/f where f = desired updates/second of 1130 time -#endif - -/* ------------------------------------------------------------------------ - * Function declarations - * ------------------------------------------------------------------------ */ - -t_stat console_reset (DEVICE *dptr); - -/* ------------------------------------------------------------------------ - * Console display - on Windows builds (only) this code displays the 1130 console - * and toggle switches. It really enhances the experience. - * - * Currently, when the IPS throttle is nonzero, I update the display after every - * UPDATE_INTERVAL instructions, plus or minus a random amount to avoid aliased - * sampling in loops. When UPDATE_INTERVAL is defined as zero, we update every - * instruction no matter what the throttle. This makes the simulator too slow - * but it's cool and helpful during development. - * ------------------------------------------------------------------------ */ - -#define UNIT_V_DISPLAY (UNIT_V_UF + 0) -#define UNIT_DISPLAY (1u << UNIT_V_DISPLAY) - -MTAB console_mod[] = { - { UNIT_DISPLAY, 0, "off", "OFF", NULL }, - { UNIT_DISPLAY, UNIT_DISPLAY, "on", "ON", NULL }, - { 0 } -}; - -UNIT console_unit = {UDATA (NULL, UNIT_DISABLE|UNIT_DISPLAY, 0) }; - -DEVICE console_dev = { - "GUI", &console_unit, NULL, console_mod, - 1, 16, 16, 1, 16, 16, - NULL, NULL, console_reset, - NULL, NULL, NULL -}; - -// reset for the "console" display device - -extern char *read_line (char *cptr, int size, FILE *stream); -extern FILE *sim_log; - -#ifndef GUI_SUPPORT - void update_gui (int force) {} /* stubs for non-GUI builds */ - void forms_check (int set) {} - void print_check (int set) {} - void keyboard_select (int select) {} - void keyboard_selected (int select) {} - void disk_ready (int ready) {} - void disk_unlocked (int unlocked) {} - void gui_run (int running) {} - static void init_console_window (void) {} - static void destroy_console_window (void) {} - - t_stat console_reset (DEVICE *dptr) {return SCPE_OK;} - void stuff_cmd (char *cmd) {} - char *read_cmdline (char *ptr, int size, FILE *stream) {return read_line(ptr, size, stream);} - void remark_cmd (char *remark) {printf("%s\n", remark); if (sim_log) fprintf(sim_log, "%s\n", remark);} -#else - -t_stat console_reset (DEVICE *dptr) -{ - if (! sim_gui) { - SETBIT(console_unit.flags, UNIT_DIS); // disable the GUI - CLRBIT(console_unit.flags, UNIT_DISPLAY); // turn the GUI off - } - - update_gui(FALSE); - return SCPE_OK; -} - -/* scp_panic - report fatal internal programming error */ - -void scp_panic (char *msg) -{ - fprintf(stderr, "%s\n", msg); - exit(1); -} - -#ifdef WIN32 - /* only WIN32 is defined right now */ - -#include - -#define BUTTON_WIDTH 90 -#define BUTTON_HEIGHT 50 - -#define IDC_KEYBOARD_SELECT 0 -#define IDC_DISK_UNLOCK 1 -#define IDC_RUN 2 -#define IDC_PARITY_CHECK 3 -#define IDC_UNUSED 4 -#define IDC_FILE_READY 5 -#define IDC_FORMS_CHECK 6 -#define IDC_POWER_ON 7 -#define IDC_POWER 8 -#define IDC_PROGRAM_START 9 -#define IDC_PROGRAM_STOP 10 -#define IDC_LOAD_IAR 11 -#define IDC_KEYBOARD 12 -#define IDC_IMM_STOP 13 -#define IDC_RESET 14 -#define IDC_PROGRAM_LOAD 15 - -#define LAMPTIME 500 // 500 msec delay on updating -#define FLASH_TIMER_ID 1 -#define UPDATE_TIMER_ID 2 - -static BOOL class_defined = FALSE; -static HWND hConsoleWnd = NULL; -static HBITMAP hBitmap = NULL; -static HFONT hFont = NULL; -static HFONT hBtnFont = NULL; -static HBRUSH hbLampOut = NULL; -static HBRUSH hbWhite = NULL; -static HBRUSH hbBlack = NULL; -static HBRUSH hbGray = NULL; -static HPEN hSwitchPen = NULL; -static HPEN hWhitePen = NULL; -static HPEN hBlackPen = NULL; -static HPEN hLtGreyPen = NULL; -static HPEN hGreyPen = NULL; -static HPEN hDkGreyPen = NULL; -static int hUpdateTimer = 0; -static int hFlashTimer = 0; - -static HCURSOR hcArrow = NULL; -static HCURSOR hcHand = NULL; -static HINSTANCE hInstance; -static HDC hCDC = NULL; -static char szConsoleClassName[] = "1130CONSOLE"; -static DWORD PumpID = 0; -static HANDLE hPump = INVALID_HANDLE_VALUE; -static int bmwid, bmht; - -static struct tag_btn { - int x, y; - char *txt; - BOOL pushable, state; - COLORREF clr; - HBRUSH hbrLit, hbrDark; - HWND hBtn; -} btn[] = { - 0, 0, "KEYBOARD\nSELECT", FALSE, FALSE, RGB(255,255,180), NULL, NULL, NULL, - 0, 1, "DISK\nUNLOCK", FALSE, TRUE, RGB(255,255,180), NULL, NULL, NULL, - 0, 2, "RUN", FALSE, FALSE, RGB(0,255,0), NULL, NULL, NULL, - 0, 3, "PARITY\nCHECK", FALSE, FALSE, RGB(255,0,0), NULL, NULL, NULL, - - 1, 0, "", FALSE, FALSE, RGB(255,255,180), NULL, NULL, NULL, - 1, 1, "FILE\nREADY", FALSE, FALSE, RGB(0,255,0), NULL, NULL, NULL, - 1, 2, "FORMS\nCHECK", FALSE, FALSE, RGB(255,255,0), NULL, NULL, NULL, - 1, 3, "POWER\nON", FALSE, TRUE, RGB(255,255,180), NULL, NULL, NULL, - - 2, 0, "POWER", TRUE, FALSE, RGB(255,255,180), NULL, NULL, NULL, - 2, 1, "PROGRAM\nSTART", TRUE, FALSE, RGB(0,255,0), NULL, NULL, NULL, - 2, 2, "PROGRAM\nSTOP", TRUE, FALSE, RGB(255,0,0), NULL, NULL, NULL, - 2, 3, "LOAD\nIAR", TRUE, FALSE, RGB(0,0,255), NULL, NULL, NULL, - - 3, 0, "KEYBOARD", TRUE, FALSE, RGB(255,255,180), NULL, NULL, NULL, - 3, 1, "IMM\nSTOP", TRUE, FALSE, RGB(255,0,0), NULL, NULL, NULL, - 3, 2, "CHECK\nRESET", TRUE, FALSE, RGB(0,0,255), NULL, NULL, NULL, - 3, 3, "PROGRAM\nLOAD", TRUE, FALSE, RGB(0,0,255), NULL, NULL, NULL, -}; -#define NBUTTONS (sizeof(btn) / sizeof(btn[0])) - -static void init_console_window (void); -static void destroy_console_window (void); -LRESULT CALLBACK ConsoleWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); -static DWORD WINAPI Pump (LPVOID arg); - -#define NIXOBJECT(hObj) if (hObj != NULL) {DeleteObject(hObj); hObj = NULL;} - -/* ------------------------------------------------------------------------ - * init_console_window - display the 1130 console. Actually just creates a thread - * to run the Pump routine which does the actual work. - * ------------------------------------------------------------------------ */ - -static void init_console_window (void) -{ - static BOOL did_atexit = FALSE; - - if (hConsoleWnd != NULL) - return; - - if (PumpID == 0) - hPump = CreateThread(NULL, 0, Pump, 0, 0, &PumpID); - - if (! did_atexit) { - atexit(destroy_console_window); - did_atexit = TRUE; - } -} - -/* ------------------------------------------------------------------------ - * destroy_console_window - delete GDI objects. - * ------------------------------------------------------------------------ */ - -static void destroy_console_window (void) -{ - int i; - - if (hConsoleWnd != NULL) - SendMessage(hConsoleWnd, WM_CLOSE, 0, 0); // cross thread call is OK - - if (hPump != INVALID_HANDLE_VALUE) { // this is not the most graceful way to do it - TerminateThread(hPump, 0); - hPump = INVALID_HANDLE_VALUE; - PumpID = 0; - hConsoleWnd = NULL; - } - if (hCDC != NULL) { - DeleteDC(hCDC); - hCDC = NULL; - } - - NIXOBJECT(hBitmap) - NIXOBJECT(hbLampOut) - NIXOBJECT(hFont) - NIXOBJECT(hBtnFont); - NIXOBJECT(hcHand) - NIXOBJECT(hSwitchPen) - NIXOBJECT(hLtGreyPen) - NIXOBJECT(hGreyPen) - NIXOBJECT(hDkGreyPen) - - for (i = 0; i < NBUTTONS; i++) { - NIXOBJECT(btn[i].hbrLit); - NIXOBJECT(btn[i].hbrDark); - } - -// if (class_defined) { -// UnregisterClass(hInstance, szConsoleClassName); -// class_defined = FALSE; -// } -} - -/* ------------------------------------------------------------------------ - * these variables hold the displayed versions of the system registers - * ------------------------------------------------------------------------ */ - -static int shown_iar = 0, shown_sar = 0, shown_sbr = 0, shown_afr = 0, shown_acc = 0, shown_ext = 0; -static int shown_op = 0, shown_tag = 0, shown_irq = 0, shown_ccc = 0, shown_cnd = 0, shown_wait = 0; -static int shown_ces = 0, shown_runmode = MODE_RUN; -static int CND; - -/* ------------------------------------------------------------------------ - * RedrawRegion - mark a region for redrawing without background erase - * ------------------------------------------------------------------------ */ - -static void RedrawRegion (HWND hWnd, int left, int top, int right, int bottom) -{ - RECT r; - - r.left = left; - r.top = top; - r.right = right; - r.bottom = bottom; - - InvalidateRect(hWnd, &r, FALSE); -} - -/* ------------------------------------------------------------------------ - * RepaintRegion - mark a region for redrawing with background erase - * ------------------------------------------------------------------------ */ - -static void RepaintRegion (HWND hWnd, int left, int top, int right, int bottom) -{ - RECT r; - - r.left = left; - r.top = top; - r.right = right; - r.bottom = bottom; - - InvalidateRect(hWnd, &r, TRUE); -} - -/* ------------------------------------------------------------------------ - * update_gui - sees if anything on the console display has changed, and invalidates - * the changed regions. Then it calls UpdateWindow to force an immediate repaint. This - * function (update_gui) should probably not be called every time through the main - * instruction loop but it should be called at least whenever wait_state or int_req change, and then - * every so many instructions. It's also called after every simh command so manual changes are - * reflected instantly. - * ------------------------------------------------------------------------ */ - -void update_gui (BOOL force) -{ - int i; - BOOL state; - static int in_here = FALSE; - static int32 displayed = 0; - - if ((int32)(console_unit.flags & UNIT_DISPLAY) != displayed) { // setting has changed - displayed = console_unit.flags & UNIT_DISPLAY; - if (displayed) - init_console_window(); - else - destroy_console_window(); - } - - if (hConsoleWnd == NULL) - return; - - GUI_BEGIN_CRITICAL_SECTION /* only one thread at a time, please */ - if (in_here) { - GUI_END_CRITICAL_SECTION - return; - } - in_here = TRUE; - GUI_END_CRITICAL_SECTION - - CND = 0; /* combine carry and V as two bits */ - if (C) - CND |= 2; - if (V) - CND |= 1; - - int_lamps |= int_req; - if (ipl >= 0) - int_lamps |= (0x20 >> ipl); - - if (RUNMODE == MODE_LOAD) - SBR = CES; /* in load mode, SBR follows the console switches */ - - if (IAR != shown_iar) - {shown_iar = IAR; RedrawRegion(hConsoleWnd, 75, 8, 364, 32);} /* lamps: don't bother erasing bkgnd */ - if (SAR != shown_sar) - {shown_sar = SAR; RedrawRegion(hConsoleWnd, 75, 42, 364, 65);} - if (ACC != shown_acc) - {shown_acc = ACC; RedrawRegion(hConsoleWnd, 75, 141, 364, 164);} - if (EXT != shown_ext) - {shown_ext = EXT; RedrawRegion(hConsoleWnd, 75, 174, 364, 197);} - if (SBR != shown_sbr) - {shown_sbr = SBR; RedrawRegion(hConsoleWnd, 75, 77, 364, 97);} - if (OP != shown_op) - {shown_op = OP; RedrawRegion(hConsoleWnd, 501, 8, 595, 32);} - if (TAG != shown_tag) - {shown_tag = TAG; RedrawRegion(hConsoleWnd, 501, 77, 595, 97);} - - if (int_lamps != shown_irq) - {shown_irq = int_lamps; RedrawRegion(hConsoleWnd, 501, 108, 595, 130);} - - if (CCC != shown_ccc) - {shown_ccc = CCC; RedrawRegion(hConsoleWnd, 501, 141, 595, 164);} - if (CND != shown_cnd) - {shown_cnd = CND; RedrawRegion(hConsoleWnd, 501, 174, 595, 197);} - if ((wait_state|wait_lamp) != shown_wait) - {shown_wait= (wait_state|wait_lamp); RedrawRegion(hConsoleWnd, 380, 77, 414, 97);} - if (CES != shown_ces) - {shown_ces = CES; RepaintRegion(hConsoleWnd, 115, 230, 478, 275);} /* console entry sw: do erase bkgnd */ - if (RUNMODE != shown_runmode) - {shown_runmode = RUNMODE;RepaintRegion(hConsoleWnd, 270, 359, 330, 418);} - - int_lamps = 0; - - // this loop works with lamp buttons that are calculated on-the-fly only - for (i = 0; i < NBUTTONS; i++) { - if (btn[i].pushable) - continue; - - switch (i) { - case IDC_RUN: - state = hFlashTimer || (running && ! wait_state); - break; - - // this button is always off -// case IDC_PARITY_CHECK: - - // these buttons are enabled/disabled directly -// case IDC_POWER_ON: -// case IDC_FILE_READY: -// case IDC_FORMS_CHECK: -// case IDC_KEYBOARD_SELECT: -// case IDC_DISK_UNLOCK: - default: - continue; - } - - if (state != btn[i].state) { // state has changed - EnableWindow(btn[i].hBtn, state); - btn[i].state = state; - } - } - - in_here = FALSE; -} - -WNDPROC oldButtonProc = NULL; - -/* ------------------------------------------------------------------------ - * ------------------------------------------------------------------------ */ - -LRESULT CALLBACK ButtonProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - int i; - - i = GetWindowLong(hWnd, GWL_ID); - - if (! btn[i].pushable) { - if (uMsg == WM_LBUTTONDOWN || uMsg == WM_LBUTTONUP || uMsg == WM_LBUTTONDBLCLK) - return 0; - - if (uMsg == WM_CHAR) - if ((TCHAR) wParam == ' ') - return 0; - } - - return CallWindowProc(oldButtonProc, hWnd, uMsg, wParam, lParam); -} - -/* ------------------------------------------------------------------------ - * ------------------------------------------------------------------------ */ - -static int occurs (char *txt, char ch) -{ - int count = 0; - - while (*txt) - if (*txt++ == ch) - count++; - - return count; -} - -/* ------------------------------------------------------------------------ -// turns out to get properly colored buttons you have to paint them yourself. Sheesh. -// On the plus side, this lets do a better job of aligning the button text than -// the button would by itself. - * ------------------------------------------------------------------------ */ - -void PaintButton (LPDRAWITEMSTRUCT dis) -{ - int i = dis->CtlID, nc, nlines, x, y, dy; - BOOL down = dis->itemState & ODS_SELECTED; - HPEN hOldPen; - HFONT hOldFont; - UINT oldAlign; - COLORREF oldBk; - char *txt, *tstart; - - if (! BETWEEN(i, 0, NBUTTONS-1)) - return; - - FillRect(dis->hDC, &dis->rcItem, ((btn[i].pushable || power) && IsWindowEnabled(btn[i].hBtn)) ? btn[i].hbrLit : btn[i].hbrDark); - - if (! btn[i].pushable) { - hOldPen = SelectObject(dis->hDC, hBlackPen); - MoveToEx(dis->hDC, dis->rcItem.left, dis->rcItem.top, NULL); - LineTo(dis->hDC, dis->rcItem.right-1, dis->rcItem.top); - LineTo(dis->hDC, dis->rcItem.right-1, dis->rcItem.bottom-1); - LineTo(dis->hDC, dis->rcItem.left, dis->rcItem.bottom-1); - LineTo(dis->hDC, dis->rcItem.left, dis->rcItem.top); - } - else if (down) { - // do the three-D thing - hOldPen = SelectObject(dis->hDC, hDkGreyPen); - MoveToEx(dis->hDC, dis->rcItem.left, dis->rcItem.bottom-2, NULL); - LineTo(dis->hDC, dis->rcItem.left, dis->rcItem.top); - LineTo(dis->hDC, dis->rcItem.right-1, dis->rcItem.top); - - SelectObject(dis->hDC, hWhitePen); - MoveToEx(dis->hDC, dis->rcItem.left, dis->rcItem.bottom-1, NULL); - LineTo(dis->hDC, dis->rcItem.right-1, dis->rcItem.bottom-1); - LineTo(dis->hDC, dis->rcItem.right-1, dis->rcItem.top); - - SelectObject(dis->hDC, hGreyPen); - MoveToEx(dis->hDC, dis->rcItem.left+1, dis->rcItem.bottom-3, NULL); - LineTo(dis->hDC, dis->rcItem.left+1, dis->rcItem.top+1); - LineTo(dis->hDC, dis->rcItem.right-3, dis->rcItem.top+1); - } - else { - hOldPen = SelectObject(dis->hDC, hWhitePen); - MoveToEx(dis->hDC, dis->rcItem.left, dis->rcItem.bottom-2, NULL); - LineTo(dis->hDC, dis->rcItem.left, dis->rcItem.top); - LineTo(dis->hDC, dis->rcItem.right-1, dis->rcItem.top); - - SelectObject(dis->hDC, hDkGreyPen); - MoveToEx(dis->hDC, dis->rcItem.left, dis->rcItem.bottom-1, NULL); - LineTo(dis->hDC, dis->rcItem.right-1, dis->rcItem.bottom-1); - LineTo(dis->hDC, dis->rcItem.right-1, dis->rcItem.top); - - SelectObject(dis->hDC, hGreyPen); - MoveToEx(dis->hDC, dis->rcItem.left+1, dis->rcItem.bottom-2, NULL); - LineTo(dis->hDC, dis->rcItem.right-2, dis->rcItem.bottom-2); - LineTo(dis->hDC, dis->rcItem.right-2, dis->rcItem.top+1); - } - - SelectObject(dis->hDC, hOldPen); - - hOldFont = SelectObject(dis->hDC, hBtnFont); - oldAlign = SetTextAlign(dis->hDC, TA_CENTER|TA_TOP); - oldBk = SetBkMode(dis->hDC, TRANSPARENT); - - txt = btn[i].txt; - nlines = occurs(txt, '\n')+1; - x = (dis->rcItem.left + dis->rcItem.right) / 2; - y = (dis->rcItem.top + dis->rcItem.bottom) / 2; - - dy = 14; - y = y - (nlines*dy)/2; - - if (down) { - x += 1; - y += 1; - } - - for (;;) { - for (nc = 0, tstart = txt; *txt && *txt != '\n'; txt++, nc++) - ; - - TextOut(dis->hDC, x, y, tstart, nc); - - if (*txt == '\0') - break; - - txt++; - y += dy; - } - - SetTextAlign(dis->hDC, oldAlign); - SetBkMode(dis->hDC, oldBk); - SelectObject(dis->hDC, hOldFont); -} - -/* ------------------------------------------------------------------------ - * ------------------------------------------------------------------------ */ - -HWND CreateSubclassedButton (HWND hwParent, int i) -{ - HWND hBtn; - int x, y; - int r, g, b; - - y = bmht - (4*BUTTON_HEIGHT) + BUTTON_HEIGHT * btn[i].y; - x = (btn[i].x < 2) ? (btn[i].x*BUTTON_WIDTH) : (bmwid - (4-btn[i].x)*BUTTON_WIDTH); - - if ((hBtn = CreateWindow("BUTTON", btn[i].txt, WS_CHILD|WS_VISIBLE|BS_CENTER|BS_MULTILINE|BS_OWNERDRAW, - x, y, BUTTON_WIDTH, BUTTON_HEIGHT, hwParent, (HMENU) i, hInstance, NULL)) == NULL) - return NULL; - - btn[i].hBtn = hBtn; - - if (oldButtonProc == NULL) - oldButtonProc = (WNDPROC) GetWindowLong(hBtn, GWL_WNDPROC); - - btn[i].hbrLit = CreateSolidBrush(btn[i].clr); - - if (! btn[i].pushable) { - r = GetRValue(btn[i].clr) / 4; - g = GetGValue(btn[i].clr) / 4; - b = GetBValue(btn[i].clr) / 4; - - btn[i].hbrDark = CreateSolidBrush(RGB(r,g,b)); - EnableWindow(hBtn, FALSE); - } - - SetWindowLong(hBtn, GWL_WNDPROC, (LONG) ButtonProc); - return hBtn; -} - -/* ------------------------------------------------------------------------ - * Pump - thread that takes care of the console window. It has to be a separate thread so that it gets - * execution time even when the simulator is compute-bound or IO-blocked. This routine creates the window - * and runs a standard Windows message pump. The window function does the actual display work. - * ------------------------------------------------------------------------ */ - -static DWORD WINAPI Pump (LPVOID arg) -{ - MSG msg; - int wx, wy, i; - RECT r, ra; - BITMAP bm; - WNDCLASS cd; - HDC hDC; - HWND hActWnd; - - hActWnd = GetForegroundWindow(); - - if (! class_defined) { /* register Window class */ - hInstance = GetModuleHandle(NULL); - - memset(&cd, 0, sizeof(cd)); - cd.style = CS_NOCLOSE; - cd.lpfnWndProc = ConsoleWndProc; - cd.cbClsExtra = 0; - cd.cbWndExtra = 0; - cd.hInstance = hInstance; - cd.hIcon = NULL; - cd.hCursor = hcArrow; - cd.hbrBackground = NULL; - cd.lpszMenuName = NULL; - cd.lpszClassName = szConsoleClassName; - - if (! RegisterClass(&cd)) { - PumpID = 0; - return 0; - } - - class_defined = TRUE; - } - - hbWhite = GetStockObject(WHITE_BRUSH); /* create or fetch useful GDI objects */ - hbBlack = GetStockObject(BLACK_BRUSH); /* create or fetch useful GDI objects */ - hbGray = GetStockObject(GRAY_BRUSH); - hSwitchPen = CreatePen(PS_SOLID, 5, RGB(255,255,255)); - - hWhitePen = GetStockObject(WHITE_PEN); - hBlackPen = GetStockObject(BLACK_PEN); - hLtGreyPen = CreatePen(PS_SOLID, 1, RGB(190,190,190)); - hGreyPen = CreatePen(PS_SOLID, 1, RGB(128,128,128)); - hDkGreyPen = CreatePen(PS_SOLID, 1, RGB(64,64,64)); - - hcArrow = LoadCursor(NULL, IDC_ARROW); - hcHand = LoadCursor(hInstance, MAKEINTRESOURCE(IDC_HAND)); - - if (hBitmap == NULL) - hBitmap = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_CONSOLE)); - if (hbLampOut == NULL) - hbLampOut = CreateSolidBrush(RGB(50,50,50)); - if (hFont == NULL) - hFont = CreateFont(-10, 0, 0, 0, FW_NORMAL, 0, 0, 0, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, FIXED_PITCH, FF_SWISS, "Arial"); - if (hBtnFont == NULL) - hBtnFont = CreateFont(-12, 0, 0, 0, FW_NORMAL, 0, 0, 0, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, FIXED_PITCH, FF_SWISS, "Arial"); - - if (hConsoleWnd == NULL) { /* create window */ - if ((hConsoleWnd = CreateWindow(szConsoleClassName, "IBM 1130", WS_OVERLAPPED, 0, 0, 200, 200, NULL, NULL, hInstance, NULL)) == NULL) { - PumpID = 0; - return 0; - } - } - - GetObject(hBitmap, sizeof(bm), &bm); /* get bitmap size */ - bmwid = bm.bmWidth; - bmht = bm.bmHeight; - - for (i = 0; i < NBUTTONS; i++) { - CreateSubclassedButton(hConsoleWnd, i); - - if (! btn[i].pushable) - EnableWindow(btn[i].hBtn, btn[i].state); - } - - GetWindowRect(hConsoleWnd, &r); /* get window size as created */ - wx = r.right - r.left + 1; - wy = r.bottom - r.top + 1; - - if (hCDC == NULL) { /* get a memory DC and select the bitmap into ti */ - hDC = GetDC(hConsoleWnd); - hCDC = CreateCompatibleDC(hDC); - SelectObject(hCDC, hBitmap); - ReleaseDC(hConsoleWnd, hDC); - } - - GetClientRect(hConsoleWnd, &r); - wx = (wx - r.right - 1) + bmwid; /* compute new desired size based on how client area came out */ - wy = (wy - r.bottom - 1) + bmht; - MoveWindow(hConsoleWnd, 0, 0, wx, wy, FALSE); /* resize window */ - - ShowWindow(hConsoleWnd, SW_SHOWNOACTIVATE); /* display it */ - UpdateWindow(hConsoleWnd); - - if (hActWnd != NULL) { /* bring console (sim) window back to top */ - GetWindowRect(hConsoleWnd, &r); - ShowWindow(hActWnd, SW_NORMAL); /* and move it just below the display window */ - SetWindowPos(hActWnd, HWND_TOP, 0, r.bottom, 0, 0, SWP_NOSIZE); - GetWindowRect(hActWnd, &ra); - if (ra.bottom >= GetSystemMetrics(SM_CYSCREEN)) { /* resize if it goes of bottom of screen */ - ra.bottom = GetSystemMetrics(SM_CYSCREEN) - 1; - SetWindowPos(hActWnd, 0, 0, 0, ra.right-ra.left+1, ra.bottom-ra.top+1, SWP_NOZORDER|SWP_NOMOVE); - } - } - - if (running) /* if simulator is already running, start update timer */ - gui_run(TRUE); - - while (GetMessage(&msg, hConsoleWnd, 0, 0)) { /* message pump - this basically loops forevermore */ - TranslateMessage(&msg); - DispatchMessage(&msg); - } - - if (hConsoleWnd != NULL) { - DestroyWindow(hConsoleWnd); /* but if a quit message got posted, clean up */ - hConsoleWnd = NULL; - } - - PumpID = 0; - return 0; -} - -/* ------------------------------------------------------------------------ - * DrawBits - starting at position (x,y), draw lamps for nbits bits of word 'bits', looking only at masked bits - * ------------------------------------------------------------------------ */ - -static void DrawBits (HDC hDC, int x, int y, int bits, int nbits, int mask, char *syms) -{ - int i, b = 0x0001 << (nbits-1); - - for (i = 0; i < nbits; i++, b >>= 1) { - if (mask & b) { /* select white or black lettering then write 2 chars */ - SetTextColor(hDC, (b & bits && power) ? RGB(255,255,255) : RGB(0,0,0)); - TextOut(hDC, x, y, syms, 2); - } - syms += 2; /* go to next symbol pair */ - - if (i < 10) - x += 15; /* step between lamps */ - else - x += 19; - - if (x < 500) { - if (b & 0x1110) - x += 10; /* step over nibble divisions on left side */ - else if (b & 0x0001) - x += 9; - } - } -} - -/* ------------------------------------------------------------------------ - * DrawToggles - display the console sense switches - * ------------------------------------------------------------------------ */ - -static void DrawToggles (HDC hDC, int bits) -{ - int b, x; - - for (b = 0x8000, x = 122; b != 0; b >>= 1) { - if (shown_ces & b) { /* up */ - SelectObject(hDC, hbWhite); - Rectangle(hDC, x, 232, x+9, 240); - SelectObject(hDC, hbGray); - Rectangle(hDC, x, 239, x+9, 255); - } - else { /* down */ - SelectObject(hDC, hbWhite); - Rectangle(hDC, x, 263, x+9, 271); - SelectObject(hDC, hbGray); - Rectangle(hDC, x, 248, x+9, 264); - } - - x += (b & 0x1111) ? 31 : 21; - } -} - -/* ------------------------------------------------------------------------ - * DrawRunmode - draw the run mode rotary switch's little tip - * ------------------------------------------------------------------------ */ - -void DrawRunmode (HDC hDC, int mode) -{ - double angle = (mode*45. + 90.) * 3.1415926 / 180.; /* convert mode position to angle in radians */ - double ca, sa; /* sine and cosine */ - int x0, y0, x1, y1; - HPEN hOldPen; - - ca = cos(angle); - sa = sin(angle); - - x0 = 301 + (int) (20.*ca + 0.5); /* inner radius */ - y0 = 389 - (int) (20.*sa + 0.5); - x1 = 301 + (int) (25.*ca + 0.5); /* outer radius */ - y1 = 389 - (int) (25.*sa + 0.5); - - hOldPen = SelectObject(hDC, hSwitchPen); - - MoveToEx(hDC, x0, y0, NULL); - LineTo(hDC, x1, y1); - - SelectObject(hDC, hOldPen); -} - -/* ------------------------------------------------------------------------ - * HandleClick - handle mouse clicks on the console window. Now we just - * look at the console sense switches. Actual says this is a real click, rather - * than a mouse-region test. Return value TRUE means the cursor is over a hotspot. - * ------------------------------------------------------------------------ */ - -static BOOL HandleClick (HWND hWnd, int xh, int yh, BOOL actual) -{ - int b, x, r, ang, i; - - for (b = 0x8000, x = 122; b != 0; b >>= 1) { - if (BETWEEN(xh, x-3, x+8+3) && BETWEEN(yh, 230, 275)) { - if (actual) { - CES ^= b; /* a hit. Invert the bit and redisplay */ - update_gui(TRUE); - } - return TRUE; - } - x += (b & 0x1111) ? 31 : 21; - } - - if (BETWEEN(xh, 245, 355) && BETWEEN(yh, 345, 425)) { /* hit near rotary switch */ - ang = (int) (atan2(301.-xh, 389.-yh)*180./3.1415926); /* this does implicit 90 deg rotation by the way */ - r = (int) sqrt((xh-301)*(xh-301)+(yh-389)*(yh-389)); - if (r > 12) { - for (i = MODE_LOAD; i <= MODE_INT_RUN; i++) { - if (BETWEEN(ang, i*45-12, i*45+12)) { - if (actual) { - RUNMODE = i; - update_gui(TRUE); - } - return TRUE; - } - } - - } - } - - return FALSE; -} - -/* ------------------------------------------------------------------------ - * DrawConsole - refresh the console display. (This routine could be sped up by intersecting - * the various components' bounding rectangles with the repaint rectangle. The bounding rects - * could be put into an array and used both here and in the refresh routine). - * - * RedrawRegion -> force repaint w/o background redraw. used for lamps which are drawn in the same place in either state - * RepaintRegion-> repaint with background redraw. Used for toggles which change position. - * ------------------------------------------------------------------------ */ - -static void DrawConsole (HDC hDC) -{ - static char digits[] = " 0 1 2 3 4 5 6 7 8 9101112131415"; - static char cccs[] = "3216 8 4 2 1"; - static char cnds[] = " C V"; - static char waits[] = " W"; - HFONT hOldFont, hOldBrush; - - hOldFont = SelectObject(hDC, hFont); /* use that tiny font */ - hOldBrush = SelectObject(hDC, hbWhite); - - SetBkMode(hDC, TRANSPARENT); /* overlay letters w/o changing background */ - - DrawBits(hDC, 76, 15, shown_iar, 16, 0x3FFF, digits); - DrawBits(hDC, 76, 48, shown_sar, 16, 0x3FFF, digits); - DrawBits(hDC, 76, 81, shown_sbr, 16, 0xFFFF, digits); - DrawBits(hDC, 76, 147, shown_acc, 16, 0xFFFF, digits); - DrawBits(hDC, 76, 180, shown_ext, 16, 0xFFFF, digits); - - DrawBits(hDC, 506, 15, shown_op, 5, 0x001F, digits); - DrawBits(hDC, 506, 81, shown_tag, 4, 0x0007, digits); - DrawBits(hDC, 506, 114, shown_irq, 6, 0x003F, digits); - DrawBits(hDC, 506, 147, shown_ccc, 6, 0x003F, cccs); - DrawBits(hDC, 506, 180, shown_cnd, 2, 0x0003, cnds); - - DrawBits(hDC, 390, 81, shown_wait?1:0,1, 0x0001, waits); - - DrawToggles(hDC, shown_ces); - - DrawRunmode(hDC, shown_runmode); - - SelectObject(hDC, hOldFont); - SelectObject(hDC, hOldBrush); -} - -/* ------------------------------------------------------------------------ - * Handles button presses. Remember that this occurs in the context of - * the Pump thread, not the simulator thread. - * ------------------------------------------------------------------------ */ - -void flash_run (void) -{ - EnableWindow(btn[IDC_RUN].hBtn, TRUE); // enable the run lamp - - if (hFlashTimer != 0) - KillTimer(hConsoleWnd, FLASH_TIMER_ID); // (re)schedule lamp update - - hFlashTimer = SetTimer(hConsoleWnd, FLASH_TIMER_ID, LAMPTIME, NULL); -} - -void gui_run (int running) -{ - if (running && hUpdateTimer == 0 && hConsoleWnd != NULL) { - hUpdateTimer = SetTimer(hConsoleWnd, UPDATE_TIMER_ID, 1000/UPDATE_INTERVAL, NULL); - } - else if (hUpdateTimer != 0 && ! running) { - KillTimer(hConsoleWnd, UPDATE_TIMER_ID); - hUpdateTimer = 0; - } - flash_run(); /* keep run lamp active for a while after we stop running */ -} - -void HandleCommand (HWND hWnd, WPARAM wParam, LPARAM lParam) -{ - int i; - - switch (wParam) { - case IDC_POWER: /* toggle system power */ - power = ! power; - reset_all(0); - if (running && ! power) { /* turning off */ - reason = STOP_POWER_OFF; -// this prevents message pump from running, which unfortunately locks up -// the emulator thread when it calls gui_run(FALSE) which calls EnableWindow on the Run lamp -// while (running) -// Sleep(10); /* wait for execution thread to exit */ - } - - btn[IDC_POWER_ON].state = power; - EnableWindow(btn[IDC_POWER_ON].hBtn, power); - - for (i = 0; i < NBUTTONS; i++) /* repaint all of the lamps */ - if (! btn[i].pushable) - InvalidateRect(btn[i].hBtn, NULL, TRUE); - - break; - - case IDC_PROGRAM_START: /* begin execution */ - if (! running) { - switch (RUNMODE) { - case MODE_INT_RUN: - case MODE_RUN: - case MODE_SI: - stuff_cmd("go"); - break; - - case MODE_DISP: /* display core and advance IAR */ - ReadW(IAR); - IAR = IAR+1; - flash_run(); /* illuminate run lamp for .5 sec */ - break; - - case MODE_LOAD: /* store to core and advance IAR */ - WriteW(IAR, CES); - IAR = IAR+1; - flash_run(); - break; - } - } - break; - - case IDC_PROGRAM_STOP: - if (running) { /* potential race condition here */ - GUI_BEGIN_CRITICAL_SECTION - SETBIT(cpu_dsw, CPU_DSW_PROGRAM_STOP); - SETBIT(ILSW[5], ILSW_5_PROGRAM_STOP); - int_req |= INT_REQ_5; - GUI_END_CRITICAL_SECTION - } - break; - - case IDC_LOAD_IAR: - if (! running) { - IAR = CES & 0x3FFF; /* set IAR from console entry switches */ - } - break; - - case IDC_KEYBOARD: /* toggle between console/keyboard mode */ - break; - - case IDC_IMM_STOP: - if (running) { - reason = STOP_WAIT; /* terminate execution without setting wait_mode */ - -// this prevents message pump from running, which unfortunately locks up -// the emulator thread when it calls gui_run(FALSE) which calls EnableWindow on the Run lamp -// while (running) -// Sleep(10); /* wait for execution thread to exit */ - } - break; - - case IDC_RESET: - if (! running) { /* check-reset is disabled while running */ - reset_all(0); - forms_check(0); /* clear forms-check status */ - print_check(0); - } - break; - - case IDC_PROGRAM_LOAD: - 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, NULL) != SCPE_OK) /* load boot card */ - remark_cmd("IPL failed"); - } - break; - } - - update_gui(FALSE); -} - -/* ------------------------------------------------------------------------ - * ConsoleWndProc - window process for the console display - * ------------------------------------------------------------------------ */ - -LRESULT CALLBACK ConsoleWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - HDC hDC; - PAINTSTRUCT ps; - POINT p; - RECT clip, xsect, rbmp; - int i; - - switch (uMsg) { - case WM_CLOSE: - DestroyWindow(hWnd); - break; - - case WM_DESTROY: - gui_run(FALSE); - hConsoleWnd = NULL; - break; - - case WM_ERASEBKGND: - hDC = (HDC) wParam; - GetClipBox(hDC, &clip); - SetRect(&rbmp, 0, 0, bmwid, bmht); - if (IntersectRect(&xsect, &clip, &rbmp)) - BitBlt(hDC, xsect.left, xsect.top, xsect.right-xsect.left+1, xsect.bottom-xsect.top+1, hCDC, xsect.left, xsect.top, SRCCOPY); -// rbmp.top = rbmp.bottom; -// rbmp.bottom += 200; -// if (IntersectRect(&xsect, &clip, &rbmp)) -// FillRect(hDC, &xsect, hbBlack); - return TRUE; /* let Paint do this so we know what the update region is (ps.rcPaint) */ - - case WM_PAINT: - hDC = BeginPaint(hWnd, &ps); - DrawConsole(hDC); - EndPaint(hWnd, &ps); - break; - - case WM_COMMAND: /* button click */ - HandleCommand(hWnd, wParam, lParam); - break; - - case WM_DRAWITEM: - PaintButton((LPDRAWITEMSTRUCT) lParam); - break; - - case WM_SETCURSOR: - GetCursorPos(&p); - ScreenToClient(hWnd, &p); - SetCursor(HandleClick(hWnd, p.x, p.y, FALSE) ? hcHand : hcArrow); - return TRUE; - - case WM_LBUTTONDOWN: - HandleClick(hWnd, LOWORD(lParam), HIWORD(lParam), TRUE); - break; - - case WM_CTLCOLORBTN: - i = GetWindowLong((HWND) lParam, GWL_ID); - if (BETWEEN(i, 0, NBUTTONS-1)) - return (LRESULT) (power && IsWindowEnabled((HWND) lParam) ? btn[i].hbrLit : btn[i].hbrDark); - - case WM_TIMER: - if (wParam == FLASH_TIMER_ID && hFlashTimer != 0) { - KillTimer(hWnd, FLASH_TIMER_ID); - hFlashTimer = 0; - } - update_gui(FALSE); - break; - - default: - return DefWindowProc(hWnd, uMsg, wParam, lParam); - } - - return 0; -} - -enum {PRINTER_OK = 0, FORMS_CHECK = 1, PRINT_CHECK = 2, BOTH_CHECK = 3} printerstatus = PRINTER_OK; - -void forms_check (int set) -{ - COLORREF oldcolor = btn[IDC_FORMS_CHECK].clr; - - if (set) - SETBIT(printerstatus, FORMS_CHECK); - else - CLRBIT(printerstatus, FORMS_CHECK); - - btn[IDC_FORMS_CHECK].clr = (printerstatus & PRINT_CHECK) ? RGB(255,0,0) : RGB(255,255,0); - - btn[IDC_FORMS_CHECK].state = printerstatus; - - if (btn[IDC_FORMS_CHECK].hBtn != NULL) { - EnableWindow(btn[IDC_FORMS_CHECK].hBtn, printerstatus); - - if (btn[IDC_FORMS_CHECK].clr != oldcolor) - InvalidateRect(btn[IDC_FORMS_CHECK].hBtn, NULL, TRUE); // change color in any case - } -} - -void print_check (int set) -{ - COLORREF oldcolor = btn[IDC_FORMS_CHECK].clr; - - if (set) - SETBIT(printerstatus, PRINT_CHECK); - else - CLRBIT(printerstatus, PRINT_CHECK); - - btn[IDC_FORMS_CHECK].clr = (printerstatus & PRINT_CHECK) ? RGB(255,0,0) : RGB(255,255,0); - - btn[IDC_FORMS_CHECK].state = printerstatus; - - if (btn[IDC_FORMS_CHECK].hBtn != NULL) { - EnableWindow(btn[IDC_FORMS_CHECK].hBtn, printerstatus); - - if (btn[IDC_FORMS_CHECK].clr != oldcolor) - InvalidateRect(btn[IDC_FORMS_CHECK].hBtn, NULL, TRUE); // change color in any case - } -} - -void keyboard_selected (int select) -{ - btn[IDC_KEYBOARD_SELECT].state = select; - - if (btn[IDC_KEYBOARD_SELECT].hBtn != NULL) - EnableWindow(btn[IDC_KEYBOARD_SELECT].hBtn, select); -} - -void disk_ready (int ready) -{ - btn[IDC_FILE_READY].state = ready; - - if (btn[IDC_FILE_READY].hBtn != NULL) - EnableWindow(btn[IDC_FILE_READY].hBtn, ready); -} - -void disk_unlocked (int unlocked) -{ - btn[IDC_DISK_UNLOCK].state = unlocked; - - if (btn[IDC_DISK_UNLOCK].hBtn != NULL) - EnableWindow(btn[IDC_DISK_UNLOCK].hBtn, unlocked); -} - -CRITICAL_SECTION critsect; - -void begin_critical_section (void) -{ - static BOOL mustinit = TRUE; - - if (mustinit) { - InitializeCriticalSection(&critsect); - mustinit = FALSE; - } - - EnterCriticalSection(&critsect); -} - -void end_critical_section (void) -{ - LeaveCriticalSection(&critsect); -} - -#ifndef MIN -# define MIN(a,b) (((a) <= (b)) ? (a) : (b)) -#endif - -/* win32 - use a separate thread to read command lines so the GUI - * can insert commands as well */ - -static HANDLE hCmdThread = NULL; -static DWORD iCmdThreadID = 0; -static HANDLE hCmdReadEvent = NULL; -static HANDLE hCmdReadyEvent = NULL; -static BOOL scp_stuffed = FALSE, scp_reading = FALSE; -static char cmdbuffer[256]; - -/* CmdThread - separate thread to read commands from stdin upon request */ - -static DWORD WINAPI CmdThread (LPVOID arg) -{ - for (;;) { - WaitForSingleObject(hCmdReadEvent, INFINITE); /* wait for request */ - read_line(cmdbuffer, sizeof(cmdbuffer), stdin); /* read one line */ - scp_stuffed = FALSE; /* say how we got it */ - SetEvent(hCmdReadyEvent); /* notify main thread a line is ready */ - } - return 0; -} - -char *read_cmdline (char *ptr, int size, FILE *stream) -{ - char *cptr; - - if (hCmdThread == NULL) { /* set up command-reading thread */ - if ((hCmdReadEvent = CreateEvent(NULL, FALSE, FALSE, NULL)) == NULL) - scp_panic("Can't create command line read event"); - - if ((hCmdReadyEvent = CreateEvent(NULL, FALSE, FALSE, NULL)) == NULL) - scp_panic("Can't create command line ready event"); - /* start up the command thread */ - if ((hCmdThread = CreateThread(NULL, 0, CmdThread, NULL, 0, &iCmdThreadID)) == NULL) - scp_panic("Unable to create command line reading thread"); - } - - scp_reading = TRUE; - - SetEvent(hCmdReadEvent); /* let read thread get one line */ - WaitForSingleObject(hCmdReadyEvent, INFINITE); /* wait for read thread or GUI to respond */ - - scp_reading = FALSE; - - strncpy(ptr, cmdbuffer, MIN(size, sizeof(cmdbuffer))); /* copy line to caller's buffer */ - - for (cptr = ptr; isspace(*cptr); cptr++) /* absorb spaces */ - ; - - if (scp_stuffed) { /* stuffed command needs to be echoed */ - printf("%s\n", cptr); - if (sim_log) fprintf(sim_log, "%s\n", cptr); - } - - return cptr; -} - -/* stuff_cmd - force a command into the read_cmdline output buffer. Called asynchronously by GUI */ - -void stuff_cmd (char *cmd) -{ - strcpy(cmdbuffer, cmd); /* save the string */ - scp_stuffed = TRUE; /* note where it came from */ - SetEvent(hCmdReadyEvent); /* notify main thread a line is ready */ -} - -/* remark_cmd - print a remark from inside a command processor. This routine takes - * into account the possiblity that the command might have been stuffed, in which - * case the sim> prompt needs to be reprinted. - */ - -void remark_cmd (char *remark) -{ - printf("%s\n", remark); - if (sim_log) fprintf(sim_log, "%s\n", remark); - if (scp_reading) { - printf("sim> "); - if (sim_log) fprintf(sim_log, "sim> "); - } -} - -#endif // WIN32 defined -#endif // GUI_SUPPORT defined diff --git a/Ibm1130/ibm1130_prt.c b/Ibm1130/ibm1130_prt.c deleted file mode 100644 index dd3053cc..00000000 --- a/Ibm1130/ibm1130_prt.c +++ /dev/null @@ -1,773 +0,0 @@ -/* ibm1130_prt.c: IBM 1130 line printer emulation - - Based on the SIMH simulator package written by Robert M Supnik - - Brian Knittel - Revision History - 2002.09.13 - Added 1403 support. New file, taken from part of ibm1130_stddev.c - - Note: The 1403 is much faster, even in emulation, because it takes much - less CPU power to run it. DMS doesn't use the WAIT command when waiting for - printer operations to complete, so it ends up burning LOTS of cpu cycles. - The 1403 printer doesn't require as many. HOWEVER: DMS must be loaded for the 1403, - and Fortran IOCS control cards must specify it. - - The 1132 is still the default printer. - - As written, we can't have two printers. - - * (C) Copyright 2002, Brian Knittel. - * You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN - * RISK basis, there is no warranty of fitness for any purpose, and the rest of the - * usual yada-yada. Please keep this notice and the copyright in any distributions - * or modifications. - * - * This is not a supported product, but I welcome bug reports and fixes. - * Mail to simh@ibm1130.org - */ - -#include "ibm1130_defs.h" - -/*************************************************************************************** - * 1132 PRINTER - ***************************************************************************************/ - -#define PRT1132_DSW_READ_EMITTER_RESPONSE 0x8000 -#define PRT1132_DSW_SKIP_RESPONSE 0x4000 -#define PRT1132_DSW_SPACE_RESPONSE 0x2000 -#define PRT1132_DSW_CARRIAGE_BUSY 0x1000 -#define PRT1132_DSW_PRINT_SCAN_CHECK 0x0800 -#define PRT1132_DSW_NOT_READY 0x0400 -#define PRT1132_DSW_PRINTER_BUSY 0x0200 - -#define PRT1132_DSW_CHANNEL_MASK 0x00FF /* 1132 printer DSW bits */ -#define PRT1132_DSW_CHANNEL_1 0x0080 -#define PRT1132_DSW_CHANNEL_2 0x0040 -#define PRT1132_DSW_CHANNEL_3 0x0020 -#define PRT1132_DSW_CHANNEL_4 0x0010 -#define PRT1132_DSW_CHANNEL_5 0x0008 -#define PRT1132_DSW_CHANNEL_6 0x0004 -#define PRT1132_DSW_CHANNEL_9 0x0002 -#define PRT1132_DSW_CHANNEL_12 0x0001 - -#define PRT1403_DSW_PARITY_CHECK 0x8000 /* 1403 printer DSW bits */ -#define PRT1403_DSW_TRANSFER_COMPLETE 0x4000 -#define PRT1403_DSW_PRINT_COMPLETE 0x2000 -#define PRT1403_DSW_CARRIAGE_COMPLETE 0x1000 -#define PRT1403_DSW_RING_CHECK 0x0400 -#define PRT1403_DSW_SYNC_CHECK 0x0200 -#define PRT1403_DSW_CH9 0x0010 -#define PRT1403_DSW_CH12 0x0008 -#define PRT1403_DSW_CARRIAGE_BUSY 0x0004 -#define PRT1403_DSW_PRINTER_BUSY 0x0002 -#define PRT1403_DSW_NOT_READY 0x0001 - -#define IS_ONLINE(u) (((u)->flags & (UNIT_ATT|UNIT_DIS)) == UNIT_ATT) - -static t_stat prt1132_svc(UNIT *uptr); -static t_stat prt1403_svc(UNIT *uptr); -static t_stat prt_svc (UNIT *uptr); -static t_stat prt_reset (DEVICE *dptr); -static t_stat prt_attach (UNIT *uptr, char *cptr); -static t_stat prt_detach (UNIT *uptr); - -static int16 PRT_DSW = 0; /* device status word */ -static int32 prt_swait = 500; /* line skip wait */ -static int32 prt_cwait = 1250; /* character rotation wait */ -static int32 prt_fwait = 100; /* fast wait, for 1403 operations */ -static int32 prt_twait = 50; /* transfer wait, for 1403 operations */ -#define SKIPTARGET (uptr->u4) /* target for skip operation */ - -#define UNIT_V_FORMCHECK (UNIT_V_UF + 0) /* out of paper error */ -#define UNIT_V_DATACHECK (UNIT_V_UF + 1) /* printer overrun error */ -#define UNIT_V_SKIPPING (UNIT_V_UF + 2) /* printer skipping */ -#define UNIT_V_SPACING (UNIT_V_UF + 3) /* printer is spacing */ -#define UNIT_V_PRINTING (UNIT_V_UF + 4) /* printer printing */ -#define UNIT_V_TRANSFERRING (UNIT_V_UF + 5) /* unit is transferring print buffer (1403 only) */ -#define UNIT_V_1403 (UNIT_V_UF + 6) /* printer model is 1403 rather than 1132 */ -#define UNIT_V_PARITYCHECK (UNIT_V_UF + 7) /* error flags for 1403 */ -#define UNIT_V_RINGCHECK (UNIT_V_UF + 8) -#define UNIT_V_SYNCCHECK (UNIT_V_UF + 9) - -#define UNIT_FORMCHECK (1u << UNIT_V_FORMCHECK) -#define UNIT_DATACHECK (1u << UNIT_V_DATACHECK) -#define UNIT_SKIPPING (1u << UNIT_V_SKIPPING) -#define UNIT_SPACING (1u << UNIT_V_SPACING) -#define UNIT_PRINTING (1u << UNIT_V_PRINTING) -#define UNIT_TRANSFERRING (1u << UNIT_V_TRANSFERRING) -#define UNIT_1403 (1u << UNIT_V_1403) -#define UNIT_PARITYCHECK (1u << UNIT_V_PARITYCHECK) -#define UNIT_RINGCHECK (1u << UNIT_V_RINGCHECK) -#define UNIT_SYNCCHECK (1u << UNIT_V_SYNCCHECK) - -UNIT prt_unit[] = { - { UDATA (&prt_svc, UNIT_ATTABLE, 0) }, -}; - -#define IS_1403(uptr) (uptr->flags & UNIT_1403) /* model test */ -#define IS_1132(uptr) ((uptr->flags & UNIT_1403) == 0) /* model test */ - -/* Parameter in the unit descriptor (1132 printer) */ - -#define CMD_NONE 0 -#define CMD_SPACE 1 -#define CMD_SKIP 2 -#define CMD_PRINT 3 - -REG prt_reg[] = { - { HRDATA (PRTDSW, PRT_DSW, 16) }, /* device status word */ - { DRDATA (STIME, prt_swait, 24), PV_LEFT }, /* line skip wait */ - { DRDATA (CTIME, prt_cwait, 24), PV_LEFT }, /* character rotation wait */ - { DRDATA (CTIME, prt_fwait, 24), PV_LEFT }, /* 1403 fast wait */ - { DRDATA (CTIME, prt_twait, 24), PV_LEFT }, /* 1403 transfer wait */ - { NULL } }; - -MTAB prt_mod[] = { - { UNIT_1403, 0, "1132", "1132", NULL }, /* model option */ - { UNIT_1403, UNIT_1403, "1403", "1403", NULL }, - { 0 } }; - -DEVICE prt_dev = { - "PRT", prt_unit, prt_reg, prt_mod, - 1, 16, 16, 1, 16, 16, - NULL, NULL, &prt_reset, - NULL, prt_attach, prt_detach}; - -#define PRT_COLUMNS 120 -#define PRT_ROWLEN 120 -#define MAX_OVPRINT 20 - -static char prtbuf[PRT_ROWLEN*MAX_OVPRINT]; -static int nprint[PRT_COLUMNS], ncol[MAX_OVPRINT], maxnp; -static int prt_nchar, prt_row; /* current printwheel position, current page row */ -static int prt_nnl; /* number of queued newlines */ - -#define CC_CHANNEL_1 0x0800 /* carriage control tape punch values */ -#define CC_CHANNEL_2 0x0400 -#define CC_CHANNEL_3 0x0200 -#define CC_CHANNEL_4 0x0100 -#define CC_CHANNEL_5 0x0080 -#define CC_CHANNEL_6 0x0040 /* 7, 8, 10 and 11 are not used on 1132 printer */ -#define CC_CHANNEL_7 0x0020 -#define CC_CHANNEL_8 0x0010 -#define CC_CHANNEL_9 0x0008 -#define CC_CHANNEL_10 0x0004 -#define CC_CHANNEL_11 0x0002 -#define CC_CHANNEL_12 0x0001 - -#define CC_1403_BITS 0x0FFF /* all bits for 1403, most for 1132 */ -#define CC_1132_BITS (CC_1403_BITS & ~(CC_CHANNEL_7|CC_CHANNEL_8|CC_CHANNEL_10|CC_CHANNEL_11)) - -#define PRT_PAGELENGTH 66 - -static int cctape[PRT_PAGELENGTH]; /* standard carriage control tape */ - -static struct tag_ccpunches { /* list of rows and punches on tape */ - int row, channels; -} -ccpunches[] = { - 2, CC_CHANNEL_1, // channel 1 = top of form - 62, CC_CHANNEL_12 // channel 12 = bottom of form -}, -cccgi[] = { - 2, CC_CHANNEL_1 // channel 1 = top of form; no bottom of form -}; - -#include "ibm1130_prtwheel.h" - -// cc_format_1132 and cc_format_1403 - turn cctape bits into proper format for DSW or status read - -static int cc_format_1132 (int bits) -{ - return ((bits & (CC_CHANNEL_1|CC_CHANNEL_2|CC_CHANNEL_3|CC_CHANNEL_4|CC_CHANNEL_5|CC_CHANNEL_6)) >> 4) | - ((bits & CC_CHANNEL_9) >> 3) | - (bits & CC_CHANNEL_12); -} - -#define cc_format_1403(bits) (bits) - -// reset_prt_line - clear the print line following paper advancement - -static void reset_prt_line (void) -{ - memset(nprint, 0, sizeof(nprint)); - memset(ncol, 0, sizeof(ncol)); - maxnp = 0; -} - -// save_1132_prt_line - fire hammers for character 'ch' - -static t_bool save_1132_prt_line (int ch) -{ - int i, r, addr = 32; - int32 mask = 0, wd = 0; - - for (i = 0; i < PRT_COLUMNS; i++) { - if (mask == 0) { // fetch next word from memory - mask = 0x8000; - wd = M[addr++]; - } - - if (wd & mask) { // hammer is to fire in this column - if ((r = nprint[i]) < MAX_OVPRINT) { - if (ncol[r] <= i) { // we haven't moved this far yet - if (ncol[r] == 0) // first char in this row? - memset(prtbuf+r*PRT_ROWLEN, ' ', PRT_COLUMNS); // blank out the new row - ncol[r] = i+1; // remember new row length - } - prtbuf[r*PRT_ROWLEN + i] = (char) ch; // save the character - - nprint[i]++; // remember max overprintings for this column - maxnp = MAX(maxnp, nprint[i]); - } - } - - mask >>= 1; // prepare to examine next bit - } - - return wd & 1; // return TRUE if the last word has lsb set, which means all bits had been set -} - -// write_line - write collected line to output file. No need to trim spaces as the hammers -// are never fired for them, so ncol[r] is the last printed position on each line. - -static void newpage (FILE *fd) -{ - if (cgi) - fputs("
\n", fd); - else - putc('\f', fd); // formfeed -} - -static void flush_prt_line (FILE *fd, int spacemode) -{ - int r; - - if (! (spacemode || maxnp)) // nothing to do - return; - - prt_row = (prt_row+1) % PRT_PAGELENGTH; // NEXT line - - if (spacemode && ! maxnp) { // spacing only - if (prt_row == 0 && prt_nnl) { -#ifdef WIN32 - if (! cgi) - putc('\r', fd); // DOS/Windows: end with cr/lf -#endif - putc('\n', fd); // otherwise end with lf - if (spacemode & UNIT_SKIPPING) // add formfeed if we crossed page boundary while skipping - newpage(fd); - prt_nnl = 0; - } - else - prt_nnl++; - - return; - } - - if (prt_nnl) { // there are queued newlines -// if we spaced to top of form, don't emit formfeed. We'd only ever emit the formfeed if we skipped via control tape channels -// if (prt_row == 0 && prt_nnl) { // we spaced to top of form -//#ifdef WIN32 -// if (! cgi) -// putc('\r', fd); // DOS/Windows: end with cr/lf -//#endif -// putc('\n', fd); // otherwise end with lf -// newpage(fd); -// prt_nnl = 0; -// } -// else { - while (prt_nnl > 0) { // spit out queued newlines -#ifdef WIN32 - if (! cgi) - putc('\r', fd); // DOS/Windows: end with cr/lf -#endif - putc('\n', fd); // otherwise end with lf - prt_nnl--; - } -// } - } - - for (r = 0; r < maxnp; r++) { - if (r > 0) - putc('\r', fd); // carriage return between overprinted lines - fxwrite(&prtbuf[r*PRT_ROWLEN], 1, ncol[r], fd); - } - - reset_prt_line(); - - prt_nnl++; // queue a newline -} - -// 1132 printer commands - -#define PRT_CMD_START_PRINTER 0x0080 -#define PRT_CMD_STOP_PRINTER 0x0040 -#define PRT_CMD_START_CARRIAGE 0x0004 -#define PRT_CMD_STOP_CARRIAGE 0x0002 -#define PRT_CMD_SPACE 0x0001 - -#define PRT_CMD_MASK 0x00C7 - -extern char * saywhere (int addr); - -static void mytrace (int start, char *what) -{ - char *where; - - if ((where = saywhere(prev_IAR)) == NULL) where = "?"; - trace_io("%s %s at %04x: %s\n", start ? "start" : "stop", what, prev_IAR, where); -} - -/* xio_1132_printer - XIO command interpreter for the 1132 printer */ - -void xio_1132_printer (int32 iocc_addr, int32 func, int32 modify) -{ - char msg[80]; - UNIT *uptr = &prt_unit[0]; - - switch (func) { - case XIO_READ: - M[iocc_addr & mem_mask] = codewheel1132[prt_nchar].ebcdic << 8; - - if ((uptr->flags & UNIT_PRINTING) == 0) /* if we're not printing, advance this after every test */ - prt_nchar = (prt_nchar + 1) % WHEELCHARS_1132; - break; - - case XIO_SENSE_DEV: - ACC = PRT_DSW; - if (modify & 0x01) { /* reset interrupts */ - CLRBIT(PRT_DSW, PRT1132_DSW_READ_EMITTER_RESPONSE | PRT1132_DSW_SKIP_RESPONSE | PRT1132_DSW_SPACE_RESPONSE); - CLRBIT(ILSW[1], ILSW_1_1132_PRINTER); - } - break; - - case XIO_CONTROL: - if (modify & PRT_CMD_START_PRINTER) { - SETBIT(uptr->flags, UNIT_PRINTING); -// mytrace(1, "printing"); - } - - if (modify & PRT_CMD_STOP_PRINTER) { - CLRBIT(uptr->flags, UNIT_PRINTING); -// mytrace(0, "printing"); - } - - if (modify & PRT_CMD_START_CARRIAGE) { - SETBIT(uptr->flags, UNIT_SKIPPING); -// mytrace(1, "skipping"); - } - - if (modify & PRT_CMD_STOP_CARRIAGE) { - CLRBIT(uptr->flags, UNIT_SKIPPING); -// mytrace(0, "skipping"); - } - - if (modify & PRT_CMD_SPACE) { - SETBIT(uptr->flags, UNIT_SPACING); -// mytrace(1, "space"); - } - - sim_cancel(uptr); - if (uptr->flags & (UNIT_SKIPPING|UNIT_SPACING|UNIT_PRINTING)) { // busy bits = doing something - SETBIT(PRT_DSW, PRT1132_DSW_PRINTER_BUSY); - sim_activate(uptr, prt_cwait); - } - else - CLRBIT(PRT_DSW, PRT1132_DSW_PRINTER_BUSY); - - if (uptr->flags & (UNIT_SKIPPING|UNIT_SPACING)) - SETBIT(PRT_DSW, PRT1132_DSW_CARRIAGE_BUSY); - else - CLRBIT(PRT_DSW, PRT1132_DSW_CARRIAGE_BUSY); - - if ((uptr->flags & (UNIT_SKIPPING|UNIT_SPACING)) == (UNIT_SKIPPING|UNIT_SPACING)) { - sprintf(msg, "1132 printer skip and space at same time?"); - xio_error(msg); - } - break; - - default: - sprintf(msg, "Invalid 1132 printer XIO function %x", func); - xio_error(msg); - } -} - -#define SET_ACTION(u,a) {(u)->flags &= ~(UNIT_SKIPPING|UNIT_SPACING|UNIT_PRINTING|UNIT_TRANSFERRING); (u)->flags |= a;} - -static t_stat prt_svc (UNIT *uptr) -{ - return IS_1403(uptr) ? prt1403_svc(uptr) : prt1132_svc(uptr); -} - -// prt1132_svc - emulated timeout for 1132 operation - -static t_stat prt1132_svc (UNIT *uptr) -{ - if (PRT_DSW & PRT1132_DSW_NOT_READY) { // cancel operation if printer went offline - SETBIT(uptr->flags, UNIT_FORMCHECK); - SET_ACTION(uptr, 0); - forms_check(TRUE); // and turn on forms check lamp - return SCPE_OK; - } - - if (uptr->flags & UNIT_SPACING) { - flush_prt_line(uptr->fileref, UNIT_SPACING); - - CLRBIT(PRT_DSW, PRT1132_DSW_CHANNEL_MASK|PRT1132_DSW_PRINTER_BUSY|PRT1132_DSW_CARRIAGE_BUSY); - SETBIT(PRT_DSW, cc_format_1132(cctape[prt_row]) | PRT1132_DSW_SPACE_RESPONSE); - SETBIT(ILSW[1], ILSW_1_1132_PRINTER); - CLRBIT(uptr->flags, UNIT_SPACING); // done with this - calc_ints(); - } - - if (uptr->flags & UNIT_SKIPPING) { - do { - flush_prt_line(uptr->fileref, UNIT_SKIPPING); - CLRBIT(PRT_DSW, PRT1132_DSW_CHANNEL_MASK); - SETBIT(PRT_DSW, cc_format_1132(cctape[prt_row])); - } while ((cctape[prt_row] & CC_1132_BITS) == 0); // slew directly to a cc tape punch - - SETBIT(PRT_DSW, cc_format_1132(cctape[prt_row]) | PRT1132_DSW_SKIP_RESPONSE); - SETBIT(ILSW[1], ILSW_1_1132_PRINTER); - calc_ints(); - } - - if (uptr->flags & UNIT_PRINTING) { - if (! save_1132_prt_line(codewheel1132[prt_nchar].ascii)) { // save previous printed line - SETBIT(uptr->flags, UNIT_DATACHECK); // buffer wasn't set in time - SET_ACTION(uptr, 0); - print_check(TRUE); // and turn on forms check lamp - return SCPE_OK; - } - - prt_nchar = (prt_nchar + 1) % WHEELCHARS_1132; // advance print drum - - SETBIT(PRT_DSW, PRT1132_DSW_READ_EMITTER_RESPONSE); // issue interrupt to tell printer to set buffer - SETBIT(ILSW[1], ILSW_1_1132_PRINTER); // we'll save the printed stuff just before next emitter response (later than on real 1130) - calc_ints(); - } - - if (uptr->flags & (UNIT_SPACING|UNIT_SKIPPING|UNIT_PRINTING)) { // still doing something - SETBIT(PRT_DSW, PRT1132_DSW_PRINTER_BUSY); - sim_activate(uptr, prt_cwait); - } - else - CLRBIT(PRT_DSW, PRT1132_DSW_PRINTER_BUSY); - - return SCPE_OK; -} - -void save_1403_prt_line (int32 addr) -{ - int i, j, r, ch, even = TRUE; - unsigned char ebcdic; - int32 wd; - - for (i = 0; i < PRT_COLUMNS; i++) { - if (even) { // fetch next word from memory - wd = M[addr++]; - ebcdic = (unsigned char) ((wd >> 8) & 0x7F); - even = FALSE; - } - else { - ebcdic = (unsigned char) (wd & 0x7F); // use low byte of previously fetched word - even = TRUE; - } - - ch = ' '; // translate ebcdic to ascii. Don't bother checking for parity errors - for (j = 0; j < WHEELCHARS_1403; j++) { - if (codewheel1403[j].ebcdic == ebcdic) { - ch = codewheel1403[j].ascii; - break; - } - } - - if (ch > ' ') { - if ((r = nprint[i]) < MAX_OVPRINT) { - if (ncol[r] <= i) { // we haven't moved this far yet - if (ncol[r] == 0) // first char in this row? - memset(prtbuf+r*PRT_ROWLEN, ' ', PRT_COLUMNS); // blank out the new row - ncol[r] = i+1; // remember new row length - } - prtbuf[r*PRT_ROWLEN + i] = (char) ch; // save the character - - nprint[i]++; // remember max overprintings for this column - maxnp = MAX(maxnp, nprint[i]); - } - } - } -} - -void xio_1403_printer (int32 iocc_addr, int32 func, int32 modify) -{ - UNIT *uptr = &prt_unit[0]; - - switch (func) { - case XIO_INITW: /* print a line */ - save_1403_prt_line(iocc_addr); /* put formatted line into our print buffer */ - - SETBIT(uptr->flags, UNIT_TRANSFERRING); /* schedule transfer complete interrupt */ - SETBIT(PRT_DSW, PRT1403_DSW_PRINTER_BUSY); - sim_activate(uptr, prt_twait); - break; - - case XIO_CONTROL: /* initiate single space */ - if (uptr->flags & UNIT_SKIPPING) { - xio_error("1403 printer skip and space at same time?"); - } - else { - SETBIT(uptr->flags, UNIT_SPACING); - SETBIT(PRT_DSW, PRT1403_DSW_CARRIAGE_BUSY); - sim_activate(uptr, prt_fwait); - } - break; - - case XIO_WRITE: /* initiate skip */ - if (uptr->flags & UNIT_SPACING) { - xio_error("1403 printer skip and space at same time?"); - } - else { - SETBIT(uptr->flags, UNIT_SKIPPING); - SKIPTARGET = ReadW(iocc_addr) & CC_1403_BITS; /* get CC bits that we're to match */ - SETBIT(PRT_DSW, PRT1403_DSW_CARRIAGE_BUSY); - sim_activate(uptr, prt_fwait); - } - break; - - case XIO_SENSE_DEV: /* get device status word */ - ACC = PRT_DSW; - if (modify & 0x01) { /* reset interrupts */ - CLRBIT(PRT_DSW, PRT1403_DSW_PARITY_CHECK | PRT1403_DSW_TRANSFER_COMPLETE | - PRT1403_DSW_PRINT_COMPLETE | PRT1403_DSW_CARRIAGE_COMPLETE | - PRT1403_DSW_RING_CHECK | PRT1403_DSW_SYNC_CHECK); - CLRBIT(ILSW[4], ILSW_4_1403_PRINTER); - } - break; - } -} - -static t_stat prt1403_svc(UNIT *uptr) -{ - if (PRT_DSW & PRT1403_DSW_NOT_READY) { // cancel operation if printer went offline - SET_ACTION(uptr, 0); - forms_check(TRUE); // and turn on forms check lamp - } - else if (uptr->flags & UNIT_TRANSFERRING) { // end of transfer - CLRBIT(uptr->flags, UNIT_TRANSFERRING); - SETBIT(uptr->flags, UNIT_PRINTING); // schedule "print complete" - - SETBIT(PRT_DSW, PRT1403_DSW_TRANSFER_COMPLETE); // issue transfer complete interrupt - SETBIT(ILSW[4], ILSW_4_1403_PRINTER); - } - else if (uptr->flags & UNIT_PRINTING) { - CLRBIT(uptr->flags, UNIT_PRINTING); - CLRBIT(PRT_DSW, PRT1403_DSW_PRINTER_BUSY); - - SETBIT(PRT_DSW, PRT1403_DSW_PRINT_COMPLETE); - SETBIT(ILSW[4], ILSW_4_1403_PRINTER); // issue print complete interrupt - } - else if (uptr->flags & UNIT_SKIPPING) { - do { // find line with exact match of tape punches - flush_prt_line(uptr->fileref, UNIT_SKIPPING); - } while (cctape[prt_row] != SKIPTARGET); // slew directly to requested cc tape punch - - CLRBIT(uptr->flags, UNIT_SKIPPING); // done with this - CLRBIT(PRT_DSW, PRT1403_DSW_CARRIAGE_BUSY); - - SETBIT(PRT_DSW, PRT1403_DSW_CARRIAGE_COMPLETE); - SETBIT(ILSW[4], ILSW_4_1403_PRINTER); - } - else if (uptr->flags & UNIT_SPACING) { - flush_prt_line(uptr->fileref, UNIT_SPACING); - - CLRBIT(uptr->flags, UNIT_SPACING); // done with this - CLRBIT(PRT_DSW, PRT1403_DSW_CARRIAGE_BUSY); - - SETBIT(PRT_DSW, PRT1403_DSW_CARRIAGE_COMPLETE); - SETBIT(ILSW[4], ILSW_4_1403_PRINTER); - } - - if (uptr->flags & (UNIT_PRINTING|UNIT_SKIPPING|UNIT_SPACING|UNIT_TRANSFERRING)) - sim_activate(uptr, prt_fwait); - - CLRBIT(PRT_DSW, PRT1403_DSW_CH9|PRT1403_DSW_CH12); // set the two CC bits in the DSW - if (cctape[prt_row] & CC_CHANNEL_9) - SETBIT(PRT_DSW, PRT1403_DSW_CH9); - if (cctape[prt_row] & CC_CHANNEL_12) - SETBIT(PRT_DSW, PRT1403_DSW_CH12); - - calc_ints(); - return SCPE_OK; -} - -/* delete_cmd - SCP command to delete a file */ - -static t_stat delete_cmd (int flag, char *cptr) -{ - char gbuf[CBUFSIZE]; - int status; - - cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */ - if (*gbuf == 0) return SCPE_2FARG; - if (*cptr != 0) return SCPE_2MARG; /* now eol? */ - - status = unlink(gbuf); /* delete the file */ - - if (status != 0 && errno != ENOENT) /* print message if failed and file exists */ - perror(gbuf); - - return SCPE_OK; -} - -/* prt_reset - reset emulated printer */ - -static t_stat prt_reset (DEVICE *dptr) -{ - UNIT *uptr = &prt_unit[0]; - int i; - -// add a DELETE filename command so we can be sure to have clean listings - register_cmd("DELETE", &delete_cmd, 0, "del{ete} filename remove file\n"); - - sim_cancel(uptr); - - memset(cctape, 0, sizeof(cctape)); // copy punch list into carriage control tape image - - if (cgi) - for (i = 0; i < (sizeof(cccgi)/sizeof(cccgi[0])); i++) - cctape[cccgi[i].row-1] |= cccgi[i].channels; - else - for (i = 0; i < (sizeof(ccpunches)/sizeof(ccpunches[0])); i++) - cctape[ccpunches[i].row-1] |= ccpunches[i].channels; - - prt_nchar = 0; - prt_row = 0; - prt_nnl = 0; - - CLRBIT(uptr->flags, UNIT_FORMCHECK|UNIT_DATACHECK|UNIT_PRINTING|UNIT_SPACING|UNIT_SKIPPING| - UNIT_TRANSFERRING|UNIT_PARITYCHECK|UNIT_RINGCHECK|UNIT_SYNCCHECK); - - if (IS_1132(uptr)) { - CLRBIT(ILSW[1], ILSW_1_1132_PRINTER); - PRT_DSW = cc_format_1132(cctape[prt_row]); - if (! IS_ONLINE(uptr)) - SETBIT(PRT_DSW, PRT1132_DSW_NOT_READY); - } - else { - CLRBIT(ILSW[4], ILSW_4_1403_PRINTER); - PRT_DSW = 0; - if (cctape[prt_row] & CC_CHANNEL_9) - SETBIT(PRT_DSW, PRT1403_DSW_CH9); - if (cctape[prt_row] & CC_CHANNEL_12) - SETBIT(PRT_DSW, PRT1403_DSW_CH12); - if (! IS_ONLINE(uptr)) - SETBIT(PRT_DSW, PRT1403_DSW_NOT_READY); - } - - SET_ACTION(uptr, 0); - calc_ints(); - reset_prt_line(); - - forms_check(FALSE); - return SCPE_OK; -} - -static t_stat prt_attach (UNIT *uptr, char *cptr) -{ - t_stat rval; - /* assume failure */ - SETBIT(PRT_DSW, IS_1132(uptr) ? PRT1132_DSW_NOT_READY : PRT1403_DSW_NOT_READY); - - if (uptr->flags & UNIT_ATT) { - if ((rval = prt_detach(uptr)) != SCPE_OK) { - return rval; - } - } - - sim_cancel(uptr); - - if (strcmp(cptr, "-") == 0) { /* connect printer to stdout */ - if (uptr -> flags & UNIT_DIS) return SCPE_UDIS; /* disabled? */ - uptr->filename = calloc(CBUFSIZE, sizeof(char)); - strcpy(uptr->filename, "(stdout)"); - uptr->fileref = stdout; - SETBIT(uptr->flags, UNIT_ATT); - uptr->pos = 0; - } - else if ((rval = attach_unit(uptr, cptr)) != SCPE_OK) { - return rval; - } - - fseek(uptr->fileref, 0, SEEK_END); /* if we opened an existing file, append to it */ - - if (IS_1132(uptr)) { - CLRBIT(ILSW[1], ILSW_1_1132_PRINTER); - CLRBIT(uptr->flags, UNIT_FORMCHECK|UNIT_DATACHECK); - } - else { - CLRBIT(ILSW[4], ILSW_4_1403_PRINTER); - CLRBIT(uptr->flags, UNIT_PARITYCHECK|UNIT_RINGCHECK|UNIT_SYNCCHECK); - } - - SET_ACTION(uptr, 0); - calc_ints(); - - prt_nchar = 0; - prt_nnl = 0; - prt_row = 0; - reset_prt_line(); - - if (IS_1132(uptr)) { - PRT_DSW = (PRT_DSW & ~PRT1132_DSW_CHANNEL_MASK) | cc_format_1132(cctape[prt_row]); - - if (IS_ONLINE(uptr)) - CLRBIT(PRT_DSW, PRT1132_DSW_NOT_READY); - } - else { - CLRBIT(PRT_DSW, PRT1403_DSW_CH9 | PRT1403_DSW_CH12); - if (cctape[prt_row] & CC_CHANNEL_9) - SETBIT(PRT_DSW, PRT1403_DSW_CH9); - if (cctape[prt_row] & CC_CHANNEL_12) - SETBIT(PRT_DSW, PRT1403_DSW_CH12); - - if (IS_ONLINE(uptr)) - CLRBIT(PRT_DSW, PRT1132_DSW_NOT_READY); - } - - forms_check(FALSE); - return SCPE_OK; -} - -static t_stat prt_detach (UNIT *uptr) -{ - t_stat rval; - - flush_prt_line(uptr->fileref, TRUE); - - if (uptr->fileref == stdout) { - CLRBIT(uptr->flags, UNIT_ATT); - free(uptr->filename); - uptr->filename = NULL; - } - else if ((rval = detach_unit(uptr)) != SCPE_OK) - return rval; - - sim_cancel(uptr); - - if (IS_1132(uptr)) { - CLRBIT(ILSW[1], ILSW_1_1132_PRINTER); - CLRBIT(uptr->flags, UNIT_FORMCHECK|UNIT_DATACHECK); - SETBIT(PRT_DSW, PRT1132_DSW_NOT_READY); - } - else { - CLRBIT(ILSW[4], ILSW_4_1403_PRINTER); - SETBIT(PRT_DSW, PRT1403_DSW_NOT_READY); - } - SET_ACTION(uptr, 0); - - calc_ints(); - - forms_check(FALSE); - return SCPE_OK; -} diff --git a/Ibm1130/ibm1130_prtwheel.h b/Ibm1130/ibm1130_prtwheel.h deleted file mode 100644 index c39c1e59..00000000 --- a/Ibm1130/ibm1130_prtwheel.h +++ /dev/null @@ -1,126 +0,0 @@ -/* - * (C) Copyright 2002, Brian Knittel. - * You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN - * RISK basis, there is no warranty of fitness for any purpose, and the rest of the - * usual yada-yada. Please keep this notice and the copyright in any distributions - * or modifications. - * - * This is not a supported product, but I welcome bug reports and fixes. - * Mail to sim@ibm1130.org - */ - -struct tag_codewheel { - unsigned char ascii; - unsigned char ebcdic; -}; - -static struct tag_codewheel codewheel1132[] = -{ /* characters and EBCDIC codes in printwheel order */ - 'A', 0xC1, - 'B', 0xC2, - 'C', 0xC3, - 'D', 0xC4, - 'F', 0xC6, - 'H', 0xC8, - 'I', 0xC9, - 'S', 0xE2, - 'T', 0xE3, - 'U', 0xE4, - 'V', 0xE5, - '1', 0xF1, - '2', 0xF2, - '3', 0xF3, - '4', 0xF4, - '5', 0xF5, - '6', 0xF6, - '7', 0xF7, - '8', 0xF8, - '9', 0xF9, - '0', 0xF0, - '=', 0x7E, - '$', 0x5B, - '.', 0x4B, - '\'', 0x7D, - ',', 0x6B, - ')', 0x5D, - '-', 0x60, - '(', 0x4D, - '+', 0x4E, - '/', 0x61, - '*', 0x5C, - '&', 0x50, - 'J', 0xD1, - 'K', 0xD2, - 'L', 0xD3, - 'M', 0xD4, - 'N', 0xD5, - 'O', 0xD6, - 'P', 0xD7, - 'Q', 0xD8, - 'R', 0xD9, - 'E', 0xC5, - 'G', 0xC7, - 'W', 0xE6, - 'X', 0xE7, - 'Y', 0xE8, - 'Z', 0xE9, -}; - -#define WHEELCHARS_1132 (sizeof(codewheel1132)/sizeof(codewheel1132[0])) - -static struct tag_codewheel codewheel1403[] = -{ - 'A', 0x64, - 'B', 0x25, - 'C', 0x26, - 'D', 0x67, - 'E', 0x68, - 'F', 0x29, - 'G', 0x2A, - 'H', 0x6B, - 'I', 0x2C, - 'J', 0x58, - 'K', 0x19, - 'L', 0x1A, - 'M', 0x5B, - 'N', 0x1C, - 'O', 0x5D, - 'P', 0x5E, - 'Q', 0x1F, - 'R', 0x20, - 'S', 0x0D, - 'T', 0x0E, - 'U', 0x4F, - 'V', 0x10, - 'W', 0x51, - 'X', 0x52, - 'Y', 0x13, - 'Z', 0x54, - '0', 0x49, - '1', 0x40, - '2', 0x01, - '3', 0x02, - '4', 0x43, - '5', 0x04, - '6', 0x45, - '7', 0x46, - '8', 0x07, - '9', 0x08, - ' ', 0x7F, - '.', 0x6E, - '(', 0x57, - '+', 0x6D, - '&', 0x15, - '$', 0x62, - '*', 0x23, - ')', 0x2F, - '-', 0x61, - '/', 0x4C, - ',', 0x16, - '\'', 0x0B, - '=', 0x4A, -}; - -#define WHEELCHARS_1403 (sizeof(codewheel1403)/sizeof(codewheel1403[0])) - - diff --git a/Ibm1130/ibm1130_stddev.c b/Ibm1130/ibm1130_stddev.c deleted file mode 100644 index 0cc477d4..00000000 --- a/Ibm1130/ibm1130_stddev.c +++ /dev/null @@ -1,1274 +0,0 @@ -/* ibm1130_stddev.c: IBM 1130 standard I/O devices simulator - - Based on the SIMH simulator package written by Robert M Supnik - - Brian Knittel - - Revision History: - 2003.06.15 - added output translation code to accomodate APL font - added input translation feature to assist emulation of 1130 console keyboard for APL - changes to console input and output IO emulation, fixed bugs exposed by APL interpreter - - 2002.09.13 - pulled 1132 printer out of this file into ibm1130_prt.c - - * (C) Copyright 2002, Brian Knittel. - * You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN - * RISK basis, there is no warranty of fitness for any purpose, and the rest of the - * usual yada-yada. Please keep this notice and the copyright in any distributions - * or modifications. - * - * This is not a supported product, but I welcome bug reports and fixes. - * Mail to simh@ibm1130.org - * - * Notes about overstrike mapping: - * The 1130 console printer used a Selectric typewriter element. The APL interpreter - * used overprinting to construct some APL symbols, for example, a round O overstruck] - * with | to get the greek phi. This doesn't accomodate a glass terminal! Instead, - * modern APL fonts have separate character codes for the complex characters. - * To have APL\1130 output appear correctly, we have to do three things: - * - * use simh's telnet feature to connect to the 1130 console stream - * have the telnet program use an APL font - * detect combinations of overstruck symbols, and generate the approrpiate alternate codes. - * - * There is a built-in table of font mappings and overstrike mappings, for the APLPLUS.TTF - * truetype font widely available on the Internet. An font descriptor file can be used - * to specify alternate mappings. - * - * The APL font codes and overstrike mapping can be enabled with the simh command - * - * set tto apl - * - * and disabled with - * - * set tto ascii (this is the default) - * - * APL also uses the red and black ribbon selection. The emulator will output - * ansi red/black foreground commands with the setting - * - * set tto ansi - * - * The codes can be disabled with - * - * set tto noansi (this is the default) - * - * Finally, when APL mode is active, the emulator does some input key translations - * to let the standard ASCII keyboard more closely match the physical layout of the - * 1130 console keyboard. The numeric and punctuation key don't have their - * traditional meaning under APL. The input mapping lets you use the APL keyboard - * layout shown in the APL documentation. - * - * The translations are: - * FROM - * ASCII Position on keyboard To 1130 Key APL interpretation - * ------------------------------------ -------------------------------- - * [ (key to right of P) \r Enter left arrow - * ; (1st key to right of L) \b Backspace [ - * ' (2nd key to right of L) ^U Erase Fld ] - * 2 (key above Q) @ @ up shift - * 3 (key above W) % % up right shift - * 4 (key above E) * * + - * 5 (key above R) < < multiply - * 8 (key above U) - - Return - * 9 (key above I) / / Backspace - * - (key above P) ^Q INT REQ ATTN - * Enter - - Return - * backsp / / Backspace - */ - -#include "ibm1130_defs.h" -#include - -/* #define DEBUG_CONSOLE */ - -/* ---------------------------------------------------------------------------- */ - -static void badio (char *dev) -{ -// the real 1130 just ignores attempts to use uninstalled devices. They get tested -// at times, so it's best to be quiet about this -// printf("%s I/O is not yet supported", dev); -// wait_state = WAIT_INVALID_OP; -} - -void xio_1134_papertape (int32 addr, int32 func, int32 modify) {badio("papertape");} -void xio_1627_plotter (int32 addr, int32 func, int32 modify) {badio("plotter");} -void xio_1231_optical (int32 addr, int32 func, int32 modify) {badio("optical mark");} -void xio_2501_card (int32 addr, int32 func, int32 modify) {badio("2501 card");} -void xio_1131_synch (int32 addr, int32 func, int32 modify) {badio("SCA");} -void xio_system7 (int32 addr, int32 func, int32 modify) {badio("System 7");} - -/* ---------------------------------------------------------------------------- */ - -#define MAX_OUTPUT_COLUMNS 100 /* width of 1130 console printer */ -#define MAX_OS_CHARS 4 /* maximum number of overstruck characters that can be mapped */ -#define MAX_OS_MAPPINGS 100 /* maximum number of overstrike mappings */ - -typedef struct tag_os_map { /* os_map = overstrike mapping */ - int ch; /* ch = output character */ - int nin; /* nin = number of overstruck characters */ - unsigned char inlist[MAX_OS_CHARS]; /* inlist = overstruck ASCII characters, sorted. NOT NULL TERMINATED */ -} OS_MAP; - -extern UNIT *sim_clock_queue; -extern int cgi; - -static int32 tti_dsw = 0; /* device status words */ -static int32 tto_dsw = 0; -static int32 con_dsw = 0; - -static unsigned char conout_map[256]; /* 1130 console code to ASCII translation. 0 = undefined, 0xFF = IGNR_ = no output */ -static unsigned char conin_map[256]; /* input mapping */ -static int curcol = 0; /* current typewriter element column, leftmost = 0 */ -static int maxcol = 0; /* highest curcol seen in this output line */ -static char black_ribbon[30]; /* output escape sequence for black ribbon shift */ -static char red_ribbon[30]; /* output escape sequence for red ribbon shift */ - -static OS_MAP os_buf[MAX_OUTPUT_COLUMNS]; /* current typewriter output line, holds character struck in each column */ -static OS_MAP os_map[MAX_OS_MAPPINGS]; /* overstrike mapping entries */ -static int n_os_mappings; /* number of overstrike mappings */ - -static t_stat tti_svc(UNIT *uptr); -static t_stat tto_svc(UNIT *uptr); -static t_stat tti_reset(DEVICE *dptr); -static t_stat tto_reset(DEVICE *dptr); - -static t_stat emit_conout_character(int ch); -static t_stat map_conout_character(int ch); -static void reset_mapping (void); -static void set_conout_mapping(int32 flags); -static t_stat validate_conout_mapping(UNIT *uptr, int32 match, char *cvptr, void *desc); -static void set_default_mapping(int32 flags); -static void finish_conout_mapping(int32 flags); -static void strsort (int n, unsigned char *s); /* sorts an array of n characters */ -static int os_map_comp (OS_MAP *a, OS_MAP *b); /* compares two mapping entries */ -static t_stat font_cmd(int32 flag, char *cptr); /* handles font command */ -static void read_map_file(FILE *fd); /* reads a font map file */ -static t_bool str_match(char *str, char *keyword); /* keyword/string comparison */ -static char * handle_map_ansi_definition(char **pc); /* input line parsers for map file sections */ -static char * handle_map_input_definition(char **pc); -static char * handle_map_output_definition(char **pc); -static char * handle_map_overstrike_definition(char **pc); - -extern t_stat sim_poll_kbd(void); -extern t_stat sim_wait_kbd(void); -extern t_stat sim_putchar(int32 out); - -#define UNIT_V_CSET (UNIT_V_UF + 0) /* user flag: character set */ -#define UNIT_V_LOCKED (UNIT_V_UF + 2) /* user flag: keyboard locked */ -#define UNIT_V_ANSI (UNIT_V_UF + 3) - -#define CSET_ASCII (0u << UNIT_V_CSET) -#define CSET_1130 (1u << UNIT_V_CSET) -#define CSET_APL (2u << UNIT_V_CSET) -#define CSET_MASK (3u << UNIT_V_CSET) -#define ENABLE_ANSI (1u << UNIT_V_ANSI) - -#define KEYBOARD_LOCKED (1u << UNIT_V_LOCKED) - -#define IRQ_KEY 0x11 /* ctrl-Q */ -#define PROGRAM_STOP_KEY 0x10 /* ctrl-P */ - -#include "ibm1130_conout.h" /* conout_to_ascii table */ -#include "ibm1130_conin.h" /* ascii_to_conin table */ - -/* TTI data structures - - tti_dev TTI device descriptor - tti_unit TTI unit descriptor - tti_reg TTI register list -*/ - -UNIT tti_unit = { UDATA (&tti_svc, 0, 0), KBD_POLL_WAIT }; - -REG tti_reg[] = { - { ORDATA (BUF, tti_unit.buf, 16) }, - { ORDATA (DSW, tti_dsw, 16) }, - { DRDATA (POS, tti_unit.pos, 31), PV_LEFT }, - { DRDATA (STIME, tti_unit.wait, 24), REG_NZ + PV_LEFT }, - { NULL } }; - -MTAB tti_mod[] = { - { CSET_MASK, CSET_ASCII, "ASCII", "ASCII", NULL}, - { CSET_MASK, CSET_1130, "1130", "1130", NULL}, - { 0 } }; - -DEVICE tti_dev = { - "KEYBOARD", &tti_unit, tti_reg, tti_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &tti_reset, - NULL, NULL, NULL }; - -/* TTO data structures - - tto_dev TTO device descriptor - tto_unit TTO unit descriptor - tto_reg TTO register list -*/ - -UNIT tto_unit = { UDATA (&tto_svc, 0, 0), SERIAL_OUT_WAIT }; - -REG tto_reg[] = { - { ORDATA (BUF, tto_unit.buf, 16) }, - { ORDATA (DSW, tto_dsw, 16) }, - { DRDATA (POS, tto_unit.pos, 31), PV_LEFT }, - { DRDATA (STIME, tto_unit.wait, 24), PV_LEFT }, - { NULL } }; - -MTAB tto_mod[] = { - { CSET_MASK, CSET_ASCII, "ASCII", "ASCII", validate_conout_mapping, NULL, NULL}, - { CSET_MASK, CSET_1130, "1130", "1130", validate_conout_mapping, NULL, NULL}, - { CSET_MASK, CSET_APL, "APL", "APL", validate_conout_mapping, NULL, NULL}, - { ENABLE_ANSI,0, "NOANSI", "NOANSI", NULL}, - { ENABLE_ANSI,ENABLE_ANSI, "ANSI", "ANSI", NULL}, - { 0 } }; - -DEVICE tto_dev = { - "TTO", &tto_unit, tto_reg, tto_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &tto_reset, - NULL, NULL, NULL }; - -/* Terminal input routines - - tti_svc process event (character ready) - tti_reset process reset - tto_svc process event (print character) - tto_reset process reset -*/ - -#define TT_DSW_PRINTER_RESPONSE 0x8000 -#define TT_DSW_KEYBOARD_RESPONSE 0x4000 -#define TT_DSW_INTERRUPT_REQUEST 0x2000 -#define TT_DSW_KEYBOARD_CONSOLE 0x1000 -#define TT_DSW_PRINTER_BUSY 0x0800 -#define TT_DSW_PRINTER_NOT_READY 0x0400 -#define TT_DSW_KEYBOARD_BUSY 0x0200 - -void xio_1131_console (int32 iocc_addr, int32 func, int32 modify) -{ - int ch; - char msg[80]; - - switch (func) { - case XIO_CONTROL: - SETBIT(tti_dsw, TT_DSW_KEYBOARD_BUSY); /* select and unlock the keyboard */ - keyboard_selected(TRUE); - CLRBIT(tti_unit.flags, KEYBOARD_LOCKED); - tti_unit.buf = 0; /* no key character yet */ - break; - - case XIO_READ: - WriteW(iocc_addr, tti_unit.buf); /* return keycode */ - CLRBIT(tti_dsw, TT_DSW_KEYBOARD_BUSY); /* this ends selected mode */ - keyboard_selected(FALSE); - SETBIT(tti_unit.flags, KEYBOARD_LOCKED); /* keyboard is locked when not selected */ - tti_unit.buf = 0; /* subsequent reads will return zero */ - break; - - case XIO_WRITE: - ch = (ReadW(iocc_addr) >> 8) & 0xFF; /* get character to write */ - tto_unit.buf = emit_conout_character(ch); /* output character and save write status */ - - SETBIT(tto_dsw, TT_DSW_PRINTER_BUSY); - sim_activate(&tto_unit, tto_unit.wait); /* schedule interrupt */ - break; - - case XIO_SENSE_DEV: - ACC = tto_dsw | tti_dsw; - if (modify & 0x01) { /* reset interrupts */ - CLRBIT(tto_dsw, TT_DSW_PRINTER_RESPONSE); - CLRBIT(tti_dsw, TT_DSW_KEYBOARD_RESPONSE); - CLRBIT(tti_dsw, TT_DSW_INTERRUPT_REQUEST); - CLRBIT(ILSW[4], ILSW_4_CONSOLE); - } - break; - - default: - sprintf(msg, "Invalid console XIO function %x", func); - xio_error(msg); - } -} - -// emit_conout_character - write character with 1130 console code 'ch' - -t_stat emit_conout_character (int ch) -{ - t_stat status; - -#ifdef DEBUG_CONSOLE - printf("{%02x}", ch); -#endif - - if ((tto_unit.flags & CSET_MASK) == CSET_1130) /* 1130 (binary) mode, write the raw 8-bit value */ - return sim_putchar(ch); - - if (ch & COUT_IS_CTRL) { - /* red/black shift can be combined with another control */ - /* if present, emit the color shift characters alone */ - - if (ch & COUT_CTRL_BLACK) { - if ((status = map_conout_character(COUT_IS_CTRL|COUT_CTRL_BLACK)) != SCPE_OK) - return status; - } - else if (ch & COUT_CTRL_RED) { - if ((status = map_conout_character(COUT_IS_CTRL|COUT_CTRL_RED)) != SCPE_OK) - return status; - } - - ch &= ~(COUT_CTRL_BLACK|COUT_CTRL_RED); /* remove the ribbon shift bits */ - - if (ch & ~COUT_IS_CTRL) { /* if another control remains, emit it */ - if ((status = map_conout_character(ch)) != SCPE_OK) - return status; - } - - return SCPE_OK; - } - - return map_conout_character(ch); -} - -static void Beep (void) // notify user keyboard was locked or key was bad -{ - sim_putchar(7); -} - -// tti_svc - keyboard polling (never stops) - -static t_stat tti_svc (UNIT *uptr) -{ - int32 temp; - - if (cgi) /* if running in CGI mode, no keyboard and no keyboard polling! */ - return SCPE_OK; - /* otherwise, so ^E can interrupt the simulator, */ - sim_activate(&tti_unit, tti_unit.wait); /* always continue polling keyboard */ - - temp = sim_poll_kbd(); - - if (temp < SCPE_KFLAG) - return temp; /* no char or error? */ - - temp &= 0xFF; /* remove SCPE_KFLAG */ - - if ((tti_unit.flags & CSET_MASK) == CSET_ASCII) - temp = conin_map[temp] & 0xFF; /* perform input translation */ - - if (temp == IRQ_KEY) { /* INT REQ (interrupt request) key */ - SETBIT(tti_dsw, TT_DSW_INTERRUPT_REQUEST); /* queue interrupt */ - SETBIT(ILSW[4], ILSW_4_CONSOLE); - calc_ints(); - - CLRBIT(tti_unit.flags, KEYBOARD_LOCKED); /* keyboard restore, according to func. char. manual */ - -#ifdef DEBUG_CONSOLE - printf("[*IRQ*]"); -#endif - tti_unit.buf = 0; /* subsequent reads need to return 0 (required by APL\1130) */ - return SCPE_OK; - } - - if (temp == PROGRAM_STOP_KEY) { /* simulate the program stop button */ - SETBIT(con_dsw, CPU_DSW_PROGRAM_STOP); - SETBIT(ILSW[5], ILSW_5_PROGRAM_STOP); - calc_ints(); - -#ifdef DEBUG_CONSOLE - printf("[*PSTOP*]"); -#endif - - return SCPE_OK; - } - - if ((tti_unit.flags & KEYBOARD_LOCKED) || ! (tti_dsw & TT_DSW_KEYBOARD_BUSY)) { - Beep(); - return SCPE_OK; - } - - if ((tti_unit.flags & CSET_MASK) == CSET_ASCII) - temp = ascii_to_conin[temp]; - - if (temp == 0) { /* ignore invalid characters */ - Beep(); - calc_ints(); - return SCPE_OK; - } - - tti_unit.buf = temp & 0xFFFE; /* save keystroke except last bit (not defined) */ - tti_unit.pos = tti_unit.pos + 1; /* but it lets us distinguish 0 from no punch ' ' */ - -#ifdef DEBUG_CONSOLE - printf("[%04x]", tti_unit.buf & 0xFFFF); -#endif - -// CLRBIT(tti_dsw, TT_DSW_KEYBOARD_BUSY); /* clear busy flag (unselect keyboard) */ -// keyboard_selected(FALSE); - - SETBIT(tti_unit.flags, KEYBOARD_LOCKED); /* prevent further keystrokes */ - - SETBIT(tti_dsw, TT_DSW_KEYBOARD_RESPONSE); /* queue interrupt */ - SETBIT(ILSW[4], ILSW_4_CONSOLE); - calc_ints(); - - return SCPE_OK; -} - -static t_stat tti_reset (DEVICE *dptr) -{ - tti_unit.buf = 0; - tti_dsw = 0; - - CLRBIT(ILSW[4], ILSW_4_CONSOLE); - calc_ints(); - keyboard_selected(FALSE); - - SETBIT(tti_unit.flags, KEYBOARD_LOCKED); - - if (cgi) - sim_cancel(&tti_unit); /* in cgi mode, never poll keyboard */ - else - sim_activate(&tti_unit, tti_unit.wait); /* otherwise, always poll keyboard */ - - return SCPE_OK; -} - -t_bool keyboard_is_busy (void) /* return TRUE if keyboard is not expecting a character */ -{ - return (tti_dsw & TT_DSW_KEYBOARD_BUSY); -} - -static t_stat tto_svc (UNIT *uptr) -{ - CLRBIT(tto_dsw, TT_DSW_PRINTER_BUSY); - SETBIT(tto_dsw, TT_DSW_PRINTER_RESPONSE); - - SETBIT(ILSW[4], ILSW_4_CONSOLE); - calc_ints(); - - return (t_stat) tto_unit.buf; /* return status saved during output conversion */ -} - -static t_stat tto_reset (DEVICE *dptr) -{ - tto_unit.buf = 0; - tto_dsw = 0; - - CLRBIT(ILSW[4], ILSW_4_CONSOLE); - calc_ints(); - - sim_cancel(&tto_unit); /* deactivate unit */ - - set_conout_mapping(tto_unit.flags); /* initialize the overstrike mappings */ - /* register the font-mapping command */ - register_cmd("FONT", font_cmd, 0, "font MAPFILE use font mapping definitions in MAPFILE\n"); - - return SCPE_OK; -} - -#ifdef _MSC_VER -# pragma warning(disable:4245) /* enable int->char demotion warning caused by characters with high-bit set */ -#endif - -static struct { /* default input mapping for APL */ - unsigned char in; - unsigned char out; -} conin_to_APL[] = -{ /* these map input keys to those in like positions on 1130 keyboard */ - '[', '\r', /* enter (EOF) is APL left arrow */ - ';', '\b', /* backspace is APL [ */ - '\'', '\x15', /* ctrl-U, erase field, is APL ]*/ - '2', '@', /* APL upshift */ - '3', '%', /* APL rightshift */ - '4', '*', /* APL + and - */ - '5', '<', /* APL x and divide */ - '8', '-', /* APL return */ - '9', '/', /* APL backspace */ - '-', IRQ_KEY, /* ctrl-q (INT REQ), APL ATTN */ - '\r', '-', /* APL return */ - '\b', '/' /* APL backspace */ -}; - -#define NCONIN_TO_APL (sizeof(conin_to_APL)/sizeof(conin_to_APL[0])) - -static struct { /* default output mapping for APLPLUS font */ - unsigned char in; - unsigned char out; -} conout_to_APL[] = -{ - '\x01', IGNR_, /* controls */ - '\x03', '\n', - '\x05', IGNR_, /* (black and red are handled by ansi sequences) */ - '\x09', IGNR_, - '\x11', '\b', - '\x21', ' ', - '\x41', '\t', - '\x81', CRLF_, - - '\xC4', '\x30', /* (if you're curious, order here is position on APL typeball) */ - '\xE4', '\x38', - '\xD4', '\x37', - '\xF4', '\x35', - '\xDC', '\x33', - '\xFC', '\x31', - '\xC2', '\x29', - '\xE2', '\x9F', - '\xD2', '\x89', - '\xF2', '\x88', - '\xDA', '\xAF', - '\xC6', '\x5E', - '\xE6', '\xAC', - '\xD6', '\x3E', - '\xF6', '\x3D', - '\xDE', '\x3C', - '\xFE', '\xA8', - '\xC0', '\x5D', - '\xE0', '\x39', - '\xD0', '\x36', - '\xF0', '\x34', - '\xD8', '\x32', - - '\x84', '\x84', - '\xA4', '\x59', - '\x94', '\x58', - '\xB4', '\x56', - '\x9C', '\x54', - '\xBC', '\x2F', - '\x82', '\x3B', - '\xA2', '\x9B', - '\x92', '\xBE', - '\xB2', '\x87', - '\x9A', '\x97', - '\x86', '\x85', - '\xA6', '\x86', - '\x96', '\x9C', - '\xB6', '\x9E', - '\x9E', '\x7E', - '\xBE', '\x5C', - '\x80', '\x2C', - '\xA0', '\x5A', - '\x90', '\x57', - '\xB0', '\x55', - '\x98', '\x53', - - '\x44', '\x2B', - '\x64', '\x51', - '\x54', '\x50', - '\x74', '\x4E', - '\x5C', '\x4C', - '\x7C', '\x4A', - '\x42', '\x28', - '\x62', '\xBD', - '\x52', '\xB1', - '\x72', '\x7C', - '\x5A', '\x27', - '\x46', '\x2D', - '\x66', '\x3F', - '\x56', '\x2A', - '\x76', '\x82', - '\x5E', '\x8C', - '\x7E', '\xB0', - '\x40', '\x5B', - '\x60', '\x52', - '\x50', '\x4F', - '\x70', '\x4D', - '\x58', '\x4B', - - '\x04', '\xD7', - '\x24', '\x48', - '\x14', '\x47', - '\x34', '\x45', - '\x1C', '\x43', - '\x3C', '\x41', - '\x02', '\x3A', - '\x22', '\xBC', - '\x12', '\x5F', - '\x32', '\x98', - '\x1A', '\x83', - '\x06', '\xF7', - '\x26', '\x91', - '\x16', '\x92', - '\x36', '\xB9', - '\x1E', '\x9D', - '\x3E', '\xB8', - '\x00', '\x2E', - '\x20', '\x49', - '\x10', '\x46', - '\x30', '\x44', - '\x18', '\x42', -}; - -#define NCONOUT_TO_APL (sizeof(conout_to_APL)/sizeof(conout_to_APL[0])) - -static OS_MAP default_os_map[] = // overstrike mapping for APLPLUS font -{ - '\x8a', 2, "\x5e\x7e", - '\x8b', 2, "\x9f\x7e", - '\x8d', 2, "\x8c\x27", - '\x8e', 3, "\x8c\x2d\x3a", - '\x8f', 2, "\x91\x5f", - '\x90', 2, "\x92\x7e", - '\x93', 2, "\x91\x7c", - '\x94', 2, "\x92\x7c", - '\x95', 2, "\xb0\x82", - '\x96', 2, "\xb0\x83", - '\x99', 2, "\x2d\x5c", - '\x9a', 2, "\x2d\x2f", - '\xae', 2, "\x2c\x2d", - '\xb2', 2, "\xb1\x7c", - '\xb3', 2, "\xb1\x5c", - '\xb4', 2, "\xb1\x2d", - '\xb5', 2, "\xb1\x2a", - '\xba', 2, "\xb9\x5f", - '\xd0', 2, "\x30\x7e", - '\xd8', 2, "\x4f\x2f", - '\x21', 2, "\x27\x2e", - '\xa4', 2, "\xb0\xb1", /* map degree in circle to circle cross (APL uses this as character error symbol) */ - '\xf0', 2, "\xb0\xa8", - '\xfe', 2, "\x3a\xa8", -}; - -#ifdef _MSC_VER -# pragma warning(default:4245) /* enable int->char demotion warning */ -#endif - -/* os_map_comp - compare to OS_MAP entries */ - -static int os_map_comp (OS_MAP *a, OS_MAP *b) -{ - unsigned char *sa, *sb; - int i; - - if (a->nin > b->nin) - return +1; - - if (a->nin < b->nin) - return -1; - - sa = a->inlist; - sb = b->inlist; - - for (i = a->nin; --i >= 0;) { - if (*sa > *sb) - return +1; - - if (*sa < *sb) - return -1; - - sa++; - sb++; - } - - return 0; -} - -/* strsort - sorts the n characters of array 's' using insertion sort */ - -static void strsort (int n, unsigned char *s) -{ - unsigned char temp; - int i, big; - - while (--n > 0) { // repeatedly - big = 0; // find largest value of s[0]...s[n] - for (i = 1; i <= n; i++) - if (s[i] > s[big]) big = i; - - temp = s[n]; // put largest value at end of array - s[n] = s[big]; - s[big] = temp; - } -} - -/* file format: - -[font XXX] // font named XXX -OUT // failure character -OUT IN // single character mapping -OUT IN IN ... // overstrike mapping - -*/ - -static void set_conout_mapping (int32 flags) -{ - curcol = 0; - maxcol = 0; - - // set the default mappings. We may later override them with settings from an ini file - - set_default_mapping(flags); -} - -// finish_conout_mapping - sort the finalized overstrike mapping - -static void finish_conout_mapping (int32 flags) -{ - int i, n, big; - OS_MAP temp; - - for (i = 0; i < n_os_mappings; i++) // sort the inlist strings individually - strsort(os_map[i].nin, os_map[i].inlist); - - for (n = n_os_mappings; --n > 0; ) { // then sort the os_map array itself with insertion sort - big = 0; // find largest value of s[0]...s[n] - for (i = 1; i <= n; i++) - if (os_map_comp(os_map+i, os_map+big) > 0) big = i; - - if (big != n) { - temp = os_map[n]; // put largest value at end of array - os_map[n] = os_map[big]; - os_map[big] = temp; - } - } -} - -// validate_conout_mapping - called when set command gets a new value - -static t_stat validate_conout_mapping (UNIT *uptr, int32 match, char *cvptr, void *desc) -{ - set_conout_mapping(match); - return SCPE_OK; -} - -static void reset_mapping (void) -{ - int i; - - black_ribbon[0] = '\0'; /* erase the ribbon sequences */ - red_ribbon[0] = '\0'; - - memset(conout_map, 0, sizeof(conout_map)); /* erase output mapping */ - - n_os_mappings = 0; /* erase overstrike mapping */ - - for (i = (sizeof(conin_map)/sizeof(conin_map[0])); --i >= 0; ) - conin_map[i] = (unsigned char) i; /* default conin_map is identity map */ -} - -// set_default_mapping - create standard font and overstrike map - -static void set_default_mapping (int32 flags) -{ - int i; - - reset_mapping(); - - strcpy(black_ribbon, "\033[30m"); - strcpy(red_ribbon, "\033[31m"); - - switch (flags & CSET_MASK) { - case CSET_1130: - break; - - case CSET_ASCII: - memcpy(conout_map, conout_to_ascii, sizeof(conout_to_ascii)); - break; - - case CSET_APL: - for (i = NCONOUT_TO_APL; --i >= 0; ) - conout_map[conout_to_APL[i].in] = conout_to_APL[i].out; - - for (i = NCONIN_TO_APL; --i >= 0; ) - conin_map[conin_to_APL[i].in] = conin_to_APL[i].out; - - memcpy(os_map, default_os_map, sizeof(default_os_map)); - n_os_mappings = (sizeof(default_os_map) / sizeof(default_os_map[0])); - break; - } - - finish_conout_mapping(flags); // sort conout mapping if necessary -} - -// sim_putstr - write a string to the console - -t_stat sim_putstr (char *s) -{ - t_stat status; - - while (*s) { - if ((status = sim_putchar(*s)) != SCPE_OK) - return status; - - s++; - } - - return SCPE_OK; -} - -// map_conout_character - translate and write a single character - -static t_stat map_conout_character (int ch) -{ - t_stat status; - int i, cmp; - - if (ch == (COUT_IS_CTRL|COUT_CTRL_BLACK)) - return (tto_unit.flags & ENABLE_ANSI) ? sim_putstr(black_ribbon) : SCPE_OK; - - if (ch == (COUT_IS_CTRL|COUT_CTRL_RED)) - return (tto_unit.flags & ENABLE_ANSI) ? sim_putstr(red_ribbon) : SCPE_OK; - - if ((ch = conout_map[ch & 0xFF]) == 0) - ch = '?'; // unknown character? print ? - - if (ch == '\n') { // newline: reset overstrike buffer - curcol = 0; - maxcol = -1; - } - else if (ch == '\r') { // carriage return: rewind to column 0 - curcol = 0; - maxcol = -1; // assume it advances paper too - } - else if (ch == '\b') { // backspace: back up one character - if (curcol > 0) - curcol--; - } - else if (n_os_mappings && ch != (unsigned char) IGNR_) { - if (curcol > maxcol) { // first time in this column, no overstrike possible yet - os_buf[curcol].nin = 0; - maxcol = curcol; - } - - if (ch != ' ' && ch != 0) { // (if it's not a blank or unknown) - os_buf[curcol].inlist[os_buf[curcol].nin] = (unsigned char) ch; - strsort(++os_buf[curcol].nin, os_buf[curcol].inlist); - } - - if (os_buf[curcol].nin == 0) // if nothing but blanks seen, - ch = ' '; // output is a blank - else if (os_buf[curcol].nin == 1) { // if only one printing character seen, display it - ch = os_buf[curcol].inlist[0]; - } - else { // otherwise look up mapping - ch = '?'; - - for (i = 0; i < n_os_mappings; i++) { - cmp = os_map_comp(&os_buf[curcol], &os_map[i]); - if (cmp == 0) { // a hit - ch = os_map[i].ch; - break; - } - else if (cmp < 0) // not found - break; - } - } - - if (curcol < MAX_OUTPUT_COLUMNS) - curcol++; - } - - switch (ch) { - case IGNR_: - break; - - case CRLF_: - if (! cgi) { - if ((status = sim_putchar('\r')) != SCPE_OK) - return status; - - tto_unit.pos++; - } - - if ((status = sim_putchar('\n')) != SCPE_OK) - return status; - - tto_unit.pos++; /* hmm, why do we count these? */ - break; - - default: - if ((status = sim_putchar(ch)) != SCPE_OK) - return status; - - tto_unit.pos++; - break; - } - - return SCPE_OK; -} - -/* font_cmd - parse a font mapping file. Sets input and output translations */ - -static t_stat font_cmd (int32 flag, char *cptr) -{ - char *fname, quote; - FILE *fd; - - while (*cptr && (*cptr <= ' ')) cptr++; /* skip blanks */ - if (! *cptr) return SCPE_2FARG; /* argument missing */ - - fname = cptr; /* save start */ - while (*cptr && (*cptr > ' ')) { - if (*cptr == '\'' || *cptr == '"') { /* quoted string */ - quote = *cptr; /* remember quote character */ - strcpy(cptr, cptr+1); /* slide string down over the quote */ - - while (*cptr && *cptr != quote) /* find closing quote */ - cptr++; - - if (*cptr == quote) /* if closer was found, slide down over it */ - strcpy(cptr, cptr+1); - } - else /* skip over regular character */ - cptr++; - } - *cptr = '\0'; /* terminate name */ - - if ((fd = fopen(fname, "r")) == NULL) - return SCPE_OPENERR; - - reset_mapping(); /* remove all default mappings */ - - read_map_file(fd); - fclose(fd); - - finish_conout_mapping(tto_unit.flags); - return SCPE_OK; -} - -/* str_match - compare the string str to the keyword, case insensitive */ - -static t_bool str_match (char *str, char *keyword) -{ - char kch, sch; - - while (*keyword) { /* see if str matches the keyword... */ - kch = *keyword++; /* get pair of characters */ - sch = *str++; - - if (BETWEEN(kch, 'A', 'Z')) kch += 32; /* change upper to lower case */ - if (BETWEEN(sch, 'A', 'Z')) sch += 32; - - if (kch != sch) /* characters must match; if not, quit */ - return FALSE; - } - - return *str <= ' ' || *str == ';'; /* success if the input string ended or is in whitespace or comment */ -} - -/* read_map_file - process definition lines in opened mapping file */ - -static void read_map_file (FILE *fd) -{ - char str[256], *c, *errmsg; - int lineno = 0; - enum {SECT_UNDEFINED, SECT_DEFAULT, SECT_ANSI, SECT_INPUT, SECT_OUTPUT, SECT_OVERSTRIKE} - section = SECT_UNDEFINED; - - while (fgets(str, sizeof(str), fd) != NULL) { - ++lineno; /* count input lines */ - - if ((c = strchr(str, '\n')) != NULL) /* terminate at newline */ - *c = '\0'; - - for (c = str; *c && *c <= ' '; c++) /* skip blanks */ - ; - - if (c[0] == '\0' || c[0] == ';') /* ignore blank lines and lines starting with ; */ - continue; - - if (*c == '[') { - if (str_match(c, "[default]")) { /* check for section separators */ - set_default_mapping(tto_unit.flags); - section = SECT_UNDEFINED; - continue; - } - if (str_match(c, "[ansi]")) { - section = SECT_ANSI; - continue; - } - if (str_match(c, "[input]")) { - section = SECT_INPUT; - continue; - } - if (str_match(c, "[output]")) { - section = SECT_OUTPUT; - continue; - } - if (str_match(c, "[overstrike]")) { - section = SECT_OVERSTRIKE; - continue; - } - } - - switch (section) { /* if we get here, we have a definition line */ - case SECT_ANSI: - errmsg = handle_map_ansi_definition(&c); - break; - case SECT_INPUT: - errmsg = handle_map_input_definition(&c); - break; - case SECT_OUTPUT: - errmsg = handle_map_output_definition(&c); - break; - case SECT_OVERSTRIKE: - errmsg = handle_map_overstrike_definition(&c); - break; - default: - errmsg = "line occurs before valid [section]"; - break; - } - - if (errmsg == NULL) { /* if no other error detected, */ - while (*c && *c <= ' ') /* skip past any whitespace */ - c++; - - if (*c && *c != ';') /* if line doesn't end or run into a comment, complain */ - errmsg = "too much stuff on input line"; - } - - if (errmsg != NULL) { /* print error message and offending line */ - printf("* Warning: %s", errmsg); - - switch (section) { /* add section name if possible */ - case SECT_ANSI: errmsg = "ansi"; break; - case SECT_INPUT: errmsg = "input"; break; - case SECT_OUTPUT: errmsg = "output"; break; - case SECT_OVERSTRIKE: errmsg = "overstrike"; break; - default: errmsg = NULL; break; - } - if (errmsg != NULL) - printf(" in [%s] section", errmsg); - - printf(", line %d\n%s\n", lineno, str); - } - } -} - -/* get_num_char - read an octal or hex character specification of exactly 'ndigits' digits - * the input pointers is left pointing to the last character of the number, so that it - * may be incremented by the caller - */ - -static char * get_num_char (char **pc, unsigned char *out, int ndigits, int base, char *errmsg) -{ - unsigned char ch = 0, digit; - char *c = *pc; - - while (--ndigits >= 0) { /* collect specified number of digits */ - if (BETWEEN(*c, '0', '9')) - digit = *c - '0'; - else if (BETWEEN(*c, 'A', 'F')) - digit = *c - 'A' + 10; - else if (BETWEEN(*c, 'a', 'f')) - digit = *c - 'a' + 10; - else - digit = base; - - if (digit >= base) /* bad digit */ - return errmsg; - - ch = ch * base + digit; /* accumulate digit */ - c++; - } - - *out = ch; /* return parsed character */ - *pc = c-1; /* make input pointer point to last character seen */ - return NULL; /* no error */ -} - -/* get_characters - read character specification(s) from input string pointed to - * by *pc. Results stored in outstr; up to nmax characters parsed. Actual number - * found returned in *nout. Returns NULL on success or error message if syntax - * error encountered. *pc is advanced to next whitespace or whatever followed input. - */ - -static char * get_characters (char **pc, char *outstr, int nmax, int *nout) -{ - char *c = *pc, *out = outstr, *errstr; - - while (*c && *c <= ' ') /* skip leading whitespace */ - c++; - - while (--nmax >= 0) { /* get up to maximum number of characters */ - if (*c == ';' || *c <= ' ') /* we ran into a comment, whitespace or end of string: we're done */ - break; - - if (*c == '\\') { /* backslash escape of some sort */ - switch (*++c) { - case 'b': /* backspace */ - case 'B': - *out++ = '\b'; - break; - - case 'e': /* ascii ESCAPE */ - case 'E': - *out++ = '\033'; - break; - - case 'f': /* formfeed */ - case 'F': - *out++ = '\f'; - break; - - case 'n': /* newline */ - case 'N': - *out++ = '\n'; - break; - - case 'r': /* return */ - case 'R': - *out++ = '\r'; - break; - - case 't': /* tab */ - case 'T': - *out++ = '\t'; - break; - - case 'x': /* hex specification */ - case 'X': - c++; - if ((errstr = get_num_char(&c, out, 2, 16, "bad hex character")) != NULL) - return errstr; - - out++; /* advance out pointer */ - break; - - default: /* anything else */ - if (BETWEEN(*c, '0', '7')) { /* octal specification */ - if ((errstr = get_num_char(&c, out, 3, 8, "bad octal character")) != NULL) - return errstr; - - out++; /* advance out pointer */ - } - else if (BETWEEN(*c, 'A', 'Z') || BETWEEN(*c, 'a', 'z')) - return "invalid \\ escape"; /* other \x letters are bad */ - else { - *out++ = *c; /* otherwise, accept \x as literal character x */ - } - break; - } - } - else if (*c == '^') { /* control character */ - c++; - if (BETWEEN(*c, 'A', 'Z')) /* convert alpha, e.g. A -> 1 */ - *out++ = *c - 'A' + 1; - else if (BETWEEN(*c, 'a', 'z')) - *out++ = *c - 'z' + 1; - else /* non alpha is bad */ - return "invalid control letter"; - } - else if (str_match(c, "IGNORE")) { /* magic word: a character that will never be output */ - *out++ = IGNR_; - c += 6; - } - else { - *out++ = *c; /* save literal character */ - } - - c++; - } - - if (*c && *c != ';' && *c > ' ') /* we should be at end of string, whitespace or comment */ - return "too many characters specified"; - - *pc = c; /* save advanced pointer */ - *nout = out-outstr; /* save number of characters stored */ - - return NULL; /* no error */ -} - -/* handle_map_ansi_definition - process line in [ansi] section */ - -static char * handle_map_ansi_definition (char **pc) -{ - char *outstr, *errmsg; - int n; - - if (str_match(*pc, "black")) { /* find which string we're setting */ - outstr = black_ribbon; /* this is where we'll save the output string */ - *pc += 5; /* skip over the token */ - } - else if (str_match(*pc, "red")) { - outstr = red_ribbon; - *pc += 3; - } - else - return "invalid variable name"; - /* get list of characters */ - if ((errmsg = get_characters(pc, outstr, sizeof(black_ribbon)-1, &n)) != NULL) - return errmsg; - - outstr[n] = '\0'; /* null terminate the string */ - - return (n > 0) ? NULL : "missing output string"; /* NULL if OK, error msg if no characters */ -} - -/* handle_map_input_definition - process line in [input] section */ - -static char * handle_map_input_definition (char **pc) -{ - unsigned char cin, cout; - char *errmsg; - int n; - - if ((errmsg = get_characters(pc, &cin, 1, &n)) != NULL) /* get input character */ - return errmsg; - - if (n != 1) - return "missing input character"; - - if ((errmsg = get_characters(pc, &cout, 1, &n)) != NULL) /* get output character */ - return errmsg; - - if (n != 1) - return "missing output character"; - - conin_map[cin] = cout; /* set the mapping */ - return NULL; -} - -/* handle_map_output_definition - process line in [output] section */ - -static char * handle_map_output_definition (char **pc) -{ - unsigned char cin, cout; - char *errmsg; - int n; - - if ((errmsg = get_characters(pc, &cin, 1, &n)) != NULL) /* get input character */ - return errmsg; - - if (n != 1) - return "missing input character"; - - if ((errmsg = get_characters(pc, &cout, 1, &n)) != NULL) /* get output character */ - return errmsg; - - if (n != 1) - return "missing output character"; - - conout_map[cin] = cout; /* set the mapping */ - return NULL; -} - -/* handle_map_overstrike_definition - process line in [overstrike] section */ - -static char * handle_map_overstrike_definition (char **pc) -{ - unsigned char ch, inlist[MAX_OS_CHARS]; - char *errmsg; - int nin; - - if (n_os_mappings >= MAX_OS_MAPPINGS) /* os_map is full, no more room */ - return "too many overstrike mappings"; - /* get output character */ - if ((errmsg = get_characters(pc, &ch, 1, &nin)) != NULL) - return errmsg; - - if (nin != 1) - return "missing output character"; - /* get input list */ - if ((errmsg = get_characters(pc, inlist, MAX_OS_CHARS, &nin)) != NULL) - return errmsg; - - if (nin < 2) /* expect at least two characters overprinted */ - return "missing input list"; - - os_map[n_os_mappings].ch = ch; /* save in next os_map slot */ - os_map[n_os_mappings].nin = nin; - memmove(os_map[n_os_mappings].inlist, inlist, nin); - - n_os_mappings++; - return NULL; -} diff --git a/Ibm1130/ibm1130_sys.c b/Ibm1130/ibm1130_sys.c deleted file mode 100644 index ba3a4f49..00000000 --- a/Ibm1130/ibm1130_sys.c +++ /dev/null @@ -1,495 +0,0 @@ -/* ibm1130_sys.c: IBM 1130 simulator interface - - Based on PDP-11 simulator written by Robert M Supnik - - Revision History - 0.26 2002Apr24 - Added !BREAK in card deck file to stop simulator - 0.25 2002Apr18 - Fixed some card reader problems. It starts the reader - properly if you attach a deck while it's waiting to a read. - 0.24 2002Mar27 - Fixed BOSC bug; BOSC works in short instructions too - 0.23 2002Feb26 - Added @decklist feature for ATTACH CR. - 0.22 2002Feb26 - Replaced "strupr" with "upcase" for compatibility. - 0.21 2002Feb25 - Some compiler compatibiity changes, couple of compiler-detected - bugs - 0.01 2001Jul31 - Derived from pdp11_sys.c, which carries this disclaimer: - - * (C) Copyright 2002, Brian Knittel. - * You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN - * RISK basis, there is no warranty of fitness for any purpose, and the rest of the - * usual yada-yada. Please keep this notice and the copyright in any distributions - * or modifications. - * - * This is not a supported product, but I welcome bug reports and fixes. - * Mail to simh@ibm1130.org - */ - -#include "ibm1130_defs.h" -#include -#include - -extern DEVICE cpu_dev, console_dev, dsk_dev, cr_dev, cp_dev; -extern DEVICE tti_dev, tto_dev, prt_dev, log_dev; -extern DEVICE gdu_dev, console_dev; - -extern UNIT cpu_unit; -extern REG cpu_reg[]; -extern int32 saved_PC; - -/* 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[] = "IBM 1130"; -char sim_version[] = "V0.30"; - -REG *sim_PC = &cpu_reg[0]; - -int32 sim_emax = 4; - -DEVICE *sim_devices[] = { - &cpu_dev, /* the cpu */ - &dsk_dev, /* disk drive(s) */ - &cr_dev, /* card reader/punch */ - &cp_dev, - &tti_dev, /* console keyboard, selectric printer */ - &tto_dev, - &prt_dev, /* 1132 printer */ - &console_dev, /* console display (windows GUI) */ - &gdu_dev, /* 2250 display */ - NULL -}; - -const char *sim_stop_messages[] = { - "Unknown error", - "Wait", - "Invalid command", - "Simulator breakpoint", - "Use of incomplete simulator function", - "Power off", - "!BREAK in card deck file", - "Phase load break", - "Program has run amok", - "Run time limit exceeded" -}; - -/* Loader. IPL is normally performed by card reader (boot command). This function - * loads hex data from a file for testing purposes. The format is: - * - * blank lines or lines starting with ; / or # are ignored as comments - * - * @XXXX set load addresss to hex value XXXX - * XXXX store hex word value XXXX at current load address and increment address - * ... - * =XXXX set IAR to hex value XXXX - * ZXXXX zero XXXX words and increment load address - * SXXXX set console entry switches to XXXX. This lets a program specify the - * default value for the toggle switches. - * - * Multiple @ and data sections may be entered. If more than one = or S value is specified - * the last one wins. - * - * Note: the load address @XXXX and data values XXXX can be followed by the letter - * R to indicate that the values are relocatable addresses. This is ignored in this loader, - * but the asm1130 cross assembler may put them there. - */ - -t_stat my_load (FILE *fileref, char *cptr, char *fnam) -{ - char line[150], *c; - int iaddr = -1, runaddr = -1, val, nwords; - - while (fgets(line, sizeof(line), fileref) != NULL) { - for (c = line; *c && *c <= ' '; c++) // find first nonblank - ; - - if (*c == '\0' || *c == '#' || *c == '/' || *c == ';') - continue; // empty line or comment - - if (*c == '@') { // set load address - if (sscanf(c+1, "%x", &iaddr) != 1) - return SCPE_FMT; - } - else if (*c == '=') { - if (sscanf(c+1, "%x", &runaddr) != 1) - return SCPE_FMT; - } - else if (*c == 's' || *c == 'S') { - if (sscanf(c+1, "%x", &val) != 1) - return SCPE_FMT; - - CES = val & 0xFFFF; // preload console entry switches - } - else if (*c == 'z' || *c == 'Z') { - if (sscanf(c+1, "%x", &nwords) != 1) - return SCPE_FMT; - - if (iaddr == -1) - return SCPE_FMT; - - while (--nwords >= 0) { - WriteW(iaddr, 0); - iaddr++; - } - } - else if (strchr("0123456789abcdefABCDEF", *c) != NULL) { - if (sscanf(c, "%x", &val) != 1) - return SCPE_FMT; - - if (iaddr == -1) - return SCPE_FMT; - - WriteW(iaddr, val); // store data - iaddr++; - } - else - return SCPE_FMT; // unexpected data - } - - if (runaddr != -1) - IAR = runaddr; - - return SCPE_OK; -} - -t_stat my_save (FILE *fileref, char *cptr, char *fnam) -{ - int iaddr, nzeroes = 0, nwords = (int) (MEMSIZE/2), val; - - fprintf(fileref, "=%04x\r\n", IAR); - fprintf(fileref, "@0000\r\n"); - for (iaddr = 0; iaddr < nwords; iaddr++) { - val = ReadW(iaddr); - if (val == 0) // queue up zeroes - nzeroes++; - else { - if (nzeroes >= 4) { // spit out a Z directive - fprintf(fileref, "Z%04x\r\n", nzeroes); - nzeroes = 0; - } - else { // write queued zeroes literally - while (nzeroes > 0) { - fprintf(fileref, " 0000\r\n"); - nzeroes--; - } - } - fprintf(fileref, " %04x\r\n", val); - } - } - if (nzeroes >= 4) { // emit any queued zeroes - fprintf(fileref, "Z%04x\r\n", nzeroes); - nzeroes = 0; - } - else { - while (nzeroes > 0) { - fprintf(fileref, " 0000\r\n"); - nzeroes--; - } - } - - return SCPE_OK; -} - -t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag) -{ - if (flag) - return my_save(fileref, cptr, fnam); - else - return my_load(fileref, cptr, fnam); -} - -/* Specifier decode - - Inputs: - *of = output stream - addr = current PC - spec = specifier - nval = next word - flag = TRUE if decoding for CPU - iflag = TRUE if decoding integer instruction - Outputs: - count = -number of extra words retired -*/ - -/* 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 words retired -*/ - -static char *opcode[] = { - "?00 ", "XIO ", "SLA ", "SRA ", - "LDS ", "STS ", "WAIT", "?07 ", - "BSI ", "BSC ", "?0A ", "?0B ", - "LDX ", "STX ", "MDX ", "?0F ", - "A ", "AD ", "S ", "SD ", - "M ", "D ", "?16 ", "?17 ", - "LD ", "LDD ", "STO ", "STD ", - "AND ", "OR ", "EOR ", "?1F ", -}; - -static char relative[] = { // true if short mode displacements are IAR relative - FALSE, TRUE, FALSE, FALSE, - FALSE, TRUE, FALSE, FALSE, - TRUE, FALSE, FALSE, FALSE, - TRUE, TRUE, TRUE, FALSE, - TRUE, TRUE, TRUE, TRUE, - TRUE, TRUE, FALSE, FALSE, - TRUE, TRUE, TRUE, TRUE, - TRUE, TRUE, TRUE, FALSE -}; - -static char *lsopcode[] = {"SLA ", "SLCA ", "SLT ", "SLC "}; -static char *rsopcode[] = {"SRA ", "?188 ", "SRT ", "RTE "}; -static char tagc[] = " 123"; - -static int ascii_to_ebcdic_table[128] = -{ - 0x00,0x01,0x02,0x03,0x37,0x2d,0x2e,0x2f, 0x16,0x05,0x25,0x0b,0x0c,0x0d,0x0e,0x0f, - 0x10,0x11,0x12,0x13,0x3c,0x3d,0x32,0x26, 0x18,0x19,0x3f,0x27,0x1c,0x1d,0x1e,0x1f, - 0x40,0x5a,0x7f,0x7b,0x5b,0x6c,0x50,0x7d, 0x4d,0x5d,0x5c,0x4e,0x6b,0x60,0x4b,0x61, - 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7, 0xf8,0xf9,0x7a,0x5e,0x4c,0x7e,0x6e,0x6f, - - 0x7c,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7, 0xc8,0xc9,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6, - 0xd7,0xd8,0xd9,0xe2,0xe3,0xe4,0xe5,0xe6, 0xe7,0xe8,0xe9,0xba,0xe0,0xbb,0xb0,0x6d, - 0x79,0x81,0x82,0x83,0x84,0x85,0x86,0x87, 0x88,0x89,0x91,0x92,0x93,0x94,0x95,0x96, - 0x97,0x98,0x99,0xa2,0xa3,0xa4,0xa5,0xa6, 0xa7,0xa8,0xa9,0xc0,0x4f,0xd0,0xa1,0x07, -}; - -static int ebcdic_to_ascii (int ch) -{ - int j; - - for (j = 32; j < 128; j++) - if (ascii_to_ebcdic_table[j] == ch) - return j; - - return '?'; -} - -t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, UNIT *uptr, int32 sw) -{ - int32 cflag, ch, OP, F, TAG, INDIR, DSPLC, IR, eaddr; - char *mnem, tst[12]; - - cflag = (uptr == NULL) || (uptr == &cpu_unit); - -// if (sw & SWMASK ('A')) { /* ASCII? not useful */ -// fprintf (of, (c1 < 040)? "<%03o>": "%c", c1); -// return SCPE_OK; -// } - - if (sw & SWMASK ('C')) /* character? not useful -- make it EBCDIC */ - sw |= SWMASK('E'); - - if (sw & SWMASK ('E')) { /* EBCDIC! */ - ch = ebcdic_to_ascii((val[0] >> 8) & 0xFF); /* take high byte first */ - fprintf (of, (ch < ' ')? "<%03o>": "%c", ch); - ch = ebcdic_to_ascii(val[0] & 0xFF); - fprintf (of, (ch < ' ')? "<%03o>": "%c", ch); - return SCPE_OK; - } - - if (sw & SWMASK ('H')) { /* HOLLERITH! now THIS is useful! */ - ch = hollerith_to_ascii((int16) val[0]); - fprintf (of, (ch < ' ')? "<%03o>": "%c", ch); - return SCPE_OK; - } - - if (! (sw & SWMASK ('M'))) - return SCPE_ARG; - - IR = val[0]; - OP = (IR >> 11) & 0x1F; /* opcode */ - F = IR & 0x0400; /* format bit: 1 = long instr */ - TAG = IR & 0x0300; /* tag bits: index reg select */ - if (TAG) - TAG >>= 8; - - if (F) { /* long instruction, ASSUME it's valid (have to decrement IAR if not) */ - INDIR = IR & 0x0080; /* indirect bit */ - DSPLC = IR & 0x007F; /* displacement or modifier */ - if (DSPLC & 0x0040) - DSPLC |= ~ 0x7F; /* sign extend */ - - eaddr = val[1]; /* get reference address */ - } - else { /* short instruction, use displacement */ - INDIR = 0; /* never indirect */ - DSPLC = IR & 0x00FF; /* get displacement */ - if (DSPLC & 0x0080) - DSPLC |= ~ 0xFF; - - eaddr = DSPLC; - if (relative[OP] && ! TAG) - eaddr += addr+1; /* turn displacement into address */ - } - - mnem = opcode[OP]; /* get mnemonic */ - if (OP == 0x02) { /* left shifts are special */ - mnem = lsopcode[(DSPLC >> 6) & 0x0003]; - DSPLC &= 0x003F; - eaddr = DSPLC; - } - else if (OP == 0x03) { /* right shifts too */ - mnem = rsopcode[(DSPLC >> 6) & 0x0003]; - DSPLC &= 0x003F; - eaddr = DSPLC; - } - else if ((OP == 0x08 && F)|| OP == 0x09) { // BSI L and BSC any - if (OP == 0x09 && (IR & 0x40)) - mnem = "BOSC"; - - tst[0] = '\0'; - if (DSPLC & 0x20) strcat(tst, "Z"); - if (DSPLC & 0x10) strcat(tst, "-"); - if (DSPLC & 0x08) strcat(tst, "+"); - if (DSPLC & 0x04) strcat(tst, "E"); - if (DSPLC & 0x02) strcat(tst, "C"); - if (DSPLC & 0x01) strcat(tst, "O"); - - if (F) { - fprintf(of, "%04x %s %c%c %s,%04x ", IR & 0xFFFF, mnem, F ? (INDIR ? 'I' : 'L') : ' ', tagc[TAG], tst, eaddr & 0xFFFF); - return -1; - } - fprintf(of, "%04x %s %c%c %s ", IR & 0xFFFF, mnem, F ? (INDIR ? 'I' : 'L') : ' ', tagc[TAG], tst); - return SCPE_OK; - } - else if (OP == 0x0e && TAG == 0) { // MDX with no tag => MDM or jump - if (F) { - fprintf(of, "%04x %s %c%c %04x,%x (%d) ", IR & 0xFFFF, "MDM ", (INDIR ? 'I' : 'L'), tagc[TAG], eaddr & 0xFFFF, DSPLC & 0xFFFF, DSPLC); - return -1; - } - mnem = "JMP "; - } - - fprintf(of, "%04x %s %c%c %04x ", IR & 0xFFFF, mnem, F ? (INDIR ? 'I' : 'L') : ' ', tagc[TAG], eaddr & 0xFFFF); - return F ? -1 : SCPE_OK; /* inform how many words we read */ -} - -int32 get_reg (char *cptr, const char *strings[], char mchar) -{ -return -1; -} - -/* Number or memory address - - Inputs: - *cptr = pointer to input string - *dptr = pointer to output displacement - *pflag = pointer to accumulating flags - Outputs: - cptr = pointer to next character in input string - NULL if parsing error - - Flags: 0 (no result), A_NUM (number), A_REL (relative) -*/ - -char *get_addr (char *cptr, int32 *dptr, int32 *pflag) -{ - return 0; -} - -/* Specifier decode - - Inputs: - *cptr = pointer to input string - addr = current PC - n1 = 0 if no extra word used - -1 if extra word used in prior decode - *sptr = pointer to output specifier - *dptr = pointer to output displacement - cflag = true if parsing for the CPU - iflag = true if integer specifier - Outputs: - status = = -1 extra word decoded - = 0 ok - = +1 error -*/ - -t_stat get_spec (char *cptr, t_addr addr, int32 n1, int32 *sptr, t_value *dptr, - int32 cflag, int32 iflag) -{ - return -1; -} - -/* Symbolic input - - Inputs: - *cptr = pointer to input string - addr = current PC - *uptr = pointer to unit - *val = pointer to output values - sw = switches - Outputs: - status = > 0 error code - <= 0 -number of extra words -*/ - -t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw) -{ - return SCPE_ARG; -} - -#ifndef WIN32 - -int strnicmp (char *a, char *b, int n) -{ - int ca, cb; - - for (;;) { - if (--n < 0) // still equal after n characters? quit now - return 0; - - if ((ca = *a) == 0) // get character, stop on null terminator - return *b ? -1 : 0; - - if (ca >= 'a' && ca <= 'z') // fold lowercase to uppercase - ca -= 32; - - cb = *b; - if (cb >= 'a' && cb <= 'z') - cb -= 32; - - if ((ca -= cb) != 0) // if different, return comparison - return ca; - - a++, b++; - } -} - -int strcmpi (char *a, char *b) -{ - int ca, cb; - - for (;;) { - if ((ca = *a) == 0) // get character, stop on null terminator - return *b ? -1 : 0; - - if (ca >= 'a' && ca <= 'z') // fold lowercase to uppercase - ca -= 32; - - cb = *b; - if (cb >= 'a' && cb <= 'z') - cb -= 32; - - if ((ca -= cb) != 0) // if different, return comparison - return ca; - - a++, b++; - } -} - -#endif diff --git a/Ibm1130/ibm1130res.h b/Ibm1130/ibm1130res.h deleted file mode 100644 index ce47382e..00000000 --- a/Ibm1130/ibm1130res.h +++ /dev/null @@ -1,18 +0,0 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Visual C++ generated include file. -// Used by ibm1130.rc -// - -#define IDB_CONSOLE 101 -#define IDC_HAND 102 - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 103 -#define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1000 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif diff --git a/Ibm1130/makefile b/Ibm1130/makefile deleted file mode 100644 index 7aabb801..00000000 --- a/Ibm1130/makefile +++ /dev/null @@ -1,74 +0,0 @@ -# (This makefile is for operating systems other than Windows, -# or compilers other than Microsoft's. For MS builds, use the -# .mak files found in this directory and the utils directory). -# -# If you are building the emulator and utilities as part of -# the SIMH package, please: -# -# Be sure that you there are NO copies of scp.c, scp_tty.c, -# sim_sock.c, sim_tmxr.c, sim_rev.h, sim_defs.h, sim_sock.h and -# sim_tmxr.h in the ibm1130 subdirectory. Delete them if there -# are. -# -# Do not use this makefile with "make all" or "make ibm1130". -# Use the SIMH build files instead. -# -# If and when you download updates for this simulator from -# www.ibm1130.org, get ibm1130code.zip and ibm1130software.zip -# separately. -# -# If you have downloaded the emulator independently of SIMH (e.g, from -# www.ibm1130.org), please: -# -# Be sure that you DO have copies of scp.c, scp_tty.c, sim_sock.c, -# sim_tmxr.c, sim_rev.h, sim_defs.h, sim_sock.h and sim_tmxr.h -# in this folder. -# -# Use this file to make the emulator. -# -# If and when you download updates for this simulator from -# www.ibm1130.org, get ibm1130.zip. When you expand it, -# also expand ibm1130sofware.zip, which is inside. -# -# In either case, if you want to build DMS or work with assembly -# language programs outside of DMS, you'll want to make the utilities -# by cd'ing to the utils directory and running make there. - -# CC Command -# -# Note: -O2 is sometimes broken in GCC when setjump/longjump is being -# used. Try -O2 only with released simulators. -# -CC = gcc -O0 -lm -I . -#CC = gcc -O2 -g -lm -I . - - -# -# Common Libraries -# -BIN = -SIM = scp.c scp_tty.c sim_sock.c sim_tmxr.c -SIM_INC = sim_defs.h sim_rev.h sim_sock.h sim_tmxr.h - -# -# Emulator source files and compile time options -# - -ibm1130D = ./ -ibm1130 = ${ibm1130D}ibm1130_sys.c ${ibm1130D}ibm1130_cpu.c \ - ${ibm1130D}ibm1130_cr.c ${ibm1130D}ibm1130_disk.c \ - ${ibm1130D}ibm1130_stddev.c ${ibm1130D}ibm1130_gdu.c \ - ${ibm1130D}ibm1130_gui.c ${ibm1130D}ibm1130_prt.c \ - ${ibm1130D}ibm1130_fmt.c - -ibm1130_INC = ibm1130res.h ibm1130_conin.h ibm1130_conout.h \ - ibm1130_defs.h ibm1130_prtwheel.h ibm1130_fmt.h \ - dmsr2v12phases.h dmsr2v12slet.h - -# -# Build the emulator -# - -${BIN}ibm1130 : ${ibm1130} ${SIM} ${ibm1130_INC} ${SIM_INC} - ${CC} ${ibm1130} ${SIM} -o $@ - diff --git a/Ibm1130/readme1130.txt b/Ibm1130/readme1130.txt deleted file mode 100644 index e7a20831..00000000 --- a/Ibm1130/readme1130.txt +++ /dev/null @@ -1,189 +0,0 @@ -Here's the 1130 simulator as it stands now. - -Status: 22Jul2003 - - * Added support for APL\1130 output translations - and some bug fixes uncovered by APL. - -Status: 13Sep2002 - - * Added support for 1403 printer. It's MUCH faster - even in emulation. Not important for general use, - but it will help the CGI version a lot. - -Status: 16Aug2002 - - * Disk Monitor System R2V12 is available including the - Macro Assembler, Fortran Compiler and System Library. - - * There was a bug in the multiply instruction. This has - been fixed, and now the single precision trig functions - work correctly. - - * The card punch does not yet work correctly. - - * The card reader, punch and disk don't compute their device - status word until an XIO requests it; this is probably bad - as the "examine" command will show the wrong value. Doesn't - affect functioning of emulated software, though. - - * Documentation is a work in progress, see ibm1130.doc - in ibm1130software.zip. We hope to have it finished in - October. This is a Word document. Will distribute as a - PDF when it's finished. - - * Thanks to Oscar E Wyss (www.cosecans.ch) for - the DMS V12 source code listings and one card - programs, to Douglas W. Jones for the DMS V10, 11 and - 12 microfiche (which will end up scanned on IBM1130.org). - - * Thanks to Robert Alan Byer for adding the 1130 - to the simh makefiles & testing the builds on several - platforms. - - * For updated information about the 1130 and for - future 1130 OS and application software developments, - check www.ibm1130.org periodically. Sign up for the - mailing list to get updates as they occur! - - * Cross-assembler has been updated to handle card image input - correctly. The DMS sources seems to mix up @ and ' - as a leading symbol in labels, I have to find out why - this is. - -BUILD NOTES: if you download this simulator directly from -IBM1130.org, the makefile, source, and binaries are all in -the main directory. If you use the version from Bob Supnik's -SIMH distribution, the makefile is in the main simh -directory, and the SCP files used are Bob's. For a -Windows build, use the .mak file in the IBM1130 directory, -as this incorporates the GUI. - -Make the utilities in the utils directory if you want -to actually build and load DMS from scratch. Move the -executables to a common directory in your search path - -Brian Knittel -brian@ibm1130.org - --------------------------------------------------------------------------- -Some sample things to run: -(it's best to hit CHECK RESET or type "reset" between program runs!) - -* Run a Fortran Program - ibm1130 - do job roots - do job csort - -* List the monitor system disk's contents - ibm1130 - do job list - -* Look into the files "job", "roots.job" and "csort.job" and "list.job" - to see the actual input files - -* When the jobs have run (stop at 2A with 1000 in the - accumulator), detach the printer (det prt) and look at - the output file: for.lst or asm.lst. The supplied "job" - script displays the print output automatically on Windows - builds. - --------------------------------------------------------------------------- -Contents: - -There are several programs: - - ibm1130 the simulator - asm1130 cross assembler - bindump dumps contents of relocatable format object decks (xxx.bin) - checkdisk validates DMS disk format - diskview dumps contents of DMS disk directory - mkboot creates IPL and Core Image Format Decks from .bin - viewdeck displays contents of Hollerith-format binary decks - -Files in the software (sw) directory: - - actual 1130 software: - dms.dsk disk image file containing Disk Monitor System - zdcip.asm disk cartridge initialization program - zcrdumpc.asm a cold-start-mode one card memory dump program - dmsboot.asm source code for the DMS cold start loader - - contributed software: - onecard/* one-card programs from Oscar Wyss - --------------------------------------------------------------------------- -Status of the simulator: - -* There is a reasonably fun console GUI available for Windows builds, - as well as support for the 2250 graphical display. - -* The card reader emulator now supports deck files with literal cards and - breakpoints. The command "attach cr @filename" tells the simulator to - read data from the files named in the specified file. Input lines are of - the following form: - - filename a -- input file to be read as ascii text - filename b -- input file to be read as binary card images - !xyz... -- literal text xyz..., treated as a card - !break -- halts the simulator - #comment -- remarks - -* The do command may have arguments after the filename. These may be - interpolated in the script and in card reader deck files with %1, %2, etc - --------------------------------------------------------------------------- -sample usage --------------------------------------------------------------------------- - -ibm1130 - starts SIMH-based simulator. - Optional command line arguments: -q quiet mode, -g no GUI - - Enhancements: - - * Windows builds display a console window - - * CPU activity log - - the command "attach cpu file.log" will make the simulator - write a detailed log of CPU and IO activity, good for - debugging. Turn off with "detach cpu". - - * DO command [arg1 arg2...] - reads file 'filename' for SIMH commands. Lets you write - simh command files to be run from the prompt rather - than just the command line. In the do command file, %1 will - be replaced by the first command line argument, etc. This - applies to the script run from the ibm1130 command line too. - - * DELETE filename - deletes the named file - - * VIEW filename - displays the named file with "notepad." (Windows only). - --------------------------------------------------------------------------- -asm1130 -l program.asm - - compiles source file, creates simulator load - file (program.out) and listing file (program.lst) - - The cross assembler wants files either in strict column - layout matching the IBM spec, or, if tabs are present in the - source file, - - labelopcodeflagsoperand - - The output file is in the format used by the 1130 simulator's - load command. - --------------------------------------------------------------------------- - -Note: the DMS disk is built with the Windows batch file "mkdms.bat". - -Subnote: DMS cannot be built with the 1130's native assembler. - - --------------------------------------------------------------------------- -check www.ibm1130.org for updates... \ No newline at end of file diff --git a/Ibm1130/readme_update.txt b/Ibm1130/readme_update.txt deleted file mode 100644 index aab52dbc..00000000 --- a/Ibm1130/readme_update.txt +++ /dev/null @@ -1,48 +0,0 @@ -Version: 10 July 2003 - -History (partial): - -2003-07-10 Fixed disk and console terminal bugs uncovered by - APL\1130. Added APL keyboard and output font support - to enable use of APL\1130. APL will be released soon. - -2003-03-18 Fixed bug in asm1130 that produced an error message - with a (legal) offset of +127 in MDX instructions. - - Fixed sign bug in 1130 emulator divide instruction. - -Interim 1130 distribution: --------------------------------------------- - -folders: - . sources - winrel windows executables - windebug windows executables - utils accessory programs - utils\winrel windows executables - utils\windebug windows executables - sw working directory for DMS build & execution - sw\dmsR2V12 Disk Monitor System sources - -programs: - asm1130 cross assembler - bindump object deck dump tool, also used to sort decks by phase id - checkdisk DMS disk image check and dump - diskview work in progress, interpreted disk image dump - ibm1130 emulator - mkboot object deck to IPL and core image converter - viewdeck binary to hollerith deck viewer if needed to view phase ID cards and ident fields - -batch file: - mkdms.bat builds DMS objects and binary cards. Need a shell script version of this. - -IBM1130 simulator DO command scripts: - format format a disk image named DMS.DSK - loaddms format and install DMS onto the formatted DMS.DSK - for run a Fortran program - list list the disk contents - asm assemble a program - -ancillary files: - loaddms.deck list of files stacked into the card reader for loaddms - *.deck other sample deck files diff --git a/Ibm1130/utils/asm1130.c b/Ibm1130/utils/asm1130.c deleted file mode 100644 index 5cf9e31f..00000000 --- a/Ibm1130/utils/asm1130.c +++ /dev/null @@ -1,4499 +0,0 @@ -/* - * (C) Copyright 2002, Brian Knittel. - * You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN - * RISK basis, there is no warranty of fitness for any purpose, and the rest of the - * usual yada-yada. Please keep this notice and the copyright in any distributions - * or modifications. - * - * This is not a supported product, but I welcome bug reports and fixes. - * Mail to sim@ibm1130.org - */ - -// --------------------------------------------------------------------------------- -// ASM1130 - IBM 1130 Cross Assembler -// -// Version -// 1.08 - 2003Mar18 - Fixed bug that complained about valid MDX displacement of +127 -// 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 -// it's looking like it happens twice in PTMASMBL. -// This version still doesn't do fixed point numbers and -// negative floats may be wrong. -// 1.04 - 2002Apr18 - Added binary (card loader format) output, removed -// interim IPL output formats and moved that to MKBOOT. -// Enhanced relocatable code handling. Added floating -// point constants, but don't know how to make fixed point -// constants yet. Made amenable to syntax variations found -// in the DMS sources. Doesn't properly handle ILS -// modules yet and ISS is probably wrong. -// 1.03 - 2002Apr10 - numerous fixes, began to add relative/absolute support -// 1.02 - 2002Feb26 - replaced "strupr" with "upcase" for compatibility -// 1.01 - 2002Feb25 - minor compiler compatibility changes -// 1.00 - 2002Feb01 - first release. Tested only under Win32. -// --------------------------------------------------------------------------------- -// -// Usage: -// asm1130 [-bvsx] [-o[file]] [-l[file]] [-rN.M] file... -// -// Description: -// -b binary output (.bin, relocatable absolute format) -// -v verbose -// -s print symbol table -// -x print cross references -// -o output file (default is name of first source file + extension .out or .bin) -// -l listing file (default is name of first source file + extension .lst) -// -y preload system symbol table SYMBOLS.SYS (from the current directory) -// -w write the system symbol table SYMBOLS.SYS in the current directory -// -W same as -w but don't prompt to confirm overwriting existing file -// -r set DMS release to release N version M, for sbrk cards -// -// Listing and symbol table output can be turned on by *LIST directives in the source, too -// Listing file default extension is .LST -// -// Input files can use strict IBM 1130 Assembler column format, or loose formatting -// with tabs, or any mix on a line-by-line basis. Input files default extension is .ASM. -// -// Strict specification is: -// -// label columns 1 - 5 -// opcode 7 - 10 -// tag 12 -// index 13 -// arguments 15 - 51 -// -// Loose, indicated by presence of ascii tab character(s): -// -// labelopcodeindex and format indicatorsarguments -// -// In both cases, the IBM convention that the arguments section ends with the -// first nonblank applies. This means that ".DC 1, 2, 3" assembles only the 1! -// -// Output file format is that used by the LOAD command in my 1130 -// simulator. Lines are any of the following. All values are in hex: -// -// @addr load address for subsequent words is addr -// Znwords Zero the next "nwords" and increment load address by nwords. -// =addr set IAR register to address addr (a convenience) -// value load value at load address and increment load address -// -// Output file default extension is .OUT or .BIN for binary assemblies -// -// Note: this version does not handle relative assembly, and so doesn't carry -// absolute/relative indication through expression calculation. -// -// Seems to work. Was able to assemble the resident monitor OK. -// >>> Look for "bug here" though, for things to check out. -// -// Notes: -// org_advanced tells whether * in an expression refers to the address AFTER the -// instruction (1 or 2 words, depending on length). This is the case for opcodes -// but not all directives. -// -// Added special coldstart format directives: -// -// .IPL 1130,XXXXXXXX -// .IPL 1800,XXXXXXXX -// -// (these are not standard IBM) -// -// These directives cause the output file to be written in binary in either 1130 or -// 1800 IPL format. In 1130 format, the index bits are lost and the displacement -// is sign extended. In 1800 format, the data are punched 8 bits at a time into -// two columns per word. If an identifier is not given, data are punched into -// all 80 columns. If an identifier is given, data is punched in columns 0 through -// 72, and the identification XXXXXXXX is punched in columns 73 through 80. (If -// there are multiple output cards the last ident character is incremented). A -// warning is issued if 1130 assembly results in lost bits. These directives -// should be the first in the file as you don't want text and binary mixed in -// the same output file. -// -// Revision History -// 16Apr02 1.03 Added sector break, relocation flag output -// 02Apr02 1.02 Fixed bug in BOSC: it CAN be a short instruction. -// Added directives for 1130 and 1800 IPL output formats -// Added conditional assembly directives -// --------------------------------------------------------------------------------- - -#include -#include -#include -#include -#include -#include -#include - -// ---------------------------------------------------------------1------------------ -// DEFINITIONS -// --------------------------------------------------------------------------------- - -// I have found some IBM source code where @ and ' seem interchangable. -// Comment out this define to make @ and ' different in symbol names, keep to make equivalent - -#if defined(VMS) - # include /* to pick up 'unlink' */ -#endif - -#define BETWEEN(v,a,b) (((v) >= (a)) && ((v) <= (b))) -#define MIN(a,b) (((a) <= (b)) ? (a) : (b)) -#define MAX(a,b) (((a) >= (b)) ? (a) : (b)) - -#ifndef WIN32 - int strnicmp (char *a, char *b, int n); - int strcmpi (char *a, char *b); -#endif - -#define FIX_ATS - -#define DMSVERSION "V2M12" /* required 5 characters on sector break card col 67-71 */ - -#define DOLLAREXIT "/38" // hmmm, are these really fixed absolutely in all versions? -#define DOLLARDUMP "/3F" - -#define SYSTEM_TABLE "SYMBOLS.SYS" - -#define BOOL int -#define TRUE 1 -#define FALSE 0 - -#define VERSION "ASM1130 CROSS ASSEMBLER V1.08" - -#define ISTV 0x33 // magic number from DMS R2V12 monitorm symbol @ISTV - -#define MAXLITERALS 300 -#define MAXENTRIES 14 - -#define LINEFORMAT " %4ld | %s" -#define LEFT_MARGIN " |" - // XXXX XXXX XXXX XXXX XXXX XXXX - // org w1 w2 w3 w4 w5 - // XXXX 1111 2222 3333 4444 LLLL | - // 12345678901234567890123456789012 - -typedef enum {ABSOLUTE = 0, RELATIVE = 1, LIBF = 2, CALL = 3} RELOC; - -typedef struct tag_symbol { // symbol table entry: - char *name; // name of symbol - int value; // value (absolute) - int pass; // defined during pass # - int defined; // definition state, see #defines below - RELOC relative; // ABSOLUTE = absolute, RELATIVE = relative - struct tag_symbol *next; // next symbol in list - struct tag_xref *xrefs; // cross references -} SYMBOL, *PSYMBOL; - -#define S_UNDEFINED 0 // values of 'defined' -#define S_PROVISIONAL 1 // usually an expression with forward references -#define S_DEFINED 2 // ordering must be undef < prov < def - -typedef struct tag_xref { // cross reference entry - char *fname; // filename - int lno; // line number - BOOL definition; // true = definition, false = reference - struct tag_xref *next; // next reference -} XREF, *PXREF; - -typedef struct tag_expr { // expression result: absolute or relative - int value; - RELOC relative; -} EXPR; - -typedef enum {PROGTYPE_ABSOLUTE = 1, PROGTYPE_RELOCATABLE = 2, PROGTYPE_LIBF = 3, PROGTYPE_CALL = 4, - PROGTYPE_ISSLIBF = 5, PROGTYPE_ISSCALL = 6, PROGTYPE_ILS = 7} PROGTYPE; - -typedef enum {SUBTYPE_INCORE = 0, SUBTYPE_FORDISK = 1, SUBTYPE_ARITH = 2, - SUBTYPE_FORNONDISK = 3, SUBTYPE_FUNCTION=8} SUBTYPE; - -typedef enum {INTMODE_UNSPECIFIED = 0, INTMODE_MATCHREAL = 0x0080, INTMODE_ONEWORD = 0x0090} INTMODE; -typedef enum {REALMODE_UNSPECIFIED = 0, REALMODE_STANDARD = 0x0001, REALMODE_EXTENDED = 0x0002} REALMODE; - -#define OP_INDEXED 0x0300 // 1130 opcode modifier bits -#define OP_LONG 0x0400 -#define OP_INDIRECT 0x0080 - -typedef enum {OUTMODE_LOAD, OUTMODE_1130, OUTMODE_1800, OUTMODE_BINARY} OUTMODE; - -#ifdef WIN32 -# define OUTWRITEMODE "wb" // write outfile in binary mode -# define ENDLINE "\r\n" // explictly write CR/LF -#else -# define OUTWRITEMODE "w" // use native mode -# define ENDLINE "\n" -#endif - -// --------------------------------------------------------------------------------- -// GLOBALS -// --------------------------------------------------------------------------------- - -// command line syntax -char *usestr = -"Usage: asm1130 [-bpsvwxy] [-o[file]] [-l[file]] [-rN.M] file...\n\n" -"-b binary (relocatable format) output; default is simulator LOAD format\n" -"-p count passes required; no assembly output is created with this flag" -"-s add symbol table to listing\n" -"-v verbose mode\n" -"-w write system symbol table as SYMBOLS.SYS\n" -"-W same as -w but do not confirm overwriting previous file\n" -"-x add cross reference table to listing\n" -"-y preload system symbol table SYMBOLS.SYS\n" -"-o set output file; default is first input file + .out or .bin\n" -"-l create listing file; default is first input file + .lst\n" -"-r set dms version to VN RM for system SBRK cards"; - -BOOL verbose = FALSE; // verbose mode flag -BOOL tabformat = FALSE; // TRUE if tabs were seen in the file -int pass; // current assembler pass (1 or 2) -char curfn[256]; // current input file name -char progname[8]; // base name of primary input file -char *outfn = NULL; // output file name -int lno; // current input file line number -BOOL preload = FALSE; // preload system symbol table -BOOL savetable = FALSE; // write system symbol table -BOOL saveprompt = TRUE; // prompt before overwriting -int nerrors = 0; // count of errors -int nwarnings = 0; // count of warnings -FILE *fin = NULL; // current input file -FILE *fout = NULL; // output file stream -OUTMODE outmode = OUTMODE_LOAD; // output file mode -int outcols = 0; // columns written in using card output -int maxiplcols = 80; -char cardid[9]; // characters used for IPL card ID -FILE *flist = NULL; // listing file stream -char *listfn = NULL; // listing filename -BOOL do_list = FALSE; // flag: create listing -BOOL passcount = FALSE; // flag: count passes only -BOOL list_on = TRUE; // listing is currently enabled -BOOL do_xref = FALSE; // cross reference listing -BOOL do_syms = FALSE; // symbol table listing -BOOL ended = FALSE; // end of current file -BOOL hasforward = FALSE; // true if there are any forward references -char listline[350]; // output listing line -BOOL line_error; // already saw an error on current line -RELOC relocate = RELATIVE; // relocatable assembly mode -BOOL assembled = FALSE; // true if any output has been generated -int nwout; // number of words written on current line -int org = 0; // output address (origin) -int org_advanced; // if TRUE, * means instruction addr+(value) during evaluation -int pta = -1; // program transfer address -BOOL cexpr = FALSE; // "C" expression syntax -PSYMBOL symbols = NULL; // the symbol table (linear search) -BOOL check_control = TRUE; // check for control cards -PROGTYPE progtype = PROGTYPE_RELOCATABLE; // program type -INTMODE intmode = INTMODE_UNSPECIFIED; // integer mode -REALMODE realmode = REALMODE_UNSPECIFIED; // real mode -int nintlevels = 0; // # of interrupt levels for ISS -int intlevel_primary = 0; // primary level for ISS and level for ILS -int intlevel_secondary = 0; // secondary level for ISS -int iss_number = 0; // ISS number -PSYMBOL entry[MAXENTRIES]; // entries for subroutines -int nentries = 0; -int ndefined_files = 0; - -struct lit { // accumulated literals waiting to be output - int value; // constant value - int tagno; // constant symbol tag number (e.g. _L001) - BOOL hex; // constant was expressed in hex - BOOL even; // constant was operand of a double-width instruction (e.g. AD) -} literal[MAXLITERALS]; - -int n_literals = 0, lit_tag = 0; -BOOL requires_even_address; // target of current instruction -BOOL dmes_saved; // odd character left over from dmes ending in ' -int dmes_savew; -char opfield[256]; // extracted operand field from source line -char dmsversion[12] = DMSVERSION; // version number for SBRK cards -const char whitespace[] = " \t"; // whitespace - -int ascii_to_ebcdic_table[128] = -{ -// - 0x00,0x01,0x02,0x03,0x37,0x2d,0x2e,0x2f, 0x16,0x05,0x25,0x0b,0x0c,0x0d,0x0e,0x0f, -// - 0x10,0x11,0x12,0x13,0x3c,0x3d,0x32,0x26, 0x18,0x19,0x3f,0x27,0x1c,0x1d,0x1e,0x1f, -// spac ! " # $ % & ' ( ) * + , - . / - 0x40,0x5a,0x7f,0x7b,0x5b,0x6c,0x50,0x7d, 0x4d,0x5d,0x5c,0x4e,0x6b,0x60,0x4b,0x61, -// 0 1 2 3 4 5 6 7 8 9 : ; < = > ? - 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7, 0xf8,0xf9,0x7a,0x5e,0x4c,0x7e,0x6e,0x6f, -// @ A B C D E F G H I J K L M N O - 0x7c,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7, 0xc8,0xc9,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6, -// P Q R S T U V W X Y Z [ \ ] & _ - 0xd7,0xd8,0xd9,0xe2,0xe3,0xe4,0xe5,0xe6, 0xe7,0xe8,0xe9,0xba,0xe0,0xbb,0xb0,0x6d, -// a b c d e f g h i j k l m n o - 0x79,0x81,0x82,0x83,0x84,0x85,0x86,0x87, 0x88,0x89,0x91,0x92,0x93,0x94,0x95,0x96, -// p q r s t u v w x y z { | } ~ - 0x97,0x98,0x99,0xa2,0xa3,0xa4,0xa5,0xa6, 0xa7,0xa8,0xa9,0xc0,0x4f,0xd0,0xa1,0x07, -}; - -int ascii_to_1403_table[128] = -{ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f */ - 0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f, 0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f, - 0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f, 0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f, - 0x7f,0x7f,0x7f,0x7f,0x62,0x7f,0x15,0x0b, 0x57,0x2f,0x23,0x6d,0x16,0x61,0x6e,0x4c, - 0x49,0x40,0x01,0x02,0x43,0x04,0x45,0x46, 0x07,0x08,0x7f,0x7f,0x7f,0x4a,0x7f,0x7f, - 0x7f,0x64,0x25,0x26,0x67,0x68,0x29,0x2a, 0x6b,0x2c,0x58,0x19,0x1a,0x5b,0x1c,0x5d, - 0x5e,0x1f,0x20,0x0d,0x0e,0x4f,0x10,0x51, 0x52,0x13,0x54,0x7f,0x7f,0x7f,0x7f,0x7f, - 0x7f,0x64,0x25,0x26,0x67,0x68,0x29,0x2a, 0x6b,0x2c,0x58,0x19,0x1a,0x5b,0x1c,0x5d, - 0x5e,0x1f,0x20,0x0d,0x0e,0x4f,0x10,0x51, 0x52,0x13,0x54,0x7f,0x7f,0x7f,0x7f,0x7f -}; - -#include "../ibm1130_conout.h" /* conout_to_ascii_table */ -#include "../ibm1130_prtwheel.h" /* 1132 printer printwheel data */ - -// --------------------------------------------------------------------------------- -// PROTOTYPES -// --------------------------------------------------------------------------------- - -void bail (char *msg); -void flag (char *arg); -void proc (char *fname); -void startpass (int n); -void errprintf (char *fmt, ...); -void asm_error (char *fmt, ...); -void asm_warning (char *fmt, ...); -char *astring (char *str); -PSYMBOL lookup_symbol (char *name, BOOL define); -void add_xref (PSYMBOL s, BOOL definition); -int get_symbol (char *name); -void set_symbol (char *name, int value, int known, RELOC relative); -char * gtok (char **pc, char *tok); -char *skipbl (char *c); -void sym_list (void); -void xref_list (void); -void listhdr (void); -int getexpr (char *pc, BOOL undefined_ok, EXPR *expr); -void passreport (void); -void listout (BOOL reset); -void output_literals (BOOL eof); -char *upcase (char *str); -void prep_line (char *line); -int ascii_to_hollerith (int ch); -char *detab (char *str); -void preload_symbols (void); -void save_symbols (void); -void bincard_init (void); -void bincard_writecard (char *sbrk_text); -void bincard_writedata (void); -void bincard_flush (void); -void bincard_sbrk (char *line); -void bincard_setorg (int neworg); -void bincard_writew (int word, RELOC relative); -void bincard_endcard (void); -void handle_sbrk (char *line); -void bincard_typecard (void); -void namecode (unsigned short *words, char *tok); - -// --------------------------------------------------------------------------------- -// main routine -// --------------------------------------------------------------------------------- - -int main (int argc, char **argv) -{ - int i, sawfile = FALSE; - - for (i = 1; i < argc; i++) // process command line switches - if (*argv[i] == '-') - flag(argv[i]+1); - - startpass(1); // first pass, process files - - for (i = 1; i < argc; i++) - if (*argv[i] != '-') - proc(argv[i]), sawfile = TRUE; - - if (! sawfile) // should have seen at least one file - bail(usestr); - - if (passcount) { - passreport(); - return 0; - } - - startpass(2); // second pass, process files again - - for (i = 1; i < argc; i++) - if (*argv[i] != '-') - proc(argv[i]); - - if (outmode == OUTMODE_LOAD) { - if (pta >= 0) // write start address to the load file - fprintf(fout, "=%04x" ENDLINE, pta & 0xFFFF); - } - else - bincard_endcard(); - - if (flist) { - if (nerrors || nwarnings) { // summarize (or summarise) - if (nerrors == 0) - fprintf(flist, "There %s ", (nwarnings == 1) ? "was" : "were"); - else - fprintf(flist, "\nThere %s %d error%s %s", - (nerrors == 1) ? "was" : "were", nerrors, (nerrors == 1) ? "" : "s", nwarnings ? "and " : ""); - - if (nwarnings > 0) - fprintf(flist, "%d warning%s ", nwarnings, (nwarnings == 1) ? "" : "s"); - - fprintf(flist, "in this assembly\n"); - } - else - fprintf(flist, "\nThere were no errors in this assembly\n"); - } - - if (flist) { // finish the listing - if (pta >= 0) - fprintf(flist, "\nProgram transfer address = %04x\n", pta); - - if (do_xref) - xref_list(); - else if (do_syms) - sym_list(); - } - - if (savetable) - save_symbols(); - - return 0; // all done -} - -// --------------------------------------------------------------------------------- -// flag - process one command line switch -// --------------------------------------------------------------------------------- - -void flag (char *arg) -{ - int major, minor; - - while (*arg) { - switch (*arg++) { - case 'o': // output (load) file name - if (! *arg) - bail(usestr); - outfn = arg; - return; - - case 'p': - passcount = TRUE; - break; - - case 'v': // mumble while running - verbose = TRUE; - break; - - case 'x': // print cross reference table - do_xref = TRUE; - break; - - case 's': // print symbol table - do_syms = TRUE; - break; - - case 'l': // listing file name - listfn = (* arg) ? arg : NULL; - do_list = TRUE; - return; - - case 'W': - saveprompt = FALSE; - // fall through - case 'w': - savetable = TRUE; - break; - - case 'y': - preload = TRUE; - break; - - case 'b': - outmode = OUTMODE_BINARY; - break; - - case 'r': - if (sscanf(arg, "%d.%d", &major, &minor) != 2) - bail(usestr); - sprintf(dmsversion, "V%01.1dM%02.2d", major, minor); - return; - - default: - bail(usestr); - break; - } - } -} - -// --------------------------------------------------------------------------------- -// bail - print error message on stderr (only) and exit -// --------------------------------------------------------------------------------- - -void bail (char *msg) -{ - fprintf(stderr, "%s\n", msg); - exit(1); -} - -// --------------------------------------------------------------------------------- -// errprintf - print error message to stderr -// --------------------------------------------------------------------------------- - -void errprintf (char *fmt, ...) -{ - va_list args; - - va_start(args, fmt); // get pointer to argument list - - vfprintf(stderr, fmt, args); // write errors to terminal (stderr) - - va_end(args); -} - -// --------------------------------------------------------------------------------- -// asm_error - report an error to listing file and to user's console -// --------------------------------------------------------------------------------- - -void asm_error (char *fmt, ...) -{ - va_list args; - - if (pass == 1) // only print on pass 2 - return; - - va_start(args, fmt); // get pointer to argument list - - fprintf(stderr, "E: %s (%d): ", curfn, lno); - vfprintf(stderr, fmt, args); // write errors to terminal (stderr) - putc('\n', stderr); - - if (flist != NULL && list_on) { - listout(FALSE); - line_error = TRUE; - - fprintf(flist, "**** Error: "); - vfprintf(flist, fmt, args); // write errors to listing file - putc('\n', flist); - } - - nerrors++; - va_end(args); -} - -// --------------------------------------------------------------------------------- -// asm_warning - same but warnings are not counted -// --------------------------------------------------------------------------------- - -void asm_warning (char *fmt, ...) -{ - va_list args; - - if (pass == 1) // only print on pass 2 - return; - - va_start(args, fmt); // get pointer to argument list - - fprintf(stderr, "W: %s (%d): ", curfn, lno); - vfprintf(stderr, fmt, args); // write errors to terminal (stderr) - putc('\n', stderr); - - if (flist != NULL && list_on) { - listout(FALSE); - line_error = TRUE; - - fprintf(flist, "**** Warning: "); - vfprintf(flist, fmt, args); // write errors to listing file - putc('\n', flist); - } - - nwarnings++; -} - -// --------------------------------------------------------------------------------- -// sym_list - print the symbol table -// --------------------------------------------------------------------------------- - -void sym_list (void) -{ - PSYMBOL s; - int n = 5; - - if (symbols == NULL || flist == NULL) - return; - - fprintf(flist, "\n=== SYMBOL TABLE ==============================================================\n"); - - for (s = symbols, n = 0; s != NULL; s = s->next) { - if (n >= 5) { - putc('\n', flist); - n = 0; - } - else if (n > 0) - fprintf(flist, " "); - - fprintf(flist, "%-6s ", s->name); - if (s->defined == S_DEFINED) - fprintf(flist, "%04x%s", s->value & 0xFFFF, s->relative ? "R" : " "); - else - fprintf(flist, "UUUU "); - - n++; - } - fprintf(flist, "\n"); -} - -// --------------------------------------------------------------------------------- -// passreport - report # of passes required for assembly on the 1130 -// --------------------------------------------------------------------------------- - -void passreport (void) -{ - PSYMBOL s; - - for (s = symbols; s != NULL; s = s->next) { - if (s->defined == S_UNDEFINED || s->defined == S_PROVISIONAL) { - printf("There are undefined symbols. Cannot determine pass requirement.\n"); - return; - } - } - - if (hasforward) - printf("There are forward references. Two passes are required.\n"); - else - printf("There are no forward references. Only one pass is required.\n"); -} - -// --------------------------------------------------------------------------------- -// xref_list - print the cross-reference table -// --------------------------------------------------------------------------------- - -void xref_list (void) -{ - int n = 0; - PXREF x; - PSYMBOL s; - - if (flist == NULL || symbols == NULL) - return; - - fprintf(flist, "\n=== CROSS REFERENCES ==========================================================\n"); - - if (symbols == NULL || flist == NULL) - return; - - fprintf(flist, "Name Val Defd Referenced\n"); - - for (s = symbols; s != NULL; s = s->next) { - fprintf(flist, "%-5s %04x%s", s->name, s->value & 0xFFFF, s->relative ? "R" : " "); - - for (x = s->xrefs; x != NULL; x = x->next) - if (x->definition) - break; - - if (x == NULL) - fprintf(flist, "----"); - else - fprintf(flist, " %4d", x->lno); - - for (n = 0, x = s->xrefs; x != NULL; x = x->next) { - if (x->definition) - continue; - - if (n >= 12) { - n = 0; - fprintf(flist, "\n "); - } - fprintf(flist, " %4d", x->lno); - n++; - } - putc('\n', flist); - } -} - -// --------------------------------------------------------------------------------- -// listhdr - print a banner header in the listing file. Since it's not paginated -// at this time, this is not used often. -// --------------------------------------------------------------------------------- - -void listhdr (void) -{ - time_t t; - - time(&t); - fprintf(flist, "%s -- %s -- %s\n", VERSION, dmsversion, ctime(&t)); -} - -// --------------------------------------------------------------------------------- -// astring - allocate a copy of a string -// --------------------------------------------------------------------------------- - -char *astring (char *str) -{ - static char *s = NULL; - - if (s != NULL) - if (strcmp(s, str) == 0) // if same as immediately previous allocation - return s; // return same pointer (why did I do this?) - - if ((s = malloc(strlen(str)+1)) == NULL) - bail("out of memory"); - - strcpy(s, str); - return s; -} - -// --------------------------------------------------------------------------------- -// lookup_symbol - get pointer to a symbol. -// If define is TRUE, creates and marks 'undefined' if not previously defined. -// --------------------------------------------------------------------------------- - -PSYMBOL lookup_symbol (char *name, BOOL define) -{ - PSYMBOL s, n, prv = NULL; - int c; - char *at; - - if (strlen(name) > 5) { // (sigh) - asm_error("Symbol '%s' is longer than 5 letters", name); - name[5] = '\0'; - } - -#ifdef FIX_ATS - while ((at = strchr(name, '@')) != NULL) - *at = '\''; -#endif - // search sorted list of symbols - for (s = symbols; s != NULL; prv = s, s = s->next) { - c = strcmpi(s->name, name); - if (c == 0) - return s; - if (c > 0) - break; - } - - if (! define) - return NULL; // not found - - if ((n = malloc(sizeof(SYMBOL))) == NULL) - bail("out of memory"); - - n->name = astring(name); // symbol was undefined -- add it now - n->value = 0; - n->defined = FALSE; - n->xrefs = NULL; - n->defined = FALSE; - - n->next = s; // link in alpha order - - if (prv == NULL) // we stopped before first item in list - symbols = n; - else - prv->next = n; // insert after item before place we stopped - - return n; -} - -// --------------------------------------------------------------------------------- -// add_xref - add a cross reference entry to a symbol -// --------------------------------------------------------------------------------- - -void add_xref (PSYMBOL s, BOOL definition) -{ - PXREF x, prv = NULL, n; - - if (pass == 1 || ! do_xref) // define only during 2nd pass and only if listing was requested - return; - - for (x = s->xrefs; x != NULL; prv = x, x = x->next) - if (strcmpi(x->fname, curfn) == 0 && x->lno == lno) - return; // ignore multiple refs on same line - - if ((n = malloc(sizeof(XREF))) == NULL) - bail("out of memory"); - - n->fname = astring(curfn); - n->lno = lno; - n->definition = definition; - - n->next = x; // link at end of existing list - - if (prv == NULL) - s->xrefs = n; - else - prv->next = n; -} - -// --------------------------------------------------------------------------------- -// get_symbol - get a symbol value, defining if necessary -// --------------------------------------------------------------------------------- - -int get_symbol (char *name) -{ - PSYMBOL s; - - s = lookup_symbol(name, TRUE); // lookup, define if necessary - - if (pass == 2) // should be defined by now - if (! s->defined) - asm_error("Symbol '%s' is undefined", name); - - add_xref(s, FALSE); // note the reference - - return s->value; -} - -// --------------------------------------------------------------------------------- -// set_symbol - set a symbol value. Known = TRUE means we really know the value; -// FALSE means we're calculating it with forward referenced values or something like -// that. -// --------------------------------------------------------------------------------- - -void set_symbol (char *name, int value, int known, RELOC relative) -{ - PSYMBOL s; - char *at; - - if (strlen(name) > 5) { - asm_error("Symbol '%s' is longer than 5 letters", name); - name[5] = '\0'; - } - -#ifdef FIX_ATS - while ((at = strchr(name, '@')) != NULL) - *at = '\''; -#endif - - s = lookup_symbol(name, TRUE); - - if (s->defined == S_DEFINED) // once defined, it should not change - if (s->value != value) - asm_error("Symbol '%s' %s", name, (s->pass == pass) ? "is multiply defined" : "changed between passes"); - - s->value = value; - s->relative = relative; - s->defined = known ? S_DEFINED : S_PROVISIONAL; - s->pass = pass; - - if (! known) - hasforward = TRUE; - - add_xref(s, TRUE); // record the place of definition -} - -// --------------------------------------------------------------------------------- -// skipbl - return pointer to first nonblank character in string s -// --------------------------------------------------------------------------------- - -char *skipbl (char *s) -{ - while (*s && *s <= ' ') - s++; - - return s; -} - -// --------------------------------------------------------------------------------- -// gtok - extracts a whitespace-delimited token from the string pointed to by *pc; -// stores the token into the buffer tok and returns pointer to same. Returns NULL -// when there are no tokens. Best to call repeatedly with a pointer to the source -// buffer, e.g. -// char *pbuf = buf; -// while (gtok(&pbuf, token) != NULL) ... -// --------------------------------------------------------------------------------- - -char * gtok (char **pc, char *tok) -{ - char *s = *pc, *otok = tok; - - while (*s && *s <= ' ') // skip blanks - s++; - - if (! *s) { // no tokens to be found - *tok = '\0'; - *pc = s; - return NULL; - } - - while (*s > ' ') // save nonblanks into 'tok' - *tok++ = *s++; - - *tok = '\0'; // terminate - *pc = s; // adjust caller's pointer - - return otok; // return pointer to token -} - -// listing format: -// -// ADDR CODE SOURCE -// 0000 0000 0000 0000 0000 | XXXXXXXXXXXXXXXXX - -// --------------------------------------------------------------------------------- -// trim - remove trailing whitespace from string s -// --------------------------------------------------------------------------------- - -char *trim (char *s) -{ - char *os = s, *nb; - - for (nb = s-1; *s; s++) - if (*s > ' ') - nb = s; - - nb[1] = '\0'; - return os; -} - -// --------------------------------------------------------------------------------- -// listout - emit current constructed output listing line held in "listline" and -// if "reset" is true, prepare listline for second and subsequent listing lines -// for a given input statement. -// --------------------------------------------------------------------------------- - -void listout (BOOL reset) -{ - if (flist && list_on && ! line_error) { - trim(listline); - fputs(listline, flist); - putc('\n', flist); - if (reset) - sprintf(listline, LEFT_MARGIN, org); - } -} - -// --------------------------------------------------------------------------------- -// storew - store a word in the output medium (hex or binary file). Most of the time -// writew is used. Advances the origin! -// --------------------------------------------------------------------------------- - -void storew (int word, RELOC relative) -{ - if (pass == 2) { // save in output (load) file. - switch (outmode) { - case OUTMODE_BINARY: - bincard_writew(word, relative); - break; - - case OUTMODE_LOAD: - fprintf(fout, " %04x%s" ENDLINE, word & 0xFFFF, - (relative == ABSOLUTE) ? "" : (relative == RELATIVE) ? "R" : - (relative == LIBF) ? "L" : (relative == CALL) ? "$" : "?"); - break; - - default: - bail("in storew, can't happen"); - } - } - - if (relative != LIBF) - org++; - - assembled = TRUE; // remember that we wrote something -} - -// --------------------------------------------------------------------------------- -// setw - store a word value in the current listing output line in position 'pos'. -// --------------------------------------------------------------------------------- - -void setw (int pos, int word, RELOC relative) -{ - char tok[10], *p; - int i; - - if (flist == NULL || ! list_on) - return; - - sprintf(tok, "%04x", word & 0xFFFF); - - for (i = 0, p = listline + 5*pos; i < 4; i++) - p[i] = tok[i]; - - if (relative == RELATIVE) - p[i] = 'R'; - else if (relative != ABSOLUTE) - p[i] = '*'; -} - -// --------------------------------------------------------------------------------- -// writew - emit an assembled word value. Words are also displayed in the listing file. -// if relative is true, a relocation entry should be recorded. -// --------------------------------------------------------------------------------- - -void writew (int word, RELOC relative) -{ // first, the listing stuff... - if (nwout == 0) { // on first output word, display address in column 0 - setw(0, org, FALSE); - } - else if (nwout >= 4) { // if 4 words have already been written, start new line - listout(TRUE); - nwout = 0; - } - - nwout++; - setw(nwout, word, relative); // display word in the listing line - - storew(word, relative); // write it to the output medium -} - -// --------------------------------------------------------------------------------- -// setorg - take note of new load address -// --------------------------------------------------------------------------------- - -void setorg (int neworg) -{ - if (pass == 2) { - setw(0, neworg, FALSE); // display in listing file in column 0 - - if (outmode == OUTMODE_LOAD) { // write new load address to the output file - fprintf(fout, "@%04x%s" ENDLINE, neworg & 0xFFFF, relocate ? "R" : ""); - } - else { - bincard_setorg(neworg); - } - } - - org = neworg; -} - -// --------------------------------------------------------------------------------- -// org_even - force load address to an even address -// --------------------------------------------------------------------------------- - -void org_even (void) -{ - if (org & 1) - setorg(org+1); -} - -// --------------------------------------------------------------------------------- -// tabtok - get the token in tab-delimited column number i, from source string c, -// saving in string 'tok'. If save is nonnull, we copy the entire remainder of -// the input string in buffer 'save' (in contrast to 'tok' which gets only the -// first whitespace delimited token). -// --------------------------------------------------------------------------------- - -void tabtok (char *c, char *tok, int i, char *save) -{ - *tok = '\0'; - - while (--i >= 0) { // skip to i'th tab-delimited field - if ((c = strchr(c, '\t')) == NULL) { - if (save) // was none - *save = '\0'; - return; - } - c++; - } - - while (*c == ' ') // skip leading blanks - c++; - - if (save != NULL) // save copy of entire remainder - strcpy(save, c); - - while (*c > ' ') { // take up to any whitespace - if (*c == '(') { // if we start with a paren, take all up to closing paren including spaces - while (*c && *c != ')') - *tok++ = *c++; - } - else if (*c == '.') { // period means literal character following - *tok++ = *c++; - if (*c) - *tok++ = *c++; - } - else - *tok++ = *c++; - } - - *tok = '\0'; -} - -// --------------------------------------------------------------------------------- -// coltok - extract a token from string c, saving to buffer tok, by examining -// columns ifrom through ito only. If save is nonnull, the entire remainder -// of the input from ifrom to the end is saved there. In this routine -// if condense is true, we save all nonwhite characters in the column range; -// not the usual thing. This helps us coalesce the format, tag, & index things -// nto one string for the simple minded parser. If condense is FALSE, we terminate -// on the first nonblank, except that if we start with a (, we take up to ) and -// then terminate on a space. -// -// ifrom and ito on entry are column numbers, not indices; we change that right away -// --------------------------------------------------------------------------------- - -void coltok (char *c, char *tok, int ifrom, int ito, BOOL condense, char *save) -{ - char *otok = tok; - int i; - - ifrom--; - ito--; - - for (i = 0; i < ifrom; i++) { - if (c[i] == '\0') { // line ended before this column - *tok = '\0'; - if (save) - *save = '\0'; - return; - } - } - - if (save) // save from ifrom on - strcpy(save, c+i); - - if (condense) { - for (; i <= ito; i++) { // save only nonwhite characters - if (c[i] > ' ') - *tok++ = c[i]; - } - } - else { - if (c[i] == ' ' && save != NULL)// if it starts with a space, it's empty - *save = '\0'; - - while (i <= ito) { // take up to any whitespace - if (c[i] <= ' ') - break; - else if (c[i] == '(') { // starts with paren? take to close paren - while (i <= ito && c[i]) { - if ((*tok++ = c[i++]) == ')') - break; - } - } - else if (c[i] == '.') { // period means literal character following - *tok++ = c[i++]; - if (i <= ito && c[i]) - *tok++ = c[i++]; - } - else - *tok++ = c[i++]; - } - } - - *tok = '\0'; - trim(otok); -} - -// --------------------------------------------------------------------------------- -// opcode table -// --------------------------------------------------------------------------------- - -// modifiers for the opcode definition table: - -#define L "L" // long -#define X "X" // absolute displacement -#define I "I" // indirect -#define IDX "0123" // indexed (some LDX commands in the DMS source say LDX L0, so accept 0 -#define E "E" // even address -#define NONE "" -#define ALL L X I IDX // hope non-Microsoft C accepts and concatenates strings like this -#define ANY "\xFF" -#define NUMS "0123456789" - -#define IS_DBL 0x0001 // double word operand implies even address -#define IS_ABS 0x0002 // always uses absolute addressing mode (implied X) -#define NO_IDX 0x0004 // even with 1 or 2 modifier, this is not really indexed (for STX/LDX) -#define NO_ARGS 0x0008 // statement takes no arguments -#define TRAP 0x1000 // debug this instruction - -struct tag_op { // OPCODE TABLE - char *mnem; - int opcode; - void (*handler)(struct tag_op *op, char *label, char *mods, char *arg); - char *mods_allowed; - char *mods_implied; - int flags; -}; - // special opcode handlers -void std_op (struct tag_op *op, char *label, char *mods, char *arg); -void b_op (struct tag_op *op, char *label, char *mods, char *arg); -void bsc_op (struct tag_op *op, char *label, char *mods, char *arg); -void bsi_op (struct tag_op *op, char *label, char *mods, char *arg); -void mdx_op (struct tag_op *op, char *label, char *mods, char *arg); -void shf_op (struct tag_op *op, char *label, char *mods, char *arg); - -void x_aif (struct tag_op *op, char *label, char *mods, char *arg); -void x_aifb (struct tag_op *op, char *label, char *mods, char *arg); -void x_ago (struct tag_op *op, char *label, char *mods, char *arg); -void x_agob (struct tag_op *op, char *label, char *mods, char *arg); -void x_anop (struct tag_op *op, char *label, char *mods, char *arg); -void x_abs (struct tag_op *op, char *label, char *mods, char *arg); -void x_call (struct tag_op *op, char *label, char *mods, char *arg); -void x_dsa (struct tag_op *op, char *label, char *mods, char *arg); -void x_file (struct tag_op *op, char *label, char *mods, char *arg); -void x_link (struct tag_op *op, char *label, char *mods, char *arg); -void x_libf (struct tag_op *op, char *label, char *mods, char *arg); -void x_org (struct tag_op *op, char *label, char *mods, char *arg); -void x_opt (struct tag_op *op, char *label, char *mods, char *arg); -void x_ces (struct tag_op *op, char *label, char *mods, char *arg); -void x_bes (struct tag_op *op, char *label, char *mods, char *arg); -void x_bss (struct tag_op *op, char *label, char *mods, char *arg); -void x_dc (struct tag_op *op, char *label, char *mods, char *arg); -void x_dec (struct tag_op *op, char *label, char *mods, char *arg); -void x_ebc (struct tag_op *op, char *label, char *mods, char *arg); -void x_end (struct tag_op *op, char *label, char *mods, char *arg); -void x_ent (struct tag_op *op, char *label, char *mods, char *arg); -void x_epr (struct tag_op *op, char *label, char *mods, char *arg); -void x_equ (struct tag_op *op, char *label, char *mods, char *arg); -void x_exit (struct tag_op *op, char *label, char *mods, char *arg); -void x_ils (struct tag_op *op, char *label, char *mods, char *arg); -void x_iss (struct tag_op *op, char *label, char *mods, char *arg); -void x_libr (struct tag_op *op, char *label, char *mods, char *arg); -void x_lorg (struct tag_op *op, char *label, char *mods, char *arg); -void x_dmes (struct tag_op *op, char *label, char *mods, char *arg); -void x_dn (struct tag_op *op, char *label, char *mods, char *arg); -void x_dump (struct tag_op *op, char *label, char *mods, char *arg); -void x_pdmp (struct tag_op *op, char *label, char *mods, char *arg); -void x_hdng (struct tag_op *op, char *label, char *mods, char *arg); -void x_list (struct tag_op *op, char *label, char *mods, char *arg); -void x_spac (struct tag_op *op, char *label, char *mods, char *arg); -void x_spr (struct tag_op *op, char *label, char *mods, char *arg); -void x_ejct (struct tag_op *op, char *label, char *mods, char *arg); -void x_trap (struct tag_op *op, char *label, char *mods, char *arg); -void x_xflc (struct tag_op *op, char *label, char *mods, char *arg); - -struct tag_op ops[] = { - ".OPT", 0, x_opt, NONE, NONE, 0, // non-IBM extensions - "TRAP", 0, x_trap, NONE, NONE, 0, // assembler breakpoint trap - ".CES", 0, x_ces, NONE, NONE, 0, // lets us specify simulated console entry switch values for startup - - "ABS", 0, x_abs, NONE, NONE, 0, - "BES", 0, x_bes, E, NONE, 0, // standard pseudo-ops - "BSS", 0, x_bss, E, NONE, 0, - "DC", 0, x_dc, NONE, NONE, 0, - "DEC", 0, x_dec, E, E, IS_DBL, - "DMES", 0, x_dmes, ANY, NONE, 0, - "DN", 0, x_dn, NONE, NONE, 0, - "DSA", 0, x_dsa, NONE, NONE, 0, - "DUMP", 0, x_dump, NONE, NONE, 0, - "EBC", 0, x_ebc, NONE, NONE, 0, - "EJCT", 0, x_ejct, NONE, NONE, 0, - "END", 0, x_end, NONE, NONE, 0, - "ENT", 0, x_ent, NONE, NONE, 0, - "EPR", 0, x_epr, NONE, NONE, 0, - "EQU", 0, x_equ, NONE, NONE, 0, - "EXIT", 0, x_exit, NONE, NONE, 0, // alias for call $exit since we don't have macros yet - "FILE", 0, x_file, NONE, NONE, 0, - "HDNG", 0, x_hdng, ANY, NONE, 0, - "ILS", 0, x_ils, NUMS, NONE, 0, - "ISS", 0, x_iss, NUMS, NONE, 0, - "LIBF", 0, x_libf, NONE, NONE, 0, - "LIBR", 0, x_libr, NONE, NONE, 0, - "LINK", 0, x_link, NONE, NONE, 0, - "LIST", 0, x_list, NONE, NONE, 0, - "LORG", 0, x_lorg, NONE, NONE, 0, - "ORG", 0, x_org, NONE, NONE, 0, - "PDMP", 0, x_pdmp, NONE, NONE, 0, - "SPAC", 0, x_spac, NONE, NONE, 0, - "SPR", 0, x_spr, NONE, NONE, 0, - "XFLC", 0, x_xflc, NONE, NONE, 0, - - "A", 0x8000, std_op, ALL, NONE, 0, // standard addressing ops - "AD", 0x8800, std_op, ALL, NONE, IS_DBL, - "AND", 0xE000, std_op, ALL, NONE, 0, - "BSI", 0x4000, bsi_op, ALL, NONE, 0, - "CALL", 0x4000, x_call, ALL, L, 0, // alias for BSI L, or external call - "D" , 0xA800, std_op, ALL, NONE, 0, - "EOR", 0xF000, std_op, ALL, NONE, 0, - "LD", 0xC000, std_op, ALL, NONE, 0, - "LDD", 0xC800, std_op, ALL, NONE, IS_DBL, - "LDS", 0x2000, std_op, NONE, NONE, IS_ABS, - "LDX", 0x6000, std_op, ALL, NONE, IS_ABS|NO_IDX, - "M", 0xA000, std_op, ALL, NONE, 0, - "MDX", 0x7000, mdx_op, ALL, NONE, 0, - "MDM", 0x7000, mdx_op, L, L, 0, // like MDX L - "NOP", 0x1000, std_op, NONE, NONE, NO_ARGS, - "OR", 0xE800, std_op, ALL, NONE, 0, - "S", 0x9000, std_op, ALL, NONE, 0, - "SD", 0x9800, std_op, ALL, NONE, IS_DBL, - "STD", 0xD800, std_op, ALL, NONE, IS_DBL, - "STO", 0xD000, std_op, ALL, NONE, 0, - "STS", 0x2800, std_op, ALL, NONE, 0, - "STX", 0x6800, std_op, ALL, NONE, NO_IDX, - "WAIT", 0x3000, std_op, NONE, NONE, NO_ARGS, - "XCH", 0x1810, std_op, NONE, NONE, 0, // same as RTE 16 - "XIO", 0x0800, std_op, ALL, NONE, IS_DBL, - - "BSC", 0x4800, bsc_op, ALL, NONE, 0, // branch family - "BOSC", 0x4840, bsc_op, ALL, NONE, 0, // is BOSC always long form? No. - "SKP", 0x4800, bsc_op, NONE, NONE, 0, // alias for BSC one word version - - "B", 0x4800, b_op, ALL, NONE, 0, // alias for MDX or BSC L - "BC", 0x4802, std_op, ALL, L, 0, // alias for BSC L - "BN", 0x4828, std_op, ALL, L, 0, // alias for BSC L - "BNN", 0x4810, std_op, ALL, L, 0, // alias for BSC L - "BNP", 0x4808, std_op, ALL, L, 0, // alias for BSC L - "BNZ", 0x4820, std_op, ALL, L, 0, // alias for BSC L - "BO", 0x4801, std_op, ALL, L, 0, // alias for BSC L - "BOD", 0x4840, std_op, ALL, L, 0, // alias for BSC L - "BP", 0x4830, std_op, ALL, L, 0, // alias for BSC L - "BZ", 0x4818, std_op, ALL, L, 0, // alias for BSC L - - "RTE", 0x18C0, shf_op, IDX X, X, 0, // shift family - "SLA", 0x1000, shf_op, IDX X, X, 0, - "SLC", 0x10C0, shf_op, IDX X, X, 0, - "SLCA", 0x1040, shf_op, IDX X, X, 0, - "SLT", 0x1080, shf_op, IDX X, X, 0, - "SRA", 0x1800, shf_op, IDX X, X, 0, - "SRT", 0x1880, shf_op, IDX X, X, 0, - - "AIF", 0, x_aif, NONE, NONE, 0, // assemble if - "AIFB", 0, x_aifb, NONE, NONE, 0, // assemble if - "AGO", 0, x_ago, NONE, NONE, 0, // assemble goto - "AGOB", 0, x_agob, NONE, NONE, 0, // assemble goto - "ANOP", 0, x_anop, NONE, NONE, 0, // assemble target - - NULL // end of table -}; - -// --------------------------------------------------------------------------------- -// addextn - apply file extension 'extn' to filename 'fname' and put result in 'outbuf' -// if outbuf is NULL, we allocate a buffer -// --------------------------------------------------------------------------------- - -char *addextn (char *fname, char *extn, char *outbuf) -{ - char *buf, line[500], *c; - - buf = (outbuf == NULL) ? line : outbuf; - - strcpy(buf, fname); // create listfn from first source filename (e.g. xxx.lst); - if ((c = strrchr(buf, '\\')) == NULL) - if ((c = strrchr(buf, '/')) == NULL) - if ((c = strrchr(buf, ':')) == NULL) - c = buf; - - if ((c = strrchr(c, '.')) == NULL) - strcat(buf, extn); - else - strcpy(c, extn); - - return (outbuf == NULL) ? astring(line) : outbuf; -} - -// --------------------------------------------------------------------------------- -// controlcard - examine an assembler control card (* in column 1) -// --------------------------------------------------------------------------------- - -BOOL controlcard (char *line) -{ - if (strnicmp(line, "*LIST", 5) == 0) { // turn on listing file even if not specified on command line - do_list = list_on = TRUE; - return TRUE; - } - - if (strnicmp(line, "*XREF", 5) == 0) { - do_xref = TRUE; - return TRUE; - } - - if (strnicmp(line, "*PRINT SYMBOL TABLE", 19) == 0) { - do_syms = TRUE; - return TRUE; - } - - if (strnicmp(line, "*SAVE SYMBOL TABLE", 18) == 0) { - savetable = TRUE; - return TRUE; - } - - if (strnicmp(line, "*SYSTEM SYMBOL TABLE", 20) == 0) { - preload = TRUE; - preload_symbols(); - return TRUE; - } - - return FALSE; -} - -// --------------------------------------------------------------------------------- -// stuff - insert characters into a line -// --------------------------------------------------------------------------------- - -void stuff (char *buf, char *tok, int maxchars) -{ - while (*tok) { - *buf++ = *tok++; - - if (maxchars) - if (--maxchars <= 0) - break; - } -} - -// --------------------------------------------------------------------------------- -// format_line - construct a source code input line from components -// --------------------------------------------------------------------------------- - -void format_line (char *buf, char *label, char *op, char *mods, char *args, char *remarks) -{ - int i; - - if (tabformat) { - sprintf(buf, "%s\t%s\t%s\t%s\t%s", label, op, mods, args, remarks); - } - else { - for (i = 0; i < 72; i++) - buf[i] = ' '; - buf[i] = '\0'; - - stuff(buf+20, label, 5); - stuff(buf+26, op, 4); - stuff(buf+31, mods, 2); - stuff(buf+34, args, 72-34); - } -} - -// --------------------------------------------------------------------------------- -// lookup_op - find an opcode -// --------------------------------------------------------------------------------- - -struct tag_op * lookup_op (char *mnem) -{ - struct tag_op *op; - int i; - - for (op = ops; op->mnem != NULL; op++) { - if ((i = strcmp(op->mnem, mnem)) == 0) - return op; - - if (i > 0) - break; - } - return NULL; -} - -// --------------------------------------------------------------------------------- -// bincard - routines to write IBM 1130 Card object format -// --------------------------------------------------------------------------------- - -unsigned short bincard[54]; // the 54 data words that can fit on a binary format card -char binflag[45]; // the relocation flags of the 45 buffered object words (0, 1, 2, 3) -int bincard_n = 0; // number of object words stored in bincard (0-45) -int bincard_seq = 0; // card output sequence number -int bincard_org = 0; // origin of current card-full -int bincard_maxaddr = 0; -BOOL bincard_first = TRUE; // TRUE when we're to write the program type card - -// bincard_init - prepare a new object data output card - -void bincard_init (void) -{ - memset(bincard, 0, sizeof(bincard)); // clear card data - memset(binflag, 0, sizeof(binflag)); // clear relocation data - bincard_n = 0; // no data - bincard[0] = bincard_org; // store load address - bincard_maxaddr = MAX(bincard_maxaddr, bincard_org-1); // save highest address written-to (this may be a BSS) -} - -// binard_writecard - emit a card. sbrk_text = NULL for normal data cards, points to comment text for sbrk card -// note: sbrk_text if not NULL MUST be a writeable buffer of at LEAST 71 characters - -void bincard_writecard (char *sbrk_text) -{ - unsigned short binout[80]; - char ident[12]; - int i, j; - - if (sbrk_text != NULL) { // sbrk card has 4 binary words followed by comment text - for (j = 66; j < 71; j++) // be sure input columns 67..71 are nonblank (have version number) - if (sbrk_text[j] <= ' ') - break; - - if (j < 71) // sbrk card didn't have the info, stuff in current release - for (j = 0; j < 5; j++) - sbrk_text[66+j] = dmsversion[j]; - - binout[0] = 0; - binout[1] = 0; - binout[2] = 0; - binout[3] = 0x1000; - - sbrk_text += 5; // start at the real column 6 (after *SBRK - for (j = 5; j < 72; j++) - binout[j] = (*sbrk_text) ? ascii_to_hollerith(*sbrk_text++) : 0; - - } - else { // binary card format packs 54 words into 72 columns - for (i = j = 0; i < 54; i += 3, j += 4) { - binout[j ] = ( bincard[i] & 0xFFF0); - binout[j+1] = ((bincard[i] << 12) & 0xF000) | ((bincard[i+1] >> 4) & 0x0FF0); - binout[j+2] = ((bincard[i+1] << 8) & 0xFF00) | ((bincard[i+2] >> 8) & 0x00F0); - binout[j+3] = ((bincard[i+2] << 4) & 0xFFF0); - } - } - - sprintf(ident, "%08ld", ++bincard_seq); // append sequence text - memmove(ident, progname, MIN(strlen(progname), 4)); - - for (i = 0; i < 8; i++) - binout[j++] = ascii_to_hollerith(ident[i]); - - fwrite(binout, sizeof(binout[0]), 80, fout); // write card image -} - -// binard_writedata - emit an object data card - -void bincard_writedata (void) -{ - unsigned short rflag = 0; - int i, j, nflag = 0; - - bincard[1] = 0; // checksum - bincard[2] = 0x0A00 | bincard_n; // data card type + word count - - for (i = 0, j = 3; i < bincard_n; i++) { // construct relocation indicator bitmap - if (nflag == 8) { - bincard[j++] = rflag; - rflag = 0; - nflag = 0; - } - rflag = (rflag << 2) | (binflag[i] & 3); - nflag++; - } - - if (nflag > 0) - bincard[j] = rflag << (16 - 2*nflag); - - bincard_writecard(FALSE); // emit the card -} - -// bincard_flush - flush any pending binary data - -void bincard_flush (void) -{ - if (bincard_n > 0) - bincard_writedata(); - - bincard_init(); -} - -// bincard_sbrk - emit an SBRK card - -void bincard_sbrk (char *line) -{ - if (bincard_first) - bincard_typecard(); - else - bincard_flush(); - - bincard_writecard(line); -} - -// bincard_setorg - set the origin - -void bincard_setorg (int neworg) -{ - bincard_org = neworg; // set origin for next card - bincard_flush(); // flush any current data & store origin -} - -// bincard_endcard - write end of program card - -void bincard_endcard (void) -{ - bincard_flush(); - - bincard[0] = (bincard_maxaddr + 2) & ~1; // effective length: add 1 to max origin, then 1 more to round up - bincard[1] = 0; - bincard[2] = 0x0F00; - bincard[3] = pta & 0xFFFF; - - bincard_writecard(NULL); -} - -// bincard_typecard - write the program type - -void bincard_typecard (void) -{ - int i; - - if (! bincard_first) - return; - - bincard_first = FALSE; - - memset(bincard, 0, sizeof(bincard)); - - bincard[2] = (unsigned short) ((progtype << 8) | intmode | realmode); - -// all indices not listed are documented as 'reserved' - - switch (progtype) { - case PROGTYPE_ABSOLUTE: - case PROGTYPE_RELOCATABLE: -// bincard[ 4] = 0; // length of common (fortran only) - bincard[ 5] = 0x0003; -// bincard[ 6] = 0; // length of work area (fortran only) - bincard[ 8] = ndefined_files; - namecode(&bincard[9], progname); - bincard[11] = (pta < 0) ? 0 : pta; - break; - - case PROGTYPE_LIBF: - case PROGTYPE_CALL: - bincard[ 5] = 3*nentries; - for (i = 0; i < nentries; i++) { - namecode(&bincard[9+3*i], entry[i]->name); - bincard[11+3*i] = entry[i]->value; - } - break; - - case PROGTYPE_ISSLIBF: - case PROGTYPE_ISSCALL: - bincard[ 5] = 6+nintlevels; - namecode(&bincard[9], entry[0]->name); - bincard[11] = entry[0]->value; - bincard[12] = iss_number + ISTV; // magic number ISTV is 0x33 in DMS R2V12 - bincard[13] = iss_number; - bincard[14] = nintlevels; - bincard[15] = intlevel_primary; - bincard[16] = intlevel_secondary; - bincard[29] = 1; - break; - - case PROGTYPE_ILS: - bincard[ 2] = (unsigned short) (progtype << 8); - bincard[ 5] = 4; - bincard[12] = intlevel_primary; - break; - - default: - bail("in bincard_typecard, can't happen"); - } - - bincard[1] = 0; // checksum - - bincard_writecard(NULL); - - bincard_init(); -} - -// bincard_writew - write a word to the current output card. - -void bincard_writew (int word, RELOC relative) -{ - if (pass != 2) - return; - - if (bincard_first) - bincard_typecard(); - else if (bincard_n >= 45) // flush full card buffer - bincard_flush(); - - binflag[bincard_n] = relative & 3; // store relocation bits and data word - bincard[9+bincard_n++] = word; - - if (relative != LIBF) { - bincard_maxaddr = MAX(bincard_maxaddr, bincard_org); - bincard_org++; - } -} - -// writetwo - notification that we are about to write two words which must stay together - -void writetwo (void) -{ - if (pass == 2 && outmode == OUTMODE_BINARY && bincard_n >= 44) - bincard_flush(); -} - -// handle_sbrk - handle an SBRK directive. -// This was not part of the 1130 assembler; they assembled DMS on a 360 - -void handle_sbrk (char *line) -{ - char rline[90]; - - if (pass != 2) - return; - - strncpy(rline, line, 81); // get a copy and pad it if necessary to 80 characters - rline[80] = '\0'; - while (strlen(rline) < 80) - strcat(rline, " "); - - switch (outmode) { - case OUTMODE_LOAD: - fprintf(fout, "#SBRK%s\n", trim(rline+5)); - - case OUTMODE_BINARY: - bincard_sbrk(rline); - break; - - default: - bail("in handle_sbrk, can't happen"); - } -} - -// --------------------------------------------------------------------------------- -// namecode - turn a string into a two-word packed name -// --------------------------------------------------------------------------------- - -void namecode (unsigned short *words, char *tok) -{ - long val = 0; - int i, ch; - - for (i = 0; i < 5; i++) { // pick up bits - if (*tok) - ch = *tok++; - else - ch = ' '; - - val = (val << 6) | (ascii_to_ebcdic_table[ch] & 0x3F); - } - - words[0] = (unsigned short) (val >> 16); - words[1] = (unsigned short) val; -} - -// --------------------------------------------------------------------------------- -// parse_line - parse one input line. -// --------------------------------------------------------------------------------- - -void parse_line (char *line) -{ - char label[100], mnem[100], arg[200], mods[20], *c; - struct tag_op *op; - - if (line[0] == '/' && line[1] == '/') // job control card? probably best to ignore it - return; - - if (line[0] == '*') { // control card comment or comment in tab-format file - if (check_control) // pay attention to control cards only at top of file - if (! controlcard(line)) - check_control = FALSE; // first non-control card shuts off sensitivity to them - - if (strnicmp(line+1, "SBRK", 4) == 0) - handle_sbrk(line); - - return; - } - - check_control = FALSE; // non-control card, consider them no more - - label[0] = '\0'; // prepare to extract fields - mods[0] = '\0'; - mnem[0] = '\0'; - arg[0] = '\0'; - - if (tabformat || strchr(line, '\t') != NULL) { // if input line has tabs, parse loosely - tabformat = TRUE; // this is a tab-formatted file - - for (c = line; *c && *c <= ' '; c++) // find first nonblank - ; - - if (*c == '*' || ! *c) // ignore as a comment - return; - - tabtok(line, label, 0, NULL); - tabtok(line, mnem, 1, NULL); - tabtok(line, mods, 2, NULL); - tabtok(line, arg, 3, opfield); - } - else { // if no tabs, use strict card-column format - if (line[20] == '*') // comment - return; - - line[72] = '\0'; // clip off sequence - - coltok(line, label, 21, 25, TRUE, NULL); - coltok(line, mnem, 27, 30, TRUE, NULL); - coltok(line, mods, 32, 33, TRUE, NULL); - coltok(line, arg, 35, 72, FALSE, opfield); - } - -// I don't know where I got this idea, but it's wrong... -// if (strchr(mods, '1') || strchr(mods, '2') || strchr(mods, '3')) { // index + X means ignore X -// if ((c = strchr(mods, 'X')) != NULL) -// strcpy(c, c+1); // remove the X -// } - - if (*label) // display org in any line with a label - setw(0, org, FALSE); - - if (! *mnem) { // label w/o mnemonic, just define the symbol - if (*label) - set_symbol(label, org, TRUE, relocate); - return; - } - - if ((op = lookup_op(mnem)) == NULL) { // look up mnemonic - if (*label) - set_symbol(label, org, TRUE, relocate);// at least define the label - - asm_error("Unknown opcode '%s'", mnem); - return; - } - - if (op->flags & TRAP) // assembler debugging breakpoint - x_trap(op, label, mods, arg); - - if (*op->mods_allowed != '\xFF') { // validate modifiers against list of allowed characters - for (c = mods; *c; ) { - if (strchr(op->mods_allowed, *c) == NULL) { - asm_warning("Modifier '%c' not permitted", *c); - strcpy(c, c+1); // remove it and keep parsing - } - else - c++; - } - } - - strcat(mods, op->mods_implied); // tack on implied modifiers - - if (strchr(mods, 'I')) // indirect implies long - strcat(mods, "L"); - - requires_even_address = op->flags & IS_DBL; - - org_advanced = strchr(mods, 'L') ? 2 : 1; // by default, * means address + 1 or 2. Sometimes it doesn't - (op->handler)(op, label, mods, arg); -} - -// --------------------------------------------------------------------------------- -// get one input line from current file or macro -// --------------------------------------------------------------------------------- - -BOOL get_line (char *buf, int nbuf, BOOL onelevel) -{ - char *retval; - - if (ended) // we hit the END command - return FALSE; - - // if macro active, return line from macro buffer, otherwise read from file - // do not pop end-of-macro if onelevel is TRUE - - if ((retval = fgets(buf, nbuf, fin)) == NULL) - return FALSE; - - lno++; // count the line - return TRUE; -} - -// --------------------------------------------------------------------------------- -// proc - process one pass of one source file -// --------------------------------------------------------------------------------- - -void proc (char *fname) -{ - char line[256], *c; - int i; - - if (strchr(fname, '.') == NULL) // if input file has no extension, - addextn(fname, ".asm", curfn); // set appropriate file extension - else - strcpy(curfn, fname); // otherwise use extension specified - -// 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) - if ((c = strrchr(curfn, '/')) == NULL) - if ((c = strrchr(curfn, ':')) == NULL) - c = curfn; - - strncpy(progname, c, sizeof(progname)); // take name after path - progname[sizeof(progname)-1] = '\0'; - if ((c = strchr(progname, '.')) != NULL)// remove extension - *c = '\0'; - } - - lno = 0; // reset global input line number - ended = FALSE; // have not seen END statement - - if (listfn == NULL) // if list file name is undefined, - listfn = addextn(fname, ".lst", NULL); // create from first filename - - if (verbose) - fprintf(stderr, "--- Starting file %s pass %d\n", curfn, pass); - - if ((fin = fopen(curfn, "r")) == NULL) { - perror(curfn); // oops - exit(1); - } - - if (flist) { // put banner in listing file - strcpy(listline,"=== FILE ======================================================================"); - for (i = 9, c = curfn; *c;) - listline[i++] = *c++; - listline[i] = ' '; - fputs(listline, flist); - putc('\n', flist); - list_on = TRUE; - } - // read all lines till EOF or END statement - while (get_line(line, sizeof(line), FALSE)) { - prep_line(line); // preform standard line prep - parse_line(line); // parse - listout(FALSE); // complete the listing - } - - fclose(fin); - - if (n_literals > 0) { // force out any pending literal constants at end of file - output_literals(TRUE); - listout(FALSE); - } -} - -// --------------------------------------------------------------------------------- -// prep_line - prepare input line for parsing -// --------------------------------------------------------------------------------- - -void prep_line (char *line) -{ - char *c; - - upcase(line); // uppercase it - nwout = 0; // number of words output so far - line_error = FALSE; // no errors on this line so far - - for (c = line; *c; c++) { // truncate at newline - if (*c == '\r' || *c == '\n') { - *c = '\0'; - break; - } - } - - if (flist && list_on) { // construct beginning of listing line - if (tabformat) - sprintf(listline, LINEFORMAT, lno, detab(line)); - else { - if (strlen(line) > 20) // get the part where the commands start - c = line+20; - else - c = ""; - - sprintf(listline, LINEFORMAT, lno, c); - stuff(listline, line, 20); // stuff the left margin in to the left side - } - } -} - -// --------------------------------------------------------------------------------- -// opcmp - operand name comparison routine for qsort -// --------------------------------------------------------------------------------- - -int opcmp (const void *a, const void *b) -{ - return strcmp(((struct tag_op *) a)->mnem, ((struct tag_op *) b)->mnem); -} - -// --------------------------------------------------------------------------------- -// preload_symbols - load a saved symbol table -// --------------------------------------------------------------------------------- - -void preload_symbols (void) -{ - FILE *fd; - char str[200], sym[20]; - int v; - static BOOL preloaded_already = FALSE; - - if (pass > 1 || preloaded_already) - return; - - preloaded_already = TRUE; - - if ((fd = fopen(SYSTEM_TABLE, "r")) == NULL) // read the system symbol tabl - perror(SYSTEM_TABLE); - else { - while (fgets(str, sizeof(str), fd) != NULL) { - if (sscanf(str, "%s %x", sym, &v) == 2) - set_symbol(sym, v, TRUE, FALSE); - } - fclose(fd); - } -} - -// --------------------------------------------------------------------------------- -// save_symbols - save a symbol table -// --------------------------------------------------------------------------------- - -void save_symbols (void) -{ - FILE *fd; - char str[20]; - PSYMBOL s; - - if (relocate) { - fprintf(stderr, "Can't save symbol table unless ABS assembly\n"); - return; - } - - if ((fd = fopen(SYSTEM_TABLE, "r")) != NULL) { - fclose(fd); - if (saveprompt) { - printf("Overwrite system symbol table %s? ", SYSTEM_TABLE); - fgets(str, sizeof(str), stdin); - if (str[0] != 'y' && str[0] != 'Y') - return; - } - unlink(SYSTEM_TABLE); - } - - if ((fd = fopen(SYSTEM_TABLE, "w")) == NULL) { - perror(SYSTEM_TABLE); - return; - } - - for (s = symbols; s != NULL; s = s->next) - fprintf(fd, "%-5s %04x\n", s->name, s->value); - - fclose(fd); -} - -// --------------------------------------------------------------------------------- -// startpass - initialize data structures, prepare to start a pass -// --------------------------------------------------------------------------------- - -void startpass (int n) -{ - int nops; - struct tag_op *p; - - pass = n; // reset globals: pass number - nerrors = 0; // error count - org = 0; // load address (origin) - lno = 0; // input line number - relocate = TRUE; // relocatable assembly mode - assembled = FALSE; // true if any output has been generated - list_on = do_list; // listing enable - dmes_saved = FALSE; // partial character strings output - - n_literals = 0; // literal values pending output - lit_tag = 0; - - if (pass == 1) { // first pass only - for (nops = 0, p = ops; p->mnem != NULL; p++, nops++) // count opcodes - ; - - qsort(ops, nops, sizeof(*p), opcmp); // sort the opcode table - - if (preload) - preload_symbols(); - } - else { // second pass only - if (outfn == NULL) - outfn = addextn(curfn, (outmode == OUTMODE_LOAD) ? ".out" : ".bin" , NULL); - - if ((fout = fopen(outfn, OUTWRITEMODE)) == NULL) { // open output file - perror(outfn); - exit(1); - } - - if (do_list) { // open listing file - if ((flist = fopen(listfn, "w")) == NULL) { - perror(listfn); - exit(1); - } - listhdr(); // print banner - } - } -} - -// --------------------------------------------------------------------------------- -// x_dc - DC define constant directive -// --------------------------------------------------------------------------------- - -void x_dc (struct tag_op *op, char *label, char *mods, char *arg) -{ - EXPR expr; -// char *tok; - - org_advanced = 1; // assume * means this address+1 -// doesn't make sense, but I think I found DMS listings to support it - - if (strchr(mods, 'E') != NULL) // force even address - org_even(); - - setw(0, org, FALSE); // display org in listing line - - if (*label) // define label - set_symbol(label, org, TRUE, relocate); - -// just one!? - getexpr(arg, FALSE, &expr); - writew(expr.value, expr.relative); // store value - - // pick up values, comma delimited -// for (tok = strtok(arg, ","); tok != NULL; tok = strtok(NULL, ",")) { -// getexpr(tok, FALSE, &expr); -// writew(expr.value, expr.relative); // store value -// } -} - -// --------------------------------------------------------------------------------- -// x_dec - DEC define double word constant directive. -// --------------------------------------------------------------------------------- - -// wd[0]: 8 unused bits | characteristic (= exponent+128) -// wd[1]: sign + 15 msb of mantissa in 2's complement -// wd[2]: 16 lsb of mantissa - -// NOTE: these are wrong with Fixed point numbers - -void convert_double_to_extended (double d, unsigned short *wd) -{ - int neg, exp; - unsigned long mantissa; - unsigned char *byte = (unsigned char *) &d; - - if (d == 0.) { - wd[0] = wd[1] = wd[2] = 0; - return; - } - // 7 6 5 4 0 - // d = ansi real*8 SXXX XXXX XXXX MMMM MMMM MMMM MMMM MMMM ... MMMM MMMM - - neg = byte[7] & 0x80; - exp = ((byte[7] & 0x7F) << 4) | ((byte[6] & 0xF0) >> 4); // extract exponent - exp -= 1023; // remove bias - - exp++; // shift to account for implied 1 we added - - // get 32 bits worth of mantissa. add the implied point - mantissa = 0x80000000L | ((byte[6] & 0x0F) << 27) | (byte[5] << 19) | (byte[4] << 11) | (byte[3] << 3) | ((byte[2] & 0xE0) >> 5); - - if (mantissa & (0x80000000L >> 31)) // keep 31 bits, round if necessary - mantissa += (0x80000000L >> 31); - - mantissa >>= (32-31); // get into low 31 bits - - // now turn into IBM 1130 extended precision - - exp += 128; - - if (neg) - mantissa = (unsigned long) (- (long) mantissa); // two's complement - - wd[0] = (unsigned short) (exp & 0xFF); - wd[1] = (unsigned short) ((neg ? 0x8000 : 0) | ((mantissa >> (31-15)) & 0x7FFF)); - wd[2] = (unsigned short) (mantissa & 0xFFFF); -} - -void convert_double_to_standard (double d, unsigned short *wd) -{ - int neg, exp; - unsigned long mantissa; - unsigned char *byte = (unsigned char *) &d; - - if (d == 0.) { - wd[0] = wd[1] = 0; - return; - } - // 7 6 5 4 0 - // d = ansi real*8 SXXX XXXX XXXX MMMM MMMM MMMM MMMM MMMM ... MMMM MMMM - - neg = byte[7] & 0x80; - exp = ((byte[7] & 0x7F) << 4) | ((byte[6] & 0xF0) >> 4); // extract exponent - exp -= 1023; // remove bias - - exp++; // shift to account for implied 1 we added - - // get 32 bits worth of mantissa. add the implied point - mantissa = 0x80000000L | ((byte[6] & 0x0F) << 27) | (byte[5] << 19) | (byte[4] << 11) | (byte[3] << 3) | ((byte[2] & 0xE0) >> 5); - -// if (mantissa & (0x80000000L >> 23)) // keep 23 bits, round if necessary -// mantissa += (0x80000000L >> 23); - -// DEBUG -// printf("%8.4lf: %08lx %d\n", d, mantissa, exp); - - mantissa >>= (32-23); // get into low 23 bits - - // now turn into IBM 1130 standard precision - - exp += 128; - - if (neg) - mantissa = (unsigned long) (- (long) mantissa); // two's complement - - wd[0] = (unsigned short) ((neg ? 0x8000 : 0) | ((mantissa >> (23-15)) & 0x7FFF)); - wd[1] = (unsigned short) ((mantissa & 0x00FF) << 8) | (exp & 0xFF); - -// DEBUG -// printf(" D %04x%04x\n", wd[0], wd[1]); -} - -void convert_double_to_fixed (double d, unsigned short *wd, int bexp) -{ - int neg, exp, rshift; - unsigned long mantissa; - unsigned char *byte = (unsigned char *) &d; - - if (d == 0.) { - wd[0] = wd[1] = 0; - return; - } - // 7 6 5 4 0 - // d = ansi real*8 SXXX XXXX XXXX MMMM MMMM MMMM MMMM MMMM ... MMMM MMMM - - neg = byte[7] & 0x80; - exp = ((byte[7] & 0x7F) << 4) | ((byte[6] & 0xF0) >> 4); // extract exponent - exp -= 1023; // remove bias - - exp++; // shift to account for implied 1 we added - - // get 32 bits worth of mantissa. add the implied point - mantissa = 0x80000000L | ((byte[6] & 0x0F) << 27) | (byte[5] << 19) | (byte[4] << 11) | (byte[3] << 3) | ((byte[2] & 0xE0) >> 5); - - mantissa >>= 1; // shift it out of the sign bit - -// DEBUG -// printf("%8.4lf: %08lx %d\n", d, mantissa, exp); - - rshift = bexp - exp; - - if (rshift > 0) { - mantissa >>= rshift; - } - else if (rshift < 0) { - mantissa >>= (-rshift); - asm_warning("Fixed point overflow"); - } - - if (neg) - mantissa = (unsigned long) (- (long) mantissa); // two's complement - -// DEBUG -// printf(" B %08lx\n", mantissa); - - wd[0] = (unsigned short) ((mantissa >> 16) & 0xFFFF); // return all of the bits; no exponent here - wd[1] = (unsigned short) (mantissa & 0xFFFF); -} - -void getDconstant (char *tok, unsigned short *wd) -{ - unsigned long l; - char *b, *fmt; - double d; - int bexp, fixed; - - wd[0] = 0; - wd[1] = 0; - - if (strchr(tok, '.') == NULL && strchr(tok, 'B') == NULL && strchr(tok, 'E') == NULL) { - fmt = "%ld"; - if (*tok == '/') { // I don't see that this is legal but can't hurt to allow it - fmt = "%lx"; - tok++; - } - if (sscanf(tok, fmt, &l) != 1) { // no decimal means it's an integer? - asm_error("Syntax error in constant"); - } - else { - wd[0] = (unsigned short) ((l >> 16) & 0xFFFF); // high word - wd[1] = (unsigned short) (l & 0xFFFF); // low word - } - return; - } - - fixed = 0; - if ((b = strchr(tok, 'B')) != NULL) { - fixed = 1; - bexp = atoi(b+1); - *b = '\0'; // truncate at the b - } - if (sscanf(tok, "%lg", &d) != 1) { - asm_error("Syntax error in constant"); - return; - } - - if (fixed) - convert_double_to_fixed(d, wd, bexp); - else - convert_double_to_standard(d, wd); -} - -// If the input value is an integer with no decimal point and no B or E, -// DEC generates a double INTEGER value. -// IBM documentation ranges from ambiguous to wrong on this point, but -// examination of the DMS microfiche supports this. - -void x_dec (struct tag_op *op, char *label, char *mods, char *arg) -{ -// char *tok; - unsigned short wd[2]; - - org_advanced = 2; // assume * means address after this location, since it's +1 for dc? - - org_even(); // even address is implied - setw(0, org, FALSE); // display the origin - - if (*label) // define label - set_symbol(label, org, TRUE, relocate); - -// just one!? - getDconstant(arg, wd); - writew(wd[0], FALSE); // write hiword, then loword - writew(wd[1], FALSE); - - // pick up values, comma delimited -// for (tok = strtok(arg, ","); tok != NULL; tok = strtok(NULL, ",")) { -// getDconstant(tok, wd); -// -// writew(wd[0], FALSE); // write hiword, then loword -// writew(wd[1], FALSE); -} - -void x_xflc (struct tag_op *op, char *label, char *mods, char *arg) -{ - char *tok, *b; - double d; - int bexp, fixed; - unsigned short wd[3]; - - org_advanced = 2; // who knows? - - setw(0, org, FALSE); // display the origin - - if (*label) // define label - set_symbol(label, org, TRUE, relocate); - // pick up values, comma delimited - for (tok = strtok(arg, ","); tok != NULL; tok = strtok(NULL, ",")) { - bexp = 0; - if ((b = strchr(tok, 'B')) != NULL) { - bexp = atoi(b+1); - fixed = TRUE; - *b = '\0'; // truncate at the b - asm_warning("Fixed point extended floating constant?"); - } - - if (sscanf(tok, "%lg", &d) != 1) { - asm_error("Syntax error in constant"); - d = 0.; - } - - convert_double_to_extended(d, wd); - - writew(wd[0], ABSOLUTE); - writew(wd[1], ABSOLUTE); - writew(wd[2], ABSOLUTE); - } -} - -// --------------------------------------------------------------------------------- -// x_equ - EQU directive -// --------------------------------------------------------------------------------- - -void x_equ (struct tag_op *op, char *label, char *mods, char *arg) -{ - EXPR expr; - - org_advanced = FALSE; // * means this address, not incremented - - getexpr(arg, FALSE, &expr); - - setw(0, expr.value, expr.relative); // show this as address - - if (*label) // EQU is all about defining labels, better have one - set_symbol(label, expr.value, TRUE, expr.relative); -// else // IBM assembler doesn't complain about this -// asm_error("EQU without label?"); -} - -// --------------------------------------------------------------------------------- -// x_lorg - LORG directive -- output queued literal values -// --------------------------------------------------------------------------------- - -void x_lorg (struct tag_op *op, char *label, char *mods, char *arg) -{ - org_advanced = FALSE; // * means this address (not used, though) - output_literals(FALSE); // generate .DC's for queued literal values -} - -// --------------------------------------------------------------------------------- -// x_abs - ABS directive -// --------------------------------------------------------------------------------- - -void x_abs (struct tag_op *op, char *label, char *mods, char *arg) -{ - if (assembled) - asm_error("ABS must be first statement"); - - relocate = ABSOLUTE; - - switch (progtype) { - case PROGTYPE_ABSOLUTE: - case PROGTYPE_RELOCATABLE: - progtype = PROGTYPE_ABSOLUTE; // change program type, still assumed to be mainline - break; - - case PROGTYPE_LIBF: - case PROGTYPE_CALL: - case PROGTYPE_ISSLIBF: - case PROGTYPE_ISSCALL: - case PROGTYPE_ILS: - asm_error("ABS not allowed with LIBF, ENT, ILS or ISS"); - break; - - default: - bail("in x_libr, can't happen"); - } -} - -// --------------------------------------------------------------------------------- -// x_call - ORG pseudo-op -// --------------------------------------------------------------------------------- - -void x_call (struct tag_op *op, char *label, char *mods, char *arg) -{ - unsigned short words[2]; - static struct tag_op *bsi = NULL; - - if (*label) // define label - set_symbol(label, org, TRUE, relocate); - - if (! *arg) { - asm_error("CALL missing argument"); - return; - } - - if (pass == 1) { // it will take two words in any case - org += 2; - return; - } - - setw(0, org, FALSE); // display origin - - if (lookup_symbol(arg, FALSE) != NULL) { // it's a defined symbol? - if (bsi == NULL) - if ((bsi = lookup_op("BSI")) == NULL) - bail("Can't find BSI op"); - - (bsi->handler)(bsi, "", "L", arg); - } - else { - namecode(words, arg); // emit namecode for loader - - writetwo(); - writew(words[0], CALL); - writew(words[1], ABSOLUTE); - } -} - -// --------------------------------------------------------------------------------- -// x_org - ORG directive -// --------------------------------------------------------------------------------- - -void x_org (struct tag_op *op, char *label, char *mods, char *arg) -{ - EXPR expr; - - org_advanced = FALSE; // * means this address - - if (*label) // label is defined BEFORE the new origin is set!!! - set_symbol(label, org, TRUE, relocate); - - if (getexpr(arg, FALSE, &expr) != S_DEFINED) - return; - - setorg(expr.value); // set origin to this value -} - -// --------------------------------------------------------------------------------- -// x_end - END directive -// --------------------------------------------------------------------------------- - -void x_end (struct tag_op *op, char *label, char *mods, char *arg) -{ - EXPR expr; - - org_advanced = FALSE; // * means this address - - if (*arg) { // they're specifing the program start address - if (getexpr(arg, FALSE, &expr) == S_DEFINED) - pta = expr.value; - } - - if (*label) // define label - set_symbol(label, org, TRUE, relocate); - - setw(0, org, FALSE); // display origin - - ended = TRUE; // assembly is done, stop reading file -} - -// --------------------------------------------------------------------------------- -// x_ent - ENT op -// --------------------------------------------------------------------------------- - -void x_ent (struct tag_op *op, char *label, char *mods, char *arg) -{ - PSYMBOL s; - - org_advanced = FALSE; // * means this address - - if (pass < 2) - return; - -// if (*label) // define label -// set_symbol(label, org, TRUE, relocate); -// -// setw(0, org, FALSE); // display origin - - if (! *arg) - asm_error("No entry label specified"); - - else if ((s = lookup_symbol(arg, FALSE)) == NULL) - asm_error("Entry symbol %s not defined", arg); - - else if (nentries >= MAXENTRIES) - asm_error("Too many entries, limit is %d", MAXENTRIES); - - else - entry[nentries++] = s; // save symbol pointer - - switch (progtype) { - case PROGTYPE_ABSOLUTE: - asm_error("ENT not allowed with ABS"); - break; - case PROGTYPE_RELOCATABLE: - progtype = PROGTYPE_CALL; - break; - case PROGTYPE_LIBF: - case PROGTYPE_CALL: - case PROGTYPE_ISSLIBF: - case PROGTYPE_ISSCALL: - break; - case PROGTYPE_ILS: - asm_error("Can't mix ENT and ILS, can you?"); - break; - default: - bail("in x_libr, can't happen"); - } -} - -// --------------------------------------------------------------------------------- -// declare a libf-type subprogram -// --------------------------------------------------------------------------------- - -void x_libr (struct tag_op *op, char *label, char *mods, char *arg) -{ - switch (progtype) { - case PROGTYPE_ABSOLUTE: - asm_error("LIBR not allowed with ABS"); - break; - case PROGTYPE_RELOCATABLE: - case PROGTYPE_LIBF: - case PROGTYPE_CALL: - progtype = PROGTYPE_LIBF; - break; - case PROGTYPE_ISSLIBF: - case PROGTYPE_ISSCALL: - progtype = PROGTYPE_ISSLIBF; - break; - case PROGTYPE_ILS: - asm_error("Can't use LIBR in an ILS"); - break; - default: - bail("in x_libr, can't happen"); - } -} - -// --------------------------------------------------------------------------------- -// x_ils - ILS directive -// --------------------------------------------------------------------------------- - -void x_ils (struct tag_op *op, char *label, char *mods, char *arg) -{ - switch (progtype) { - case PROGTYPE_ABSOLUTE: - asm_error("ILS not allowed with ABS"); - break; - case PROGTYPE_RELOCATABLE: - case PROGTYPE_ILS: - progtype = PROGTYPE_ILS; - break; - case PROGTYPE_LIBF: - case PROGTYPE_CALL: - asm_error("Invalid placement of ILS"); - break; - case PROGTYPE_ISSLIBF: - case PROGTYPE_ISSCALL: - break; - default: - bail("in x_libr, can't happen"); - } - - intlevel_primary = atoi(mods); -} - -// --------------------------------------------------------------------------------- -// x_iss - ISS directive -// --------------------------------------------------------------------------------- - -void x_iss (struct tag_op *op, char *label, char *mods, char *arg) -{ - char *tok; - - switch (progtype) { - case PROGTYPE_ABSOLUTE: - asm_error("ISS not allowed with ABS"); - break; - case PROGTYPE_RELOCATABLE: - case PROGTYPE_CALL: - case PROGTYPE_ISSCALL: - progtype = PROGTYPE_ISSCALL; - break; - case PROGTYPE_LIBF: - case PROGTYPE_ISSLIBF: - progtype = PROGTYPE_ISSLIBF; - break; - case PROGTYPE_ILS: - asm_error("Can't mix ISS and ILS"); - default: - bail("in x_libr, can't happen"); - } - - iss_number = atoi(mods); // get ISS number - - opfield[16] = '\0'; // be sure not to look too far into this - - nintlevels = 0; // # of interrupt levels for ISS - intlevel_primary = 0; // primary level for ISS and level for ILS - intlevel_secondary = 0; // secondary level for ISS - - if ((tok = strtok(opfield, " ")) == NULL) - asm_error("ISS missing entry label"); - else - x_ent(NULL, label, "", arg); // process as an ENT - - if ((tok = strtok(NULL, " ")) != NULL) { // get associated levels - nintlevels++; - intlevel_primary = atoi(tok); - } - - if ((tok = strtok(NULL, " ")) != NULL) { - nintlevels++; - intlevel_secondary = atoi(tok); - } -} - -void x_spr (struct tag_op *op, char *label, char *mods, char *arg) -{ - realmode = REALMODE_STANDARD; -} - -void x_epr (struct tag_op *op, char *label, char *mods, char *arg) -{ - realmode = REALMODE_EXTENDED; -} - -void x_dsa (struct tag_op *op, char *label, char *mods, char *arg) -{ - unsigned short words[2]; - - setw(0, org, FALSE); // display origin - - if (*label) // define label - set_symbol(label, org, TRUE, relocate); - - if (! *arg) { - asm_error("DSA missing filename"); - } - else { - namecode(words, arg); - writetwo(); - writew(words[0], CALL); // special relocation bits here 3 and 1 - writew(words[1], RELATIVE); - } -} - -void x_link (struct tag_op *op, char *label, char *mods, char *arg) -{ - unsigned short words[2]; - char nline[128]; - - setw(0, org, FALSE); // display origin - - if (*label) // define label - set_symbol(label, org, TRUE, relocate); - - if (! *arg) { - asm_error("LINK missing program name"); - } - else { - format_line(nline, label, "CALL", "", "$LINK", ""); - parse_line(nline); - - namecode(words, arg); - writew(words[0], ABSOLUTE); // special relocation bits here 3 and 1 - writew(words[1], ABSOLUTE); - } -} - -void x_libf (struct tag_op *op, char *label, char *mods, char *arg) -{ - unsigned short words[2]; - - if (*label) // define label - set_symbol(label, org, TRUE, relocate); - - if (! *arg) { - asm_error("LIBF missing argument"); - return; - } - - if (pass == 1) { // it will take one words in any case - org++; - return; - } - - setw(0, org, FALSE); // display origin - - namecode(words, arg); // emit namecode for loader - - writetwo(); - writew(words[0], LIBF); // this one does NOT advance org! - writew(words[1], ABSOLUTE); -} - -void x_file (struct tag_op *op, char *label, char *mods, char *arg) -{ - int i, n, r; - EXPR vals[5]; - char *tok; - - for (i = 0; i < 5; i++) { - if ((tok = strtok(arg, ",")) == NULL) { - asm_error("FILE has insufficient arguments"); - return; - } - arg = NULL; // for next strtok call - - if (i == 3) { - if (strcmpi(tok, "U") != 0) - asm_error("Argument 4 must be the letter U"); - } - else if (getexpr(tok, FALSE, &vals[i]) == S_DEFINED) { - if (i <= 3 && vals[i].relative) - asm_error("Argument %d must be absolute", i+1); - else if (pass == 2 && vals[i].value == 0) - asm_error("Argument %d must be nonzero", i+1); - } - } - - writew(vals[0].value, ABSOLUTE); - writew(vals[1].value, ABSOLUTE); - writew(vals[2].value, ABSOLUTE); - writew(vals[4].value, vals[i].relative); - writew(0, ABSOLUTE); - n = MAX(1, vals[2].value); - r = 320/n; - writew(r, ABSOLUTE); - r = MAX(1, r); - writew((16*vals[1].value)/r, ABSOLUTE); - - if (pass == 2) - ndefined_files++; -} - -// --------------------------------------------------------------------------------- -// x_trap - place to set a breakpoint -// --------------------------------------------------------------------------------- - -void x_trap (struct tag_op *op, char *label, char *mods, char *arg) -{ - // debugging breakpoint -} - -// --------------------------------------------------------------------------------- -// x_ces - .CES directive (nonstandard). Specify a value for the console entry -// switches. When this program is loaded into the simulator, the switches will -// be set accordingly. Handy for bootstraps and other programs that read -// the switches. -// --------------------------------------------------------------------------------- - -void x_ces (struct tag_op *op, char *label, char *mods, char *arg) -{ - EXPR expr; - - if (outmode != OUTMODE_LOAD) // this works only in our loader format - return; - - if (getexpr(arg, FALSE, &expr) != S_DEFINED) - return; - - if (pass == 2) - fprintf(fout, "S%04x" ENDLINE, expr.value & 0xFFFF); -} - -// --------------------------------------------------------------------------------- -// x_bss - BSS directive - reserve space in core -// --------------------------------------------------------------------------------- - -void x_bss (struct tag_op *op, char *label, char *mods, char *arg) -{ - EXPR expr; - - org_advanced = FALSE; // * means this address - - if (! *arg) { - expr.value = 0; - expr.relative = ABSOLUTE; - } - else if (getexpr(arg, FALSE, &expr) != S_DEFINED) - return; - - if (strchr(mods, 'E') != NULL) // force even address - org_even(); - - if (expr.relative) - asm_error("BSS size must be an absolute value"); - - setw(0, org, FALSE); // display origin - - if (*label) // define label - set_symbol(label, org, TRUE, relocate); - - if (expr.value < 0) - asm_warning("Negative BSS size"); - - else if (expr.value > 0) { - if (outmode == OUTMODE_LOAD) { - org += expr.value; // advance the origin by appropriate number of words - if (pass == 2) // emit new load address in output file - fprintf(fout, "@%04x%s" ENDLINE, org & 0xFFFF, relocate ? "R" : ""); - } - else { - org += expr.value; // advance the origin by appropriate number of words - if (pass == 2) - bincard_setorg(org); - } - } -} - -// --------------------------------------------------------------------------------- -// x_bes - Block Ended by Symbol directive. Like BSS but label gets address AFTER the space, instead of first address -// --------------------------------------------------------------------------------- - -void x_bes (struct tag_op *op, char *label, char *mods, char *arg) -{ - EXPR expr; - - org_advanced = FALSE; // * means this address - - if (! *arg) { // arg field = space - expr.value = 0; - expr.relative = ABSOLUTE; - } - else if (getexpr(arg, FALSE, &expr) != S_DEFINED) - return; - - if (strchr(mods, 'E') != NULL && (org & 1) != 0) - org_even(); // force even address - - if (expr.relative) - asm_error("BES size must be an absolute value"); - - if (expr.value < 0) - asm_warning("Negative BES size"); - - else if (expr.value > 0) { - setw(0, org+expr.value, FALSE); // display NEW origin - - if (outmode == OUTMODE_LOAD) { - org += expr.value; // advance the origin - if (pass == 2) // emit new load address in output file - fprintf(fout, "@%04x%s" ENDLINE, org & 0xFFFF, relocate ? "R" : ""); - } - else { - org += expr.value; // advance the origin - bincard_setorg(org); - } - } - - if (*label) // NOW define the label - set_symbol(label, org, TRUE, relocate); -} - -// --------------------------------------------------------------------------------- -// x_dmes - DMES define message directive. Various encodings, none pretty. -// --------------------------------------------------------------------------------- - -int dmes_wd; -int dmes_nc; -enum {CODESET_CONSOLE, CODESET_1403, CODESET_1132, CODESET_EBCDIC} dmes_cs; -void stuff_dmes (int ch, int rpt); - -void x_dmes (struct tag_op *op, char *label, char *mods, char *arg) -{ - int rpt; - char *c = opfield; - BOOL cont = FALSE; - - if (dmes_saved) { // previous DMES had an odd character saved - dmes_wd = dmes_savew; - dmes_nc = 1; // stick it into the outbut buffer - } - else - dmes_nc = dmes_wd = 0; // clear output buffer - - trim(opfield); // remove trailing blanks from rest of input line (use whole thing) - setw(0, org, FALSE); // display origin - - if (*label) // define label - set_symbol(label, org, TRUE, relocate); - - if (strchr(mods, '1') != NULL) // determine the encoding scheme - dmes_cs = CODESET_1403; - else if (strchr(mods, '2') != NULL) - dmes_cs = CODESET_1132; - else if (strchr(mods, '0') != NULL || ! *mods) - dmes_cs = CODESET_CONSOLE; - else { - asm_error("Invalid printer code in tag field"); - dmes_cs = CODESET_EBCDIC; - } - - while (*c) { // pick up characters - if (*c == '\'') { // quote (') is the escape character - c++; - - rpt = 0; // get repeat count - while (BETWEEN(*c, '0', '9')) { - rpt = rpt*10 + *c++ - '0'; - } - if (rpt <= 0) // no count = insert one copy - rpt = 1; - - switch (*c) { // handle escape codes - case '\'': - stuff_dmes(*c, 1); - break; - - case 'E': - *c = '\0'; // end - break; - - case 'X': - case 'S': - stuff_dmes(' ', rpt); - break; - - case 'F': - stuff_dmes(*++c, rpt); // repeat character - break; - - case ' ': - case '\0': - cont = TRUE; - *c = '\0'; // end - break; - - case 'T': - if (dmes_cs != CODESET_CONSOLE) { -badcode: asm_error("Invalid ' escape for selected printer"); - break; - } - stuff_dmes(0x41, -rpt); // tab - break; - - case 'D': - if (dmes_cs != CODESET_CONSOLE) goto badcode; - stuff_dmes(0x11, -rpt); // backspace - break; - - case 'B': - if (dmes_cs != CODESET_CONSOLE) goto badcode; - stuff_dmes(0x05, -rpt); // black - break; - - case 'A': - if (dmes_cs != CODESET_CONSOLE) goto badcode; - stuff_dmes(0x09, -rpt); // red - break; - - case 'R': - if (dmes_cs != CODESET_CONSOLE) goto badcode; - stuff_dmes(0x81, -rpt); // return - break; - - case 'L': - if (dmes_cs != CODESET_CONSOLE) goto badcode; - stuff_dmes(0x03, -rpt); // line feed - break; - - default: - asm_error("Invalid ' escape in DMES"); - *c = '\0'; - break; - } - } - else // just copy literal character - stuff_dmes(*c, 1); - - if (*c) - c++; - } - - dmes_saved = FALSE; - - if (dmes_nc) { // odd number of characters - if (cont) { - dmes_saved = TRUE; - dmes_savew = dmes_wd; // save for next time - } - else - stuff_dmes(' ', 1); // pad with a space to force out even # of characters - } -} - -// --------------------------------------------------------------------------------- -// stuff_dmes - insert 'rpt' copies of character 'ch' into output words -// --------------------------------------------------------------------------------- - -void stuff_dmes (int ch, int rpt) -{ - int nch, i; // nch is translated output value - - if (rpt < 0) { // negative repeat means no translation needed - rpt = -rpt; - nch = ch; - } - else { - switch (dmes_cs) { - case CODESET_CONSOLE: - nch = 0x21; - for (i = 0; i < 256; i++) { - if (conout_to_ascii[i] == ch) { - nch = i; - break; - } - } - break; - - case CODESET_EBCDIC: - nch = ascii_to_ebcdic_table[ch & 0x7F]; - if (nch == 0) - nch = 0x7F; - break; - - case CODESET_1403: - nch = ascii_to_1403_table[ch & 0x7F]; - if (nch == 0) - nch = 0x7F; - break; - - case CODESET_1132: - nch = 0x40; - for (i = 0; i < WHEELCHARS_1132; i++) { - if (codewheel1132[i].ascii == ch) { - nch = codewheel1132[i].ebcdic; - break; - } - } - break; - - default: - bail("bad cs in x_dmes, can't happen"); - break; - } - } - - while (--rpt >= 0) { // pack them into words, output when we have two - if (dmes_nc == 0) { - dmes_wd = (nch & 0xFF) << 8; - dmes_nc = 1; - } - else { - dmes_wd |= (nch & 0xFF); - writew(dmes_wd, FALSE); - dmes_nc = 0; - } - } -} - -// --------------------------------------------------------------------------------- -// x_ebc - handle EBCDIC string definition (delimited with periods) -// --------------------------------------------------------------------------------- - -void x_ebc (struct tag_op *op, char *label, char *mods, char *arg) -{ - char *p; - -// setw(0, org, FALSE); - if (*label) - set_symbol(label, org, TRUE, relocate); - - p = trim(opfield); // remove trailing blanks from rest of input line (use whole thing) - - if (*p != '.') { - asm_error("EBC data must start with ."); - return; - } - p++; // skip leading period - - dmes_nc = dmes_wd = 0; // clear output buffer (we're borrowing the DMES packer) - dmes_cs = CODESET_EBCDIC; - - while (*p && *p != '.') // store packed ebcdic - stuff_dmes(*p++, 1); - - if (dmes_nc) // odd number of characters - stuff_dmes(' ', 1); // pad with a space to force out even # of characters - - if (*p != '.') - asm_error("EBC missing closing ."); -} - -// --------------------------------------------------------------------------------- -// x_dn - define name DN directive. Pack 5 characters into two words. This by the -// way is the reason the language Forth is not Fourth. -// --------------------------------------------------------------------------------- - -void x_dn (struct tag_op *op, char *label, char *mods, char *arg) -{ - unsigned short words[2]; - - setw(0, org, FALSE); // display origin - - if (*label) // define label - set_symbol(label, org, TRUE, relocate); - - namecode(words, arg); - - writew(words[0], ABSOLUTE); - writew(words[1], ABSOLUTE); -} - -// --------------------------------------------------------------------------------- -// x_dump - DUMP directive - pretend we saw "call $dump, call $exit" -// --------------------------------------------------------------------------------- - -void x_dump (struct tag_op *op, char *label, char *mods, char *arg) -{ - x_pdmp(op, label, mods, arg); - x_exit(NULL, "", "", ""); // compile "call $exit" -} - -// --------------------------------------------------------------------------------- -// x_pdmp - PDMP directive - like DUMP but without the call $exit -// --------------------------------------------------------------------------------- - -void x_pdmp (struct tag_op *op, char *label, char *mods, char *arg) -{ - char nline[200], *tok; - EXPR addr[3]; - int i; - - for (i = 0, tok = strtok(arg, ","); i < 3 && tok != NULL; i++, tok = strtok(NULL, ",")) { - if (getexpr(tok, FALSE, addr+i) != S_DEFINED) { - addr[i].value = (i == 1) ? 0x3FFF : 0; - addr[i].relative = ABSOLUTE; - } - } - - org_advanced = FALSE; // * means this address+1 - - format_line(nline, label, "BSI", "L", DOLLARDUMP, ""); - parse_line(nline); // compile "call $dump" - - writew(addr[2].value, ABSOLUTE); // append arguments (0, start, end address) - writew(addr[0].value, addr[0].relative); - writew(addr[1].value, addr[1].relative); -} - -// --------------------------------------------------------------------------------- -// x_hdng - HDNG directive -// --------------------------------------------------------------------------------- - -void x_hdng (struct tag_op *op, char *label, char *mods, char *arg) -{ - char *c; - - // label is not entered into the symbol table - - if (flist == NULL || ! list_on) { - line_error = TRUE; // inhibit listing: don't print the HDNG statement - return; - } - - line_error = TRUE; // don't print the statement - - c = skipbl(opfield); - trim(c); - fprintf(flist, "\f%s\n\n", c); // print page header -} - -// --------------------------------------------------------------------------------- -// x_list - LIST directive. enable or disable listing -// --------------------------------------------------------------------------------- - -void x_list (struct tag_op *op, char *label, char *mods, char *arg) -{ - BOOL on; - - // label is not entered into the symbol table - - line_error = TRUE; // don't print the LIST statement - - if (flist == NULL || ! list_on) { - return; - } - - if (strcmpi(arg, "ON") == 0) - on = TRUE; - else if (strcmpi(arg, "OFF") == 0) - on = FALSE; - else - on = do_list; - - list_on = on; -} - -// --------------------------------------------------------------------------------- -// x_spac - SPAC directive. Put blank lines in listing -// --------------------------------------------------------------------------------- - -void x_spac (struct tag_op *op, char *label, char *mods, char *arg) -{ - EXPR expr; - - // label is not entered into the symbol table - - if (flist == NULL || ! list_on) { - line_error = TRUE; // don't print the SPAC statement - return; - } - - if (getexpr(arg, FALSE, &expr) != S_DEFINED) - return; - - line_error = TRUE; // don't print the statement - - while (--expr.value >= 0) - putc('\n', flist); -} - -// --------------------------------------------------------------------------------- -// x_ejct - EJCT directive - put formfeed in listing -// --------------------------------------------------------------------------------- - -void x_ejct (struct tag_op *op, char *label, char *mods, char *arg) -{ - // label is not entered into the symbol table - - if (flist == NULL || ! list_on) { - line_error = TRUE; // don't print the EJCT statement - return; - } - - line_error = TRUE; // don't print the statement - - putc('\f', flist); -} - -// --------------------------------------------------------------------------------- -// basic_opcode - construct a standard opcode value from op table entry and modifier chars -// --------------------------------------------------------------------------------- - -int basic_opcode (struct tag_op *op, char *mods) -{ - int opcode = op->opcode; // basic code value - - if (strchr(mods, '1') != 0) // indexing - opcode |= 0x0100; - else if (strchr(mods, '2') != 0) - opcode |= 0x0200; - else if (strchr(mods, '3') != 0) - opcode |= 0x0300; - - if (strchr(mods, 'L')) { // two-word format - opcode |= OP_LONG; - if (strchr(mods, 'I') != 0) // and indirect to boot - opcode |= OP_INDIRECT; - } - - return opcode; -} - -// --------------------------------------------------------------------------------- -// std_op - assemble a vanilla opcode -// --------------------------------------------------------------------------------- - -void std_op (struct tag_op *op, char *label, char *mods, char *arg) -{ - EXPR expr; - int opcode = basic_opcode(op, mods); - BOOL val_ok = FALSE; - - if (*label) // define label - set_symbol(label, org, TRUE, relocate); - - if (*arg && ! (op->flags & NO_ARGS)) { // get value argument - if (getexpr(arg, FALSE, &expr) == S_DEFINED) - val_ok = TRUE; - } - else { - expr.value = 0; - expr.relative = FALSE; - } - - if (opcode & OP_LONG) { // two-word format, just write code and value - writew(opcode, FALSE); - writew(expr.value, expr.relative); - } - else { // one-word format - if (strchr(mods, 'I') != 0) - asm_error("Indirect mode not permitted on one-word instructions"); - - if (val_ok && ! (strchr(mods, 'X') || (op->flags & IS_ABS) || ((opcode & OP_INDEXED) && ! (op->flags & NO_IDX)))) - expr.value -= (org+1); // compute displacement - - if (expr.value < -128 || expr.value > 127) {// check range - asm_error("Offset of %d is too large", expr.value); - expr.value = 0; - } - - writew(opcode | (expr.value & 0x00FF), FALSE);// that's the code - } -} - -// --------------------------------------------------------------------------------- -// mdx_op - assemble a MDX family instruction -// --------------------------------------------------------------------------------- - -void mdx_op (struct tag_op *op, char *label, char *mods, char *arg) -{ - EXPR dest, incr = {0, FALSE}; - int opcode = basic_opcode(op, mods); - char *tok; - - if (*label) // define label - set_symbol(label, org, TRUE, relocate); - - if ((tok = strtok(arg, ",")) == NULL) { // argument format is dest[,increment] -// asm_error("Destination not specified"); // seems not to be an error, IBM omits it sometimes - dest.value = 0; - dest.relative = ABSOLUTE; - } - else - getexpr(tok, FALSE, &dest); // parse the address - - tok = strtok(NULL, ","); // look for second argument - - if (opcode & OP_LONG) { // two word format - if (opcode & OP_INDEXED) { // format: MDX 2 dest - if (tok != NULL) - asm_error("This format takes only one argument"); - } - else { // format: MDX dest,increment - if (opcode & OP_INDIRECT) - asm_error("Indirect can't be used without indexing"); - - if (tok == NULL) { -// asm_error("This format takes two arguments"); - incr.value = 0; - incr.relative = ABSOLUTE; - } - else - getexpr(tok, FALSE, &incr); - - if (incr.value < -128 || incr.value > 127) // displacement style (fixed in ver 1.08) - asm_error("Invalid increment value (8 bits signed)"); - - opcode |= (incr.value & 0xFF); - } - - writew(opcode, ABSOLUTE); - writew(dest.value, dest.relative); - } - else { // one word format MDX val - if (tok != NULL) - asm_error("This format takes only one argument"); - - if (! (strchr(mods, 'X') || (opcode & OP_INDEXED))) - dest.value -= (org+1); // compute displacement - - if (dest.value < -128 || dest.value > 127) - asm_error("Offset/Increment of %d is too large", dest.value); - - writew(opcode | (dest.value & 0xFF), FALSE); - } -} - -// --------------------------------------------------------------------------------- -// bsi_op - BSI long instruction is like a BSC L, short is standard -// --------------------------------------------------------------------------------- - -void bsi_op (struct tag_op *op, char *label, char *mods, char *arg) -{ - if (strchr(mods, 'L') || strchr(mods, 'I')) - bsc_op(op, label, mods, arg); - else - std_op(op, label, mods, arg); -} - -// --------------------------------------------------------------------------------- -// b_op - branch; use short or long version -// -------------------------------------------------------------------------------- - -void b_op (struct tag_op *op, char *label, char *mods, char *arg) -{ - static struct tag_op *mdx = NULL; - - if (strchr(mods, 'L') || strchr(mods, 'I')) { - bsi_op(op, label, mods, arg); - return; - } - - if (mdx == NULL) - if ((mdx = lookup_op("MDX")) == NULL) - bail("Can't find MDX op"); - - (mdx->handler)(mdx, label, mods, arg); -} - -// --------------------------------------------------------------------------------- -// bsc_op - compute a BSC family instruction -// --------------------------------------------------------------------------------- - -void bsc_op (struct tag_op *op, char *label, char *mods, char *arg) -{ - EXPR dest; - int opcode = basic_opcode(op, mods); - char *tok, *tests; - - if (*label) // define label - set_symbol(label, org, TRUE, relocate); - - if (opcode & OP_LONG) { // two word format - if ((tok = strtok(arg, ",")) == NULL) { // format is BSC dest[,tests] - asm_error("Destination not specified"); - dest.value = 0; - dest.relative = ABSOLUTE; - } - else - getexpr(tok, FALSE, &dest); - - tests = strtok(NULL, ","); // get test characters - } - else - tests = arg; // short format is BSC tests - - if (tests != NULL) { // stick in the testing bits - for (; *tests; tests++) { - switch (*tests) { - // bit 0x40 is the BOSC bit - case 'Z': opcode |= 0x20; break; - case '-': opcode |= 0x10; break; - case '+': - case '&': opcode |= 0x08; break; - case 'E': opcode |= 0x04; break; - case 'C': opcode |= 0x02; break; - case 'O': opcode |= 0x01; break; - default: - asm_error("Invalid test flag: '%c'", *tests); - } - } - } - - writew(opcode, ABSOLUTE); // emit code - if (opcode & OP_LONG) - writew(dest.value, dest.relative); -} - -// --------------------------------------------------------------------------------- -// shf_op - assemble a shift instruction -// --------------------------------------------------------------------------------- - -void shf_op (struct tag_op *op, char *label, char *mods, char *arg) -{ - EXPR expr; - int opcode = basic_opcode(op, mods); - - if (*label) // define label - set_symbol(label, org, TRUE, relocate); - - if (opcode & OP_INDEXED) { // shift value comes from index register - expr.value = 0; - expr.relative = ABSOLUTE; - } - else - getexpr(arg, FALSE, &expr); - - if (expr.relative) { - asm_error("Shift value is a relative address"); - expr.relative = ABSOLUTE; - } - - if (expr.value < 0 || expr.value > 32) { // check range - asm_error("Shift count of %d is invalid", expr.value); - expr.value = 0; - } - - writew(opcode | (expr.value & 0x3F), FALSE); // put shift count into displacement field -} - -// --------------------------------------------------------------------------------- -// x_mdm - MDM instruction -// --------------------------------------------------------------------------------- - -void x_mdm (struct tag_op *op, char *label, char *mods, char *arg) -{ - int opcode = basic_opcode(op, mods); - - if (*label) // define label - set_symbol(label, org, TRUE, relocate); - // oh dear: bug here - asm_error("'%s' is not yet supported", op->mnem); -} - -// --------------------------------------------------------------------------------- -// x_exit - EXIT directive. Assembler manual says it treats like CALL $EXIT, but -// object code reveals the truth: jump to $EXIT, which is a small value, so we can use LDX. -// --------------------------------------------------------------------------------- - -void x_exit (struct tag_op *op, char *label, char *mods, char *arg) -{ - char nline[120]; - - format_line(nline, label, "LDX", "X", DOLLAREXIT, ""); - parse_line(nline); -} - -// --------------------------------------------------------------------------------- -// x_opt - .OPT directive. Nonstandard. Possible values: -// -// .OPT CEXPR - use C precedence in evaluating expressions rather than strict left-right -// --------------------------------------------------------------------------------- - -void x_opt (struct tag_op *op, char *label, char *mods, char *arg) -{ - char *tok; - - org_advanced = FALSE; // * means this address - - if (*label) { - asm_error("Label not permitted on .OPT statement"); - return; - } - // look for OPT arguments - for (tok = strtok(arg, ","); tok != NULL; tok = strtok(NULL, ",")) { - if (strcmp(tok, "CEXPR") == 0) { - cexpr = TRUE; // use C expression precedence (untested) - } - else - asm_error("Unknown .OPT: '%s'", tok); - } -} - -// --------------------------------------------------------------------------------- -// askip - skip input lines until a line with the target label appears -// --------------------------------------------------------------------------------- - -void askip (char *target) -{ - char nline[200], cur_label[20], *c; - - while (get_line(nline, sizeof(nline), TRUE)) { // read next line (but don't exit a macro) - listout(FALSE); // end listing of previous input line - - prep_line(nline); // preform standard line prep - - strncpy(cur_label, nline, 6); // get first 5 characters - cur_label[5] = '\0'; - - for (c = cur_label; *c > ' '; c++) // truncate at first whitespace - ; - *c = '\0'; - // stop if there's a match - if ((target == NULL) ? (cur_label[0] == '\0') : strcmp(target, cur_label) == 0) { - parse_line(nline); // process this line - return; - } - } - - if (target != NULL) - asm_error("Label %s not found", target); -} - -// --------------------------------------------------------------------------------- -// x_aif - process conditional assembly jump -// --------------------------------------------------------------------------------- - -void x_aif (struct tag_op *op, char *label, char *mods, char *arg) -{ - char *target, *tok; - EXPR expr1, expr2; - BOOL istrue; - enum {OP_EQ, OP_LT, OP_GT, OP_NE, OP_LE, OP_GE} cmp_op; - - // label is not entered into the symbol table - - arg = skipbl(arg); - if (*arg != '(') { - asm_error("AIF operand must start with ("); - return; - } - - arg++; // skip the paren - - // normally whitespace is never found in the arg string (see tabtok and coltok). - // However, spaces inside parens are permitted. - - if ((tok = strtok(arg, whitespace)) == NULL) { - asm_error("AIF missing first expression"); - return; - } - - getexpr(tok, FALSE, &expr1); - - if ((tok = strtok(NULL, whitespace)) == NULL) { - asm_error("AIF missing conditional operator"); - return; - } - - if (strcmp(tok, "EQ") == 0) - cmp_op = OP_EQ; - else if (strcmp(tok, "LT") == 0) - cmp_op = OP_LT; - else if (strcmp(tok, "GT") == 0) - cmp_op = OP_GT; - else if (strcmp(tok, "NE") == 0) - cmp_op = OP_NE; - else if (strcmp(tok, "LE") == 0) - cmp_op = OP_LE; - else if (strcmp(tok, "GE") == 0) - cmp_op = OP_GE; - else { - asm_error("AIF: %s is not a valid conditional operator", tok); - return; - } - - if ((tok = strtok(NULL, ")")) == NULL) { - asm_error("AIF missing second expression"); - return; - } - - getexpr(tok, FALSE, &expr2); - - switch (cmp_op) { // test the condition - case OP_EQ: istrue = expr1.value == expr2.value; break; - case OP_LT: istrue = expr1.value < expr2.value; break; - case OP_GT: istrue = expr1.value > expr2.value; break; - case OP_NE: istrue = expr1.value != expr2.value; break; - case OP_LE: istrue = expr1.value <= expr2.value; break; - case OP_GE: istrue = expr1.value >= expr2.value; break; - default: bail("in aif, can't happen"); - } - - // After the closing paren coltok and tabtok guarantee we will have no whitespace - - if ((target = strtok(arg, ",")) == NULL) // get target label - asm_warning("Missing target label"); - - if (istrue) - askip(target); // skip to the target -} - -// --------------------------------------------------------------------------------- -// x_aifb - conditional assembly jump back (macro only) -// --------------------------------------------------------------------------------- - -void x_aifb (struct tag_op *op, char *label, char *mods, char *arg) -{ - asm_error("aifb valid in macros only and not implemented in any case"); -} - -// --------------------------------------------------------------------------------- -// x_ago -// --------------------------------------------------------------------------------- - -void x_ago (struct tag_op *op, char *label, char *mods, char *arg) -{ - char *target; - - // label is not entered into the symbol table - - // handle differently in a macro - - if ((target = strtok(arg, ",")) == NULL) // get target label - asm_warning("Missing target label"); - - askip(target); // skip to the target -} - -// --------------------------------------------------------------------------------- -// --------------------------------------------------------------------------------- - -void x_agob (struct tag_op *op, char *label, char *mods, char *arg) -{ - asm_error("agob valid in macros only and not implemented in any case"); -} - -// --------------------------------------------------------------------------------- -// --------------------------------------------------------------------------------- - -void x_anop (struct tag_op *op, char *label, char *mods, char *arg) -{ - // label is not entered into the symbol table - // do nothing else -} - -// --------------------------------------------------------------------------------- -// expression parser, borrowed from older code, no comments, sorry -// --------------------------------------------------------------------------------- - -char *exprptr, *oexprptr; - -#define GETNEXT (*exprptr++) -#define UNGET --exprptr - -#define LETTER 0 /* character types */ -#define DIGIT 1 -#define ETC 2 -#define ILL 3 -#define SPACE 4 -#define MULOP 5 -#define ADDOP 6 -#define EXPOP 7 - -int getnb (void); -void c_expr (EXPR *ap); -void c_expr_m (EXPR *ap); -void c_expr_e (EXPR *ap); -void c_expr_u (EXPR *ap); -void c_term (EXPR *ap); -int c_number (int c, int r, int nchar); -int digit (int c, int r); -int c_esc (int c); -void exprerr (int n); -void a1130_expr (EXPR *ap); -void a1130_term (EXPR *ap); - -char ctype[128] = { // character types -/*^0ABCDEFG */ ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL, -/*^HIJKLMNO */ ILL, SPACE, SPACE, ILL, SPACE, SPACE, ILL, ILL, -/*^PQRSTUVW */ ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL, -/*^XYZ */ ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL, -/* !"#$%&' */ SPACE, ETC, ETC, LETTER, LETTER, MULOP, MULOP, LETTER, /* $ # @ and ' are letters here */ -/* ()*+,-./ */ ETC, ETC, MULOP, ADDOP, ETC, ADDOP, ETC, MULOP, -/* 01234567 */ DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, -/* 89:;<=>? */ DIGIT, DIGIT, ETC, ETC, MULOP, ETC, MULOP, ETC, -/* @ABCDEFG */ LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, -/* HIJKLMNO */ LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, -/* PQRSTUVW */ LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, -/* XYZ[\]^_ */ LETTER, LETTER, LETTER, ETC, ETC, ETC, EXPOP, LETTER, -/* `abcdefg */ ETC, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, -/* hijklmno */ LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, -/* pqrstuvw */ LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, -/* xyz{|}~ */ LETTER, LETTER, LETTER, ETC, ADDOP, ETC, ETC, ETC -}; - -char *errstr[] = { - "Missing exponent", // 0 - "Undefined symbol", // 1 - "Division by zero", // 2 - "Illegal operator", // 3 - ") expected", // 4 - "Char expected after '", // 5 - "Char expected after .", // 6 - "Number expected after =", // 7 - "Syntax error", // 8 - "Number syntax", // 9 - "Char expected after \\", // 10 - "Relocation error" // 11 -}; - -int getnb () { - int c; - - if (cexpr) { // in C mode, handle normally - while (ctype[(c = GETNEXT)] == SPACE) - ; - } // in 1130 mode, a space terminates the expression. Here, eat the rest - else if ((c = GETNEXT) == ' ') { - while ((c = GETNEXT) != '\0') - ; - } - - return c; -} - -int symbest, exprerrno; -jmp_buf exprjmp; - -// --------------------------------------------------------------------------------- -// getexpr -// --------------------------------------------------------------------------------- - -int getexpr (char *pc, BOOL undefined_ok, EXPR *pval) -{ - symbest = S_DEFINED; // assume no questionable symbols - - pval->value = 0; - pval->relative = ABSOLUTE; - - if (! *pc) // blank expression is same as zero, ok? - return S_DEFINED; - - if (setjmp(exprjmp) != 0) { // encountered a syntax error & bailed - pval->value = 0; - pval->relative = ABSOLUTE; - return S_UNDEFINED; - } - - exprptr = oexprptr = pc; // make global the buffer pointer - - c_expr(pval); - - if (GETNEXT) // expression should have been entirely eaten - exprerr(8); // if characters are left, it's an error - - if (pval->relative < 0 || pval->relative > 1) - exprerr(11); // has to work out to an absolute or a single relative term - - if (symbest == S_DEFINED) // tell how it came out - return S_DEFINED; - - pval->value = 0; - pval->relative = ABSOLUTE; - return (pass == 1 && undefined_ok) ? S_PROVISIONAL : S_UNDEFINED; -} - -// --------------------------------------------------------------------------------- -// output_literals - construct .DC assembler lines to assemble pending literal -// constant values that have accumulated. -// --------------------------------------------------------------------------------- - -void output_literals (BOOL eof) -{ - char line[120], label[12], num[20]; - int i; - - for (i = 0; i < n_literals; i++) { // generate DC statements for any pending literal constants - if (literal[i].even && literal[i].hex) // create the value string - sprintf(num, "/%08lx", literal[i].value); - else if (literal[i].even) - sprintf(num, "%ld", literal[i].value); - else if (literal[i].hex) - sprintf(num, "/%04x", literal[i].value & 0xFFFF); - else - sprintf(num, "%d", literal[i].value); - - sprintf(label, "_L%03d", literal[i].tagno); - format_line(line, label, literal[i].even ? "DEC" : "DC", "", num, "GENERATED LITERAL CONSTANT"); - - if (eof) { - eof = FALSE; // at end of file, for first literal, only prepare blank line - sprintf(listline, LEFT_MARGIN, org); - } - else - listout(TRUE); // push out any pending line(s) - - if (flist && list_on) // this makes stuff appear in the listing - sprintf(listline, LEFT_MARGIN " %s", detab(line)); - - nwout = 0; - - parse_line(line); // assemble the constant definition - } - - n_literals = 0; // clear list -} - -// --------------------------------------------------------------------------------- -// a1130_term - extract one term of an expression -// --------------------------------------------------------------------------------- - -void a1130_term (EXPR *ap) -{ - PSYMBOL s; - char token[80], *t; - int c; - - if (cexpr) { // use C syntax - c_term(ap); - return; - } - - c = GETNEXT; - - if (ctype[c] == DIGIT) { /* number */ - ap->value = c_number(c,10,-1); - ap->relative = ABSOLUTE; - } - else if (c == '+') { /* unary + */ - a1130_term(ap); - } - else if (c == '-') { /* unary - */ - a1130_term(ap); - ap->value = - ap->value; - } - else if (c == '/') { /* / starts a hex constant */ - ap->value = c_number(c,16,-1); - ap->relative = ABSOLUTE; - } - else if (c == '*') { /* asterisk alone = org */ - ap->value = org + org_advanced; // here is where that offset matters! - ap->relative = relocate; - } - else if (c == '.') { /* EBCDIC constant */ - c = GETNEXT; - if (c == '\0') { - UNGET; - c = ' '; - } - c = ascii_to_ebcdic_table[c]; - ap->value = c; // VALUE IS IN LOW BYTE!!! - ap->relative = ABSOLUTE; - } - else if (ctype[c] == LETTER) { /* symbol */ - t = token; - do { - *t++ = c; - c = GETNEXT; - } while (ctype[c] == LETTER || ctype[c] == DIGIT); - UNGET; - *t++ = '\0'; - - s = lookup_symbol(token, TRUE); - add_xref(s, FALSE); - ap->value = s->value; - ap->relative = s->relative; - - symbest = MIN(symbest, s->defined); // this goes to lowest value (undefined < provisional < defined) - if (pass == 2 && s->defined != S_DEFINED) - exprerr(1); - } - else - exprerr(8); -} - -// --------------------------------------------------------------------------------- -// c_expr - evalate an expression -// --------------------------------------------------------------------------------- - -void c_expr (EXPR *ap) -{ - int c; - EXPR rop; - - c_expr_m(ap); // get combined multiplicative terms - for (;;) { // handle +/- precedence operators - if (ctype[c=getnb()] != ADDOP) { - UNGET; - break; - } - c_expr_m(&rop); // right hand operand - switch (c) { - case '+': - ap->value += rop.value; - ap->relative += rop.relative; - break; - - case '-': - ap->value -= rop.value; - ap->relative -= rop.relative; - break; - - case '|': - if (ap->relative || rop.relative) - exprerr(11); - ap->value = ((long) (ap->value)) | ((long) rop.value); - break; - - default: - printf("In expr, can't happen\n"); - } - } -} - -// --------------------------------------------------------------------------------- -// c_expr_m - get multiplicative precedence terms. Again, this is not usually used -// --------------------------------------------------------------------------------- - -void c_expr_m (EXPR *ap) -{ - int c; - EXPR rop; - - c_expr_e(ap); // get exponential precedence term - for (;;) { // get operator - c = getnb(); - if ((c=='<') || (c=='>')) - if (c != getnb()) // << or >> - exprerr(3); - if (ctype[c] != MULOP) { - UNGET; - break; - } - c_expr_e(&rop); // right hand operand - - switch(c) { - case '*': - if (ap->relative && rop.relative) - exprerr(11); - - ap->value *= rop.value; - ap->relative = (ap->relative || rop.relative) ? RELATIVE : ABSOLUTE; - break; - - case '/': - if (rop.value == 0) - exprerr(2); - if (ap->relative || rop.relative) - exprerr(11); - - ap->value /= rop.value; - break; - - case '%': - if (rop.value == 0) - exprerr(2); - if (ap->relative || rop.relative) - exprerr(11); - - ap->value = ((long) (ap->value)) % ((long) rop.value); - break; - - case '&': - if (ap->relative || rop.relative) - exprerr(11); - - ap->value = ((long) (ap->value)) & ((long) rop.value); - break; - - case '>': - if (ap->relative || rop.relative) - exprerr(11); - - ap->value = ((long) (ap->value)) >> ((long) rop.value); - break; - - case '<': - if (ap->relative || rop.relative) - exprerr(11); - - ap->value = ((long) (ap->value)) << ((long) rop.value); - break; - - default: - printf("In expr_m, can't happen\n"); - } - } -} - -// --------------------------------------------------------------------------------- -// c_expr_e - get exponential precedence terms. Again, this is not usually used -// --------------------------------------------------------------------------------- - -void c_expr_e (EXPR *ap) -{ - int c, i, v; - EXPR rop; - - c_expr_u(ap); - for (;;) { - c = getnb(); - if (ctype[c] != EXPOP) { - UNGET; - break; - } - c_expr_u(&rop); - - switch(c) { - case '^': - if (ap->relative || rop.relative) - exprerr(11); - - v = ap->value; - ap->value = 1; - for (i = 0; i < rop.value; i++) - ap->value *= v; - break; - - default: - printf("In expr_e, can't happen\n"); - } - } -} - -// --------------------------------------------------------------------------------- -// c_expr_u - get unary precedence terms. Again, this is not usually used -// --------------------------------------------------------------------------------- - -void c_expr_u (EXPR *ap) -{ - int c; - - if ((c = getnb()) == '!') { - a1130_term(ap); - ap->value = ~ ((long)(ap->value)); - if (ap->relative) - exprerr(11); - } - else if (c == '-') { - a1130_term(ap); - ap->value = - ap->value; - if (ap->relative) - exprerr(11); - } - else { - UNGET; - a1130_term(ap); - } -} - -// --------------------------------------------------------------------------------- -// c_term - get basic operand or parenthesized expression. Again, this is not usually used -// --------------------------------------------------------------------------------- - -void c_term (EXPR *ap) -{ - int c, cc; - PSYMBOL s; - char token[80], *t; - - ap->relative = ABSOLUTE; /* assume absolute */ - - if ((c = getnb()) == '(') { /* parenthesized expr */ - c_expr(ap); /* start over at the top! */ - if ((cc = getnb()) != ')') - exprerr(4); - } - else if (c == '\'') { /* single quote: char */ - if ((c = GETNEXT) == '\0') - c = ' '; - ap->value = c_esc(c); - } - else if (ctype[c] == DIGIT) { /* number */ - ap->value = c_number(c,10,-1); - } - else if (c == '0') { /* 0 starts a hex or octal constant */ - if ((c = GETNEXT) == 'x') { - c = GETNEXT; - ap->value = c_number(c,16,-1); - } - else { - ap->value = c_number(c,8,-1); - } - } - else if (c == '*') { /* asterisk alone = org */ - ap->value = org + org_advanced; - ap->relative = relocate; - } - else if (ctype[c] == LETTER) { /* symbol */ - t = token; - do { - *t++ = c; - c = GETNEXT; - } while (ctype[c] == LETTER || ctype[c] == DIGIT); - UNGET; - *t++ = '\0'; - - s = lookup_symbol(token, TRUE); - ap->value = s->value; - ap->relative = s->relative; - add_xref(s, FALSE); - symbest = MIN(symbest, s->defined); // this goes to lowest value (undefined < provisional < defined) - - if (pass == 2 && s->defined != S_DEFINED) - exprerr(1); - } - else - exprerr(8); -} - -// --------------------------------------------------------------------------------- -// c_number - get a C format constant value. Again, this is not usually used -// --------------------------------------------------------------------------------- - -int c_number (int c, int r, int nchar) -{ - int v, n; - - nchar--; - - if (c == '/' && ! cexpr) { /* special radix stuff */ - r = 16; - c = GETNEXT; - } - else if (r == 10 && c == '0' && cexpr) { /* accept C style 0x## also */ - c = GETNEXT; - if (c == 'x') { - r = 16; - c = GETNEXT; - } - else { - r = 8; - UNGET; - c = '0'; - } - } - - n = 0; /* decode number */ - while ((nchar-- != 0) && (v = digit(c, r)) >= 0) { - if (v >= r) /* out of range! */ - exprerr(9); - - n = r*n + v; - - c = GETNEXT; - if (c == '.') { // maybe make it decimal? - c = GETNEXT; - break; - } - } - - UNGET; - return (n); -} - -// --------------------------------------------------------------------------------- -// digit - get digit value of character c in radix r -// --------------------------------------------------------------------------------- - -int digit (int c, int r) -{ - if (r == 16) { - if (c >= 'A' && c <= 'F') - return (c - 'A' + 10); - } - - if (c >= '0' && c <= '9') - return (c - '0'); - - return (-1); -} - -// --------------------------------------------------------------------------------- -// c_esc - handle C character escape -// --------------------------------------------------------------------------------- - -int c_esc (int c) -{ - if (c != '\\') /* not escaped */ - return(c); - - if ((c = GETNEXT) == '\0') /* must be followed by something */ - exprerr(10); - if ((c >= 'A') && (c <= 'Z')) /* handle upper case */ - c += 'a'-'A'; - if (ctype[c] == LETTER) /* control character abbrevs */ - switch (c) { - case 'b': c = '\b'; break; /* backspace */ - case 'e': c = 27 ; break; /* escape */ - case 'f': c = '\f'; break; /* formfeed */ - case 'n': c = '\n'; break; /* newline */ - case 'r': c = '\r'; break; /* return */ - case 't': c = '\t'; break; /* horiz. tab */ - } - else if (ctype[c] == DIGIT) { /* get character by the numbers */ - c = c_number(c,8,3); /* force octal */ - } - - return c; -} - -// --------------------------------------------------------------------------------- -// exprerr - note an expression syntax error. Longjumps back to caller with failure code -// --------------------------------------------------------------------------------- - -void exprerr (int n) -{ - char msg[256]; - int nex = exprptr-oexprptr; - - strncpy(msg, oexprptr, nex); // show where the problem was - msg[nex] = '\0'; - strcat(msg, " << "); - strcat(msg, errstr[n]); - - asm_error(msg); - - exprerrno = n; - longjmp(exprjmp, 1); -} - -/* ------------------------------------------------------------------------ - * upcase - force a string to uppercase (ASCII) - * ------------------------------------------------------------------------ */ - -char *upcase (char *str) -{ - char *s; - - for (s = str; *s; s++) { - if (*s >= 'a' && *s <= 'z') - *s -= 32; - } - - return str; -} - -/* ------------------------------------------------------------------------ - * hollerith table for IPL card ident field - * ------------------------------------------------------------------------ */ - -typedef struct { - int hollerith; - char ascii; -} CPCODE; - -static CPCODE cardcode_029[] = -{ - 0x0000, ' ', - 0x8000, '&', // + in 026 Fortran - 0x4000, '-', - 0x2000, '0', - 0x1000, '1', - 0x0800, '2', - 0x0400, '3', - 0x0200, '4', - 0x0100, '5', - 0x0080, '6', - 0x0040, '7', - 0x0020, '8', - 0x0010, '9', - 0x9000, 'A', - 0x8800, 'B', - 0x8400, 'C', - 0x8200, 'D', - 0x8100, 'E', - 0x8080, 'F', - 0x8040, 'G', - 0x8020, 'H', - 0x8010, 'I', - 0x5000, 'J', - 0x4800, 'K', - 0x4400, 'L', - 0x4200, 'M', - 0x4100, 'N', - 0x4080, 'O', - 0x4040, 'P', - 0x4020, 'Q', - 0x4010, 'R', - 0x3000, '/', - 0x2800, 'S', - 0x2400, 'T', - 0x2200, 'U', - 0x2100, 'V', - 0x2080, 'W', - 0x2040, 'X', - 0x2020, 'Y', - 0x2010, 'Z', - 0x0820, ':', - 0x0420, '#', // = in 026 Fortran - 0x0220, '@', // ' in 026 Fortran - 0x0120, '\'', - 0x00A0, '=', - 0x0060, '"', - 0x8820, 'c', // cent - 0x8420, '.', - 0x8220, '<', // ) in 026 Fortran - 0x8120, '(', - 0x80A0, '+', - 0x8060, '|', - 0x4820, '!', - 0x4420, '$', - 0x4220, '*', - 0x4120, ')', - 0x40A0, ';', - 0x4060, 'n', // not - 0x2820, 'x', // what? - 0x2420, ',', - 0x2220, '%', // ( in 026 Fortran - 0x2120, '_', - 0x20A0, '>', - 0x2060, '>', -}; - -int ascii_to_hollerith (int ch) -{ - int i; - - for (i = 0; i < sizeof(cardcode_029) / sizeof(CPCODE); i++) - if (cardcode_029[i].ascii == ch) - return cardcode_029[i].hollerith; - - return 0; -} - -/* ------------------------------------------------------------------------ - * detab - replace tabs with spaces for listing files - * ------------------------------------------------------------------------ */ - -char *detab (char *instr) -{ - static char outstr[256]; - char *out = outstr; - int col = 0; - - while (*instr) { - if (*instr == '\t') { - do { - *out++ = ' '; - col++; - } - while (col & 7); - } - else { - *out++ = *instr; - col++; - } - - instr++; - } - - *out = '\0'; - - return outstr; -} - - -#ifndef WIN32 - -int strnicmp (char *a, char *b, int n) -{ - int ca, cb; - - for (;;) { - if (--n < 0) // still equal after n characters? quit now - return 0; - - if ((ca = *a) == 0) // get character, stop on null terminator - return *b ? -1 : 0; - - if (ca >= 'a' && ca <= 'z') // fold lowercase to uppercase - ca -= 32; - - cb = *b; - if (cb >= 'a' && cb <= 'z') - cb -= 32; - - if ((ca -= cb) != 0) // if different, return comparison - return ca; - - a++, b++; - } -} - -int strcmpi (char *a, char *b) -{ - int ca, cb; - - for (;;) { - if ((ca = *a) == 0) // get character, stop on null terminator - return *b ? -1 : 0; - - if (ca >= 'a' && ca <= 'z') // fold lowercase to uppercase - ca -= 32; - - cb = *b; - if (cb >= 'a' && cb <= 'z') - cb -= 32; - - if ((ca -= cb) != 0) // if different, return comparison - return ca; - - a++, b++; - } -} - -#endif diff --git a/Ibm1130/utils/asm1130.mak b/Ibm1130/utils/asm1130.mak deleted file mode 100644 index b072c224..00000000 --- a/Ibm1130/utils/asm1130.mak +++ /dev/null @@ -1,161 +0,0 @@ -# Microsoft Visual C++ Generated NMAKE File, Format Version 2.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Console Application" 0x0103 - -!IF "$(CFG)" == "" -CFG=Win32 Debug -!MESSAGE No configuration specified. Defaulting to Win32 Debug. -!ENDIF - -!IF "$(CFG)" != "Win32 Release" && "$(CFG)" != "Win32 Debug" -!MESSAGE Invalid configuration "$(CFG)" specified. -!MESSAGE You can specify a configuration when running NMAKE on this makefile -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "asm1130.mak" CFG="Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "Win32 Release" (based on "Win32 (x86) Console Application") -!MESSAGE "Win32 Debug" (based on "Win32 (x86) Console Application") -!MESSAGE -!ERROR An invalid configuration is specified. -!ENDIF - -################################################################################ -# Begin Project -# PROP Target_Last_Scanned "Win32 Debug" -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "WinRel" -# PROP BASE Intermediate_Dir "WinRel" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "WinRel" -# PROP Intermediate_Dir "WinRel" -OUTDIR=.\WinRel -INTDIR=.\WinRel - -ALL : $(OUTDIR)/asm1130.exe $(OUTDIR)/asm1130.bsc - -$(OUTDIR) : - if not exist $(OUTDIR)/nul mkdir $(OUTDIR) - -# ADD BASE CPP /nologo /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /FR /c -# ADD CPP /nologo /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /FR /c -CPP_PROJ=/nologo /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE"\ - /FR$(INTDIR)/ /Fp$(OUTDIR)/"asm1130.pch" /Fo$(INTDIR)/ /c -CPP_OBJS=.\WinRel/ -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -BSC32_FLAGS=/nologo /o$(OUTDIR)/"asm1130.bsc" -BSC32_SBRS= \ - $(INTDIR)/asm1130.sbr - -$(OUTDIR)/asm1130.bsc : $(OUTDIR) $(BSC32_SBRS) - $(BSC32) @<< - $(BSC32_FLAGS) $(BSC32_SBRS) -<< - -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NOLOGO /SUBSYSTEM:console /MACHINE:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib /NOLOGO /SUBSYSTEM:console /MACHINE:I386 -LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib /NOLOGO /SUBSYSTEM:console\ - /INCREMENTAL:no /PDB:$(OUTDIR)/"asm1130.pdb" /MACHINE:I386\ - /OUT:$(OUTDIR)/"asm1130.exe" -DEF_FILE= -LINK32_OBJS= \ - $(INTDIR)/asm1130.obj - -$(OUTDIR)/asm1130.exe : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS) - $(LINK32) @<< - $(LINK32_FLAGS) $(LINK32_OBJS) -<< - -!ELSEIF "$(CFG)" == "Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "WinDebug" -# PROP BASE Intermediate_Dir "WinDebug" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "WinDebug" -# PROP Intermediate_Dir "WinDebug" -OUTDIR=.\WinDebug -INTDIR=.\WinDebug - -ALL : $(OUTDIR)/asm1130.exe $(OUTDIR)/asm1130.bsc - -$(OUTDIR) : - if not exist $(OUTDIR)/nul mkdir $(OUTDIR) - -# ADD BASE CPP /nologo /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /FR /c -# ADD CPP /nologo /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /FR /c -CPP_PROJ=/nologo /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE"\ - /FR$(INTDIR)/ /Fp$(OUTDIR)/"asm1130.pch" /Fo$(INTDIR)/\ - /Fd$(OUTDIR)/"asm1130.pdb" /c -CPP_OBJS=.\WinDebug/ -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -BSC32_FLAGS=/nologo /o$(OUTDIR)/"asm1130.bsc" -BSC32_SBRS= \ - $(INTDIR)/asm1130.sbr - -$(OUTDIR)/asm1130.bsc : $(OUTDIR) $(BSC32_SBRS) - $(BSC32) @<< - $(BSC32_FLAGS) $(BSC32_SBRS) -<< - -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NOLOGO /SUBSYSTEM:console /DEBUG /MACHINE:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib /NOLOGO /SUBSYSTEM:console /DEBUG /MACHINE:I386 -LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib /NOLOGO /SUBSYSTEM:console\ - /INCREMENTAL:yes /PDB:$(OUTDIR)/"asm1130.pdb" /DEBUG /MACHINE:I386\ - /OUT:$(OUTDIR)/"asm1130.exe" -DEF_FILE= -LINK32_OBJS= \ - $(INTDIR)/asm1130.obj - -$(OUTDIR)/asm1130.exe : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS) - $(LINK32) @<< - $(LINK32_FLAGS) $(LINK32_OBJS) -<< - -!ENDIF - -.c{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -.cpp{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -.cxx{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -################################################################################ -# Begin Group "Source Files" - -################################################################################ -# Begin Source File - -SOURCE=.\asm1130.c - -$(INTDIR)/asm1130.obj : $(SOURCE) $(INTDIR) - -# End Source File -# End Group -# End Project -################################################################################ diff --git a/Ibm1130/utils/bindump.c b/Ibm1130/utils/bindump.c deleted file mode 100644 index 332e42ee..00000000 --- a/Ibm1130/utils/bindump.c +++ /dev/null @@ -1,752 +0,0 @@ -/* - * (C) Copyright 2002, Brian Knittel. - * You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN - * RISK basis, there is no warranty of fitness for any purpose, and the rest of the - * usual yada-yada. Please keep this notice and the copyright in any distributions - * or modifications. - * - * This is not a supported product, but I welcome bug reports and fixes. - * Mail to sim@ibm1130.org - */ - -// --------------------------------------------------------------------------------- -// BINDUMP - dumps card deck files in assembler object format -// -// Usage: -/// bindump deckfile lists object header info & sector break cards -// bindump -v deckfile lists object data records as well -// bindump -p deckfile for system program, lists phase IDs in the deck -// bindump -s deckfile >outfile for system program, sorts the phases & writes to stdout - -#include -#include -#ifdef WIN32 -# include -# include -# include -#endif - -#ifndef TRUE - #define BOOL int - #define TRUE 1 - #define FALSE 0 -#endif - -typedef enum {R_ABSOLUTE = 0, R_RELATIVE = 1, R_LIBF = 2, R_CALL = 3} RELOC; - -BOOL verbose = FALSE; -BOOL phid = FALSE; -BOOL sort = FALSE; -unsigned short card[80], buf[54], cardtype; - -// bindump - dump a binary (card format) deck to verify sbrks, etc - -void bail (char *msg); -void dump (char *fname); -void dump_data (char *fname); -void dump_phids (char *fname); -char *getname (unsigned short *ptr); -char *getseq (void); -int hollerith_to_ascii (unsigned short h); -void process (char *fname); -void show_raw (char *name); -void show_data (void); -void show_core (void); -void show_endc (void); -void show_81 (void); -void show_main (void); -void show_sub (void); -void show_ils (void); -void show_iss (void); -void show_end (void); -void sort_phases (char *fname); -void trim (char *s); -void unpack (unsigned short *card, unsigned short *buf); -void verify_checksum(unsigned short *buf); - -int main (int argc, char **argv) -{ - char *arg; - static char usestr[] = "Usage: bindump [-psv] filename..."; - int i; - - for (i = 1; i < argc; i++) { - arg = argv[i]; - if (*arg == '-') { - arg++; - while (*arg) { - switch (*arg++) { - case 'v': - verbose = TRUE; - break; - case 'p': - phid = TRUE; // print only phase ID's - break; - case 's': - sort = TRUE; // sort deck by phases, writing to stdout - break; - default: - bail(usestr); - } - } - } - } - - for (i = 1; i < argc; i++) { - arg = argv[i]; - if (*arg != '-') - process(arg); - } - return 0; -} - -void process (char *nm) -{ -#ifdef WIN32 - WIN32_FIND_DATA fd; - HANDLE hFind; - char *c, buf[256]; - - if (strchr(nm, '*') == NULL && strchr(nm, '?') == NULL) - dump(nm); - - else if ((hFind = FindFirstFile(nm, &fd)) == INVALID_HANDLE_VALUE) - fprintf(stderr, "No files matching '%s'\n", nm); - - else { - if ((c = strrchr(nm, '\\')) == NULL) - c = strrchr(nm, ':'); - - do { - if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) - continue; - - if (c == NULL) - dump(fd.cFileName); - else { - strcpy(buf, nm); - strcpy(buf + (c-nm+1), fd.cFileName); - dump(buf); - } - - } while (FindNextFile(hFind, &fd)); - - FindClose(hFind); - } -#else - dump(nm); // on unices, sh globs for us -#endif -} - -void dump (char *fname) -{ - if (sort) - sort_phases(fname); - else if (phid) - dump_phids(fname); - else - dump_data(fname); -} - -struct tag_card { - int phid, seq; - unsigned short card[80]; -}; - -int cardcomp (const void *a, const void *b) -{ - short diff; - - diff = ((struct tag_card *) a)->phid - ((struct tag_card *) b)->phid; - - return diff ? diff : (((struct tag_card *) a)->seq - ((struct tag_card *) b)->seq); -} - -void sort_phases (char *fname) -{ - int i, ncards, cardtype, len, seq = 0, phid; - struct tag_card *deck; - FILE *fd; - BOOL saw_sbrk = TRUE; - - if ((fd = fopen(fname, "rb")) == NULL) { - perror(fname); - return; - } - - fseek(fd, 0, SEEK_END); - len = ftell(fd); // get length of file - fseek(fd, 0, SEEK_SET); - - if (len <= 0 || (len % 160) != 0) { - fprintf(stderr, "%s is not a binard deck image\n"); - fclose(fd); - return; - } - - ncards = len / 160; - - if ((deck = (struct tag_card *) malloc(ncards*sizeof(struct tag_card))) == NULL) { - fprintf(stderr, "%s: can't sort, insufficient memory\n"); - fclose(fd); - return; - } - - phid = 0; - for (i = 0; i < ncards; i++) { - if (fread(deck[i].card, sizeof(card[0]), 80, fd) != 80) { - free(deck); - fprintf(stderr, "%s: error reading deck\n"); - fclose(fd); - return; - } - - unpack(deck[i].card, buf); - deck[i].seq = seq++; - deck[i].phid = phid; - - verify_checksum(buf); - - cardtype = (buf[2] >> 8) & 0xFF; - - if (cardtype == 1 || cardtype == 2) { // start of deck is same as sector break - saw_sbrk = TRUE; - } - else if (cardtype == 0) { - fprintf(stderr, "%s is a core image deck\n"); - free(deck); - fclose(fd); - return; - } - else if (cardtype == 0x0A && saw_sbrk) { - phid = (int) (signed short) buf[10]; - if (phid < 0) - phid = -phid; - - deck[i].phid = phid; // this belongs to the new phase - deck[i-1].phid = phid; // as does previous card - saw_sbrk = FALSE; - } - } - fclose(fd); - - qsort(deck, ncards, sizeof(struct tag_card), cardcomp); // sort the deck - -#ifdef WIN32 - _setmode(_fileno(stdout), _O_BINARY); // set standard output to binary mode -#endif - - for (i = 0; i < ncards; i++) // write to stdout - fwrite(deck[i].card, sizeof(card[0]), 80, stdout); - - free(deck); -} - -void dump_phids (char *fname) -{ - FILE *fp; - BOOL first = TRUE; - BOOL saw_sbrk = TRUE, neg; - short id; - - if ((fp = fopen(fname, "rb")) == NULL) { - perror(fname); - return; - } - - printf("\n%s:\n", fname); - - while (fread(card, sizeof(card[0]), 80, fp) > 0) { - unpack(card, buf); - verify_checksum(buf); - - cardtype = (buf[2] >> 8) & 0xFF; - - if (cardtype == 1 && ! first) { // sector break - saw_sbrk = TRUE; - continue; - } - else { - switch (cardtype) { - case 0x00: - printf(" This is a core image deck\n"); - goto done; - break; - case 0x01: - case 0x02: - case 0x03: - case 0x04: - case 0x05: - case 0x06: - case 0x07: - case 0x0F: - break; - - case 0x0A: - if (saw_sbrk) { - id = buf[10]; - if (id < 0) - id = -id, neg = TRUE; - else - neg = FALSE; - printf(" : %3d / %02x%s\n", id, id, neg ? " (neg)" : ""); - saw_sbrk = FALSE; - } - break; - - default: - show_raw("??? "); - } - } -done: - first = FALSE; - } - - fclose(fp); -} - -void dump_data (char *fname) -{ - FILE *fp; - BOOL first = TRUE; - char str[80]; - int i; - - if ((fp = fopen(fname, "rb")) == NULL) { - perror(fname); - return; - } - - printf("\n%s:\n", fname); - - while (fread(card, sizeof(card[0]), 80, fp) > 0) { - unpack(card, buf); - verify_checksum(buf); - - cardtype = (buf[2] >> 8) & 0xFF; - - if (cardtype == 1 && ! first) { // sector break - for (i = 4; i < 72; i++) - str[i] = hollerith_to_ascii(card[i]); - - str[i] = '\0'; - trim(str+4); - printf("*SBRK %s\n", str+4); - continue; - } - else { - switch (cardtype) { - case 0x00: - if (first) - show_raw("CORE"); - if (verbose) - show_core(); - break; - - case 0x01: - show_raw("ABS "); - show_main(); - break; - case 0x02: - show_raw("REL "); - show_main(); - break; - case 0x03: - show_raw("LIB "); - show_sub(); - break; - case 0x04: - show_raw("SUB "); - show_sub(); - break; - case 0x05: - show_raw("ISSL"); - show_iss(); - break; - case 0x06: - show_raw("ISSC"); - show_iss(); - break; - case 0x07: - show_raw("ILS "); - show_ils(); - break; - case 0x0F: - show_raw("END "); - show_end(); - break; - case 0x80: - show_raw("ENDC"); - show_endc(); - break; - case 0x81: - show_raw("81 "); - show_81(); - break; - case 0x0A: - if (verbose) - show_data(); - break; - default: - show_raw("??? "); - } - } - - first = FALSE; - } - - fclose(fp); -} - -void show_data (void) -{ - int i, n, jrel, rflag, nout, ch, reloc; - BOOL first = TRUE; - - n = buf[2] & 0x00FF; - - printf("%04x: ", buf[0]); - - jrel = 3; - nout = 0; - rflag = buf[jrel++]; - for (i = 0; i < n; i++) { - if (nout >= 8) { - rflag = buf[jrel++]; - if (first) { - printf(" %s", getseq()); - first = FALSE; - } - printf("\n "); - nout = 0; - } - reloc = (rflag >> 14) & 0x03; - ch = (reloc == R_ABSOLUTE) ? ' ' : - (reloc == R_RELATIVE) ? 'R' : - (reloc == R_LIBF) ? 'L' : '@'; - - printf("%04x%c ", buf[9+i], ch); - rflag <<= 2; - nout++; - } - putchar('\n'); -} - -void show_core (void) -{ - int i, n, nout; - BOOL first = TRUE; - - n = buf[2] & 0x00FF; - - printf("%04x: ", buf[0]); - - nout = 0; - for (i = 0; i < n; i++) { - if (nout >= 8) { - if (first) { - printf(" %s", getseq()); - first = FALSE; - } - printf("\n "); - nout = 0; - } - printf("%04x ", buf[9+i]); - nout++; - } - putchar('\n'); -} - -void info (int i, char *nm, char type) -{ - if (nm) - printf("%s ", nm); - - switch (type) { - case 'd': - printf("%d ", buf[i]); - break; - - case 'x': - printf("%04x ", buf[i]); - break; - - case 'b': - printf("%02x ", buf[i] & 0xFF); - break; - - case 'n': - printf("%s ", getname(buf+i)); - break; - - default: - bail("BAD TYPE"); - } -} - -void show_main (void) -{ - printf(" "); - info(2, "prec", 'b'); - info(4, "common", 'd'); - info(6, "work", 'd'); - info(8, "files", 'd'); - info(9, "name", 'n'); - info(11, "pta", 'x'); - putchar('\n'); -} - -void show_sub (void) -{ - int i, n; - - printf(" "); - info( 2, "prec", 'b'); - - n = buf[5] / 3; - for (i = 0; i < n; i++) { - info( 9+3*i, "ent", 'n'); - info(11+3*i, NULL, 'x'); - } - - putchar('\n'); -} - -void show_iss (void) -{ - printf(" "); - info(12, "level", 'd'); - putchar('\n'); -} - -void show_ils (void) -{ - printf(" "); - info( 2, "prec", 'b'); - info( 5, "nint6", 'd'); - info( 9, "ent", 'n'); - info(11, NULL, 'x'); - info(14, "nint", 'd'); - info(15, "il1", 'd'); - info(16, "il2", 'd'); - putchar('\n'); -} - -void show_end (void) -{ - printf(" "); - info(0, "size", 'd'); - info(3, "pta", 'x'); - putchar('\n'); -} - -void show_endc(void) -{ - printf(" "); - info(52, "IX3", 'x'); - info(53, "pta", 'x'); - putchar('\n'); -} - -void show_81(void) -{ -} - -void show_raw (char *name) -{ - int i; - printf("*%s", name); - - for (i = 0; i < 12; i++) - printf(" %04x", buf[i]); - - printf(" %s\n", getseq()); -} - -char * getseq (void) -{ - static char seq[10]; - int i; - - for (i = 0; i < 8; i++) - seq[i] = hollerith_to_ascii(card[72+i]); - - seq[i] = '\0'; - return seq; -} - - -void bail (char *msg) -{ - fprintf(stderr, "%s\n", msg); - exit(1); -} - -void unpack (unsigned short *icard, unsigned short *obuf) -{ - int i, j; - unsigned short wd1, wd2, wd3, wd4; - - for (i = j = 0; i < 54; i += 3, j += 4) { - wd1 = icard[j]; - wd2 = icard[j+1]; - wd3 = icard[j+2]; - wd4 = icard[j+3]; - - obuf[i ] = (wd1 & 0xFFF0) | ((wd2 >> 12) & 0x000F); - obuf[i+1] = ((wd2 << 4) & 0xFF00) | ((wd3 >> 8) & 0x00FF); - obuf[i+2] = ((wd3 << 8) & 0xF000) | ((wd4 >> 4) & 0x0FFF); - } -} - -void verify_checksum (unsigned short *obuf) -{ -// unsigned short sum; - - if (obuf[1] == 0) // no checksum - return; - -// if (sum != card[1]) -// printf("Checksum %04x doesn't match card %04x\n", sum, card[1]); -} - -typedef struct { - unsigned short hollerith; - char ascii; -} CPCODE; - -static CPCODE cardcode_029[] = -{ - 0x0000, ' ', - 0x8000, '&', // + in 026 Fortran - 0x4000, '-', - 0x2000, '0', - 0x1000, '1', - 0x0800, '2', - 0x0400, '3', - 0x0200, '4', - 0x0100, '5', - 0x0080, '6', - 0x0040, '7', - 0x0020, '8', - 0x0010, '9', - 0x9000, 'A', - 0x8800, 'B', - 0x8400, 'C', - 0x8200, 'D', - 0x8100, 'E', - 0x8080, 'F', - 0x8040, 'G', - 0x8020, 'H', - 0x8010, 'I', - 0x5000, 'J', - 0x4800, 'K', - 0x4400, 'L', - 0x4200, 'M', - 0x4100, 'N', - 0x4080, 'O', - 0x4040, 'P', - 0x4020, 'Q', - 0x4010, 'R', - 0x3000, '/', - 0x2800, 'S', - 0x2400, 'T', - 0x2200, 'U', - 0x2100, 'V', - 0x2080, 'W', - 0x2040, 'X', - 0x2020, 'Y', - 0x2010, 'Z', - 0x0820, ':', - 0x0420, '#', // = in 026 Fortran - 0x0220, '@', // ' in 026 Fortran - 0x0120, '\'', - 0x00A0, '=', - 0x0060, '"', - 0x8820, 'c', // cent - 0x8420, '.', - 0x8220, '<', // ) in 026 Fortran - 0x8120, '(', - 0x80A0, '+', - 0x8060, '|', - 0x4820, '!', - 0x4420, '$', - 0x4220, '*', - 0x4120, ')', - 0x40A0, ';', - 0x4060, 'n', // not - 0x2820, 'x', // what? - 0x2420, ',', - 0x2220, '%', // ( in 026 Fortran - 0x2120, '_', - 0x20A0, '>', - 0x2060, '>', -}; - -int hollerith_to_ascii (unsigned short h) -{ - int i; - - h &= 0xFFF0; - - for (i = 0; i < sizeof(cardcode_029) / sizeof(CPCODE); i++) - if (cardcode_029[i].hollerith == h) - return cardcode_029[i].ascii; - - return '?'; -} - -// --------------------------------------------------------------------------------- -// trim - remove trailing whitespace from string s -// --------------------------------------------------------------------------------- - -void trim (char *s) -{ - char *nb; - - for (nb = s-1; *s; s++) - if (*s > ' ') - nb = s; - - nb[1] = '\0'; -} - -int ascii_to_ebcdic_table[128] = -{ - 0x00,0x01,0x02,0x03,0x37,0x2d,0x2e,0x2f, 0x16,0x05,0x25,0x0b,0x0c,0x0d,0x0e,0x0f, - 0x10,0x11,0x12,0x13,0x3c,0x3d,0x32,0x26, 0x18,0x19,0x3f,0x27,0x1c,0x1d,0x1e,0x1f, - 0x40,0x5a,0x7f,0x7b,0x5b,0x6c,0x50,0x7d, 0x4d,0x5d,0x5c,0x4e,0x6b,0x60,0x4b,0x61, - 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7, 0xf8,0xf9,0x7a,0x5e,0x4c,0x7e,0x6e,0x6f, - - 0x7c,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7, 0xc8,0xc9,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6, - 0xd7,0xd8,0xd9,0xe2,0xe3,0xe4,0xe5,0xe6, 0xe7,0xe8,0xe9,0xba,0xe0,0xbb,0xb0,0x6d, - 0x79,0x81,0x82,0x83,0x84,0x85,0x86,0x87, 0x88,0x89,0x91,0x92,0x93,0x94,0x95,0x96, - 0x97,0x98,0x99,0xa2,0xa3,0xa4,0xa5,0xa6, 0xa7,0xa8,0xa9,0xc0,0x4f,0xd0,0xa1,0x07, -}; - -char *getname (unsigned short *ptr) -{ - static char str[6]; - int i, j, ch; - long v; - - v = (ptr[0] << 16L) | ptr[1]; - - for (i = 0; i < 5; i++) { - ch = ((v >> 24) & 0x3F) | 0xC0; // recover those lost two bits - v <<= 6; - - str[i] = ' '; - - for (j = 0; j < (sizeof(ascii_to_ebcdic_table)/sizeof(ascii_to_ebcdic_table[0])); j++) { - if (ascii_to_ebcdic_table[j] == ch) { - str[i] = j; - break; - } - } - } - - str[5] = '\0'; - return str; -} - diff --git a/Ibm1130/utils/bindump.mak b/Ibm1130/utils/bindump.mak deleted file mode 100644 index 192cd550..00000000 --- a/Ibm1130/utils/bindump.mak +++ /dev/null @@ -1,161 +0,0 @@ -# Microsoft Visual C++ Generated NMAKE File, Format Version 2.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Console Application" 0x0103 - -!IF "$(CFG)" == "" -CFG=Win32 Debug -!MESSAGE No configuration specified. Defaulting to Win32 Debug. -!ENDIF - -!IF "$(CFG)" != "Win32 Release" && "$(CFG)" != "Win32 Debug" -!MESSAGE Invalid configuration "$(CFG)" specified. -!MESSAGE You can specify a configuration when running NMAKE on this makefile -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "bindump.mak" CFG="Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "Win32 Release" (based on "Win32 (x86) Console Application") -!MESSAGE "Win32 Debug" (based on "Win32 (x86) Console Application") -!MESSAGE -!ERROR An invalid configuration is specified. -!ENDIF - -################################################################################ -# Begin Project -# PROP Target_Last_Scanned "Win32 Debug" -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "WinRel" -# PROP BASE Intermediate_Dir "WinRel" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "WinRel" -# PROP Intermediate_Dir "WinRel" -OUTDIR=.\WinRel -INTDIR=.\WinRel - -ALL : $(OUTDIR)/bindump.exe $(OUTDIR)/bindump.bsc - -$(OUTDIR) : - if not exist $(OUTDIR)/nul mkdir $(OUTDIR) - -# ADD BASE CPP /nologo /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /FR /c -# ADD CPP /nologo /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /FR /c -CPP_PROJ=/nologo /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE"\ - /FR$(INTDIR)/ /Fp$(OUTDIR)/"bindump.pch" /Fo$(INTDIR)/ /c -CPP_OBJS=.\WinRel/ -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -BSC32_FLAGS=/nologo /o$(OUTDIR)/"bindump.bsc" -BSC32_SBRS= \ - $(INTDIR)/bindump.sbr - -$(OUTDIR)/bindump.bsc : $(OUTDIR) $(BSC32_SBRS) - $(BSC32) @<< - $(BSC32_FLAGS) $(BSC32_SBRS) -<< - -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NOLOGO /SUBSYSTEM:console /MACHINE:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib /NOLOGO /SUBSYSTEM:console /MACHINE:I386 -LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\ - /NOLOGO /SUBSYSTEM:console /INCREMENTAL:no /PDB:$(OUTDIR)/"bindump.pdb"\ - /MACHINE:I386 /OUT:$(OUTDIR)/"bindump.exe" -DEF_FILE= -LINK32_OBJS= \ - $(INTDIR)/bindump.obj - -$(OUTDIR)/bindump.exe : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS) - $(LINK32) @<< - $(LINK32_FLAGS) $(LINK32_OBJS) -<< - -!ELSEIF "$(CFG)" == "Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "WinDebug" -# PROP BASE Intermediate_Dir "WinDebug" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "WinDebug" -# PROP Intermediate_Dir "WinDebug" -OUTDIR=.\WinDebug -INTDIR=.\WinDebug - -ALL : $(OUTDIR)/bindump.exe $(OUTDIR)/bindump.bsc - -$(OUTDIR) : - if not exist $(OUTDIR)/nul mkdir $(OUTDIR) - -# ADD BASE CPP /nologo /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /FR /c -# ADD CPP /nologo /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /FR /c -CPP_PROJ=/nologo /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE"\ - /FR$(INTDIR)/ /Fp$(OUTDIR)/"bindump.pch" /Fo$(INTDIR)/\ - /Fd$(OUTDIR)/"bindump.pdb" /c -CPP_OBJS=.\WinDebug/ -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -BSC32_FLAGS=/nologo /o$(OUTDIR)/"bindump.bsc" -BSC32_SBRS= \ - $(INTDIR)/bindump.sbr - -$(OUTDIR)/bindump.bsc : $(OUTDIR) $(BSC32_SBRS) - $(BSC32) @<< - $(BSC32_FLAGS) $(BSC32_SBRS) -<< - -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NOLOGO /SUBSYSTEM:console /DEBUG /MACHINE:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib /NOLOGO /SUBSYSTEM:console /DEBUG /MACHINE:I386 -LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\ - /NOLOGO /SUBSYSTEM:console /INCREMENTAL:yes /PDB:$(OUTDIR)/"bindump.pdb" /DEBUG\ - /MACHINE:I386 /OUT:$(OUTDIR)/"bindump.exe" -DEF_FILE= -LINK32_OBJS= \ - $(INTDIR)/bindump.obj - -$(OUTDIR)/bindump.exe : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS) - $(LINK32) @<< - $(LINK32_FLAGS) $(LINK32_OBJS) -<< - -!ENDIF - -.c{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -.cpp{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -.cxx{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -################################################################################ -# Begin Group "Source Files" - -################################################################################ -# Begin Source File - -SOURCE=.\bindump.c - -$(INTDIR)/bindump.obj : $(SOURCE) $(INTDIR) - -# End Source File -# End Group -# End Project -################################################################################ diff --git a/Ibm1130/utils/checkdisk.c b/Ibm1130/utils/checkdisk.c deleted file mode 100644 index 82a879e0..00000000 --- a/Ibm1130/utils/checkdisk.c +++ /dev/null @@ -1,264 +0,0 @@ -/* - * (C) Copyright 2002, Brian Knittel. - * You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN - * RISK basis, there is no warranty of fitness for any purpose, and the rest of the - * usual yada-yada. Please keep this notice and the copyright in any distributions - * or modifications. - * - * This is not a supported product, but I welcome bug reports and fixes. - * Mail to sim@ibm1130.org - */ - -// checkdisk - validates and optionally dumps an IBM1130 DMS2 disk image file -// -// Usage: -// checkdisk [-f] [-d cyl.sec|abssec] [-n count] filename -// -// Examples: -// checkdisk file.dsk -// report any misnumbered sectors in file.dsk -// -// checkdisk -f file.dsk -// report and fix any misnumbered sectors -// -// checkdisk -d 198.0 file.dsk -// dump cylinder 198 sector 0 -// -// checkdisk -d 0 file.dsk -// dump absolute sector 0 -// -// checkdisk -d 198.0 -n 4 file.dsk -// dump 4 sectors starting at m.n -// ----------------------------------------------------------------------------------------- -#include -#include -#include -#include "util_io.h" - -#ifdef WIN32 -# include -#else - long filelength (int fno); -# include -# include -#endif - -#ifndef TRUE -# define BOOL int -# define TRUE 1 -# define FALSE 0 -#endif - -#define DSK_NUMWD 321 /* words/sector */ -#define DSK_NUMSC 4 /* sectors/surface */ -#define DSK_NUMSF 2 /* surfaces/cylinder */ -#define DSK_NUMCY 203 /* cylinders/drive */ -#define DSK_NUMDR 5 /* drives/controller */ -#define DSK_SIZE (DSK_NUMCY * DSK_NUMSF * DSK_NUMSC * DSK_NUMWD) /* words/drive */ - -char *usestr = "Usage: checkdisk [-f] [-d cyl.sec|abssec] [-n count] diskfile"; -char *baddisk = "Cannot fix this"; - -void bail (char *msg); -char *lowcase (char *str); - -int main (int argc, char **argv) -{ - FILE *fp; - char *fname = NULL, *arg, *argval; - int i, j, cyl, sec, pos, asec, retry, nbad = 0, nfixed = 0, nline; - BOOL fixit = FALSE, dump = FALSE; - int dsec, nsec = 1; - unsigned short wd, buf[DSK_NUMWD]; - - util_io_init(); - - for (i = 1; i < argc;) { - arg = argv[i++]; - if (*arg == '-') { - arg++; - lowcase(arg); - while (*arg) { - switch (*arg++) { - case 'f': - fixit = TRUE; - break; - - case 'd': - dump = TRUE; - - if (i >= argc) - bail(usestr); - - argval = argv[i++]; - if (strchr(argval, '.') != NULL) { - if (sscanf(argval, "%d.%d", &cyl, &sec) != 2) - bail(usestr); - - dsec = cyl*(DSK_NUMSF*DSK_NUMSC) + sec; - } - else if (sscanf(argval, "%d", &dsec) != 1) - bail(usestr); - - if (dsec < 0 || dsec >= (DSK_NUMCY*DSK_NUMSF*DSK_NUMSC)) - bail("No such sector"); - - break; - - case 'n': - if (i >= argc) - bail(usestr); - - argval = argv[i++]; - if (sscanf(argval, "%d", &nsec) != 1) - bail(usestr); - - if (nsec <= 0) - bail(usestr); - - break; - - default: - bail(usestr); - } - } - } - else if (fname == NULL) - fname = arg; - else - bail(usestr); - } - - if (fname == NULL) - bail(usestr); - - if ((fp = fopen(fname, "rb+")) == NULL) { - perror(fname); - return 1; - } - - if (filelength(fileno(fp)) != 2*DSK_SIZE) { - fprintf(stderr, "File is wrong length, expected %d\n", DSK_SIZE); - bail(baddisk); - } - - for (cyl = 0; cyl < DSK_NUMCY; cyl++) { - for (sec = 0; sec < (DSK_NUMSF*DSK_NUMSC); sec++) { - retry = 1; -again: - asec = cyl*(DSK_NUMSF*DSK_NUMSC) + sec; - pos = asec*2*DSK_NUMWD; - - if (fseek(fp, pos, SEEK_SET) != 0) { - fprintf(stderr, "Error seeking to pos %x\n", pos); - bail(baddisk); - } - - if (fxread(&wd, sizeof(wd), 1, fp) != 1) { - fprintf(stderr, "Error reading word at abs sec %x, cyl %x, sec %x at offset %x\n", asec, cyl, sec, pos); - bail(baddisk); - } - - if (wd != asec) { - fprintf(stderr, "Bad sector #%x at abs sec %x, cyl %x, sec %x at offset %x\n", wd, asec, cyl, sec, pos); - nbad++; - - if (fixit) { - if (fseek(fp, pos, SEEK_SET) != 0) { - fprintf(stderr, "Error seeking to pos %x\n", pos); - bail(baddisk); - } - - if (fxwrite(&asec, sizeof(wd), 1, fp) != 1) { - fprintf(stderr, "Error writing sector # to abs sec %x, cyl %x, sec %x at offset %x\n", asec, cyl, sec, pos); - bail(baddisk); - } - - if (retry) { - retry = 0; - nfixed++; - goto again; - } - - fprintf(stderr, "Failed after retry\n"); - bail(baddisk); - } - } - } - } - - if (nbad) - printf("%d bad sector mark%s %s\n", nbad, (nbad == 1) ? "" : "s", fixit ? "fixed" : "found"); - else if (! dump) - printf("All sector marks OK\n"); - - if (! dump) - return 0; - - pos = dsec*2*DSK_NUMWD; - if (fseek(fp, pos, SEEK_SET) != 0) { - fprintf(stderr, "Error seeking to pos %x\n", pos); - bail(baddisk); - } - - for (i = 0; i < nsec; i++) { - cyl = dsec / (DSK_NUMSF*DSK_NUMSC); - sec = dsec - cyl*(DSK_NUMSF*DSK_NUMSC); - - if (fxread(&buf, sizeof(buf[0]), DSK_NUMWD, fp) != DSK_NUMWD) { - fprintf(stderr, "Error reading abs sec %x, cyl %x, sec %x at offset %x\n", dsec, cyl, sec, pos); - bail(baddisk); - } - - printf("\nSector %d.%d - %d - /%04x label %04x\n", cyl, sec, dsec, dsec, buf[0]); - for (nline = 0, j = 1; j < DSK_NUMWD; j++) { - printf("%04x", buf[j]); - if (++nline == 16) { - putchar('\n'); - nline = 0; - } - else - putchar(' '); - } - - dsec++; - } - - return 0; -} - -void bail (char *msg) -{ - fprintf(stderr, "%s\n", msg); - exit(1); -} - -/* ------------------------------------------------------------------------ - * lowcase - force a string to lower case (ASCII) - * ------------------------------------------------------------------------ */ - -char *lowcase (char *str) -{ - char *s; - - for (s = str; *s; s++) { - if (*s >= 'A' && *s <= 'Z') - *s += 32; - } - - return str; -} - -#ifndef WIN32 - -long filelength (int fno) -{ - struct stat sb; - - if (fstat(fno, &sb) != 0) - return 0; - - return (long) sb.st_size; -} -#endif - diff --git a/Ibm1130/utils/checkdisk.mak b/Ibm1130/utils/checkdisk.mak deleted file mode 100644 index e03d955b..00000000 --- a/Ibm1130/utils/checkdisk.mak +++ /dev/null @@ -1,177 +0,0 @@ -# Microsoft Visual C++ Generated NMAKE File, Format Version 2.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Console Application" 0x0103 - -!IF "$(CFG)" == "" -CFG=Win32 Debug -!MESSAGE No configuration specified. Defaulting to Win32 Debug. -!ENDIF - -!IF "$(CFG)" != "Win32 Release" && "$(CFG)" != "Win32 Debug" -!MESSAGE Invalid configuration "$(CFG)" specified. -!MESSAGE You can specify a configuration when running NMAKE on this makefile -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "checkdisk.mak" CFG="Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "Win32 Release" (based on "Win32 (x86) Console Application") -!MESSAGE "Win32 Debug" (based on "Win32 (x86) Console Application") -!MESSAGE -!ERROR An invalid configuration is specified. -!ENDIF - -################################################################################ -# Begin Project -# PROP Target_Last_Scanned "Win32 Release" -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "WinRel" -# PROP BASE Intermediate_Dir "WinRel" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "WinRel" -# PROP Intermediate_Dir "WinRel" -OUTDIR=.\WinRel -INTDIR=.\WinRel - -ALL : $(OUTDIR)/checkdisk.exe $(OUTDIR)/checkdisk.bsc - -$(OUTDIR) : - if not exist $(OUTDIR)/nul mkdir $(OUTDIR) - -# ADD BASE CPP /nologo /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /FR /c -# ADD CPP /nologo /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /FR /c -CPP_PROJ=/nologo /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE"\ - /FR$(INTDIR)/ /Fp$(OUTDIR)/"checkdisk.pch" /Fo$(INTDIR)/ /c -CPP_OBJS=.\WinRel/ -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -BSC32_FLAGS=/nologo /o$(OUTDIR)/"checkdisk.bsc" -BSC32_SBRS= \ - $(INTDIR)/checkdisk.sbr \ - $(INTDIR)/util_io.sbr - -$(OUTDIR)/checkdisk.bsc : $(OUTDIR) $(BSC32_SBRS) - $(BSC32) @<< - $(BSC32_FLAGS) $(BSC32_SBRS) -<< - -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NOLOGO /SUBSYSTEM:console /MACHINE:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib /NOLOGO /SUBSYSTEM:console /MACHINE:I386 -LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib /NOLOGO\ - /SUBSYSTEM:console /INCREMENTAL:no /PDB:$(OUTDIR)/"checkdisk.pdb" /MACHINE:I386\ - /OUT:$(OUTDIR)/"checkdisk.exe" -DEF_FILE= -LINK32_OBJS= \ - $(INTDIR)/checkdisk.obj \ - $(INTDIR)/util_io.obj - -$(OUTDIR)/checkdisk.exe : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS) - $(LINK32) @<< - $(LINK32_FLAGS) $(LINK32_OBJS) -<< - -!ELSEIF "$(CFG)" == "Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "WinDebug" -# PROP BASE Intermediate_Dir "WinDebug" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "WinDebug" -# PROP Intermediate_Dir "WinDebug" -OUTDIR=.\WinDebug -INTDIR=.\WinDebug - -ALL : $(OUTDIR)/checkdisk.exe $(OUTDIR)/checkdisk.bsc - -$(OUTDIR) : - if not exist $(OUTDIR)/nul mkdir $(OUTDIR) - -# ADD BASE CPP /nologo /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /FR /c -# ADD CPP /nologo /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /FR /c -CPP_PROJ=/nologo /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE"\ - /FR$(INTDIR)/ /Fp$(OUTDIR)/"checkdisk.pch" /Fo$(INTDIR)/\ - /Fd$(OUTDIR)/"checkdisk.pdb" /c -CPP_OBJS=.\WinDebug/ -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -BSC32_FLAGS=/nologo /o$(OUTDIR)/"checkdisk.bsc" -BSC32_SBRS= \ - $(INTDIR)/checkdisk.sbr \ - $(INTDIR)/util_io.sbr - -$(OUTDIR)/checkdisk.bsc : $(OUTDIR) $(BSC32_SBRS) - $(BSC32) @<< - $(BSC32_FLAGS) $(BSC32_SBRS) -<< - -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NOLOGO /SUBSYSTEM:console /DEBUG /MACHINE:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib /NOLOGO /SUBSYSTEM:console /DEBUG /MACHINE:I386 -LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib /NOLOGO\ - /SUBSYSTEM:console /INCREMENTAL:yes /PDB:$(OUTDIR)/"checkdisk.pdb" /DEBUG\ - /MACHINE:I386 /OUT:$(OUTDIR)/"checkdisk.exe" -DEF_FILE= -LINK32_OBJS= \ - $(INTDIR)/checkdisk.obj \ - $(INTDIR)/util_io.obj - -$(OUTDIR)/checkdisk.exe : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS) - $(LINK32) @<< - $(LINK32_FLAGS) $(LINK32_OBJS) -<< - -!ENDIF - -.c{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -.cpp{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -.cxx{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -################################################################################ -# Begin Group "Source Files" - -################################################################################ -# Begin Source File - -SOURCE=.\checkdisk.c -DEP_CHECK=\ - .\util_io.h\ - \MSVC20\INCLUDE\sys\types.h\ - \MSVC20\INCLUDE\sys\stat.h - -$(INTDIR)/checkdisk.obj : $(SOURCE) $(DEP_CHECK) $(INTDIR) - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\util_io.c - -$(INTDIR)/util_io.obj : $(SOURCE) $(INTDIR) - -# End Source File -# End Group -# End Project -################################################################################ diff --git a/Ibm1130/utils/diskview.c b/Ibm1130/utils/diskview.c deleted file mode 100644 index 65ee850e..00000000 --- a/Ibm1130/utils/diskview.c +++ /dev/null @@ -1,614 +0,0 @@ -/* - * (C) Copyright 2002, Brian Knittel. - * You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN - * RISK basis, there is no warranty of fitness for any purpose, and the rest of the - * usual yada-yada. Please keep this notice and the copyright in any distributions - * or modifications. - * - * This is not a supported product, but I welcome bug reports and fixes. - * Mail to sim@ibm1130.org - */ - -// DISKVIEW - lists contents of an 1130 system disk image file. Not finished yet. -// needs LET/SLET listing routine. -// -// usage: -// diskview -v diskfile - -#include -#include -#include -#include -#include "util_io.h" - -#define BETWEEN(v,a,b) (((v) >= (a)) && ((v) <= (b))) -#define MIN(a,b) (((a) <= (b)) ? (a) : (b)) -#define MAX(a,b) (((a) >= (b)) ? (a) : (b)) - -#ifndef TRUE -# define TRUE 1 -# define FALSE 0 -# define BOOL int -#endif - -#define NOT_DEF 0x0658 // defective cylinder table entry means no defect - -#define DSK_NUMWD 321 /* words/sector */ -#define DSK_NUMCY 203 /* cylinders/drive */ -#define DSK_SECCYL 8 /* sectors per cylinder */ -#define SECLEN 320 /* data words per sector */ -#define SLETLEN ((3*SECLEN)/4) /* length of slet in records */ - -typedef unsigned short WORD; - -FILE *fp; -WORD buf[DSK_NUMWD]; -WORD dcom[DSK_NUMWD]; - -#pragma pack(2) -struct tag_slet { - WORD phid; - WORD addr; - WORD nwords; - WORD sector; -} slet[SLETLEN]; - -#pragma pack() - -WORD dcyl[3]; -BOOL verbose = FALSE; - -void checksectors (void); -void dump_id (void); -void dump_dcom (void); -void dump_resmon (void); -void dump_slet (void); -void dump_hdng (void); -void dump_scra (void); -void dump_let (void); -void dump_flet (void); -void dump_cib (void); -void getsector (int sec, WORD *sbuf); -void getdcyl (void); -char *lowcase (char *str); - -void bail(char *fmt, ...); -char *trim (char *s); - -int main (int argc, char **argv) -{ - char *fname = NULL, *arg; - static char usestr[] = "Usage: diskview [-v] filename"; - int i; - - util_io_init(); - - for (i = 1; i < argc;) { - arg = argv[i++]; - if (*arg == '-') { - arg++; - lowcase(arg); - while (*arg) { - switch (*arg++) { - case 'v': - verbose = TRUE; - break; - - default: - bail(usestr); - } - } - } - else if (fname == NULL) - fname = arg; - else - bail(usestr); - } - - if (fname == NULL) - bail(usestr); - - if ((fp = fopen(fname, "rb")) == NULL) { - perror(fname); - return 2; - } - - printf("%s:\n", fname); - - checksectors(); - getdcyl(); - - dump_id(); // ID & coldstart - dump_dcom(); // DCOM - dump_resmon(); // resident image - dump_slet(); // SLET - dump_hdng(); // heading sector - dump_scra(); - dump_flet(); - dump_cib(); - dump_let(); - - fclose(fp); - return 0; -} - -// checksectors - verify that all sectors are properly numbered - -void checksectors () -{ - WORD sec = 0; - - fseek(fp, 0, SEEK_SET); - - for (sec = 0; sec < DSK_NUMCY*DSK_SECCYL; sec++) { - if (fxread(buf, sizeof(WORD), DSK_NUMWD, fp) != DSK_NUMWD) - bail("File read error or not a disk image file"); - - if (buf[0] != sec) - bail("Sector /%x is misnumbered, run checkdisk [-f]", sec); - } -} - -// get defective cylinder list - -void getdcyl (void) -{ - fseek(fp, sizeof(WORD), SEEK_SET); // skip sector count - if (fxread(dcyl, sizeof(WORD), 3, fp) != 3) - bail("Unable to read defective cylinder table"); -} - -// getsector - read specified absolute sector - -void getsector (int sec, WORD *sbuf) -{ - int i, cyl, ssec; - - sec &= 0x7FF; // mask of drive bits, if any - - cyl = sec / DSK_SECCYL; // get cylinder - ssec = sec & ~(DSK_SECCYL-1); // mask to get starting sector of cylinder - for (i = 0; i < 3; i++) { // map through defective cylinder table - if (dcyl[i] == ssec) { - sec &= (DSK_SECCYL-1); // mask to get base sector - cyl = DSK_NUMCY-3+i; // replacements are last three on disk - sec += cyl*DSK_SECCYL; // add new cylinder offset - break; - } - } - // read the sector - if (fseek(fp, (sec*DSK_NUMWD+1)*sizeof(WORD), SEEK_SET) != 0) - bail("File seek failed"); - - if (fxread(sbuf, sizeof(WORD), DSK_NUMWD, fp) != DSK_NUMWD) - bail("File read error or not a disk image file"); -} - -void dump (int nwords) -{ - int i, nline = 0; - - for (i = 0; i < nwords; i++) { - if (nline == 16) { - putchar('\n'); - nline = 0; - } - - printf("%04x", buf[i]); - nline++; - } - putchar('\n'); -} - -void showmajor (char *label) -{ - int i; - - printf("\n--- %s ", label); - - for (i = strlen(label); i < 40; i++) - putchar('-'); - - putchar('\n'); - putchar('\n'); -} - -void name (char *label) -{ - printf("%-32.32s ", label); -} - -void pbf (char *label, WORD *buf, int nwords) -{ - int i, nout; - - name(label); - - for (i = nout = 0; i < nwords; i++, nout++) { - if (nout == 8) { - putchar('\n'); - name(""); - nout = 0; - } - printf(" %04x", buf[i]); - } - - putchar('\n'); -} - -void prt (char *label, char *fmt, ...) -{ - va_list args; - - name(label); - - putchar(' '); - va_start(args, fmt); - vprintf(fmt, args); - va_end(args); - - putchar('\n'); -} - -void dump_id (void) -{ - showmajor("Sector 0 - ID & coldstart"); - getsector(0, buf); - - pbf("DCYL def cyl table", buf+ 0, 3); - pbf("CIDN cart id", buf+ 3, 1); - pbf(" copy code", buf+ 4, 1); - pbf("DTYP disk type", buf+ 7, 1); - pbf(" diskz copy", buf+ 30, 8); - pbf(" cold start pgm",buf+270, 8); -} - -// EQUIVALENCES FOR DCOM PARAMETERS -#define NAME 4 // NAME OF PROGRAM/CORE LOAD -#define DBCT 6 // BLOCK CT OF PROGRAM/CORE LOAD -#define FCNT 7 // FILES SWITCH -#define SYSC 8 // SYSTEM/NON-SYSTEM CARTRIDGE INDR -#define JBSW 9 // JOBT SWITCH -#define CBSW 10 // CLB-RETURN SWITCH -#define LCNT 11 // NO. OF LOCALS -#define MPSW 12 // CORE MAP SWITCH -#define MDF1 13 // NO. DUP CTRL RECORDS (MODIF) -#define MDF2 14 // ADDR OF MODIF BUFFER -#define NCNT 15 // NO. OF NOCALS -#define ENTY 16 // RLTV ENTRY ADDR OF PROGRAM -#define RP67 17 // 1442-5 SWITCH -#define TODR 18 // OBJECT WORK STORAGE DRIVE CODE -#define FHOL 20 // ADDR LARGEST HOLE IN FIXED AREA -#define FSZE 21 // BLK CNT LARGEST HOLE IN FXA -#define UHOL 22 // ADDR LAST HOLE IN USER AREA 2-10 -#define USZE 23 // BLK CNT LAST HOLE IN UA 2-10 -#define DCSW 24 // DUP CALL SWITCH -#define PIOD 25 // PRINCIPAL I/O DEVICE INDICATOR -#define PPTR 26 // PRINCIPAL PRINT DEVICE INDICATOR -#define CIAD 27 // RLTV ADDR IN @STRT OF CIL ADDR -#define ACIN 28 // AVAILABLE CARTRIDGE INDICATOR -#define GRPH 29 // 2250 INDICATOR 2G2 -#define GCNT 30 // NO. G2250 RECORDS 2G2 -#define LOSW 31 // LOCAL-CALLS-LOCAL SWITCH 2-2 -#define X3SW 32 // SPECIAL ILS SWITCH 2-2 -#define ECNT 33 // NO. OF *EQUAT RCDS 2-4 -#define ANDU 35 // 1+BLK ADDR END OF UA (ADJUSTED) -#define BNDU 40 // 1+BLK ADDR END OF UA (BASE) -#define FPAD 45 // FILE PROTECT ADDR -#define PCID 50 // CARTRIDGE ID, PHYSICAL DRIVE -#define CIDN 55 // CARTRIDGE ID, LOGICAL DRIVE -#define CIBA 60 // SCTR ADDR OF CIB -#define SCRA 65 // SCTR ADDR OF SCRA -#define FMAT 70 // FORMAT OF PROG IN WORKING STG -#define FLET 75 // SCTR ADDR 1ST SCTR OF FLET -#define ULET 80 // SCTR ADDR 1ST SCTR OF LET -#define WSCT 85 // BLK CNT OF PROG IN WORKING STG -#define CSHN 90 // NO. SCTRS IN CUSHION AREA - -struct tag_dcominfo { - char *nm; - int offset; - char *descr; -} dcominfo[] = { - "NAME", 4, "NAME OF PROGRAM/CORE LOAD", - "DBCT", 6, "BLOCK CT OF PROGRAM/CORE LOAD", - "FCNT", 7, "FILES SWITCH", - "SYSC", 8, "SYSTEM/NON-SYSTEM CARTRIDGE INDR", - "JBSW", 9, "JOBT SWITCH", - "CBSW", 10, "CLB-RETURN SWITCH", - "LCNT", 11, "NO. OF LOCALS", - "MPSW", 12, "CORE MAP SWITCH", - "MDF1", 13, "NO. DUP CTRL RECORDS (MODIF)", - "MDF2", 14, "ADDR OF MODIF BUFFER", - "NCNT", 15, "NO. OF NOCALS", - "ENTY", 16, "RLTV ENTRY ADDR OF PROGRAM", - "RP67", 17, "1442-5 SWITCH", - "TODR", 18, "OBJECT WORK STORAGE DRIVE CODE", - "FHOL", 20, "ADDR LARGEST HOLE IN FIXED AREA", - "FSZE", 21, "BLK CNT LARGEST HOLE IN FXA", - "UHOL", 22, "ADDR LAST HOLE IN USER AREA", - "USZE", 23, "BLK CNT LAST HOLE IN UA", - "DCSW", 24, "DUP CALL SWITCH", - "PIOD", 25, "PRINCIPAL I/O DEVICE INDICATOR", - "PPTR", 26, "PRINCIPAL PRINT DEVICE INDICATOR", - "CIAD", 27, "RLTV ADDR IN @STRT OF CIL ADDR", - "ACIN", 28, "AVAILABLE CARTRIDGE INDICATOR", - "GRPH", 29, "2250 INDICATOR", - "GCNT", 30, "NO. G2250 RECORDS", - "LOSW", 31, "LOCAL-CALLS-LOCAL SWITCH", - "X3SW", 32, "SPECIAL ILS SWITCH", - "ECNT", 33, "NO. OF *EQUAT RCDS", - "ANDU", 35, "1+BLK ADDR END OF UA (ADJUSTED)", - "BNDU", 40, "1+BLK ADDR END OF UA (BASE)", - "FPAD", 45, "FILE PROTECT ADDR", - "PCID", 50, "CARTRIDGE ID, PHYSICAL DRIVE", - "CIDN", 55, "CARTRIDGE ID, LOGICAL DRIVE", - "CIBA", 60, "SCTR ADDR OF CIB", - "SCRA", 65, "SCTR ADDR OF SCRA", - "FMAT", 70, "FORMAT OF PROG IN WORKING STG", - "FLET", 75, "SCTR ADDR 1ST SCTR OF FLET", - "ULET", 80, "SCTR ADDR 1ST SCTR OF LET", - "WSCT", 85, "BLK CNT OF PROG IN WORKING STG", - "CSHN", 90, "NO. SCTRS IN CUSHION AREA", - NULL -}; - -void dump_dcom (void) -{ - struct tag_dcominfo *d; - char txt[50]; - - showmajor("Sector 1 - DCOM"); - getsector(1, dcom); - - for (d = dcominfo; d->nm != NULL; d++) { - sprintf(txt, "%-4.4s %s", d->nm, d->descr); - pbf(txt, dcom+d->offset, 1); - } -} - -void dump_resmon (void) -{ - showmajor("Sector 2 - Resident Image"); - getsector(2, buf); - dump(verbose ? SECLEN : 32); -} - -struct { - int pfrom, pto; - int printed; - char *name; -} sletinfo[] = { - 0x01, 0x12, FALSE, "DUP", - 0x1F, 0x39, FALSE, "Fortran", - 0x51, 0x5C, FALSE, "Cobol", - 0x6E, 0x74, FALSE, "Supervisor", - 0x78, 0x84, FALSE, "Core Load Builder", - 0x8C, 0x8C, FALSE, "Sys 1403 prt", - 0x8D, 0x8D, FALSE, "Sys 1132 prt", - 0x8E, 0x8E, FALSE, "Sys console prt", - 0x8F, 0x8F, FALSE, "Sys 2501 rdr", - 0x90, 0x90, FALSE, "Sys 1442 rdr/pun", - 0x91, 0x91, FALSE, "Sys 1134 paper tape", - 0x92, 0x92, FALSE, "Sys kbd", - 0x93, 0x93, FALSE, "Sys 2501/1442 conv", - 0x94, 0x94, FALSE, "Sys 1134 conv", - 0x95, 0x95, FALSE, "Sys kbd conv", - 0x96, 0x96, FALSE, "Sys diskz", - 0x97, 0x97, FALSE, "Sys disk1", - 0x98, 0x98, FALSE, "Sys diskn", - 0x99, 0x99, FALSE, "(primary print)", - 0x9A, 0x9A, FALSE, "(primary input)", - 0x9B, 0x9B, FALSE, "(primary input excl kbd)", - 0x9C, 0x9C, FALSE, "(primary sys conv)", - 0x9D, 0x9D, FALSE, "(primary conv excl kbd)", - 0xA0, 0xA1, FALSE, "Core Image Loader", - 0xB0, 0xCC, FALSE, "RPG", - 0xCD, 0xCE, FALSE, "Dup Part 2", - 0xCF, 0xF6, FALSE, "Macro Assembler", - 0 -}; - -void dump_slet (void) -{ - int i, j, iphase, nsecs, sec, max_sec = 0; - char sstr[16], *smark; - - showmajor("Sectors 3-5 - SLET"); - for (i = 0; i < 3; i++) { - getsector(3+i, buf); - memmove(((WORD *) slet)+SECLEN*i, buf, SECLEN*sizeof(WORD)); - } - - printf("# PHID Addr Len Sector Secs\n"); - printf("------------------------------------------\n"); - for (i = 0; i < SLETLEN; i++) { - if (slet[i].phid == 0) - break; - - sec = slet[i].sector; - iphase = (int) (signed short) slet[i].phid; - nsecs = (slet[i].nwords + SECLEN-1)/SECLEN; - - if (sec & 0xF800) { - smark = "*"; - sec &= 0x7FF; - } - else - smark = " "; - - for (j = 0; sletinfo[j].pfrom != 0; j++) - if (sletinfo[j].pfrom <= iphase && sletinfo[j].pto >= iphase) - break; - - sprintf(sstr, "(%d.%d)", sec / DSK_SECCYL, slet[i].sector % DSK_SECCYL); - - printf("%3d %04x %4d %04x %04x %04x %s %-7s %3x", - i, slet[i].phid, iphase, slet[i].addr, slet[i].nwords, slet[i].sector, smark, sstr, nsecs); - - if (iphase < 0) - iphase = -iphase; - - if (sletinfo[j].pfrom == 0) - printf(" ???"); - else if (! sletinfo[j].printed) { - printf(" %s", sletinfo[j].name); - sletinfo[j].printed = TRUE; - } - - for (j = 0; j < i; j++) { - if (sec == (slet[j].sector & 0x7FF)) { - printf(" (same as %04x)", slet[j].phid); - break; - } - } - - max_sec = MAX(max_sec, sec+nsecs-1); // find last sector used - - putchar('\n'); - - if (i >= 15 && ! verbose) { - printf("...\n"); - break; - } - } -} - -int ascii_to_ebcdic_table[128] = -{ - 0x00,0x01,0x02,0x03,0x37,0x2d,0x2e,0x2f, 0x16,0x05,0x25,0x0b,0x0c,0x0d,0x0e,0x0f, - 0x10,0x11,0x12,0x13,0x3c,0x3d,0x32,0x26, 0x18,0x19,0x3f,0x27,0x1c,0x1d,0x1e,0x1f, - 0x40,0x5a,0x7f,0x7b,0x5b,0x6c,0x50,0x7d, 0x4d,0x5d,0x5c,0x4e,0x6b,0x60,0x4b,0x61, - 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7, 0xf8,0xf9,0x7a,0x5e,0x4c,0x7e,0x6e,0x6f, - - 0x7c,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7, 0xc8,0xc9,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6, - 0xd7,0xd8,0xd9,0xe2,0xe3,0xe4,0xe5,0xe6, 0xe7,0xe8,0xe9,0xba,0xe0,0xbb,0xb0,0x6d, - 0x79,0x81,0x82,0x83,0x84,0x85,0x86,0x87, 0x88,0x89,0x91,0x92,0x93,0x94,0x95,0x96, - 0x97,0x98,0x99,0xa2,0xa3,0xa4,0xa5,0xa6, 0xa7,0xa8,0xa9,0xc0,0x4f,0xd0,0xa1,0x07, -}; - -int ebcdic_to_ascii (int ch) -{ - int j; - - for (j = 32; j < 128; j++) - if (ascii_to_ebcdic_table[j] == ch) - return j; - - return '?'; -} - -#define HDR_LEN 120 - -void dump_hdng(void) -{ - int i; - char str[HDR_LEN+1], *p = str; - - showmajor("Sector 7 - Heading"); - getsector(7, buf); - - for (i = 0; i < (HDR_LEN/2); i++) { - *p++ = ebcdic_to_ascii((buf[i] >> 8) & 0xFF); - *p++ = ebcdic_to_ascii( buf[i] & 0xFF); - } - - *p = '\0'; - trim(str); - printf("%s\n", str); -} - -BOOL mget (int offset, char *name) -{ - char title[80]; - - if (dcom[offset] == 0) - return FALSE; - - getsector(dcom[offset], buf); - sprintf(title, "Sector %x - %s", dcom[offset], name); - showmajor(title); - return TRUE; -} - -void dump_scra (void) -{ - if (! mget(SCRA, "SCRA")) - return; - - dump(verbose ? SECLEN : 32); -} - -void dump_let (void) -{ - if (! mget(ULET, "LET")) - return; -} - -void dump_flet (void) -{ - if (! mget(FLET, "FLET")) - return; -} - -void dump_cib (void) -{ - if (! mget(CIBA, "CIB")) - return; - - dump(verbose ? SECLEN : 32); -} - -#define LFHD 5 // WORD COUNT OF LET/FLET HEADER PMN09970 -#define LFEN 3 // NO OF WDS PER LET/FLET ENTRY PMN09980 -#define SCTN 0 // RLTY ADDR OF LET/FLET SCTR NO. PMN09990 -#define UAFX 1 // RLTV ADDR OF SCTR ADDR OF UA/FXA PMN10000 -#define WDSA 3 // RLTV ADDR OF WDS AVAIL IN SCTR PMN10010 -#define NEXT 4 // RLTV ADDR OF ADDR NEXT SCTR PMN10020 -#define LFNM 0 // RLTV ADDR OF LET/FLET ENTRY NAME PMN10030 -#define BLCT 2 // RLTV ADDR OF LET/FLET ENTRY DBCT PMN10040 - -void bail (char *fmt, ...) -{ - va_list args; - - va_start(args, fmt); - fprintf(stderr, fmt, args); - va_end(args); - putchar('\n'); - - exit(1); -} - -// --------------------------------------------------------------------------------- -// trim - remove trailing whitespace from string s -// --------------------------------------------------------------------------------- - -char *trim (char *s) -{ - char *os = s, *nb; - - for (nb = s-1; *s; s++) - if (*s > ' ') - nb = s; - - nb[1] = '\0'; - return os; -} - -/* ------------------------------------------------------------------------ - * lowcase - force a string to lowercase (ASCII) - * ------------------------------------------------------------------------ */ - -char *lowcase (char *str) -{ - char *s; - - for (s = str; *s; s++) { - if (*s >= 'A' && *s <= 'Z') - *s += 32; - } - - return str; -} - diff --git a/Ibm1130/utils/diskview.mak b/Ibm1130/utils/diskview.mak deleted file mode 100644 index ef9a8cf3..00000000 --- a/Ibm1130/utils/diskview.mak +++ /dev/null @@ -1,175 +0,0 @@ -# Microsoft Visual C++ Generated NMAKE File, Format Version 2.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Console Application" 0x0103 - -!IF "$(CFG)" == "" -CFG=Win32 Debug -!MESSAGE No configuration specified. Defaulting to Win32 Debug. -!ENDIF - -!IF "$(CFG)" != "Win32 Release" && "$(CFG)" != "Win32 Debug" -!MESSAGE Invalid configuration "$(CFG)" specified. -!MESSAGE You can specify a configuration when running NMAKE on this makefile -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "diskview.mak" CFG="Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "Win32 Release" (based on "Win32 (x86) Console Application") -!MESSAGE "Win32 Debug" (based on "Win32 (x86) Console Application") -!MESSAGE -!ERROR An invalid configuration is specified. -!ENDIF - -################################################################################ -# Begin Project -# PROP Target_Last_Scanned "Win32 Debug" -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "WinRel" -# PROP BASE Intermediate_Dir "WinRel" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "WinRel" -# PROP Intermediate_Dir "WinRel" -OUTDIR=.\WinRel -INTDIR=.\WinRel - -ALL : $(OUTDIR)/diskview.exe $(OUTDIR)/diskview.bsc - -$(OUTDIR) : - if not exist $(OUTDIR)/nul mkdir $(OUTDIR) - -# ADD BASE CPP /nologo /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /FR /c -# ADD CPP /nologo /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /FR /c -CPP_PROJ=/nologo /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE"\ - /FR$(INTDIR)/ /Fp$(OUTDIR)/"diskview.pch" /Fo$(INTDIR)/ /c -CPP_OBJS=.\WinRel/ -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -BSC32_FLAGS=/nologo /o$(OUTDIR)/"diskview.bsc" -BSC32_SBRS= \ - $(INTDIR)/diskview.sbr \ - $(INTDIR)/util_io.sbr - -$(OUTDIR)/diskview.bsc : $(OUTDIR) $(BSC32_SBRS) - $(BSC32) @<< - $(BSC32_FLAGS) $(BSC32_SBRS) -<< - -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NOLOGO /SUBSYSTEM:console /MACHINE:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib /NOLOGO /SUBSYSTEM:console /MACHINE:I386 -LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib /NOLOGO /SUBSYSTEM:console\ - /INCREMENTAL:no /PDB:$(OUTDIR)/"diskview.pdb" /MACHINE:I386\ - /OUT:$(OUTDIR)/"diskview.exe" -DEF_FILE= -LINK32_OBJS= \ - $(INTDIR)/diskview.obj \ - $(INTDIR)/util_io.obj - -$(OUTDIR)/diskview.exe : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS) - $(LINK32) @<< - $(LINK32_FLAGS) $(LINK32_OBJS) -<< - -!ELSEIF "$(CFG)" == "Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "WinDebug" -# PROP BASE Intermediate_Dir "WinDebug" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "WinDebug" -# PROP Intermediate_Dir "WinDebug" -OUTDIR=.\WinDebug -INTDIR=.\WinDebug - -ALL : $(OUTDIR)/diskview.exe $(OUTDIR)/diskview.bsc - -$(OUTDIR) : - if not exist $(OUTDIR)/nul mkdir $(OUTDIR) - -# ADD BASE CPP /nologo /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /FR /c -# ADD CPP /nologo /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /FR /c -CPP_PROJ=/nologo /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE"\ - /FR$(INTDIR)/ /Fp$(OUTDIR)/"diskview.pch" /Fo$(INTDIR)/\ - /Fd$(OUTDIR)/"diskview.pdb" /c -CPP_OBJS=.\WinDebug/ -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -BSC32_FLAGS=/nologo /o$(OUTDIR)/"diskview.bsc" -BSC32_SBRS= \ - $(INTDIR)/diskview.sbr \ - $(INTDIR)/util_io.sbr - -$(OUTDIR)/diskview.bsc : $(OUTDIR) $(BSC32_SBRS) - $(BSC32) @<< - $(BSC32_FLAGS) $(BSC32_SBRS) -<< - -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NOLOGO /SUBSYSTEM:console /DEBUG /MACHINE:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib /NOLOGO /SUBSYSTEM:console /DEBUG /MACHINE:I386 -LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib /NOLOGO /SUBSYSTEM:console\ - /INCREMENTAL:yes /PDB:$(OUTDIR)/"diskview.pdb" /DEBUG /MACHINE:I386\ - /OUT:$(OUTDIR)/"diskview.exe" -DEF_FILE= -LINK32_OBJS= \ - $(INTDIR)/diskview.obj \ - $(INTDIR)/util_io.obj - -$(OUTDIR)/diskview.exe : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS) - $(LINK32) @<< - $(LINK32_FLAGS) $(LINK32_OBJS) -<< - -!ENDIF - -.c{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -.cpp{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -.cxx{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -################################################################################ -# Begin Group "Source Files" - -################################################################################ -# Begin Source File - -SOURCE=.\diskview.c - -$(INTDIR)/diskview.obj : $(SOURCE) $(INTDIR) - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\util_io.c -DEP_UTIL_=\ - .\util_io.h - -$(INTDIR)/util_io.obj : $(SOURCE) $(DEP_UTIL_) $(INTDIR) - -# End Source File -# End Group -# End Project -################################################################################ diff --git a/Ibm1130/utils/mkboot.c b/Ibm1130/utils/mkboot.c deleted file mode 100644 index 115cdad4..00000000 --- a/Ibm1130/utils/mkboot.c +++ /dev/null @@ -1,705 +0,0 @@ -/* - * (C) Copyright 2002, Brian Knittel. - * You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN - * RISK basis, there is no warranty of fitness for any purpose, and the rest of the - * usual yada-yada. Please keep this notice and the copyright in any distributions - * or modifications. - * - * This is not a supported product, but I welcome bug reports and fixes. - * Mail to sim@ibm1130.org - */ - -// --------------------------------------------------------------------------------- -// MKBOOT - reads card loader format cards and produces an absolute core image that -// can then be dumped out in 1130 IPL, 1800 IPL or Core Image loader formats. -// -// Usage: mkboot [-v] binfile outfile [1130|1800|core [loaddr [hiaddr [ident]]]]" -// -// Arguments: -// binfile - name of assembler output file (card loader format, absolute output) -// outfile - name of output file to create -// mode - output mode, default is 1130 IPL format -// loaddr - low address to dump. Default is lowest address loaded from binfile -// hiaddr - high address to dump. Defult is highest address loaded from binfile -// ident - ident string to write in last 8 columns. Omit when when writing an -// 1130 IPL card that requires all 80 columns of data. -// -// Examples: -// mkboot somefile.bin somefile.ipl 1130 -// -// loads somefile.bin, writes object in 1130 IPL format to somefile.ipl -// Up to 80 columns will be written depending on what the object actually uses -// -// mkboot somefile.bin somefile.ipl 1130 0 48 SOMEF -// -// loads somefile.bin. Writes 72 columns (hex 48), with ident columns 73-80 = SOMEF001 -// -// mkboot somefile.bin somefile.dat core 0 0 SOMEF001 -// -// loads somefile.bin and writes a core image format deck with ident SOMEF001, SOMEF002, etc -// -// For other examples of usage, see MKDMS.BAT -// -// 1.00 - 2002Apr18 - first release. Tested only under Win32. The core image -// loader format is almost certainly wrong. Cannot handle -// relocatable input decks, but it works well enough to -// load DSYSLDR1 which is what we are after here. -// --------------------------------------------------------------------------------- - -#include -#include -#include -#include - -#ifndef TRUE - #define BOOL int - #define TRUE 1 - #define FALSE 0 -#endif - -#ifndef WIN32 - int strnicmp (char *a, char *b, int n); - int strcmpi (char *a, char *b); -#endif - -#define BETWEEN(v,a,b) (((v) >= (a)) && ((v) <= (b))) -#define MIN(a,b) (((a) <= (b)) ? (a) : (b)) -#define MAX(a,b) (((a) >= (b)) ? (a) : (b)) - -#define MAXADDR 4096 - -typedef enum {R_ABSOLUTE = 0, R_RELATIVE = 1, R_LIBF = 2, R_CALL = 3} RELOC; - -typedef enum {B_1130, B_1800, B_CORE} BOOTMODE; - -BOOL verbose = FALSE; -char *infile = NULL, *outfile = NULL; -BOOTMODE mode = B_1130; -int addr_from = 0, addr_to = 79; -int outcols = 0; // columns written in using card output -int maxiplcols = 80; -char cardid[9]; // characters used for IPL card ID -int pta = 0; -int load_low = 0x7FFFFFF; -int load_high = 0; -unsigned short mem[MAXADDR]; // small core! - -// mkboot - load a binary object deck into core and dump requested bytes as a boot card - -void bail (char *msg); -void verify_checksum(unsigned short *card); -char *upcase (char *str); -void unpack (unsigned short *card, unsigned short *buf); -void dump (char *fname); -void loaddata (char *fname); -void write_1130 (void); -void write_1800 (void); -void write_core (void); -void flushcard(void); -int ascii_to_hollerith (int ch); -void corecard_init (void); -void corecard_writecard (char *sbrk_text); -void corecard_writedata (void); -void corecard_flush (void); -void corecard_setorg (int neworg); -void corecard_writew (int word, RELOC relative); -void corecard_endcard (void); - -char *fname = NULL; -FILE *fout; - -int main (int argc, char **argv) -{ - char *arg; - static char usestr[] = "Usage: mkboot [-v] binfile outfile [1130|1800|core [loaddr [hiaddr [ident]]]]"; - int i, ano = 0, ok; - - for (i = 1; i < argc; i++) { - arg = argv[i]; - if (*arg == '-') { - arg++; - while (*arg) { - switch (*arg++) { - case 'v': - verbose = TRUE; - break; - default: - bail(usestr); - } - } - } - else { - switch (ano++) { - case 0: - infile = arg; - break; - - case 1: - outfile = arg; - break; - - case 2: - if (strcmp(arg, "1130") == 0) mode = B_1130; - else if (strcmp(arg, "1800") == 0) mode = B_1800; - else if (strcmpi(arg, "core") == 0) mode = B_CORE; - else bail(usestr); - break; - - case 3: - if (strnicmp(arg, "0x", 2) == 0) ok = sscanf(arg+2, "%x", &addr_from); - else if (arg[0] == '/') ok = sscanf(arg+1, "%x", &addr_from); - else ok = sscanf(arg, "%d", &addr_from); - if (ok != 1) bail(usestr); - break; - - case 4: - if (strnicmp(arg, "0x", 2) == 0) ok = sscanf(arg+2, "%x", &addr_to); - else if (arg[0] == '/') ok = sscanf(arg+1, "%x", &addr_to); - else ok = sscanf(arg, "%d", &addr_to); - if (ok != 1) bail(usestr); - break; - - case 5: - strncpy(cardid, arg, 9); - cardid[8] = '\0'; - upcase(cardid); - break; - - default: - bail(usestr); - } - } - } - - if (*cardid == '\0') - maxiplcols = (mode == B_1130) ? 80 : 72; - else { - while (strlen(cardid) < 8) - strcat(cardid, "0"); - maxiplcols = 72; - } - - loaddata(infile); - - if (mode == B_1800) - write_1800(); - else if (mode == B_CORE) - write_core(); - else - write_1130(); - - return 0; -} - -void write_1130 (void) -{ - int addr; - unsigned short word; - - if ((fout = fopen(outfile, "wb")) == NULL) { - perror(outfile); - exit(1); - } - - for (addr = addr_from; addr <= addr_to; addr++) { - if (outcols >= maxiplcols) - flushcard(); - - word = mem[addr]; - - // if F or L bits are set, or if high 2 bits of displacement are unequal, it's bad - if ((word & 0x0700) || ! (((word & 0x00C0) == 0) || ((word & 0x00C0) == 0x00C0))) - printf("Warning: word %04x @ %04x may not IPL properly\n", word & 0xFFFF, addr); - - word = ((word & 0xF800) >> 4) | (word & 0x7F); // convert to 1130 IPL format - - putc((word & 0x000F) << 4, fout); // write the 12 bits in little-endian binary AABBCC00 as CC00 AABB - putc((word & 0x0FF0) >> 4, fout); - outcols++; - } - flushcard(); - fclose(fout); -} - -void write_1800 (void) -{ - int addr; - unsigned short word; - - if ((fout = fopen(outfile, "wb")) == NULL) { - perror(outfile); - exit(1); - } - - for (addr = addr_from; addr <= addr_to; addr++) { - word = mem[addr]; - - if (outcols >= maxiplcols) - flushcard(); - - putc(0, fout); - putc(word & 0xFF, fout); // write the low 8 bits in little-endian binary - outcols++; - - putc(0, fout); - putc((word >> 8) & 0xFF, fout); // write the high 8 bits in little-endian binary - outcols++; - } - flushcard(); - fclose(fout); -} - -void write_core (void) -{ - int addr; - - if ((fout = fopen(outfile, "wb")) == NULL) { - perror(outfile); - exit(1); - } - - addr_from = load_low; - addr_to = load_high; - - maxiplcols = 72; - corecard_init(); - corecard_setorg(addr_from); - - for (addr = addr_from; addr <= addr_to; addr++) { - corecard_writew(mem[addr], 0); - } - - corecard_flush(); - corecard_endcard(); - fclose(fout); -} - -void flushcard (void) -{ - int i, hol, ndig; - char fmt[20], newdig[20]; - - if (outcols <= 0) - return; // nothing to flush - - while (outcols < maxiplcols) { // pad to required number of columns with blanks (no punches) - putc(0, fout); - putc(0, fout); - outcols++; - } - - if (*cardid) { // add label - for (i = 0; i < 8; i++) { // write label as specified - hol = ascii_to_hollerith(cardid[i] & 0x7F); - putc(hol & 0xFF, fout); - putc((hol >> 8) & 0xFF, fout); - } - - ndig = 0; // count trailing digits in the label - for (i = 8; --i >= 0; ndig++) - if (! isdigit(cardid[i])) - break; - - i++; // index of first digit in trailing sequence - - if (ndig > 0) { // if any, increment them - sprintf(fmt, "%%0%dd", ndig); // make, e.g. %03d - sprintf(newdig, fmt, atoi(cardid+i)+1); - newdig[ndig] = '\0'; // clip if necessary - strcpy(cardid+i, newdig); // replace for next card's sequence number - } - } - - outcols = 0; -} - -void show_data (unsigned short *buf) -{ - int i, n, jrel, rflag, nout, ch, reloc; - - n = buf[2] & 0x00FF; - - printf("%04x: ", buf[0]); - - jrel = 3; - nout = 0; - rflag = buf[jrel++]; - for (i = 0; i < n; i++) { - if (nout >= 8) { - rflag = buf[jrel++]; - putchar('\n'); - printf(" "); - nout = 0; - } - reloc = (rflag >> 14) & 0x03; - ch = (reloc == R_ABSOLUTE) ? ' ' : - (reloc == R_RELATIVE) ? 'R' : - (reloc == R_LIBF) ? 'L' : '@'; - - printf("%04x%c ", buf[9+i], ch); - rflag <<= 2; - nout++; - } - putchar('\n'); -} - -void loadcard (unsigned short *buf) -{ - int addr, n, i; - - addr = buf[0]; - n = buf[2] & 0x00FF; - - for (i = 0; i < n; i++) { - if (addr >= MAXADDR) - bail("Program doesn't fit into 4K"); - mem[addr] = buf[9+i]; - - load_low = MIN(addr, load_low); - load_high = MAX(addr, load_high); - addr++; - } -} - -void loaddata (char *fname) -{ - FILE *fp; - BOOL first = TRUE; - unsigned short card[80], buf[54], cardtype; - - if ((fp = fopen(fname, "rb")) == NULL) { - perror(fname); - exit(1); - } - - if (verbose) - printf("\n%s:\n", fname); - - while (fread(card, sizeof(card[0]), 80, fp) > 0) { - unpack(card, buf); - verify_checksum(card); - - cardtype = (buf[2] >> 8) & 0xFF; - - if (cardtype == 1 && ! first) { // sector break - if (verbose) - printf("*SBRK\n"); - continue; - } - else { - switch (cardtype) { - case 0x01: - if (verbose) - printf("*ABS\n"); - break; - case 0x02: - case 0x03: - case 0x04: - case 0x05: - case 0x06: - case 0x07: - bail("Data must be in absolute format"); - break; - - case 0x0F: - pta = buf[3]; // save program transfer address - if (verbose) - printf("*END\n"); - break; - - case 0x0A: - if (verbose) - show_data(buf); - loadcard(buf); - break; - default: - bail("Unexpected card type"); - } - } - first = FALSE; - } - - fclose(fp); -} - -void bail (char *msg) -{ - fprintf(stderr, "%s\n", msg); - exit(1); -} - -void unpack (unsigned short *card, unsigned short *buf) -{ - int i, j; - unsigned short wd1, wd2, wd3, wd4; - - for (i = j = 0; i < 54; i += 3, j += 4) { - wd1 = card[j]; - wd2 = card[j+1]; - wd3 = card[j+2]; - wd4 = card[j+3]; - - buf[i ] = (wd1 & 0xFFF0) | ((wd2 >> 12) & 0x000F); - buf[i+1] = ((wd2 << 4) & 0xFF00) | ((wd3 >> 8) & 0x00FF); - buf[i+2] = ((wd3 << 8) & 0xF000) | ((wd4 >> 4) & 0x0FFF); - } -} - -void verify_checksum (unsigned short *card) -{ -// unsigned short sum; - - if (card[1] == 0) // no checksum - return; - -// if (sum != card[1]) -// printf("Checksum %04x doesn't match card %04x\n", sum, card[1]); -} - -typedef struct { - int hollerith; - char ascii; -} CPCODE; - -static CPCODE cardcode_029[] = -{ - 0x0000, ' ', - 0x8000, '&', // + in 026 Fortran - 0x4000, '-', - 0x2000, '0', - 0x1000, '1', - 0x0800, '2', - 0x0400, '3', - 0x0200, '4', - 0x0100, '5', - 0x0080, '6', - 0x0040, '7', - 0x0020, '8', - 0x0010, '9', - 0x9000, 'A', - 0x8800, 'B', - 0x8400, 'C', - 0x8200, 'D', - 0x8100, 'E', - 0x8080, 'F', - 0x8040, 'G', - 0x8020, 'H', - 0x8010, 'I', - 0x5000, 'J', - 0x4800, 'K', - 0x4400, 'L', - 0x4200, 'M', - 0x4100, 'N', - 0x4080, 'O', - 0x4040, 'P', - 0x4020, 'Q', - 0x4010, 'R', - 0x3000, '/', - 0x2800, 'S', - 0x2400, 'T', - 0x2200, 'U', - 0x2100, 'V', - 0x2080, 'W', - 0x2040, 'X', - 0x2020, 'Y', - 0x2010, 'Z', - 0x0820, ':', - 0x0420, '#', // = in 026 Fortran - 0x0220, '@', // ' in 026 Fortran - 0x0120, '\'', - 0x00A0, '=', - 0x0060, '"', - 0x8820, 'c', // cent - 0x8420, '.', - 0x8220, '<', // ) in 026 Fortran - 0x8120, '(', - 0x80A0, '+', - 0x8060, '|', - 0x4820, '!', - 0x4420, '$', - 0x4220, '*', - 0x4120, ')', - 0x40A0, ';', - 0x4060, 'n', // not - 0x2820, 'x', // what? - 0x2420, ',', - 0x2220, '%', // ( in 026 Fortran - 0x2120, '_', - 0x20A0, '>', - 0x2060, '>', -}; - -int ascii_to_hollerith (int ch) -{ - int i; - - for (i = 0; i < sizeof(cardcode_029) / sizeof(CPCODE); i++) - if (cardcode_029[i].ascii == ch) - return cardcode_029[i].hollerith; - - return 0; -} - -// --------------------------------------------------------------------------------- -// corecard - routines to write IBM 1130 Card object format -// --------------------------------------------------------------------------------- - -unsigned short corecard[54]; // the 54 data words that can fit on a binary format card -int corecard_n = 0; // number of object words stored in corecard (0-45) -int corecard_seq = 1; // card output sequence number -int corecard_org = 0; // origin of current card-full -int corecard_maxaddr = 0; -BOOL corecard_first = TRUE; // TRUE when we're to write the program type card - -// corecard_init - prepare a new object data output card - -void corecard_init (void) -{ - memset(corecard, 0, sizeof(corecard)); // clear card data - corecard_n = 0; // no data - corecard[0] = corecard_org; // store load address - corecard_maxaddr = MAX(corecard_maxaddr, corecard_org-1); // save highest address written-to (this may be a BSS) -} - -// binard_writecard - emit a card. sbrk_text = NULL for normal data cards, points to comment text for sbrk card - -void corecard_writecard (char *sbrk_text) -{ - unsigned short binout[80]; - int i, j; - - for (i = j = 0; i < 54; i += 3, j += 4) { - binout[j ] = ( corecard[i] & 0xFFF0); - binout[j+1] = ((corecard[i] << 12) & 0xF000) | ((corecard[i+1] >> 4) & 0x0FF0); - binout[j+2] = ((corecard[i+1] << 8) & 0xFF00) | ((corecard[i+2] >> 8) & 0x00F0); - binout[j+3] = ((corecard[i+2] << 4) & 0xFFF0); - } - - for (i = 0; i < 72; i++) { - putc(binout[i] & 0xFF, fout); - putc((binout[i] >> 8) & 0xFF, fout); - } - - outcols = 72; // add the ident - flushcard(); -} - -// binard_writedata - emit an object data card - -void corecard_writedata (void) -{ - corecard[1] = 0; // checksum - corecard[2] = 0x0000 | corecard_n; // data card type + word count - corecard_writecard(FALSE); // emit the card -} - -// corecard_flush - flush any pending binary data - -void corecard_flush (void) -{ - if (corecard_n > 0) - corecard_writedata(); - - corecard_init(); -} - -// corecard_setorg - set the origin - -void corecard_setorg (int neworg) -{ - corecard_org = neworg; // set origin for next card - corecard_flush(); // flush any current data & store origin -} - -// corecard_writew - write a word to the current output card. - -void corecard_writew (int word, RELOC relative) -{ - if (corecard_n >= 50) // flush full card buffer (must be even) - corecard_flush(); - - corecard[3+corecard_n++] = word; - corecard_org++; -} - -// corecard_endcard - write end of program card - -void corecard_endcard (void) -{ - corecard_flush(); - - corecard[0] = 0; // effective length: add 1 to max origin, then 1 more to round up - corecard[1] = 0; - corecard[2] = 0x8000; // they look for negative bit but all else must be zero - corecard[52] = 0xabcd; // index register 3 value, this is for fun - corecard[53] = pta; // hmmm - - corecard_writecard(NULL); -} - -/* ------------------------------------------------------------------------ - * upcase - force a string to uppercase (ASCII) - * ------------------------------------------------------------------------ */ - -char *upcase (char *str) -{ - char *s; - - for (s = str; *s; s++) { - if (*s >= 'a' && *s <= 'z') - *s -= 32; - } - - return str; -} - -#ifndef WIN32 - -int strnicmp (char *a, char *b, int n) -{ - int ca, cb; - - for (;;) { - if (--n < 0) // still equal after n characters? quit now - return 0; - - if ((ca = *a) == 0) // get character, stop on null terminator - return *b ? -1 : 0; - - if (ca >= 'a' && ca <= 'z') // fold lowercase to uppercase - ca -= 32; - - cb = *b; - if (cb >= 'a' && cb <= 'z') - cb -= 32; - - if ((ca -= cb) != 0) // if different, return comparison - return ca; - - a++, b++; - } -} - -int strcmpi (char *a, char *b) -{ - int ca, cb; - - for (;;) { - if ((ca = *a) == 0) // get character, stop on null terminator - return *b ? -1 : 0; - - if (ca >= 'a' && ca <= 'z') // fold lowercase to uppercase - ca -= 32; - - cb = *b; - if (cb >= 'a' && cb <= 'z') - cb -= 32; - - if ((ca -= cb) != 0) // if different, return comparison - return ca; - - a++, b++; - } -} - -#endif diff --git a/Ibm1130/utils/mkboot.mak b/Ibm1130/utils/mkboot.mak deleted file mode 100644 index a7a784d1..00000000 --- a/Ibm1130/utils/mkboot.mak +++ /dev/null @@ -1,161 +0,0 @@ -# Microsoft Visual C++ Generated NMAKE File, Format Version 2.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Console Application" 0x0103 - -!IF "$(CFG)" == "" -CFG=Win32 Debug -!MESSAGE No configuration specified. Defaulting to Win32 Debug. -!ENDIF - -!IF "$(CFG)" != "Win32 Release" && "$(CFG)" != "Win32 Debug" -!MESSAGE Invalid configuration "$(CFG)" specified. -!MESSAGE You can specify a configuration when running NMAKE on this makefile -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "mkboot.mak" CFG="Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "Win32 Release" (based on "Win32 (x86) Console Application") -!MESSAGE "Win32 Debug" (based on "Win32 (x86) Console Application") -!MESSAGE -!ERROR An invalid configuration is specified. -!ENDIF - -################################################################################ -# Begin Project -# PROP Target_Last_Scanned "Win32 Debug" -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "WinRel" -# PROP BASE Intermediate_Dir "WinRel" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "WinRel" -# PROP Intermediate_Dir "WinRel" -OUTDIR=.\WinRel -INTDIR=.\WinRel - -ALL : $(OUTDIR)/mkboot.exe $(OUTDIR)/mkboot.bsc - -$(OUTDIR) : - if not exist $(OUTDIR)/nul mkdir $(OUTDIR) - -# ADD BASE CPP /nologo /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /FR /c -# ADD CPP /nologo /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /FR /c -CPP_PROJ=/nologo /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE"\ - /FR$(INTDIR)/ /Fp$(OUTDIR)/"mkboot.pch" /Fo$(INTDIR)/ /c -CPP_OBJS=.\WinRel/ -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -BSC32_FLAGS=/nologo /o$(OUTDIR)/"mkboot.bsc" -BSC32_SBRS= \ - $(INTDIR)/mkboot.sbr - -$(OUTDIR)/mkboot.bsc : $(OUTDIR) $(BSC32_SBRS) - $(BSC32) @<< - $(BSC32_FLAGS) $(BSC32_SBRS) -<< - -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NOLOGO /SUBSYSTEM:console /MACHINE:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib /NOLOGO /SUBSYSTEM:console /MACHINE:I386 -LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib /NOLOGO /SUBSYSTEM:console\ - /INCREMENTAL:no /PDB:$(OUTDIR)/"mkboot.pdb" /MACHINE:I386\ - /OUT:$(OUTDIR)/"mkboot.exe" -DEF_FILE= -LINK32_OBJS= \ - $(INTDIR)/mkboot.obj - -$(OUTDIR)/mkboot.exe : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS) - $(LINK32) @<< - $(LINK32_FLAGS) $(LINK32_OBJS) -<< - -!ELSEIF "$(CFG)" == "Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "WinDebug" -# PROP BASE Intermediate_Dir "WinDebug" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "WinDebug" -# PROP Intermediate_Dir "WinDebug" -OUTDIR=.\WinDebug -INTDIR=.\WinDebug - -ALL : $(OUTDIR)/mkboot.exe $(OUTDIR)/mkboot.bsc - -$(OUTDIR) : - if not exist $(OUTDIR)/nul mkdir $(OUTDIR) - -# ADD BASE CPP /nologo /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /FR /c -# ADD CPP /nologo /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /FR /c -CPP_PROJ=/nologo /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE"\ - /FR$(INTDIR)/ /Fp$(OUTDIR)/"mkboot.pch" /Fo$(INTDIR)/ /Fd$(OUTDIR)/"mkboot.pdb"\ - /c -CPP_OBJS=.\WinDebug/ -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -BSC32_FLAGS=/nologo /o$(OUTDIR)/"mkboot.bsc" -BSC32_SBRS= \ - $(INTDIR)/mkboot.sbr - -$(OUTDIR)/mkboot.bsc : $(OUTDIR) $(BSC32_SBRS) - $(BSC32) @<< - $(BSC32_FLAGS) $(BSC32_SBRS) -<< - -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NOLOGO /SUBSYSTEM:console /DEBUG /MACHINE:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib /NOLOGO /SUBSYSTEM:console /DEBUG /MACHINE:I386 -LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib /NOLOGO /SUBSYSTEM:console\ - /INCREMENTAL:yes /PDB:$(OUTDIR)/"mkboot.pdb" /DEBUG /MACHINE:I386\ - /OUT:$(OUTDIR)/"mkboot.exe" -DEF_FILE= -LINK32_OBJS= \ - $(INTDIR)/mkboot.obj - -$(OUTDIR)/mkboot.exe : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS) - $(LINK32) @<< - $(LINK32_FLAGS) $(LINK32_OBJS) -<< - -!ENDIF - -.c{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -.cpp{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -.cxx{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -################################################################################ -# Begin Group "Source Files" - -################################################################################ -# Begin Source File - -SOURCE=.\mkboot.c - -$(INTDIR)/mkboot.obj : $(SOURCE) $(INTDIR) - -# End Source File -# End Group -# End Project -################################################################################ diff --git a/Ibm1130/utils/viewdeck.c b/Ibm1130/utils/viewdeck.c deleted file mode 100644 index 1bbcc30d..00000000 --- a/Ibm1130/utils/viewdeck.c +++ /dev/null @@ -1,242 +0,0 @@ -/* Simple program to display a binary card-image file in ASCII. - * We assume the deck was written with one card per 16-bit word, left-justified, - * and written in PC little-endian order - * - * (C) Copyright 2002, Brian Knittel. - * You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN - * RISK basis, there is no warranty of fitness for any purpose, and the rest of the - * usual yada-yada. Please keep this notice and the copyright in any distributions - * or modifications. - * - * This is not a supported product, but I welcome bug reports and fixes. - * Mail to sim@ibm1130.org - */ - -#include -#include - -#define TRUE 1 -#define FALSE 0 -typedef int BOOL; - -int hollerith_to_ascii (unsigned short h); -void bail (char *msg); -void format_coldstart (unsigned short *buf); - -int main (int argc, char **argv) -{ - FILE *fd; - char *fname = NULL, line[82], *arg; - BOOL coldstart = FALSE; - unsigned short buf[80]; - int i, lastnb; - static char usestr[] = - "Usage: viewdeck [-c] deckfile\n" - "\n" - "-c: convert cold start card to 16-bit format as a C array initializer\n"; - - for (i = 1; i < argc; i++) { // process command line arguments - arg = argv[i]; - - if (*arg == '-') { - arg++; - while (*arg) { - switch (*arg++) { - case 'c': - coldstart = TRUE; - break; - default: - bail(usestr); - } - } - } - else if (fname == NULL) // first non-switch arg is file name - fname = arg; - else - bail(usestr); // there can be only one name - } - - if (fname == NULL) // there must be a name - bail(usestr); - - if ((fd = fopen(fname, "rb")) == NULL) { - perror(fname); - return 1; - } - - while (fread(buf, sizeof(short), 80, fd) == 80) { - if (coldstart) { - format_coldstart(buf); - break; - } - - lastnb = -1; - for (i = 0; i < 80; i++) { - line[i] = hollerith_to_ascii(buf[i]); - if (line[i] > ' ') - lastnb = i; - } - line[++lastnb] = '\n'; - line[++lastnb] = '\0'; - fputs(line, stdout); - } - - if (coldstart) { - if (fread(buf, sizeof(short), 1, fd) == 1) - bail("Coldstart deck has more than one card"); - } - - fclose(fd); - - return 0; -} - -void format_coldstart (unsigned short *buf) -{ - int i, nout = 0; - unsigned short word; - - for (i = 0; i < 80; i++) { - word = buf[i]; // expand 12-bit card data to 16-bit instruction - word = (word & 0xF800) | ((word & 0x0400) ? 0x00C0 : 0x0000) | ((word & 0x03F0) >> 4); - - if (nout >= 8) { - fputs(",\n", stdout); - nout = 0; - } - else if (i > 0) - fputs(", ", stdout); - - printf("0x%04x", word); - nout++; - } - - putchar('\n'); -} - -typedef struct { - unsigned short hollerith; - char ascii; -} CPCODE; - -static CPCODE cardcode_029[] = -{ - 0x0000, ' ', - 0x8000, '&', // + in 026 Fortran - 0x4000, '-', - 0x2000, '0', - 0x1000, '1', - 0x0800, '2', - 0x0400, '3', - 0x0200, '4', - 0x0100, '5', - 0x0080, '6', - 0x0040, '7', - 0x0020, '8', - 0x0010, '9', - 0x9000, 'A', - 0x8800, 'B', - 0x8400, 'C', - 0x8200, 'D', - 0x8100, 'E', - 0x8080, 'F', - 0x8040, 'G', - 0x8020, 'H', - 0x8010, 'I', - 0x5000, 'J', - 0x4800, 'K', - 0x4400, 'L', - 0x4200, 'M', - 0x4100, 'N', - 0x4080, 'O', - 0x4040, 'P', - 0x4020, 'Q', - 0x4010, 'R', - 0x3000, '/', - 0x2800, 'S', - 0x2400, 'T', - 0x2200, 'U', - 0x2100, 'V', - 0x2080, 'W', - 0x2040, 'X', - 0x2020, 'Y', - 0x2010, 'Z', - 0x0820, ':', - 0x0420, '#', // = in 026 Fortran - 0x0220, '@', // ' in 026 Fortran - 0x0120, '\'', - 0x00A0, '=', - 0x0060, '"', - 0x8820, '\xA2', // cent, in MS-DOS encoding - 0x8420, '.', - 0x8220, '<', // ) in 026 Fortran - 0x8120, '(', - 0x80A0, '+', - 0x8060, '|', - 0x4820, '!', - 0x4420, '$', - 0x4220, '*', - 0x4120, ')', - 0x40A0, ';', - 0x4060, '\xAC', // not, in MS-DOS encoding - 0x2420, ',', - 0x2220, '%', // ( in 026 Fortran - 0x2120, '_', - 0x20A0, '>', - 0xB000, 'a', - 0xA800, 'b', - 0xA400, 'c', - 0xA200, 'd', - 0xA100, 'e', - 0xA080, 'f', - 0xA040, 'g', - 0xA020, 'h', - 0xA010, 'i', - 0xD000, 'j', - 0xC800, 'k', - 0xC400, 'l', - 0xC200, 'm', - 0xC100, 'n', - 0xC080, 'o', - 0xC040, 'p', - 0xC020, 'q', - 0xC010, 'r', - 0x6800, 's', - 0x6400, 't', - 0x6200, 'u', - 0x6100, 'v', - 0x6080, 'w', - 0x6040, 'x', - 0x6020, 'y', - 0x6010, 'z', // these odd punch codes are used by APL: - 0x1010, '\001', // no corresponding ASCII using ^A - 0x0810, '\002', // SYN using ^B - 0x0410, '\003', // no corresponding ASCII using ^C - 0x0210, '\004', // PUNCH ON using ^D - 0x0110, '\005', // READER STOP using ^E - 0x0090, '\006', // UPPER CASE using ^F - 0x0050, '\013', // EOT using ^K - 0x0030, '\016', // no corresponding ASCII using ^N - 0x1030, '\017', // no corresponding ASCII using ^O - 0x0830, '\020', // no corresponding ASCII using ^P -}; - -int hollerith_to_ascii (unsigned short h) -{ - int i; - - h &= 0xFFF0; - - for (i = 0; i < sizeof(cardcode_029) / sizeof(CPCODE); i++) - if (cardcode_029[i].hollerith == h) - return cardcode_029[i].ascii; - - return '?'; -} - -void bail (char *msg) -{ - fprintf(stderr, "%s\n", msg); - exit(1); -} - diff --git a/Ibm1130/utils/viewdeck.mak b/Ibm1130/utils/viewdeck.mak deleted file mode 100644 index 37da412c..00000000 --- a/Ibm1130/utils/viewdeck.mak +++ /dev/null @@ -1,161 +0,0 @@ -# Microsoft Visual C++ Generated NMAKE File, Format Version 2.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Console Application" 0x0103 - -!IF "$(CFG)" == "" -CFG=Win32 Debug -!MESSAGE No configuration specified. Defaulting to Win32 Debug. -!ENDIF - -!IF "$(CFG)" != "Win32 Release" && "$(CFG)" != "Win32 Debug" -!MESSAGE Invalid configuration "$(CFG)" specified. -!MESSAGE You can specify a configuration when running NMAKE on this makefile -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "viewdeck.mak" CFG="Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "Win32 Release" (based on "Win32 (x86) Console Application") -!MESSAGE "Win32 Debug" (based on "Win32 (x86) Console Application") -!MESSAGE -!ERROR An invalid configuration is specified. -!ENDIF - -################################################################################ -# Begin Project -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "WinRel" -# PROP BASE Intermediate_Dir "WinRel" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "WinRel" -# PROP Intermediate_Dir "WinRel" -OUTDIR=.\WinRel -INTDIR=.\WinRel - -ALL : $(OUTDIR)/viewdeck.exe $(OUTDIR)/viewdeck.bsc - -$(OUTDIR) : - if not exist $(OUTDIR)/nul mkdir $(OUTDIR) - -# ADD BASE CPP /nologo /ML /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /FR /c -# ADD CPP /nologo /ML /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /FR /c -CPP_PROJ=/nologo /ML /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE"\ - /FR$(INTDIR)/ /Fp$(OUTDIR)/"viewdeck.pch" /Fo$(INTDIR)/ /c -CPP_OBJS=.\WinRel/ -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -BSC32_FLAGS=/nologo /o$(OUTDIR)/"viewdeck.bsc" -BSC32_SBRS= \ - $(INTDIR)/viewdeck.sbr - -$(OUTDIR)/viewdeck.bsc : $(OUTDIR) $(BSC32_SBRS) - $(BSC32) @<< - $(BSC32_FLAGS) $(BSC32_SBRS) -<< - -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NOLOGO /SUBSYSTEM:console /MACHINE:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib /NOLOGO /SUBSYSTEM:console /MACHINE:I386 -LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\ - advapi32.lib /NOLOGO /SUBSYSTEM:console /INCREMENTAL:no\ - /PDB:$(OUTDIR)/"viewdeck.pdb" /MACHINE:I386 /OUT:$(OUTDIR)/"viewdeck.exe" -DEF_FILE= -LINK32_OBJS= \ - $(INTDIR)/viewdeck.obj - -$(OUTDIR)/viewdeck.exe : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS) - $(LINK32) @<< - $(LINK32_FLAGS) $(LINK32_OBJS) -<< - -!ELSEIF "$(CFG)" == "Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "WinDebug" -# PROP BASE Intermediate_Dir "WinDebug" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "WinDebug" -# PROP Intermediate_Dir "WinDebug" -OUTDIR=.\WinDebug -INTDIR=.\WinDebug - -ALL : $(OUTDIR)/viewdeck.exe $(OUTDIR)/viewdeck.bsc - -$(OUTDIR) : - if not exist $(OUTDIR)/nul mkdir $(OUTDIR) - -# ADD BASE CPP /nologo /ML /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /FR /c -# ADD CPP /nologo /ML /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /FR /c -CPP_PROJ=/nologo /ML /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE"\ - /FR$(INTDIR)/ /Fp$(OUTDIR)/"viewdeck.pch" /Fo$(INTDIR)/\ - /Fd$(OUTDIR)/"viewdeck.pdb" /c -CPP_OBJS=.\WinDebug/ -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -BSC32_FLAGS=/nologo /o$(OUTDIR)/"viewdeck.bsc" -BSC32_SBRS= \ - $(INTDIR)/viewdeck.sbr - -$(OUTDIR)/viewdeck.bsc : $(OUTDIR) $(BSC32_SBRS) - $(BSC32) @<< - $(BSC32_FLAGS) $(BSC32_SBRS) -<< - -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NOLOGO /SUBSYSTEM:console /DEBUG /MACHINE:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib /NOLOGO /SUBSYSTEM:console /DEBUG /MACHINE:I386 -LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\ - advapi32.lib /NOLOGO /SUBSYSTEM:console /INCREMENTAL:yes\ - /PDB:$(OUTDIR)/"viewdeck.pdb" /DEBUG /MACHINE:I386\ - /OUT:$(OUTDIR)/"viewdeck.exe" -DEF_FILE= -LINK32_OBJS= \ - $(INTDIR)/viewdeck.obj - -$(OUTDIR)/viewdeck.exe : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS) - $(LINK32) @<< - $(LINK32_FLAGS) $(LINK32_OBJS) -<< - -!ENDIF - -.c{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -.cpp{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -.cxx{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -################################################################################ -# Begin Group "Source Files" - -################################################################################ -# Begin Source File - -SOURCE=.\viewdeck.c - -$(INTDIR)/viewdeck.obj : $(SOURCE) $(INTDIR) - -# End Source File -# End Group -# End Project -################################################################################ diff --git a/Interdata/id16_cpu.c b/Interdata/id16_cpu.c deleted file mode 100644 index 7f0eae34..00000000 --- a/Interdata/id16_cpu.c +++ /dev/null @@ -1,1720 +0,0 @@ -/* id16_cpu.c: Interdata 16b CPU simulator - - 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. - - 07-Feb-03 RMS Fixed bug in SETM, SETMR (found by Mark Pizzolato) - - 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 (R[r1]); /* 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; -uint32 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) -{ -uint32 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 deleted file mode 100644 index edbc9c0a..00000000 --- a/Interdata/id16_dboot.c +++ /dev/null @@ -1,352 +0,0 @@ -/* id16_dboot.c: Interdata 16b simulator disk bootstrap - - 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" - -#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 sw; - uint32 cap; - uint32 dtype; - uint32 offset; - uint32 adder; -}; - -static struct dboot_id dboot_tab[] = { - { "DP", 0, 2, 0x31, o_DP0, 0 }, - { "DP", SWMASK ('F'), 9, 0x32, o_DP0, o_DPF }, - { "DP", 0, 9, 0x33, o_DP0, 0 }, - { "DM", 0, 64, 0x35, o_ID0, 0 }, - { "DM", 0, 244, 0x36, o_ID0, 0 }, - { NULL } }; - -t_stat id_dboot (int32 u, DEVICE *dptr) -{ -extern DIB pt_dib, sch_dib; -extern uint32 PC; -extern int32 sim_switches; -uint32 i, typ, ctlno, off, add, 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; - add = dboot_tab[i].adder; - break; } } -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) + add); /* 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 deleted file mode 100644 index be300924..00000000 --- a/Interdata/id16_sys.c +++ /dev/null @@ -1,570 +0,0 @@ -/* 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. - - 27-Feb-03 RMS Added relative addressing support -*/ - -#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_bool cf); -t_stat parse_sym_m (char *cptr, t_addr addr, t_value *val, t_bool cf); -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, uptr == &cpu_unit); /* 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 - cf = true if decoding for CPU - 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, t_bool cf) -{ -uint32 i, j, k, inst, r1, r2, ea, 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; - fprintf (of, "%s ", opcode[i]); /* print opcode */ - switch (j) { /* case on class */ - case I_V_MR: /* mask-register */ - fprintf (of, "%-X,R%d", r1, r2); - return -1; - case I_V_RR: /* register-register */ - case I_V_FF: /* floating-floating */ - fprintf (of, "R%d,R%d", r1, r2); - return -1; - case I_V_SI: /* short immediate */ - fprintf (of, "R%d,%-X", r1, r2); - return -1; - case I_V_SB: /* short branch */ - fprintf (of, "%-X,", r1); - case I_V_SX: /* ext short branch */ - if (cf) fprintf (of, "%-X", ((inst & MSK_SBF)? - (addr + r2 + r2): (addr - r2 - r2))); - else fprintf (of, ((inst & MSK_SBF)? - ".+%-X": ".-%X"), r2 + r2); - return -1; - case I_V_R: /* register */ - fprintf (of, "R%d", r2); - return -1; - case I_V_MX: /* mask-memory */ - fprintf (of, "%-X,%-X", r1, ea); - break; - case I_V_RX: /* register-memory */ - case I_V_FX: /* floating-memory */ - fprintf (of, "R%d,%-X", r1, ea); - break; - case I_V_X: /* memory */ - fprintf (of, "%-X", 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; -} - -/* Address - - Inputs: - *cptr = pointer to input string - **tptr = pointer to moved pointer - *ea = effective address - *rel = relative flag - addr = base address - cf = true if parsing for CPU - Outputs: - status = SCPE_OK if ok, else error code -*/ - -t_stat get_addr (char *cptr, char **tptr, t_addr *ea, t_bool *rel, - t_addr addr, t_bool cf) -{ -int32 sign = 1; - -*ea = 0; -if (*cptr == '.') { /* relative? */ - *rel = TRUE; - cptr++; - if (cf) *ea = addr; - if (*cptr == '+') cptr++; /* .+? */ - else if (*cptr == '-') { /* .-? */ - sign = -1; - cptr++; } - else return SCPE_OK; } -else *rel = FALSE; -errno = 0; -*ea = *ea + (sign * ((int32) strtoul (cptr, tptr, 16))); -if (errno || (cptr == *tptr)) 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)? 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 */ - -r = parse_sym_m (cptr, addr, val, uptr == &cpu_unit); /* 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 - cf = true if parsing for CPU - Outputs: - status = > 0 error code - <= 0 -number of extra words -*/ - -t_stat parse_sym_m (char *cptr, t_addr addr, t_value *val, t_bool cf) -{ -uint32 i, j, k, t, df, db, inst, vp; -int32 st, r1, r2; -t_bool rel; -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 */ - r = get_addr (gbuf, &tptr, &t, &rel, addr, cf); /* get addr */ - if ((r != SCPE_OK) || (t > PAMASK16) || - (!cf && rel)) return SCPE_ARG; - 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 (t, 2); - return -3; - -case I_V_SB: case I_V_SX: /* short branches */ - r = get_addr (gbuf, &tptr, &t, &rel, addr, cf); /* get addr */ - if ((r != SCPE_OK) || (t & 1) || *tptr) /* error if odd */ - return SCPE_ARG; - st = t; /* signed version */ - if (cf) { /* for CPU? */ - 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 */ - else 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 */ - else return SCPE_ARG; } - else if (rel) { /* periph, must be rel */ - if ((st <= 0) && (st >= -0x1F) && /* relative back? */ - ((j == I_V_SX) || !(inst & MSK_SBF))) - inst = inst | ((-st & 0x1F) >> 1); - else if ((st >= 0) && (st < 0x1F) && /* relative fwd? */ - ((j == I_V_SX) || (inst & MSK_SBF))) - inst = inst | ((t & 0x1F) >> 1); - else return SCPE_ARG; } - else return SCPE_ARG; /* periph & ~rel, err */ - } /* end case */ - -PUTNUM (inst, 2); -return -1; -} diff --git a/Interdata/id32_cpu.c b/Interdata/id32_cpu.c deleted file mode 100644 index a0846485..00000000 --- a/Interdata/id32_cpu.c +++ /dev/null @@ -1,2028 +0,0 @@ -/* id32_cpu.c: Interdata 32b CPU simulator - - 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. - - 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], 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], 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, 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, 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, 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, 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, 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? */ - if ((loc & ~03) == MAC_STA) { /* MAC status? */ - val = mac_sta; /* read it */ - qevent = qevent & ~EV_MAC; } /* clr MAC intr */ - else val = M[loc >> 2]; } /* get mem word */ -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? */ - if ((loc & ~03) == MAC_STA) { /* MAC status? */ - val = mac_sta; /* read it */ - qevent = qevent & ~EV_MAC; } /* clr MAC intr */ - else val = M[loc >> 2]; } /* get mem word */ -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? */ - if ((loc & ~03) == MAC_STA) { /* MAC status? */ - val = mac_sta; /* read it */ - qevent = qevent & ~EV_MAC; } /* clr MAC intr */ - else val = M[loc >> 2]; } /* get mem word */ -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; - -val = val & DMASK32; -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; -} - -/* Change memory size */ - -t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -uint32 mc = 0; -uint32 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 deleted file mode 100644 index 69215974..00000000 --- a/Interdata/id32_dboot.c +++ /dev/null @@ -1,317 +0,0 @@ -/* id32_dboot.c: Interdata 32b simulator disk bootstrap - - 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. - - 17-Feb-03 RMS Fixed for UNIX bootstrap, upper platter bootstrap -*/ - -#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, 0x2b, - 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 sw; - uint32 cap; - uint32 dtype; - uint32 offset; - uint32 adder; -}; - -static struct dboot_id dboot_tab[] = { - { "DP", 0, 2, 0x31, o_DP0, 0 }, - { "DP", SWMASK ('F'), 9, 0x32, o_DP0, o_DPF }, - { "DP", 0, 9, 0x33, o_DP0, 0 }, - { "DM", 0, 64, 0x35, o_ID0, 0 }, - { "DM", 0, 244, 0x36, o_ID0, 0 }, - { NULL } }; - -t_stat id_dboot (int32 u, DEVICE *dptr) -{ -extern DIB ttp_dib, sch_dib; -extern uint32 PC; -extern int32 sim_switches; -uint32 i, typ, ctlno, off, add, 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].sw == 0) || (dboot_tab[i].sw & sim_switches)) && - (dboot_tab[i].cap == cap)) { - typ = dboot_tab[i].dtype; - off = dboot_tab[i].offset; - add = dboot_tab[i].adder; - break; } } -if (typ == 0) return SCPE_NOFNC; - -IOWriteBlk (DBOOT_BEG, DBOOT_LEN, dboot_rom); /* copy boot */ -IOWriteB (AL_DEV, ttp_dib.dno); /* bin input dev */ -IOWriteB (AL_IOC, 0xa3); -IOWriteB (AL_DSKU, ctlno + ((u + 1) * off) + add); /* disk dev addr */ -IOWriteB (AL_DSKT, typ); /* disk type */ -IOWriteB (AL_DSKC, ctlno); /* disk ctl addr */ -IOWriteB (AL_SCH, sch_dev); -PC = DBOOT_START; -return SCPE_OK; -} diff --git a/Interdata/id32_sys.c b/Interdata/id32_sys.c deleted file mode 100644 index 40ba1399..00000000 --- a/Interdata/id32_sys.c +++ /dev/null @@ -1,699 +0,0 @@ -/* 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. - - 15-Jul-03 RMS Fixed signed/unsigned bug in get_imm - 27-Feb-03 RMS Added relative addressing support - 23-Dec-01 RMS Cloned from ID4 sources -*/ - -#include "id_defs.h" -#include - -#define MSK_SBF 0x0100 -#define SEXT15(x) (((x) & 0x4000)? ((x) | ~0x3FFF): ((x) & 0x3FFF)) - -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_bool cf); -t_stat parse_sym_m (char *cptr, t_addr addr, t_value *val, t_bool cf); -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, t_bool cf) -{ -uint32 rx2; - -if ((ea1 & 0xC000) == 0) { /* RX1 */ - fprintf (of, "%-X", ea1); - if (rx) fprintf (of, "(R%d)", rx); - return -3; } -if (ea1 & 0x8000) { /* RX2 */ - if (cf) { /* for CPU? */ - ea1 = addr + 4 + SEXT15 (ea1); - fprintf (of, "%-X", ea1 & VAMASK32); } - else { /* for dev */ - int32 disp = SEXT15 (ea1); /* get disp */ - if (disp >= -4) fprintf (of, ".+%-X", disp + 4); - else fprintf (of, ".-%-X", -4 - disp); } - 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, uptr == &cpu_unit); /* 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 - cf = true if parsing for CPU - 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, t_bool cf) -{ -uint32 i, j, k, inst, r1, r2, ea1, ea2, 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; - fprintf (of, "%s ", opcode[i]); /* print opcode */ - switch (j) { /* case on class */ - case I_V_MR: /* mask-register */ - fprintf (of, "%-X,R%d", r1, r2); - return -1; - case I_V_RR: /* register-register */ - case I_V_FF: /* floating-floating */ - fprintf (of, "R%d,R%d", r1, r2); - return -1; - case I_V_SI: /* short immediate */ - fprintf (of, "R%d,%-X", r1, r2); - return -1; - case I_V_SB: /* short branch */ - fprintf (of, "%-X,", r1); - case I_V_SX: /* ext short branch */ - if (cf) fprintf (of, "%-X", ((inst & MSK_SBF)? - (addr + r2 + r2): (addr - r2 - r2))); - else fprintf (of, ((inst & MSK_SBF)? - ".+%-X": ".-%X"), r2 + r2); - return -1; - case I_V_R: /* register */ - fprintf (of, "R%d", r2); - return -1; - case I_V_RI: /* reg-immed */ - fprintf (of, "R%d,%-X", r1, ea1); - if (r2) fprintf (of, "(R%d)", r2); - return -3; - case I_V_RF: /* reg-full imm */ - fprintf (of, "R%d,%-X", r1, (ea1 << 16) | ea2); - if (r2) fprintf (of, "(R%d)", r2); - return -5; - case I_V_MX: /* mask-memory */ - fprintf (of, "%-X,", r1); - return fprint_addr (of, addr, r2, ea1, ea2, cf); - case I_V_RX: /* register-memory */ - case I_V_FX: /* floating-memory */ - fprintf (of, "R%d,", r1); - case I_V_X: /* memory */ - return fprint_addr (of, addr, r2, ea1, ea2, cf); } - 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; -int32 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; -} - -/* Address - - Inputs: - *cptr = pointer to input string - **tptr = pointer to moved pointer - *ea = effective address - *rel = relative flag - addr = base address - cf = true if parsing for CPU - Outputs: - status = SCPE_OK if ok, else error code -*/ - -t_stat get_addr (char *cptr, char **tptr, t_addr *ea, t_bool *rel, - t_addr addr, t_bool cf) -{ -int32 sign = 1; - -*ea = 0; -if (*cptr == '.') { /* relative? */ - *rel = TRUE; - cptr++; - if (cf) *ea = addr; - if (*cptr == '+') cptr++; /* .+? */ - else if (*cptr == '-') { /* .-? */ - sign = -1; - cptr++; } - else return SCPE_OK; } -else *rel = FALSE; -errno = 0; -*ea = *ea + (sign * ((int32) strtoul (cptr, tptr, 16))); -if (errno || (cptr == *tptr)) 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 */ - -r = parse_sym_m (cptr, addr, val, uptr == &cpu_unit); /* try to parse */ -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 - cf = true if parsing for CPU - Outputs: - status = > 0 error code - <= 0 -number of extra words -*/ - -t_stat parse_sym_m (char *cptr, t_addr addr, t_value *val, t_bool cf) -{ -uint32 i, j, k, df, db, t, inst, vp; -int32 st, r1, r2, rx2; -t_stat r; -t_bool rel; -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 */ - r = get_addr (gbuf, &tptr, &t, &rel, addr, cf); /* get addr */ - if (r != SCPE_OK) 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 (!cf && rel) { /* periph, rel */ - st = t - 4; /* displ */ - if (rx2 || (st > 0x3FFF) || (st < -0x4000)) /* rx2 or too big? */ - return SCPE_ARG; - t = (st & 0x7FFF) | 0x8000; - PUTNUM (t, 2); /* store displ */ - return -3; } - if (rx2 == 0) { /* no 2nd? */ - if (t < 0x4000) { /* RX1? */ - PUTNUM (t, 2); /* store ea */ - return -3; } - st = (t - (addr + 4)); /* displ */ - if (cf && (st <= 0x3FFF) && (st >= -0x4000)) { /* RX2? CPU only */ - t = (st & 0x7FFF) | 0x8000; - PUTNUM (t, 2); /* store displ */ - return -3; } } - t = (t & VAMASK32) | 0x40000000 | (rx2 << 24); - PUTNUM (t, 4); /* RX3 */ - return -5; - -case I_V_RI: /* 16b immediate */ - r = get_imm (gbuf, &t, &inst, DMASK16); /* process imm */ - if (r != SCPE_OK) return r; - PUTNUM (inst, 2); /* store inst */ - PUTNUM (t, 2); /* store 16b imm */ - return -3; - -case I_V_RF: - r = get_imm (gbuf, &t, &inst, DMASK32); /* process imm */ - if (r != SCPE_OK) return r; - PUTNUM (inst, 2); /* store inst */ - PUTNUM (t, 4); /* store 32b imm */ - return -5; - -case I_V_SB: case I_V_SX: /* short branches */ - r = get_addr (gbuf, &tptr, &t, &rel, addr, cf); /* get addr */ - if ((r != SCPE_OK) || (t & 1) || *tptr) /* error if odd */ - return SCPE_ARG; - st = t; /* signed version */ - if (cf) { /* for CPU? */ - 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 */ - else 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 */ - else return SCPE_ARG; } - else if (rel) { /* periph, must be rel */ - if ((st <= 0) && (st >= -0x1F) && /* relative back? */ - ((j == I_V_SX) || !(inst & MSK_SBF))) - inst = inst | ((-st & 0x1F) >> 1); - else if ((st >= 0) && (st < 0x1F) && /* relative fwd? */ - ((j == I_V_SX) || (inst & MSK_SBF))) - inst = inst | ((t & 0x1F) >> 1); - else return SCPE_ARG; } - else return SCPE_ARG; /* periph & ~rel, err */ - } /* end case */ - -PUTNUM (inst, 2); -return -1; -} diff --git a/Interdata/id_defs.h b/Interdata/id_defs.h deleted file mode 100644 index 6fd75068..00000000 --- a/Interdata/id_defs.h +++ /dev/null @@ -1,487 +0,0 @@ -/* id_defs.h: Interdata 16b/32b simulator definitions - - 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. - - The author gratefully acknowledges the help of Carl Friend and Al Kossow, - who provided key documents about the Interdata product line. - - 21-Jun-03 RMS Changed subroutine argument for ARM compiler conflict - 25-Apr-03 RMS Revised for extended file support - 28-Feb-03 RMS Changed magtape device default to 0x85 -*/ - -#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) (((uint32) (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 */ - uint32 cur; /* current addr */ - uint32 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_MT 0x85 /* magtape */ -#define o_MT0 0x10 -#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_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 armdis); -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 deleted file mode 100644 index ea84a188..00000000 --- a/Interdata/id_diag.txt +++ /dev/null @@ -1,907 +0,0 @@ -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> att -e pt0 diag.bin -sim> att mt foo.tap -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 - -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 -93. DP, IDC: write with cylinder overflow advanced selch pointer -94. MT: read error must stop selector channel (if active) - diff --git a/Interdata/id_doc.txt b/Interdata/id_doc.txt deleted file mode 100644 index 22ea0fa5..00000000 --- a/Interdata/id_doc.txt +++ /dev/null @@ -1,974 +0,0 @@ -To: Users -From: Bob Supnik -Subj: Interdata 16b/32b Simulator Usage -Date: 15-Jul-2003 - - COPYRIGHT NOTICE - -The following copyright notice applies to both the SIMH source and binary: - - 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"), - 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_tape.h - sim_tmxr.h - scp.c - scp_tty.c - sim_sock.c - sim_tape.c - sim_tmxr.c - -sim/interdata/ id_defs.h - id16_cpu.c [id32_cpu.c] - id16_dboot.c [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 [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 asynchronous 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 - 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 - -All the state for a selector channel can be displayed with the command: - - SHOW SELCH 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 7B. - -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 - - CMD 16 command register - STA 8 status register - 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) frequency can be adjusted as follows: - - SET LFC 60HZ set frequency to 60Hz - SET LFC 50HZ set frequency to 50Hz - -The default is 60Hz. - -The line frequency clock 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 - -The line frequency 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 an exact multiple of 1 msec, the -programmable clock auto-calibrates; if not, it 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 7b 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. The bootstrap normally boots from the first (removable) -platter in a 5440; to boot from the second (fixed) platter, use BOOT -F. - -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.8.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.8.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. Addresses, where required, can be -specified as either absolute numbers or relative to the current -location (.+n or .-n). - -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 deleted file mode 100644 index ea7ab2e3..00000000 --- a/Interdata/id_dp.c +++ /dev/null @@ -1,564 +0,0 @@ -/* id_dp.c: Interdata 2.5MB/10MB cartridge disk 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. - - dp M46-421 2.5MB/10MB cartridge disk - - 25-Apr-03 RMS Revised for extended file support - 16-Feb-03 RMS Fixed read to test transfer ok before selch operation -*/ - -#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]; -extern FILE *sim_log; - -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 */ -uint32 dp_log = 0; /* debug log */ -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, T_ADDR_W, 0, - DP_NUMDR, PV_LEFT | REG_HRO) }, - { FLDATA (LOG, dp_log, 0), REG_HIDDEN }, - { 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 (sim_log && dp_log) fprintf (sim_log, - ">>DPC WD = %02X, STA = %02X\n", dat, dp_sta); - 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 */ - if (sim_log && dp_log) fprintf (sim_log, - ">>DPC OC = %02X, STA = %02X\n", dat, dp_sta); - 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 (sim_log && dp_log) fprintf (sim_log, - ">>DP%d WD = %02X, STA = %02X\n", u, dat, dp_sta); - 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 */ - if (sim_log && dp_log) fprintf (sim_log, - ">>DP%d OC = %02X, STA = %02X\n", u, dat, dp_sta); - 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? */ - if (dp_dter (uptr, dp_1st)) return SCPE_OK; /* check xfr err */ - dp_bptr = sch_rdmem (dp_dib.sch, dpxb, DP_NUMBY); /* read from mem */ - dp_db = dpxb[dp_bptr - 1]; /* last byte */ - 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? */ - if (dp_cyl == 0) uptr->CYL = 0; - else { - 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); /* attach unit */ -if (r != SCPE_OK) return r; /* error? */ -uptr->CYL = 0; -if ((uptr->flags & UNIT_AUTO) == 0) return SCPE_OK; /* autosize? */ -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 deleted file mode 100644 index a15b71e2..00000000 --- a/Interdata/id_fd.c +++ /dev/null @@ -1,479 +0,0 @@ -/* id_fd.c: Interdata floppy disk 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. - - 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, 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 deleted file mode 100644 index 24136f72..00000000 --- a/Interdata/id_fp.c +++ /dev/null @@ -1,471 +0,0 @@ -/* id_fp.c: Interdata floating point instructions - - 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. - - 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 deleted file mode 100644 index 97f40bb7..00000000 --- a/Interdata/id_idc.c +++ /dev/null @@ -1,693 +0,0 @@ -/* id_idc.c: Interdata MSM/IDC disk controller 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. - - idc MSM/IDC disk controller - - 25-Apr-03 RMS Revised for extended file support - 16-Feb-03 RMS Fixed read to test transfer ok before selch operation - - 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, T_ADDR_W, 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 */ - 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? */ - if (idc_dter (uptr, idc_1st)) return SCPE_OK; /* dte? done */ - idc_bptr = sch_rdmem (idc_dib.sch, idcxb, IDC_NUMBY); /* read mem */ - idc_db = idcxb[idc_bptr - 1]; /* last byte */ - 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); /* attach unit */ -if (r != SCPE_OK) return r; /* error? */ -uptr->CYL = 0; -if ((uptr->flags & UNIT_AUTO) == 0) return SCPE_OK; /* autosize? */ -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 deleted file mode 100644 index 88c7d25f..00000000 --- a/Interdata/id_io.c +++ /dev/null @@ -1,567 +0,0 @@ -/* id_io.c: Interdata CPU-independent I/O routines - - 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. - - 21-Jun-03 RMS Changed subroutine argument for ARM compiler conflict - - 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. - - 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_set_nchan (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat sch_show_reg (FILE *st, UNIT *uptr, int32 val, 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_set_nchan, NULL, &sch_reg[0] }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "0", NULL, - NULL, &sch_show_reg, NULL }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "1", NULL, - NULL, &sch_show_reg, NULL }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, 2, "2", NULL, - NULL, &sch_show_reg, NULL }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, 3, "3", NULL, - NULL, &sch_show_reg, NULL }, - { 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_set_nchan (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; -} - -/* Show channel registers */ - -t_stat sch_show_reg (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -if (val < 0) return SCPE_IERR; -if (val >= (int32) sch_max) fprintf (st, "Channel %d disabled\n", val); -else { fprintf (st, "SA: %05X\n", sch_sa[val]); - fprintf (st, "EA: %05X\n", sch_ea[val]); - fprintf (st, "CMD: %02X\n", sch_cmd[val]); - fprintf (st, "DEV: %02X\n", sch_sdv[val]); - fprintf (st, "RDP: %X\n", sch_rdp[val]); - fprintf (st, "WDC: %X\n", sch_wdc[val]); } -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 armdis) -{ -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 armdis; -} - -/* 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 deleted file mode 100644 index da118ebf..00000000 --- a/Interdata/id_lp.c +++ /dev/null @@ -1,290 +0,0 @@ -/* id_lp.c: Interdata line printer - - 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. - - lpt M46-206 line printer - - 25-Apr-03 RMS Revised for extended file support -*/ - -#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, T_ADDR_W), 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 deleted file mode 100644 index 61d671f7..00000000 --- a/Interdata/id_mt.c +++ /dev/null @@ -1,482 +0,0 @@ -/* id_mt.c: Interdata magnetic tape 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. - - mt M46-494 dual density 9-track magtape controller - - 25-Apr-03 RMS Revised for extended file support - 28-Mar-03 RMS Added multiformat support - 28-Feb-03 RMS Revised for magtape library - 20-Feb-03 RMS Fixed read to stop selch on error - - 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" -#include "sim_tape.h" - -#define UST u3 /* unit status */ -#define UCMD u4 /* unit command */ -#define MT_MAXFR (1 << 16) /* max transfer */ - -/* 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_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); -t_stat mt_map_err (UNIT *uptr, t_stat st); - -/* 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, T_ADDR_W, 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[] = { - { MTUF_WLK, 0, "write enabled", "WRITEENABLED", NULL }, - { MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL }, - { MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT", - &sim_tape_set_fmt, &sim_tape_show_fmt, 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 */ - sim_tape_wrp (uptr))) 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; -int32 u = uptr - mt_dev.units; -uint32 dev = mt_dib.dno + (u * o_MT0); -t_mtrlnt tbc; -t_stat st, r = SCPE_OK; - -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 */ - sim_tape_rewind (uptr); /* reposition */ - uptr->UCMD = 0; /* clr cmd */ - 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? */ - st = sim_tape_rdrecf (uptr, mtxb, &tbc, MT_MAXFR); /* read rec */ - if (st == MTSE_RECE) mt_sta = mt_sta | STA_ERR; /* rec in err? */ - else if (st != SCPE_OK) { /* other error? */ - r = mt_map_err (uptr, st); /* map error */ - if (sch_actv (mt_dib.sch, dev)) /* if sch, stop */ - sch_stop (mt_dib.sch); - break; } - mt_blnt = tbc; /* set buf lnt */ - } - - 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? */ - if (st = sim_tape_wrrecf (uptr, mtxb, mt_bptr)) /* write, err? */ - r = mt_map_err (uptr, st); } /* map error */ - break; /* record done */ - -/* Unit service, continued */ - -case MTC_WEOF: /* write eof */ - if (st = sim_tape_wrtmk (uptr)) /* write tmk, err? */ - r = mt_map_err (uptr, st); /* map error */ - 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 ((st = sim_tape_sprecf (uptr, &tbc)) == MTSE_OK) ; - if (st == MTSE_TMK) { /* stopped by tmk? */ - mt_sta = mt_sta | STA_EOF; /* set eof */ - if (mt_arm[u]) SET_INT (v_MT + u); } /* set intr */ - else r = mt_map_err (uptr, st); /* map error */ - break; - -case MTC_SKFR: /* skip file rev */ - while ((st = sim_tape_sprecr (uptr, &tbc)) == MTSE_OK) ; - if (st == MTSE_TMK) { /* stopped by tmk? */ - mt_sta = mt_sta | STA_EOF; /* set eof */ - if (mt_arm[u]) SET_INT (v_MT + u); } /* set intr */ - else r = mt_map_err (uptr, st); /* map error */ - break; - -case MTC_SPCR: /* backspace */ - if (st = sim_tape_sprecr (uptr, &tbc)) /* skip rec rev, err? */ - r = mt_map_err (uptr, st); /* map error */ - break; } /* end case */ - -uptr->UCMD = uptr->UCMD | MTC_STOP1; /* set stop stage 1 */ -sim_activate (uptr, mt_rtime); /* schedule */ -return r; -} - -/* Map tape error status */ - -t_stat mt_map_err (UNIT *uptr, t_stat st) -{ -int32 u = uptr - mt_dev.units; - -switch (st) { -case MTSE_FMT: /* illegal fmt */ -case MTSE_UNATT: /* not attached */ - mt_sta = mt_sta | STA_ERR; -case MTSE_OK: /* no error */ - return SCPE_IERR; -case MTSE_TMK: /* end of file */ - mt_sta = mt_sta | STA_EOF; /* set eof */ - if (mt_arm[u]) SET_INT (v_MT + u); /* set intr */ - break; -case MTSE_IOERR: /* IO error */ - mt_sta = mt_sta | STA_ERR; /* set err */ - if (mt_stopioe) return SCPE_IOERR; - break; -case MTSE_INVRL: /* invalid rec lnt */ - mt_sta = mt_sta | STA_ERR; - return SCPE_MTRLNT; -case MTSE_WRP: /* write protect */ -case MTSE_RECE: /* record in error */ -case MTSE_EOM: /* end of medium */ - mt_sta = mt_sta | STA_ERR; /* set err */ - break; -case MTSE_BOT: /* reverse into BOT */ - uptr->UST = uptr->UST | STA_EOT; /* set err */ - break; } /* end switch */ -return SCPE_OK; -} - -/* 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; - sim_tape_reset (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 = sim_tape_attach (uptr, cptr); -if (r != SCPE_OK) return r; -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; - -r = sim_tape_detach (uptr); -if (r != SCPE_OK) return r; -if (mt_arm[u]) SET_INT (v_MT + u); -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? */ -sim_tape_rewind (&mt_unit[unitno]); /* 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 deleted file mode 100644 index 03591711..00000000 --- a/Interdata/id_pas.c +++ /dev/null @@ -1,548 +0,0 @@ -/* 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) - - 09-May-03 RMS Added network device flag - - 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_NET | 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 deleted file mode 100644 index 8a499e6a..00000000 --- a/Interdata/id_pt.c +++ /dev/null @@ -1,352 +0,0 @@ -/* id_pt.c: Interdata paper tape reader - - 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. - - pt paper tape reader and punch - - 25-Apr-03 RMS Revised for extended file support - 10-Apr-03 RMS Fixed type problem in ptr service (from Mark Pizzolato) -*/ - -#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, T_ADDR_W), 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, T_ADDR_W), 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) -{ -int32 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) -{ -uint32 i, lo, hi, 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 deleted file mode 100644 index 9c72778f..00000000 --- a/Interdata/id_tt.c +++ /dev/null @@ -1,260 +0,0 @@ -/* 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 - - 25-Apr-03 RMS Revised for extended file support - 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, T_ADDR_W), 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, T_ADDR_W), 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 deleted file mode 100644 index b2f2e857..00000000 --- a/Interdata/id_ttp.c +++ /dev/null @@ -1,265 +0,0 @@ -/* 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) - - 25-Apr-03 RMS Revised for extended file support -*/ - -#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, 0, 0), KBD_POLL_WAIT }, - { UDATA (&ttpo_svc, 0, 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, T_ADDR_W), 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, T_ADDR_W), 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 deleted file mode 100644 index 24dcd7cf..00000000 --- a/Interdata/id_uvc.c +++ /dev/null @@ -1,350 +0,0 @@ -/* id_uvc.c: Interdata universal clock - - 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. - - pic precision incremental clock - lfc line frequency clock - - 01-Mar-03 RMS Added SET/SHOW LFC FREQ support - Changed precision clock algorithm for V7 UNIX -*/ - -#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 */ -uint32 pic_decr = 1; /* decrement */ -uint16 pic_time[4] = { 1, 10, 100, 1000 }; /* delays */ -uint16 pic_usec[4] = { 1, 10, 100, 1000 }; /* usec per tick */ -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); -t_stat lfc_set_freq (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat lfc_show_freq (FILE *st, UNIT *uptr, int32 val, void *desc); - -/* 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) }, - { 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 }, - { DRDATA (SAVE, pic_save, 32), REG_HRO + PV_LEFT }, - { DRDATA (DECR, pic_decr, 16), REG_HRO + PV_LEFT }, - { FLDATA (MODE, pic_cnti, 0), REG_HRO }, - { 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), PV_LEFT + REG_HRO }, - { HRDATA (DEVNO, lfc_dib.dno, 8), REG_HRO }, - { NULL } }; - -MTAB lfc_mod[] = { - { MTAB_XTD|MTAB_VDV, 100, NULL, "50HZ", - &lfc_set_freq, NULL, NULL }, - { MTAB_XTD|MTAB_VDV, 120, NULL, "60HZ", - &lfc_set_freq, NULL, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "FREQUENCY", NULL, - NULL, &lfc_show_freq, NULL }, - { 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 = 0; /* one shot? */ -pic_cic = pic_cic - pic_decr; /* 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 eff rate < 1ms, or diagnostic mode, count instructions - If eff rate = 1ms, and not diagnostic mode, use timer -*/ - -void pic_sched (t_bool strt) -{ -int32 r, t, intv, intv_usec; - -pic_save = sim_grtime (); /* save start */ -r = pic_map[GET_RATE (pic_ric)]; /* get mapped rate */ -intv = pic_cic? pic_cic: 1; /* get cntr */ -intv_usec = intv * pic_usec[r]; /* cvt to usec */ -if (!(pic_unit.flags & UNIT_DIAG) && /* not diag? */ - ((intv_usec % 1000) == 0)) { /* 1ms multiple? */ - pic_cnti = 0; /* clr mode */ - pic_decr = pic_usec[3 - r]; /* set decrement */ - if (strt) t = sim_rtcn_init (pic_time[3], TMR_PIC); /* init or */ - else t = sim_rtcn_calb (PIC_TPS, TMR_PIC); } /* calibrate */ -else { pic_cnti = 1; /* set mode */ - pic_decr = 1; /* decr = 1 */ - t = pic_time[r] * intv; /* 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_decr = 1; -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; -} - -/* Set frequency */ - -t_stat lfc_set_freq (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -if (cptr) return SCPE_ARG; -if ((val != 100) && (val != 120)) return SCPE_IERR; -lfc_tps = val; -return SCPE_OK; -} - -/* Show frequency */ - -t_stat lfc_show_freq (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -fprintf (st, (lfc_tps == 100)? "50Hz": "60Hz"); -return SCPE_OK; -} - diff --git a/NOVA/eclipse.txt b/NOVA/eclipse.txt deleted file mode 100644 index 4cc9cf08..00000000 --- a/NOVA/eclipse.txt +++ /dev/null @@ -1,24 +0,0 @@ -Charles Owen's Eclipse Modules - -1. Eclipse CPU simulator - -The Eclipse CPU simulator can be used with the Nova definitions and peripheral -modules to produce an Eclipse simulator that will run Eclipse mapped RDOS V7.5. -The compilation procedure is the same as for the Nova simulator, except: - - - the symbol ECLIPSE must be defined - - the module eclipse_cpu.c must be substituted for nova_cpu.c - - the output should be named eclipse rather than nova - -For example, to compile under UNIX, move nova_cpu.c out of the source directory -and then give this command: - - % cc -DECLIPSE eclipse_cpu.c nova_*.c -o eclipse - -2. Alternate terminal emulator - -The module eclipse_tt.c can be used with either an Eclipse or Nova CPU simulator -in place of nova_tt.c. It provides a full emulation of the cursor controls on -the Dasher video terminal but requires that the underlying operating system -interpret VT100 cursor controls. Thus, it works under VMS or UNIX but not under -Windows or OS/2. \ No newline at end of file diff --git a/NOVA/eclipse_cpu.c b/NOVA/eclipse_cpu.c deleted file mode 100644 index 76ab2ead..00000000 --- a/NOVA/eclipse_cpu.c +++ /dev/null @@ -1,3382 +0,0 @@ -/* eclipse_cpu.c: Eclipse CPU simulator - - Modified from the original NOVA simulator by Robert Supnik. - - Copyright (c) 1998-2003, Charles E Owen - Portions 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 Eclipse central processor - - 28-Jan-02 RMS Cleaned up compiler warnings - 30-Nov-01 RMS Added extended SET/SHOW support - 01-Jun-01 RMS Added second terminal, plotter support - 26-Apr-01 RMS Added device enable/disable support - - The register state for the Eclipse CPU is basically the same as - the NOVA's: - - AC[0:3]<0:15> general registers - C carry flag - PC<0:14> program counter - - In addition, certain low-memory locations are reserved for special - purposes: - - 0: I/O Return Address (from an interrupt) - 1: I/O (Interrupt) handler address - 2: System Call handler address (used by SYC instruction) - 3: Protection Fault handler address - 4: VECTOR stack pointer (VCT Instruction) - 5: Current Interrupt Priority mask - 6: VECTOR stack limit (VCT instruction) - 7: VECTOR stack fault address (VCT again) - 10: Block Pointer (later models only) - 11: Emulation Trap Handler address (microeclipse only) - 20-27: Auto-increment locations (not on microeclipse) - 30-37: Auto-decrement locations (not on microeclipse) - 40: Stack pointer - 41: Frame Pointer - 42: Stack Limit - 43: Stack fault address - 44: XOP Origin address - 45: Floating point fault address - 46: Commercial fault address (not on microeclipse) - 47: Reserved, do not use. - - Note: While all eclipses share most of the "standard" features, - some models added a few quirks and wrinkles, and other models - dropped some features or modified others. Most DG software - is written for a "standard" Eclipse, and avoids these problem - areas. A general overview: - - [subject to major changes as info becomes available!] - - Early (e.g. S/100, S/200, C/300) [Front Panel machines] - - The first Eclipses had the basic MMPU, but certain parts - were kluged, and these were fixed in later MMPU designs. - This results in incompatibility, however. Also, early - CPUs had a feature called "Commercial Instruction Set" - which contained character manipulation, translation - between commercial-format numeric data and FPU formats, - and an elaborate EDIT instruction. Later models kept - only the character manipulation part of this and called - the feature the "Character Instruction Set", leading to - confusion because the initials of both are CIS. AFAIK, - DG dropped support for this MMPU and no version of RDOS - supported it past version 6, if even that. - - Middle (e.g. S/130, C/150, S/230, C/330) [Front Panel] - - These are close to a "Standard". They have the newer, - fixed MMPU. Support for the PIT (Programmed Interval - Timer. The Commercial (not character) instruction set - and FPU are optional. (CIS standard on C models) - - Late (C/350, M/600: [Panel]; S/140, S/280 [Virtual Console]) - - All features of the Middle period are included, plus: - These late Eclipses added a few MMPU wrinkles all their - own, included support for user maps C and D. Character - instruction set is standard, FPU optional. Also, support - for the BMC device. - - MicroEclipse-based (S/20, S/120, Desktops) [Virtual cons.] - - All features of the Late period, in general, plus: - Microeclipses dropped support for the auto increment - and decrement locations at 20-37. They also added - support for invalid instruction traps thru location 11. - The Desktops have an interface to the "Attached Processor", - an 8086, at device code 4. Also, some new CPU device - features to read states info. The Character Instruction - set and FPU are standard on all models. - - The Eclipse instruction set is an elaboration of the NOVA's. The basic - NOVA set is implemented in it's entireity, plus many new Eclipse - instructions are added. Since in theory every possible 16-bit - combination is a NOVA instruction, the Eclipse commands are carved - out of the NOVA set by using the Operate format with the no-load bit - set to 1 and the skip bits set to 000. Since this combination is - in effect a no-op on the NOVA, it was rarely or never used. The - other bits are used to form Eclipse instructions, which have no - other common format. To see the instructions, refer to the Eclipse - section of the instruction decode logic in sim_instr() below. All - Eclipse instructions are checked first, so in case of conflict in - bit patterns, the Eclipse one is executed over the corresponding - NOVA pattern. - - The following discussion talks about NOVA instructions which are - Eclipse instructions also. - - The NOVA has three instruction formats: memory reference, 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 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | 0| op | AC |in| mode| displacement | memory reference - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - <0:4> mnemonic action - - 00000 JMP PC = MA - 00001 JMS AC3 = PC, PC = MA - 00010 ISZ M[MA] = M[MA] + 1, skip if M[MA] == 0 - 00011 DSZ M[MA] = M[MA] - 1, skip if M[MA] == 0 - 001'n LDA ACn = M[MA] - 010'n STA M[MA] = ACn - - <5:7> mode action - - 000 page zero direct MA = zext (IR<8:15>) - 001 PC relative direct MA = PC + sext (IR<8:15>) - 010 AC2 relative direct MA = AC2 + sext (IR<8:15>) - 011 AC3 relative direct MA = AC3 + sext (IR<8:15>) - 100 page zero indirect MA = M[zext (IR<8:15>)] - 101 PC relative dinirect MA = M[PC + sext (IR<8:15>)] - 110 AC2 relative indirect MA = M[AC2 + sext (IR<8:15>)] - 111 AC3 relative indirect MA = M[AC3 + sext (IR<8:15>)] - - Memory reference instructions can access an address space of 32K words. - An instruction can directly reference the first 256 words of memory - (called page zero), as well as 256 words relative to the PC, AC2, or - AC3; it can indirectly access all 32K words. If an indirect address - is in locations 00020-00027, the indirect address is incremented and - rewritten to memory before use; if in 00030-00037, decremented and - rewritten. -*/ - -/* The I/O transfer format is: - - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | 0 1 1| AC | opcode |pulse| device | I/O transfer - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - The IOT instruction sends the opcode, pulse, and specified AC to the - specified I/O device. The device may accept data, provide data, - initiate or cancel operations, or skip on status. - - The operate format is: - - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | 1|srcAC|dstAC| opcode |shift|carry|nl| skip | operate - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - \______/ \___/ \___/ | | | | - | | | | | | +--- reverse skip sense - | | | | | +--- skip if C == 0 - | | | | +--- skip if result == 0 - | | | +--- don't load result - | | +--- carry in (load as is, - | | set to Zero, - | | set to One, - | | load Complement) - | +--- shift (none, - | left one, - | right one, - | byte swap) - +--- operation (complement, - negate, - move, - increment, - add complement, - subtract, - add, - and) - - The operate instruction can be microprogrammed to perform operations - on the source and destination AC's and the Carry flag. -*/ - -/* This routine is the instruction decode routine for the NOVA. - 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 - infinite indirection loop - unknown I/O device and STOP_DEV flag set - I/O error in I/O simulator - - 2. Interrupts. Interrupts are maintained by four parallel variables: - - dev_done device done flags - dev_disable device interrupt disable flags - dev_busy device busy flags - int_req interrupt requests - - In addition, int_req contains the interrupt enable and ION pending - flags. If ION and ION pending are set, and at least one interrupt - request is pending, then an interrupt occurs. Note that the 16b PIO - mask must be mapped to the simulator's device bit mapping. - - 3. Non-existent memory. On the NOVA, 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: - - eclipse_defs.h add interrupt request definition - eclipse_cpu.c add IOT mask, PI mask, and routine to dev_table - eclipse_sys.c add pointer to data structures to sim_devices -*/ - -/*--------------------------------------------------------------------------- -** ECLIPSE Debugging Facilities -** -** These options are designed to find hard-to-locate flaky bugs by -** providing special error checking and logging. -** -** All are controlled by depositing a value into the DEBUG register. -** A value of zero means no special debugging facilities are turned on. -** This is the default. Debugging invokes a performance hit! Use only -** when necessary. -** -** Debugging means logging information to a file, or to a buffer in -** memory from whence it can be dumped to a file. -** -** 1XXXXX = Log all instructions executed to file "trace.log". -** **CAUTION**: This means the CPU will run SLOWLY and -** the resulting trace.log file will be HUGE. We're talking -** about a megabyte for each 5 seconds or less of wall clock -** time, depending on the speed of your CPU. Note: In this -** mode, interrupts are logged when they are received also. -** -** Note: when detailed logging is off, the last 4096 or so -** instructions executed are saved in a memory buffer, and -** when the sim stops, the "dump" command can write this -** history information to the file "history.log". This only -** works if the DEBUG register is non-zero however, because -** of the performance hit even this recording makes. -** -** XXXXDD = Log all I/O instructions to or from device number -** DD. Log is written to "trace.log", regardless of the -** setting of the instruction trace flag (1XXXXX). If both -** are on, the device traces will be interpersed with the -** instruction traces -- very useful sometimes. -** -** XXX1DD = Device Break. Does a breakpoint in any I/O to -** device DD. Useful, say when a diagnostic gives an -** error message - a device break on 11 (TTO) will stop -** as soon as the error message appears, making the -** trace log much shorter to track back on. -** -** X4XXXX = When this bit is on, the sim will stop if it sees -** an invalid instruction. When DEBUG is zero, any such -** instruction is no-oped with no warning. When DEBUG is -** non-zero, but this bit is 0, a warning will be displayed -** but execution will continue. -** -** X2XXXX = LEF break. When A LEF instruction is executed in -** mapped user space, the sim does a breakpoint right after -** executing the instruction. -** -** Whenever the DEBUG register is non-zero, special error checking -** is enabled in the sim. This will stop the sim automatically -** when a likely error occurs, such as: -** -** 1. Any execution that reaches, or will reach, location 00000. -** 2. Any I/O to device 00 -** 3. An interrupt from device 00. -** 4. An invalid instruction (stop is optional) -** -** Of course, the standard BREAK register is available for breakpoints -** as in all the sims based on this standard. ---------------------------------------------------------------------------*/ - - -#include "nova_defs.h" - -#define UNIT_V_MICRO (UNIT_V_UF) /* Microeclipse? */ -#define UNIT_V_17B (UNIT_V_UF) /* 17 bit MAP */ -#define UNIT_V_MSIZE (UNIT_V_UF+1) /* dummy mask */ -#define UNIT_MICRO (1 << UNIT_V_MICRO) -#define UNIT_17B (1 << UNIT_V_17B) -#define UNIT_MSIZE (1 << UNIT_V_MSIZE) - -unsigned int16 M[MAXMEMSIZE] = { 0 }; /* memory */ -int32 AC[4] = { 0 }; /* accumulators */ -int32 C = 0; /* carry flag */ -int32 saved_PC = 0; /* program counter */ -int32 SR = 0; /* switch register */ -int32 dev_done = 0; /* device done flags */ -int32 dev_busy = 0; /* device busy flags */ -int32 dev_disable = 0; /* int disable flags */ -int32 iot_enb = -1; /* IOT enables */ -int32 int_req = 0; /* interrupt requests */ -int32 pimask = 0; /* priority int mask */ -int32 pwr_low = 0; /* power fail flag */ -int32 ind_max = 15; /* iadr nest limit */ -int32 stop_dev = 0; /* stop on ill dev */ -int32 old_PC = 0; /* previous PC */ -int32 model = 130; /* Model of Eclipse */ -int32 speed = 0; /* Delay for each instruction */ - -int32 XCT_mode = 0; /* 1 if XCT mode */ -int32 XCT_inst = 0; /* XCT instruction */ -int32 PPC = -1; - -struct ndev dev_table[64]; /* dispatch table */ - -/* Instruction history buffer */ - -#define HISTMAX 4096 - -int32 hnext = 0; /* # of current entry */ -int32 hwrap = 0; /* 1 if wrapped */ -int32 hmax = HISTMAX; /* Maximum entries b4 wrap */ -unsigned int16 hpc[HISTMAX]; -unsigned int16 hinst[HISTMAX]; -unsigned int16 hinst2[HISTMAX]; -unsigned int16 hac0[HISTMAX]; -unsigned int16 hac1[HISTMAX]; -unsigned int16 hac2[HISTMAX]; -unsigned int16 hac3[HISTMAX]; -unsigned short hflags[HISTMAX]; - -/* Flags: 0x01 - carry bit - 0x02 - int enabled - 0x04 - user map a - 0x08 - user map b - 0x10 - user map c - 0x20 - user map d - 0x80 - this is an int, not an inst. - hpc is return addr - hinst is int_req - hac0 is device - hac1 is int addr -*/ - - - -/* the Eclipse MAP unit: This unit is standard in all Eclipse processors - except for the "original" Eclipses, the S/100, S/200, and C/300. These - use a different and more elaborate MMPU that is not compatible with - the one simulated here. All subsequent Eclipses, from the S/130 on up - to the last models S/280 and C/380 use the map simulated here, including - the MicroEclipses. There are model-dependent quirks. That's why we - have to MODEL register. - - The programming of the MMPU can be found in the LMP instruction, below, - and in the instructions directed to DEV_MAP. - - There are two user maps, called A and B, and four data channel maps, - A thru D. They can be enabled/disabled separately. Some models have - two extra user maps, C and D. These are supported where apporpriate. - -*/ - -#define PAGEMASK 01777 /* Largest physical page possible */ -#define MAPMASK 0101777 /* Valid page bits in map */ -#define INVALID 0101777 /* Mask indicating an invalid page */ -int32 MapStat = 0; /* Map status register */ -int32 Inhibit = 0; /* !0=inhibit interrupts : */ - /* 1 = single cycle inhibit */ - /* 2 = inhibit until indirection */ - /* 3 = inhibit next instruction only */ -int32 Enable = 0; /* User map to activate 1=A 2=B */ -int32 Usermap = 0; /* Active Map? 0=supvr mode, 1=user A, 2 = user B */ -int32 Map[8][32]; /* The actual MAPs 0=dch A, 1=A, 2=B, 3-5=dchB-D 6-7 User C-D */ -int32 Map31 = 037; /* Map for block 31 in supervisor mode */ -int32 SingleCycle = 0; /* Map one LDA/STA */ -int32 Check = 0; /* Page Check Register */ -int32 Fault = 0; /* Fault register */ -int32 MapInit = 0; /* 1 when map initialized */ -int32 MapIntMode = 0; /* Save of map user mode when int occurs */ - -int32 Debug_Flags = 0; /* Debug register - selects debug features */ - -int32 Tron = 0; /* For trace files */ -FILE *Trace; - -t_stat reason; -extern int32 sim_int_char; -extern int32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */ -extern DEVICE *sim_devices[]; - -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_boot (int32 unitno, DEVICE *dptr); -t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat Debug_Dump (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat map_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw); -t_stat map_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw); -t_stat map_reset (DEVICE *dptr); -t_stat map_svc (UNIT *uptr); -int32 GetMap(int32 addr); -int32 PutMap(int32 addr, int32 data); -int32 Debug_Entry(int32 PC, int32 inst, int32 inst2, int32 AC0, int32 AC1, int32 AC2, int32 AC3, int32 flags); -t_stat build_devtab (void); - -extern t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, - UNIT *uptr, int32 sw); - -/* 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 (PC, saved_PC, 15) }, - { ORDATA (AC0, AC[0], 16) }, - { ORDATA (AC1, AC[1], 16) }, - { ORDATA (AC2, AC[2], 16) }, - { ORDATA (AC3, AC[3], 16) }, - { FLDATA (C, C, 16) }, - { ORDATA (SR, SR, 16) }, - { ORDATA (PI, pimask, 16) }, - { FLDATA (ION, int_req, INT_V_ION) }, - { FLDATA (ION_DELAY, int_req, INT_V_NO_ION_PENDING) }, - { FLDATA (PWR, pwr_low, 0) }, - { ORDATA (INT, int_req, INT_V_ION+1), REG_RO }, - { ORDATA (BUSY, dev_busy, INT_V_ION+1), REG_RO }, - { ORDATA (DONE, dev_done, INT_V_ION+1), REG_RO }, - { ORDATA (DISABLE, dev_disable, INT_V_ION+1), REG_RO }, - { FLDATA (STOP_DEV, stop_dev, 0) }, - { DRDATA (INDMAX, ind_max, 16), REG_NZ + PV_LEFT }, - { ORDATA (DEBUG, Debug_Flags, 16) }, - { DRDATA (MODEL, model, 16) }, - { DRDATA (SPEED, speed, 16) }, - { ORDATA (WRU, sim_int_char, 8) }, - { NULL } }; - -MTAB cpu_mod[] = { - { UNIT_MICRO, UNIT_MICRO, "MICRO", "MICRO", NULL }, - { UNIT_MICRO, 0, "STD", "STD", 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, 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, 1048576, NULL, "1024K", &cpu_set_size }, - { UNIT_MSIZE, 0, NULL, "DUMP", &Debug_Dump }, - { 0 } }; - -DEVICE cpu_dev = { - "CPU", &cpu_unit, cpu_reg, cpu_mod, - 1, 8, 17, 1, 8, 16, - &cpu_ex, &cpu_dep, &cpu_reset, - &cpu_boot, NULL, NULL }; - -/* MAP data structures - - map_dev MAP device descriptor - map_unit MAP unit descriptor - map_reg MAP register list - map_mod MAP modifiers list -*/ - -UNIT map_unit = { UDATA (&map_svc, UNIT_17B, MAXMEMSIZE) }; - -REG map_reg[] = { - { ORDATA (STATUS, MapStat, 16) }, - { ORDATA (ENABLE, Enable, 16) }, - { ORDATA (IINHIB, Inhibit, 16) }, - { ORDATA (ACTIVE, Usermap, 16) }, - { ORDATA (MAP31, Map31, 16) }, - { ORDATA (CYCLE, SingleCycle, 16) }, - { ORDATA (CHECK, Check, 16) }, - { ORDATA (FAULT, Fault, 16) }, - { NULL } }; - -MTAB map_mod[] = { - { UNIT_17B, UNIT_17B, "17bit", "17B", NULL }, - { UNIT_17B, 0, "19bit", "19B", NULL }, - { 0 } }; - -DEVICE map_dev = { - "MAP", &map_unit, map_reg, map_mod, - 1, 8, 17, 1, 8, 16, - &map_ex, &map_dep, NULL, - NULL, NULL, NULL }; - -t_stat sim_instr (void) -{ -extern int32 sim_interval; -register int32 PC, IR, i, t, MA, j, k; -register unsigned int32 mddata, uAC0, uAC1, uAC2, uAC3; -int16 sAC0, sAC1, sAC2; -int32 sddata, mi1, mi2; -t_value simeval[20]; -void mask_out (int32 mask); -/* char debstr[128]; */ -/* char debadd[64]; */ -char debmap[4], debion[4]; -int debcar, iodev, iodata, debflags; -int32 DisMap, debpc; -/* int32 sp, sl; */ -int cmdptr, cmsptr, cmopt, cmptr; -int16 cmslen, cmdlen; -int tabaddr, tabptr; -int32 effective(int32 PC, int32 index, int32 disp); -int32 indirect(int32 d); -int32 LEFmode(int32 PC, int32 index, int32 disp, int32 indirect); -int32 LoadMap(int32 w); -int32 Bytepointer(int32 PC, int32 index); -int32 unimp(int32 PC); -int32 pushrtn(int32 pc); - -/* Restore register state */ - -if (build_devtab () != SCPE_OK) return SCPE_IERR; /* build dispatch */ -PC = saved_PC & AMASK; /* load local PC */ -C = C & 0200000; -mask_out (pimask); /* reset int system */ -reason = 0; -if (MapInit == 0) { - MapInit = 1; - for (mi1 = 0; mi1 < 6; mi1++) { /* Initialize MAPs */ - for (mi2 = 0; mi2 < 32; mi2++) { - Map[mi1][mi2] = mi2; - } - } -} - -/* Main instruction fetch/decode loop */ - -while (reason == 0) { /* loop until halted */ -if (sim_interval <= 0) { /* check clock queue */ - if (reason = sim_process_event ()) - break; -} - -if (speed > 0) for (i = 0; i < speed; i++) { j = 0; } - -if (Fault) { /* Check MAP fault */ - Usermap = 0; /* YES: shutdown map */ - MapStat &= ~01; /* Disable MMPU */ - if (Fault & 0100000) /* If it was validity, */ - MapStat &= ~0170; /* Reset other checkbits */ - MapStat |= Fault & 077777; /* Put in fault code */ - Fault = 0; /* Reset fault code */ - t = (GetMap(040) + 1) & AMASK; /* Push rtn block */ - PutMap(t, AC[0]); - t++; - PutMap(t, AC[1]); - t++; - PutMap(t, AC[2]); - t++; - PutMap(t, AC[3]); - t++; - PutMap(t, (PC & AMASK)); - if (C) PutMap(t, (GetMap(t) | 0100000)); - PutMap(040, t); - int_req = int_req & ~INT_ION; /* Disable interrupts */ - PC = indirect(M[003]); /* JMP to loc 3 */ - continue; -} - -if (int_req > INT_PENDING && !Inhibit) { /* interrupt? */ - int_req = int_req & ~INT_ION; - MapIntMode = MapStat; /* Save Status as it was */ - Usermap = 0; /* Inhibit MAP */ - MapStat &= ~1; /* Disable user map */ - if (XCT_mode) { - M[0] = PC - 1; /* If XCT mode rtn to XCT */ - XCT_mode = 0; /* turn off mode */ - } else { - M[0] = PC; /* Save Return Address */ - } - old_PC = PC; - MA = M[1]; - for (i = 0; i < ind_max * 2; i++) { /* count indirects */ - if ((MA & 0100000) == 0) break; - if ((MA & 077770) == 020) - MA = (M[MA & AMASK] = (M[MA & AMASK] + 1) & 0177777); - else if ((MA & 077770) == 030) - MA = (M[MA & AMASK] = (M[MA & AMASK] - 1) & 0177777); - else MA = M[MA & AMASK]; - } - if (i >= ind_max) { - if ((MapStat & 010) && Usermap) { - Fault = 04000; /* Map fault if IND prot */ - continue; - } else { - reason = STOP_IND_INT; - break; - } - } - if (Debug_Flags) { - iodev = 0; - iodata = int_req & (-int_req); - for (i = DEV_LOW; i <= DEV_HIGH; i++) { - if (iodata & dev_table[i].mask) { - iodev = i; - break; - } - } - if (iodev == 0) { - printf("\n<>\n"); - reason = STOP_IBKPT; - } - if (Debug_Flags & 0100000) { - fprintf(Trace, "--------- Interrupt %o (%o) to %6o ---------\n", int_req, iodev, MA); - } else { - Debug_Entry(PC, int_req, 0, iodev, MA, 0, 0, 0x80); - } - } - PC = MA; -} /* end interrupt */ - -if (Inhibit != 0) { /* Handle 1-instruction inhibit sequence */ - if (Inhibit == 3) /* Used by SYC instruction */ - Inhibit = 4; - if (Inhibit == 4) - Inhibit = 0; -} - -if (sim_brk_summ && sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */ - reason = STOP_IBKPT; /* stop simulation */ - break; -} - -if ((PC < 1 || PC > 077777) && Debug_Flags) { - if (PPC != -1) { /* Don't break on 1st instruction */ - printf("\n<>\n\r", PC, PPC); - reason = STOP_IBKPT; - break; - } -} - -PPC = PC; - -if (Debug_Flags) { - if (!Tron) { - Tron = 1; - Trace = fopen("trace.log", "w"); - } - strcpy(debmap, " "); - strcpy(debion, " "); - debcar = 0; - if (C) debcar = 1; - if (Usermap == 1) strcpy(debmap, "A"); - if (Usermap == 2) strcpy(debmap, "B"); - if (Usermap == 5) strcpy(debmap, "C"); - if (Usermap == 6) strcpy(debmap, "D"); - if (int_req & INT_ION) strcpy(debion, "I"); - if (XCT_mode == 0) { - debpc = PC; - simeval[0] = GetMap(PC); - simeval[1] = GetMap(PC+1); - } else { - debpc = 0177777; - simeval[0] = XCT_inst; - simeval[1] = 0; - } - if (Debug_Flags & 0100000) { - fprintf(Trace, "%s%s%06o acs: %06o %06o %06o %06o %01o ", - debion, debmap, debpc, AC[0], AC[1], AC[2], AC[3], debcar); - fprint_sym (Trace, debpc, simeval, NULL, SWMASK('M')); - fprintf(Trace, "\n"); - } else { - debflags = 0; - if (C) debflags |= 0x01; - if (int_req & INT_ION) debflags |= 0x02; - if (Usermap == 1) debflags |= 0x04; - if (Usermap == 2) debflags |= 0x08; - if (Usermap == 3) debflags |= 0x10; - if (Usermap == 4) debflags |= 0x20; - Debug_Entry(debpc, simeval[0], simeval[1], AC[0], AC[1], AC[2], AC[3], debflags); - } -} - -if (XCT_mode == 0) { /* XCT mode? */ - IR = GetMap(PC); /* No: fetch instr */ - if (Fault) continue; /* Give up if fault */ - PC = (PC + 1) & AMASK; /* bump PC */ -} else { - IR = XCT_inst; /* Yes: Get inst to XCT */ - XCT_mode = 0; /* Go back to normal mode */ -} -int_req = int_req | INT_NO_ION_PENDING; /* clear ION delay */ -sim_interval = sim_interval - 1; -t = IR >> 11; /* prepare to decode */ - -/* ---------------- BEGIN Eclipse modification --------------------- */ - -/* Eclipse instruction set. These instructions are checked for - before any of the NOVA ones. Eclipse instructions do not - correspond to any patterns, other than bit 0 being 1 and - the last 4 bits are 1000. Words which are not Eclipse - instructions will be interpreted as Nova instructions. */ - -/* Important Note: The order of the if statements is important. - Frequently executed instructions should come first, to enhance - the speed of the simulation. -*/ - -if ((IR & 0100017) == 0100010) { /* This pattern for all */ - /* Eclipse instructions */ - -/****************************************************************/ -/* This is the standard Eclipse instruction set */ -/****************************************************************/ - - /* Byte operations */ - - if ((IR & 0103777) == 0102710) { /* LDB: Load Byte */ - i = (IR >> 13) & 03; - MA = (AC[i] >> 1) & AMASK; - j = (IR >> 11) & 03; - if (AC[i] & 01) { - AC[j] = GetMap(MA) & 0377; - } else { - AC[j] = (GetMap(MA) >> 8) & 0377; - } - continue; - } - if ((IR & 0103777) == 0103010) { /* STB: Store Byte */ - i = (IR >> 13) & 03; - MA = (AC[i] >> 1); - j = (IR >> 11) & 03; - t = GetMap(MA); - if (AC[i] & 01) { - t &= 0177400; - t |= (AC[j] & 0377); - PutMap(MA, t); - } else { - t &= 0377; - t |= (AC[j] & 0377) << 8; - PutMap(MA, t); - } - continue; - } - - /* Fixed-point arithmetic - loads & saves */ - - if ((IR & 0162377) == 0122070) { /* ELDA: Extended LDA */ - i = (IR >> 11) & 3; - t = GetMap(PC); - if (SingleCycle) Usermap = SingleCycle; - AC[i] = GetMap(effective(PC, (IR >> 8) & 3, t)); - if (SingleCycle) { - Usermap = SingleCycle = 0; - if (Inhibit == 1) Inhibit = 3; - MapStat |= 02000; - MapStat &= 0177776; - } - PC = (PC + 1) & AMASK; - continue; - } - if ((IR & 0162377) == 0142070) { /* ESTA: Extended STA */ - i = (IR >> 11) & 3; - t = GetMap(PC); - if (SingleCycle) Usermap = SingleCycle; - PutMap((effective(PC, (IR >> 8) & 3, t)), AC[i]); - if (SingleCycle) { - Usermap = SingleCycle = 0; - if (Inhibit == 1) Inhibit = 3; - MapStat |= 02000; - MapStat &= 0177776; - } - PC = (PC + 1) & AMASK; - continue; - } - if ((IR & 0103777) == 0100010) { /* ADI: Add Immediate */ - t = (IR >> 11) & 3; - AC[t] = (AC[t] + ((IR >> 13) & 3) + 1) & 0xffff; - continue; - } - if ((IR & 0103777) == 0100110) { /* SBI: Subtract Immediate */ - t = (IR >> 11) & 3; - AC[t] = (AC[t] - (((IR >> 13) & 3) + 1)) & 0xffff; - continue; - } - if ((IR & 0163777) == 0163770) { /* ADDI: Extended Add Immed. */ - t = (IR >> 11) & 3; - i = GetMap(PC); - PC = (PC + 1) & AMASK; - AC[t] = (AC[t] + i) & 0xffff; - continue; - } - if ((IR & 0103777) == 0100710) { /* XCH: Exchange Accumulators */ - t = AC[(IR >> 11) & 3]; - AC[(IR >> 11) & 3] = AC[(IR >> 13) & 3]; - AC[(IR >> 13) & 3] = t; - continue; - } - if ((IR & 0162377) == 0162070) { /* ELEF: Load Effective Addr */ - t = GetMap(PC); - AC[(IR >> 11) & 3] = effective(PC, (IR >> 8) & 3, t); - PC = (PC + 1) & AMASK; - continue; - } - - /* Logical operations */ - - if ((IR & 0163777) == 0143770) { /* ANDI: And Immediate */ - AC[(IR >> 11) & 3] &= GetMap(PC); - PC = (PC + 1) & AMASK; - continue; - } - if ((IR & 0163777) == 0103770) { /* IORI: Inclusive Or Immed */ - AC[(IR >> 11) & 3] |= GetMap(PC); - PC = (PC + 1) & AMASK; - continue; - } - if ((IR & 0163777) == 0123770) { /* XORI: Exclusive Or Immed */ - AC[(IR >> 11) & 3] ^= GetMap(PC); - PC = (PC + 1) & AMASK; - continue; - } - if ((IR & 0103777) == 0100410) { /* IOR: Inclusive Or */ - AC[(IR >> 11) & 3] |= AC[(IR >> 13) & 3]; - continue; - } - if ((IR & 0103777) == 0100510) { /* XOR: Exclusive Or */ - AC[(IR >> 11) & 3] ^= AC[(IR >> 13) & 3]; - continue; - } - if ((IR & 0103777) == 0100610) { /* ANC: And with complemented src */ - AC[(IR >> 11) & 3] &= ~(AC[(IR >> 13) & 3]); - continue; - } - - /* Shift operations */ - - if ((IR & 0103777) == 0101210) { /* LSH: Logical Shift */ - register int16 sh; - sh = AC[(IR >> 13) & 3] & 0377; - i = (IR >> 11) & 3; - if (sh & 0200) { - sh = ~sh + 1; - AC[i] = AC[i] >> sh; - } else { - AC[i] = AC[i] << sh; - } - if (sh > 15) AC[i] = 0; - AC[i] &= 0xffff; - continue; - } - if ((IR & 0103777) == 0101310) { /* DLSH: Double logical shift */ - register int16 sh; - sh = AC[(IR >> 13) & 3] & 0377; - i = (IR >> 11) & 3; - uAC0 = AC[i] << 16; - j = i + 1; - if (j == 4) j = 0; - uAC0 |= AC[j]; - if (sh & 0200) { - sh = (~sh + 1) & 0377; - if (sh < 32) - uAC0 = uAC0 >> sh; - } else { - if (sh < 32) - uAC0 = uAC0 << sh; - } - if (sh > 31) uAC0 = 0; - AC[i] = (uAC0 >> 16) & 0xffff; - AC[j] = uAC0 & 0xffff; - continue; - } - if ((IR & 0103777) == 0101410) { /* HXL: Hex shift left */ - t = ((IR >> 13) & 3) + 1; - i = (IR >> 11) & 3; - AC[i] = AC[i] << (t * 4); - AC[i] &= 0xffff; - continue; - } - if ((IR & 0103777) == 0101510) { /* HXR: Hex shift right */ - t = ((IR >> 13) & 3) + 1; - i = (IR >> 11) & 3; - AC[i] = AC[i] >> (t * 4); - AC[i] &= 0xffff; - continue; - } - if ((IR & 0103777) == 0101610) { /* DHXL: Double Hex shift left */ - t = ((IR >> 13) & 3) + 1; - i = (IR >> 11) & 3; - j = i + 1; - if (j == 4) j = 0; - uAC0 = AC[i] << 16; - uAC0 |= AC[j]; - uAC0 = uAC0 << ((t * 4) & 0177); - AC[i] = (uAC0 >> 16) & 0xffff; - AC[j] = uAC0 & 0xffff; - continue; - } - if ((IR & 0103777) == 0101710) { /* DHXR: Double Hex shift right */ - t = ((IR >> 13) & 3) + 1; - i = (IR >> 11) & 3; - j = i + 1; - if (j == 4) j = 0; - uAC0 = AC[i] << 16; - uAC0 |= AC[j]; - uAC0 = uAC0 >> ((t * 4) & 0177); - AC[i] = (uAC0 >> 16) & 0xffff; - AC[j] = uAC0 & 0xffff; - continue; - } - - - /* Bit operations */ - - if ((IR & 0103777) == 0102010) { /* BTO: Set bit to one */ - i = (IR >> 11) & 3; - j = (IR >> 13) & 3; - if (i != j) { - k = (AC[i] >> 4) & AMASK; - MA = indirect(AC[j] + k); - } else { - MA = (AC[i] >> 4) & AMASK; - } - t = AC[i] & 017; - t = GetMap(MA) | (0100000 >> t); - PutMap(MA, t); - continue; - } - if ((IR & 0103777) == 0102110) { /* BTZ: Set bit to zero */ - i = (IR >> 11) & 3; - j = (IR >> 13) & 3; - if (i != j) { - k = (AC[i] >> 4) & AMASK; - MA = indirect(AC[j] + k); - } else { - MA = (AC[j] >> 4) & AMASK; - } - t = AC[i] & 017; - t = GetMap(MA) & ~(0100000 >> t); - PutMap(MA, t); - continue; - } - if ((IR & 0103777) == 0102210) { /* SZB: Skip on zero bit */ - i = (IR >> 11) & 3; - j = (IR >> 13) & 3; - if (i != j) { - k = (AC[i] >> 4) & AMASK; - MA = indirect(AC[j] + k); - } else { - MA = (AC[i] >> 4) & AMASK; - } - t = GetMap(MA) << (AC[i] & 017); - if (!(t & 0100000)) PC = (PC + 1) & AMASK; - continue; - } - if ((IR & 0103777) == 0102770) { /* SNB: Skip on non-zero bit */ - i = (IR >> 11) & 3; - j = (IR >> 13) & 3; - if (i != j) { - k = (AC[i] >> 4) & AMASK; - MA = indirect(AC[j] + k); - } else { - MA = (AC[j] >> 4) & AMASK; - } - t = GetMap(MA) << (AC[i] & 017); - if (t & 0100000) PC = (PC + 1) & AMASK; - continue; - } - if ((IR & 0103777) == 0102310) { /* SZBO: skip on zero bit & set to 1 */ - register int32 save; - i = (IR >> 11) & 3; - j = (IR >> 13) & 3; - if (i != j) { - k = (AC[i] >> 4) & AMASK; - MA = indirect(AC[j] + k); - } else { - MA = (AC[j] >> 4) & AMASK; - } - t = AC[i] & 017; - save = GetMap(MA); - t = save | (0100000 >> t); - PutMap(MA, t); - t = save << (AC[i] & 017); - if ((t & 0100000) == 0) - PC = (PC + 1) & AMASK; - continue; - } - if ((IR & 0103777) == 0102410) { /* LOB: Locate lead bit */ - register int32 a, r; - register int16 b, c = 0; - a = AC[(IR >> 13) & 3] & 0xffff; - for (i = 0; i < 16; i++) { - if ((a << i) & 0100000) break; - } - r = (IR >> 11) & 3; - b = AC[r]; - b += i; - AC[r] = b & 0177777; - continue; - } - if ((IR & 0103777) == 0102510) { /* LRB: Locate & reset lead bit */ - register int32 a, r; - register int16 b; - j = (IR >> 13) & 3; - a = AC[j]; - for (i = 0; i < 16; i++) { - if ((a << i) & 0100000) break; - } - r = (IR >> 11) & 3; - b = AC[r]; - b += i; - if (j != r) AC[r] = b & 0177777; - AC[j] &= ~(0100000 >> i); - AC[j] &= 0xffff; - continue; - } - if ((IR & 0103777) == 0102610) { /* COB: Count bits */ - register int32 a; - register int16 b, c = 0; - a = AC[(IR >> 13) & 3]; - for (i = 0; i < 16; i++) { - if ((a >> i) & 1) c++; - } - i = (IR >> 11) & 3; - b = AC[i]; - b += c; - AC[i] = b & 0177777; - continue; - } - - - /* Jump & similar operations */ - - if ((IR & 0176377) == 0102070) { /* EJMP: Extended JMP */ - PC = effective(PC, (IR >> 8) & 3, GetMap(PC)); - continue; - } - if ((IR & 0176377) == 0106070) { /* EJSR: Extended JMP to subr */ - t = effective(PC, (IR >> 8) & 3, GetMap(PC)); - AC[3] = (PC + 1) & AMASK; - PC = t & AMASK; - continue; - } - if ((IR & 0176377) == 0112070) { /* EISZ: Ext Inc & skip if 0 */ - MA = effective(PC, (IR >> 8) & 3, GetMap(PC)); - PutMap(MA, ((GetMap(MA) + 1) & 0xffff)); - if (GetMap(MA) == 0) PC = (PC + 1) & AMASK; - PC = (PC + 1) & AMASK; - continue; - } - if ((IR & 0176377) == 0116070) { /* EDSZ: Ext Dec & skip if 0 */ - MA = effective(PC, (IR >> 8) & 3, GetMap(PC)); - PutMap(MA, ((GetMap(MA) - 1) & 0xffff)); - if (GetMap(MA) == 0) PC = (PC + 1) & AMASK; - PC = (PC + 1) & AMASK; - continue; - } - if ((IR & 0103777) == 0101010) { /* SGT: Skip if ACS > ACD */ - register int16 a1, d1; - a1 = AC[(IR >> 13) & 3] & 0xffff; - d1 = AC[(IR >> 11) & 3] & 0xffff; - if (a1 > d1) - PC = (PC + 1) & AMASK; - continue; - } - if ((IR & 0103777) == 0101110) { /* SGE: Skip if ACS >= ACD */ - register int16 a1, d1; - a1 = AC[(IR >> 13) & 3] & 0xffff; - d1 = AC[(IR >> 11) & 3] & 0xffff; - if (a1 >= d1) - PC = (PC + 1) & AMASK; - continue; - } - if ((IR & 0103777) == 0102370) { /* CLM: Compare to limits */ - register int32 s, d, MA; - int16 H, L, ca; - s = (IR >> 13) & 3; - d = (IR >> 11) & 3; - if (s == d) { - L = GetMap(PC); - PC++; - H = GetMap(PC); - PC++; - } else { - MA = AC[d] & AMASK; - L = GetMap(MA); - H = GetMap(MA + 1); - } - ca = AC[s]; - if (ca >= L && ca <= H) PC = (PC + 1) & AMASK; - continue; - } - if ((IR & 0163777) == 0123370) { /* XCT: Execute */ - XCT_mode = 1; /* Set up to execute on next loop */ - XCT_inst = AC[(IR >> 11) & 3]; - continue; - } - - /* Memory block operations */ - - if (IR == 0113710) { /* BAM: Block add & move */ - register int32 w; - t = AC[1]; - if (t < 1 || t > 0100000) - continue; - i = indirect(AC[2]); - j = indirect(AC[3]); - while (t) { - w = GetMap(i); - PutMap(j, ((w + AC[0]) & 0xffff)); - if (Fault) break; - t--; - i++; - j++; - i &= AMASK; - j &= AMASK; - } - AC[1] = t; - AC[2] = i & AMASK; - AC[3] = j & AMASK; - continue; - } - if (IR == 0133710) { /* BLM: Block move */ - t = AC[1]; - if (t < 1 || t > 0100000) - continue; - i = indirect(AC[2]); - j = indirect(AC[3]); - while (t) { - PutMap(j, GetMap(i)); - if (Fault) break; - t--; - i++; - j++; - i &= AMASK; - j &= AMASK; - } - AC[1] = t; - AC[2] = i & AMASK; - AC[3] = j & AMASK; - continue; - } - - - /* Stack operations */ - - if ((IR & 0103777) == 0103110) { /* PSH: Push multiple accums */ - register int32 j; - j = (IR >> 11) & 3; - t = GetMap(040) & AMASK; - i = (IR >> 13) & 3; - if (i == j) { - t++; - PutMap(t, AC[i]); - PutMap(040, (t & AMASK)); - if (t > GetMap(042)) { - pushrtn(PC); - PC = indirect(GetMap(043)); - PutMap(040, (GetMap(040) & 077777)); - PutMap(042, (GetMap(042) | 0100000)); - } - continue; - } - while (i != j) { - t++; - PutMap(t, AC[i]); - i++; - if (i == 4) i = 0; - } - t++; - PutMap(t, AC[i]); - PutMap(040, (t & AMASK)); - if ((GetMap(040) & AMASK) > GetMap(042)) { - pushrtn(PC); - PC = indirect(GetMap(043)); - PutMap(040, (GetMap(040) & 077777)); - PutMap(042, (GetMap(042) | 0100000)); - } - continue; - } - if ((IR & 0103777) == 0103210) { /* POP: Pop mult accums */ - j = (IR >> 11) & 3; - t = GetMap(040) & AMASK; - i = (IR >> 13) & 3; - if (i == j) { - AC[i] = GetMap(t); - t--; - PutMap(040, (t & AMASK)); - t = GetMap(040); - if (t < 0100000 && t < 0400) { - PutMap(040, GetMap(042)); - pushrtn(PC); - PC = indirect(GetMap(043)); - PutMap(040, (GetMap(040) & 077777)); - PutMap(042, (GetMap(042) | 0100000)); - } - continue; - } - while (i != j) { - AC[i] = GetMap(t); - t--; - i--; - if (i == -1) i = 3; - } - AC[i] = GetMap(t); - t--; - PutMap(040, (t & AMASK)); - t = GetMap(040); - if (t < 0100000 && t < 0400) { - PutMap(040, GetMap(042)); - pushrtn(PC); - PC = indirect(GetMap(043)); - PutMap(040, (GetMap(040) & 077777)); - PutMap(042, (GetMap(042) | 0100000)); - } - continue; - } - if (IR == 0103710) { /* PSHR: Push return addr */ - t = (GetMap(040) + 1) & AMASK; - PutMap(t, (PC + 1)); - PutMap(040, t); - if ((GetMap(040) & AMASK) > GetMap(042)) { - pushrtn(PC); - PC = indirect(GetMap(043)); - PutMap(040, (GetMap(040) & 077777)); - PutMap(042, (GetMap(042) | 0100000)); - } - continue; - } - if (IR == 0163710) { /* SAVE */ - register int32 savep; - savep = ((GetMap(PC) + GetMap(040)) + 5) & AMASK; - if (savep > GetMap(042)) { - pushrtn(PC-1); - PC = indirect(GetMap(043)); - PutMap(040, (GetMap(040) & 077777)); - PutMap(042, (GetMap(042) | 0100000)); - continue; - } - t = GetMap(040) + 1; - PutMap(t, AC[0]); - t++; - PutMap(t, AC[1]); - t++; - PutMap(t, AC[2]); - t++; - PutMap(t, GetMap(041)); - t++; - savep = PC; - PC = (PC + 1) & AMASK; - PutMap(t, (AC[3] & AMASK)); - if (C) PutMap(t, (GetMap(t) | 0100000)); - PutMap(040, t); - AC[3] = GetMap(040) & AMASK; - PutMap(041, AC[3]); - PutMap(040, ((GetMap(040) + GetMap(savep)) & AMASK)); - continue; - } - if ((IR & 0163777) == 0103370) { /* MSP: Modify stack pointer */ - t = (GetMap(040) + AC[(IR >> 11) & 3]) & 0177777; - if (t > GetMap(042)) { - pushrtn(PC-1); - PC = indirect(GetMap(043)); - PutMap(040, (GetMap(040) & AMASK)); - PutMap(042, (GetMap(042) | 0100000)); - continue; - } - PutMap(040, t); - continue; - } - if ((IR & 0176377) == 0102270) { /* PSHJ: Push JMP */ - PutMap(040, (GetMap(040) + 1)); - PutMap((GetMap(040) & AMASK), ((PC + 1) & AMASK)); - if ((GetMap(040) & AMASK) > (GetMap(042) & AMASK)) { - pushrtn(PC+1); - PC = indirect(GetMap(043)); - PutMap(040, (GetMap(040) & 077777)); - PutMap(042, (GetMap(042) | 0100000)); - continue; - } - PC = effective(PC, (IR >> 8) & 3, GetMap(PC)); - continue; - } - if (IR == 0117710) { /* POPJ: Pop PC and Jump */ - PC = GetMap(GetMap(040)) & AMASK; - PutMap(040, (GetMap(040) - 1)); - if (MapStat & 1) { - Usermap = Enable; - Inhibit = 0; - } - t = GetMap(040); - if (t < 0100000 && t < 0400) { - pushrtn(PC); - PC = indirect(GetMap(043)); - PutMap(040, (GetMap(040) & 077777)); - PutMap(042, (GetMap(042) | 0100000)); - } - continue; - } - if (IR == 0107710) { /* POPB: Pop block */ - PC = GetMap(GetMap(040)) & AMASK; - if (GetMap(GetMap(040)) & 0100000) - C = 0200000; - else - C = 0; - PutMap(040, (GetMap(040) - 1)); - AC[3] = GetMap(GetMap(040)); - PutMap(040, (GetMap(040) - 1)); - AC[2] = GetMap(GetMap(040)); - PutMap(040, (GetMap(040) - 1)); - AC[1] = GetMap(GetMap(040)); - PutMap(040, (GetMap(040) - 1)); - AC[0] = GetMap(GetMap(040)); - PutMap(040, (GetMap(040) - 1)); - t = GetMap(040); - if (t < 0100000 && t < 0400) { - pushrtn(PC); - PC = indirect(GetMap(043)); - PutMap(040, (GetMap(040) & 077777)); - PutMap(042, (GetMap(042) | 0100000)); - } - if (MapStat & 1) { - Usermap = Enable; - Inhibit = 0; - } - continue; - } - if (IR == 0127710) { /* RTN: Return */ - PutMap(040, GetMap(041)); - PC = GetMap(GetMap(040)) & AMASK; - if (GetMap(GetMap(040)) & 0100000) - C = 0200000; - else - C = 0; - PutMap(040, (GetMap(040) - 1)); - AC[3] = GetMap(GetMap(040)); - PutMap(040, (GetMap(040) - 1)); - AC[2] = GetMap(GetMap(040)); - PutMap(040, (GetMap(040) - 1)); - AC[1] = GetMap(GetMap(040)); - PutMap(040, (GetMap(040) - 1)); - AC[0] = GetMap(GetMap(040)); - PutMap(040, (GetMap(040) - 1)); - PutMap(041, AC[3]); - t = GetMap(040); - if (t < 0100000 && t < 0400) { - pushrtn(PC); - PutMap(040, (GetMap(040) & 077777)); - PutMap(042, (GetMap(042) | 0100000)); - PC = indirect(GetMap(043)); - } - if (MapStat & 1) { - Usermap = Enable; - Inhibit = 0; - } - continue; - } - if (IR == 0167710) { /* RSTR: Restore */ - int32 SVPC; - - SVPC = PC; - PC = GetMap(GetMap(040)) & AMASK; - if (PC == 0 && Debug_Flags) { - printf("\n<>\n\r", SVPC); - reason = STOP_IBKPT; - } - if (GetMap(GetMap(040)) & 0100000) - C = 0200000; - else - C = 0; - PutMap(040, (GetMap(040) - 1)); - AC[3] = GetMap(GetMap(040)); - PutMap(040, (GetMap(040) - 1)); - AC[2] = GetMap(GetMap(040)); - PutMap(040, (GetMap(040) - 1)); - AC[1] = GetMap(GetMap(040)); - PutMap(040, (GetMap(040) - 1)); - AC[0] = GetMap(GetMap(040)); - PutMap(040, (GetMap(040) - 1)); - PutMap(043, GetMap(GetMap(040))); - PutMap(040, (GetMap(040) - 1)); - PutMap(042, GetMap(GetMap(040))); - PutMap(040, (GetMap(040) - 1)); - PutMap(041, GetMap(GetMap(040))); - PutMap(040, (GetMap(040) - 1)); - PutMap(040, GetMap(GetMap(040))); - /*t = GetMap(040); - if (t < 0100000 && t < 0400) { - pushrtn(PC); - PC = indirect(GetMap(043)); - }*/ - if (MapStat & 1) { - Usermap = Enable; - Inhibit = 0; - } - continue; - } - - /* Multiply / Divide */ - - if (IR == 0143710) { /* MUL: Unsigned Multiply */ - uAC0 = (unsigned int32) AC[0]; - uAC1 = (unsigned int32) AC[1]; - uAC2 = (unsigned int32) AC[2]; - - mddata = (uAC1 * uAC2) + uAC0; - AC[0] = (mddata >> 16) & 0177777; - AC[1] = mddata & 0177777; - continue; - } - if (IR == 0147710) { /* MULS: Signed Multiply */ - sAC0 = AC[0]; - sAC1 = AC[1]; - sAC2 = AC[2]; - - sddata = (sAC1 * sAC2) + sAC0; - AC[0] = (sddata >> 16) & 0177777; - AC[1] = sddata & 0177777; - continue; - } - if (IR == 0153710) { /* DIV: Unsigned Divide */ - uAC0 = (unsigned int32) AC[0]; - uAC1 = (unsigned int32) AC[1]; - uAC2 = (unsigned int32) AC[2]; - - if (uAC0 >= uAC2) C = 0200000; - else { C = 0; - mddata = (uAC0 << 16) | uAC1; - AC[1] = mddata / uAC2; - AC[0] = mddata % uAC2; - } - continue; - } - if (IR == 0157710) { /* DIVS: Signed Divide */ - sAC2 = AC[2]; - - C = 0; - sddata = ((AC[0] & 0xffff) << 16) | (AC[1] & 0xffff); - AC[1] = sddata / sAC2; - AC[0] = sddata % sAC2; - if (AC[0] > 077777 || AC[0] < -077776) C = 0200000; - /*if ((AC[0] & 0xFFFF0000) != 0) C = 0200000;*/ - if (AC[1] > 077777 || AC[1] < -077776) C = 0200000; - /*if ((AC[1] & 0xFFFF0000) != 0) C = 0200000;*/ - AC[0] &= 0177777; - AC[1] &= 0177777; - continue; - } - if (IR == 0137710) { /* DIVX: Sign extend and Divide */ - int32 q; - if (AC[1] & 0100000) { - AC[0] = 0177777; - } else { - AC[0] = 0; - } - sAC0 = AC[0]; - sAC1 = AC[1]; - sAC2 = AC[2]; - - C = 0; - sddata = (sAC0 << 16) | sAC1; - q = sddata / sAC2; - AC[0] = sddata % sAC2; - if (q > 0177777) { - C = 0200000; - } else { - AC[1] = q & 0xffff; - } - continue; - } - if ((IR & 0163777) == 0143370) { /* HLV: Halve */ - t = (IR >> 11) & 3; - if (AC[t] & 0100000) { - AC[t] = (0 - AC[t]) & 0xffff; - AC[t] = AC[t] >> 1; - AC[t] = (0 - AC[t]) & 0xffff; - } else { - AC[t] = (AC[t] >> 1) & 0xffff; - } - continue; - } - - /* Decimal arithmetic */ - - if ((IR & 0103777) == 0100210) { /* DAD: Decimal add */ - i = (IR >> 13) & 3; - j = (IR >> 11) & 3; - t = (AC[i] & 017) + (AC[j] & 017); - if (C) t++; - if (t > 9) { - C = 0200000; - t += 6; - } else { - C = 0; - } - AC[j] &= 0177760; - AC[j] = AC[j] | (t & 017); - continue; - } - if ((IR & 0103777) == 0100310) { /* DSB: Decimal subtract */ - i = (IR >> 13) & 3; - j = (IR >> 11) & 3; - t = (AC[j] & 017) - (AC[i] & 017); - if (!C) t--; - if (t < 0) { - C = 0; - t = 9 - (~t); - } else { - C = 0200000; - } - AC[j] &= 0177760; - AC[j] = AC[j] | (t & 017); - continue; - } - - /* Exotic, complex instructions */ - - if ((IR & 0162377) == 0142170) { /* DSPA: Dispatch */ - register int32 d; - int16 a, H, L; - MA = effective(PC, (IR >> 8) & 3, GetMap(PC)); - H = GetMap(MA - 1) & 0177777; - L = GetMap(MA - 2) & 0177777; - a = AC[(IR >> 11) & 3] & 0177777; - if (a < L || a > H) { - PC = (PC + 1) & AMASK; - continue; - } - d = GetMap(MA - L + a); - if (d == 0177777) { - PC = (PC + 1) & AMASK; - continue; - } - PC = indirect(d) & AMASK; - continue; - } - - if (((IR & 0100077) == 0100030) || - ((IR & 0102077) == 0100070)) { /* XOP: Extended Operation */ - register int32 op, d, sa, da; - op = (IR >> 6) & 037; - if ((IR & 077) == 070) op += 32; - t = GetMap(040) & AMASK; - for (i = 0; i <= 3; i++) { - t++; - PutMap(t, AC[i]); - if (((IR >> 13) & 3) == i) sa = t; - if (((IR >> 11) & 3) == i) da = t; - } - t++; - PutMap(t, PC & AMASK); - if (C) PutMap(t, (GetMap(t) | 0100000)); - PutMap(040, t); - AC[2] = sa; - AC[3] = da; - d = GetMap(GetMap(044) + op); - PC = indirect(d) & AMASK; - if ((GetMap(040) & AMASK) > (GetMap(042) & AMASK)) { - pushrtn(PC); - PC = indirect(GetMap(043)); - PutMap(040, (GetMap(040) & 077777)); - PutMap(042, (GetMap(042) | 0100000)); - } - continue; - } - if ((IR & 0103777) == 0103510) { /* SYC: System call */ - register int32 j; - DisMap = Usermap; - Usermap = 0; - MapStat &= ~1; /* Disable MAP */ - i = (IR >> 13) & 3; - j = (IR >> 11) & 3; - if (i != 0 || j != 0) { - t = (GetMap(040) + 1) & AMASK; - PutMap(t, AC[0]); - t++; - PutMap(t, AC[1]); - t++; - PutMap(t, AC[2]); - t++; - PutMap(t, AC[3]); - t++; - PutMap(t, (PC & AMASK)); - if (C) PutMap(t, (GetMap(t) | 0100000)); - PutMap(040, t); - PutMap(041, (GetMap(040) & AMASK)); - } - PC = indirect(GetMap(2)) & AMASK; - if (DisMap > 0) - Inhibit = 3; /* Special 1-instruction interrupt inhibit */ - if ((GetMap(040) & AMASK) > GetMap(042)) { - pushrtn(PC); - PC = indirect(GetMap(043)); - PutMap(040, (GetMap(040) & 077777)); - PutMap(042, (GetMap(042) | 0100000)); - } - continue; - } - if (IR == 0113410) { /* LMP: Load Map */ - register int32 w, m; - if ((Debug_Flags & 077) == 03) - fprintf(Trace, "%o LMP (Map=%o)\n", PC - 1, (MapStat>>7)&07); - t = AC[1]; - i = AC[2]; - while (t) { - if (int_req > INT_PENDING && !Inhibit) { /* interrupt? */ - PC = PC - 1; - break; - } - if (!Usermap || !(MapStat & 0140)) { /* Only load if in sup mode */ - w = (GetMap(i) + AC[0]) & 0xffff; /* Or not IO & LEF mode for user */ - m = (w >> 10) & 037; - if ((Debug_Flags & 077) == 03) - fprintf(Trace, " %o MAP L=%o W=%o P=%o\n", i, m, - (w>>15)&1, w & PAGEMASK); - LoadMap(w); - if (Fault) break; - } - t--; - i++; - } - AC[0] = 0; - AC[1] = t; - AC[2] = i & AMASK; - MapStat &= ~02000; - continue; - } - -/****************************************************************/ -/* Character Instruction Set */ -/****************************************************************/ - - if ((IR & 0162377) == 0102170) { /* ELDB */ - t = Bytepointer(PC, (IR >> 8) & 3); - i = (IR >> 11) & 03; - MA = (t >> 1) & AMASK; - if (t & 01) { - AC[i] = GetMap(MA) & 0377; - } else { - AC[i] = (GetMap(MA) >> 8) & 0377; - } - PC = (PC + 1) & AMASK; - continue; - } - if ((IR & 0162377) == 0122170) { /* ESTB */ - t = Bytepointer(PC, (IR >> 8) & 3); - i = (IR >> 11) & 03; - MA = (t >> 1) & AMASK; - j = GetMap(MA); - if (t & 01) { - j &= 0177400; - j |= (AC[i] & 0377); - PutMap(MA, j); - } else { - j &= 0377; - j |= (AC[i] & 0377) << 8; - PutMap(MA, j); - } - PC = (PC + 1) & AMASK; - continue; - } - - if ((IR & 077) == 050) { /* All CIS end with 050 except ELDB/ESTB */ - - if (IR == 0153650) { /* CMV Character Move */ - cmdlen = AC[0] & 0177777; /* Set up length & direction */ - cmslen = AC[1] & 0177777; /* For both source & dest */ - cmsptr = AC[3]; /* init byte pointers */ - cmdptr = AC[2]; - C = 0; /* Do carry now b4 cmslen changes */ - if (abs(cmslen) > abs(cmdlen)) - C = 0200000; - for (i = 0; i < abs(cmdlen); i++) { /* Move loop */ - MA = (cmsptr >> 1) & AMASK; /* do an LDB */ - if (cmsptr & 01) { - uAC2 = GetMap(MA) & 0377; /* Use uAC2 for temp */ - } else { - uAC2 = (GetMap(MA) >> 8) & 0377; - } - if (cmslen == 0) { - uAC2 = ' ' & 0377; /* Handle short source */ - } - MA = (cmdptr >> 1) & AMASK; /* do an STB */ - j = GetMap(MA); - if (cmdptr & 01) { - j &= 0177400; - j |= (uAC2 & 0377); - PutMap(MA, j); - } else { - j &= 0377; - j |= (uAC2 & 0377) << 8; - PutMap(MA, j); - } - if (cmslen > 0) { - cmsptr++; - cmslen--; - } - if (cmslen < 0) { - cmsptr--; - cmslen++; - } - if (cmdlen > 0) { - cmdptr++; - } else { - cmdptr--; - } - } - AC[0] = 0; - AC[1] = cmslen & 0177777; - AC[2] = cmdptr & 0177777; - AC[3] = cmsptr & 0177777; - continue; - } - - if (IR == 0157650) { /* CMP Character compare */ - cmdlen = AC[0] & 0177777; /* Set up length & direction */ - cmslen = AC[1] & 0177777; /* For both source & dest */ - cmsptr = AC[3]; /* init byte pointers */ - cmdptr = AC[2]; - t = 0; /* Equal unless otherwise */ - while (1) { /* Compare loop */ - MA = (cmsptr >> 1) & AMASK; /* do an LDB - string 1 */ - if (cmslen != 0) { - if (cmsptr & 01) { - uAC2 = GetMap(MA) & 0377; /* Use uAC2 for temp */ - } else { - uAC2 = (GetMap(MA) >> 8) & 0377; - } - } else { - uAC2 = ' ' & 0377; - } - MA = (cmdptr >> 1) & AMASK; /* do an LDB - string 2 */ - if (cmdlen != 0) { - if (cmdptr & 01) { - uAC3 = GetMap(MA) & 0377; /* Use uAC2 for temp */ - } else { - uAC3 = (GetMap(MA) >> 8) & 0377; - } - } else { - uAC3 = ' ' & 0377; - } - if (uAC2 > uAC3) { - t = 1; - break; - } - if (uAC2 < uAC3) { - t = -1; - break; - } - if (cmslen > 0) { - cmsptr++; - cmslen--; - } - if (cmslen < 0) { - cmsptr--; - cmslen++; - } - if (cmdlen > 0) { - cmdptr++; - cmdlen--; - } - if (cmdlen < 0) { - cmdptr--; - cmdlen++; - } - if (cmslen == 0 && cmdlen == 0) - break; - } - AC[1] = t & 0177777; - AC[0] = cmdlen & 0177777; - AC[2] = cmdptr & 0177777; - AC[3] = cmsptr & 0177777; - continue; - } - if (IR == 0163650) { /* CTR Character translate */ - tabaddr = indirect(AC[0]); /* Get address of table */ - tabptr = M[tabaddr] & 0177777; /* Get byte pointer */ - cmslen = AC[1] & 0177777; /* Length: both source & dest */ - cmopt = 0; /* Default: COMPARE option */ - if (cmslen < 0) { - cmopt=1; /* MOVE option */ - cmslen = 0 - cmslen; - } - cmsptr = AC[3]; /* init byte pointers */ - cmdptr = AC[2]; - t = 0; /* Equal unless otherwise */ - while (1) { /* Translation loop */ - MA = (cmsptr >> 1) & AMASK; /* do an LDB - string 1 */ - if (cmsptr & 01) { - j = GetMap(MA) & 0377; - } else { - j = (GetMap(MA) >> 8) & 0377; - } - cmptr = tabptr + j; /* Translate */ - MA = (cmptr >> 1) & AMASK; - if (cmptr & 01) { - uAC2 = GetMap(MA) & 0377; - } else { - uAC2 = (GetMap(MA) >> 8) & 0377; - } - if (cmopt) { /* MOVE... */ - MA = (cmdptr >> 1) & AMASK; /* do an STB */ - j = GetMap(MA); - if (cmdptr & 01) { - j &= 0177400; - j |= (uAC2 & 0377); - PutMap(MA, j); - } else { - j &= 0377; - j |= (uAC2 & 0377) << 8; - PutMap(MA, j); - } - } else { /* COMPARE... */ - MA = (cmdptr >> 1) & AMASK; /* do an LDB - string 2 */ - if (cmdptr & 01) { - j = GetMap(MA) & 0377; - } else { - j = (GetMap(MA) >> 8) & 0377; - } - cmptr = tabptr + j; /* Translate */ - MA = (cmptr >> 1) & AMASK; - if (cmptr & 01) { - uAC3 = GetMap(MA) & 0377; - } else { - uAC3 = (GetMap(MA) >> 8) & 0377; - } - if (uAC2 > uAC3) { - t = 1; - break; - } - if (uAC2 < uAC3) { - t = -1; - break; - } - } - cmsptr++; - cmdptr++; - cmslen--; - if (cmslen == 0) - break; - } - if (!cmopt) AC[1] = t; - else - AC[1] = 0; - AC[0] = tabaddr & 077777; - AC[2] = cmdptr & 0177777; - AC[3] = cmsptr & 0177777; - continue; - } - if (IR == 0167650) { /* CMT Char move till true */ - tabaddr = indirect(AC[0]); /* Set up length & direction */ - cmslen = AC[1] & 0177777; /* For both source & dest */ - cmsptr = AC[3]; /* init byte pointers */ - cmdptr = AC[2]; - while (1) { /* Move loop */ - MA = (cmsptr >> 1) & AMASK; /* do an LDB */ - if (cmsptr & 01) { - uAC2 = GetMap(MA) & 0377; /* Use uAC2 for temp */ - } else { - uAC2 = (GetMap(MA) >> 8) & 0377; - } - t = M[tabaddr + (uAC2 >> 4)]; /* Test bit table */ - if (t << (uAC2 & 0x0F) & 0100000) /* quit if bit == 1 */ - break; - MA = (cmdptr >> 1) & AMASK; /* do an STB */ - j = GetMap(MA); - if (cmdptr & 01) { - j &= 0177400; - j |= (uAC2 & 0377); - PutMap(MA, j); - } else { - j &= 0377; - j |= (uAC2 & 0377) << 8; - PutMap(MA, j); - } - if (cmslen > 0) { - cmsptr++; - cmdptr++; - cmslen--; - } - if (cmslen < 0) { - cmsptr--; - cmdptr--; - cmslen++; - } - if (cmslen == 0) - break; - } - AC[0] = tabaddr & 077777; - AC[1] = cmslen & 0177777; - AC[2] = cmdptr & 0177777; - AC[3] = cmsptr & 0177777; - continue; - } - - /*********************************************************** - ** "Commercial" instructions. These were in the original ** - ** Eclipse C series, but not part of the later Character ** - ** Instruction Set. ** - ***********************************************************/ - - if ((IR & 0163777) == 0103650) { /* LDI Load Integer */ - unimp(PC); - continue; - } - if ((IR & 0163777) == 0123650) { /* STI Store Integer */ - unimp(PC); - continue; - } - if (IR == 0143650) { /* LDIX Load Int Extended */ - unimp(PC); - continue; - } - if (IR == 0143750) { /* STIX Store Int Extended */ - unimp(PC); - continue; - } - if ((IR & 0163777) == 0143150) { /* FINT Integerize */ - unimp(PC); - continue; - } - if (IR == 0177650) { /* LSN Load Sign */ - unimp(PC); - continue; - } - if (IR == 0173650) { /* EDIT */ - unimp(PC); - continue; - } - } - - /* FPU Instructions */ - - if ((IR & 0103777) == 0102050) { /* FLDS Load FP single */ - PC = (PC + 1) & AMASK; - continue; - } - if ((IR & 0103777) == 0102150) { /* FLDD Load FP double */ - PC = (PC + 1) & AMASK; - continue; - } - if ((IR & 0103777) == 0102250) { /* FSTS Store FP single */ - PC = (PC + 1) & AMASK; - continue; - } - if ((IR & 0103777) == 0102350) { /* FSTD Store FP double */ - PC = (PC + 1) & AMASK; - continue; - } - if ((IR & 0103777) == 0102450) { /* FLAS Float from AC */ - continue; - } - if ((IR & 0103777) == 0102550) { /* FLMD Float from memory */ - PC = (PC + 1) & AMASK; - continue; - } - if ((IR & 0103777) == 0102650) { /* FFAS Fix to AC */ - continue; - } - if ((IR & 0103777) == 0102750) { /* FFMD Fix to Memory */ - PC = (PC + 1) & AMASK; - continue; - } - if ((IR & 0103777) == 0103550) { /* FMOV Move FP */ - continue; - } - if ((IR & 0103777) == 0100050) { /* FAS Add single to AC */ - continue; - } - if ((IR & 0103777) == 0101050) { /* FAMS Add single to memory */ - PC = (PC + 1) & AMASK; - continue; - } - if ((IR & 0103777) == 0100150) { /* FAD Add double */ - continue; - } - if ((IR & 0103777) == 0101150) { /* FAMD Add double to memory */ - PC = (PC + 1) & AMASK; - continue; - } - if ((IR & 0103777) == 0100250) { /* FSS Sub single to AC */ - continue; - } - if ((IR & 0103777) == 0101250) { /* FSMS Sub single from memory */ - PC = (PC + 1) & AMASK; - continue; - } - if ((IR & 0103777) == 0100350) { /* FSD Sub double from AC */ - continue; - } - if ((IR & 0103777) == 0101350) { /* FSMD Sub double from memory */ - PC = (PC + 1) & AMASK; - continue; - } - if ((IR & 0103777) == 0100450) { /* FMS Mult single by AC */ - continue; - } - if ((IR & 0103777) == 0101450) { /* FMMS Mult double by memory */ - PC = (PC + 1) & AMASK; - continue; - } - if ((IR & 0103777) == 0100550) { /* FMD Mult double by AC */ - continue; - } - if ((IR & 0103777) == 0101550) { /* FMMD Mult double by memory */ - PC = (PC + 1) & AMASK; - continue; - } - if ((IR & 0103777) == 0100650) { /* FDS Div single by AC */ - continue; - } - if ((IR & 0103777) == 0101650) { /* FDMS Div double by memory */ - PC = (PC + 1) & AMASK; - continue; - } - if ((IR & 0103777) == 0100650) { /* FDD Div double by AC */ - continue; - } - if ((IR & 0103777) == 0101650) { /* FDMD Div double by memory */ - PC = (PC + 1) & AMASK; - continue; - } - if ((IR & 0163777) == 0163050) { /* FNEG Negate */ - continue; - } - if ((IR & 0163777) == 0103050) { /* FNOM Normalize*/ - continue; - } - if ((IR & 0163777) == 0143050) { /* FAB Absolute Value*/ - continue; - } - if ((IR & 0163777) == 0123050) { /* FRH Read High Word */ - continue; - } - if ((IR & 0163777) == 0103150) { /* FSCAL Scale */ - continue; - } - if ((IR & 0163777) == 0123150) { /* FEXP Load Exponent */ - continue; - } - if ((IR & 0163777) == 0163150) { /* FHLV Halve */ - continue; - } - if ((IR & 0103777) == 0103450) { /* FCMP FP Compare */ - continue; - } - if ((IR & 0163777) == 0123350) { /* FLST Load Status */ - PC = (PC + 1) & AMASK; - continue; - } - if ((IR & 0163777) == 0103350) { /* FSST Store Status */ - PC = (PC + 1) & AMASK; - continue; - } - if (IR == 0143350) { /* FTE Trap Enable */ - continue; - } - if (IR == 0147350) { /* FTD Trap Disable */ - continue; - } - if (IR == 0153350) { /* FCLE Clear Errors */ - continue; - } - if (IR == 0163350) { /* FPSH Push State */ - continue; - } - if (IR == 0167350) { /* FPOP Pop State */ - continue; - } - if (IR == 0103250) { /* FNS No Skip */ - continue; - } - if (IR == 0107250) { /* FSA Always Skip */ - continue; - } - if (IR == 0137250) { /* FSGT */ - continue; - } - if (IR == 0123250) { /* FSLT */ - continue; - } - if (IR == 0113250) { /* FSEQ */ - continue; - } - if (IR == 0133250) { /* FSLE */ - continue; - } - if (IR == 0127250) { /* FSGE */ - continue; - } - if (IR == 0117250) { /* FSNE */ - continue; - } - if (IR == 0143250) { /* FSNM */ - continue; - } - if (IR == 0153250) { /* FSNU */ - continue; - } - if (IR == 0163250) { /* FSNO */ - continue; - } - if (IR == 0147250) { /* FSND */ - continue; - } - if (IR == 0157250) { /* FSNUD */ - continue; - } - if (IR == 0167250) { /* FSNOD */ - continue; - } - if (IR == 0173250) { /* FSNUO */ - continue; - } - if (IR == 0177250) { /* FSNER */ - continue; - } - - if (Debug_Flags) { - printf("\n<>\n\r", IR, PC-1); - if (Debug_Flags & 040000) reason = STOP_IBKPT; - } -} - -if (IR == 061777) { /* VCT: Vector on Interrupt */ - int32 stkchg, vtable; - int32 ventry, dctadr; - int32 old40, old41, old42, old43; - - /* Ok, folks, this is one helluva instruction */ - - stkchg = GetMap(PC) & 0100000; /* Save stack change bit */ - vtable = GetMap(PC) & AMASK; /* Address of vector table */ - - iodev = 0; - int_req = (int_req & ~INT_DEV) | /* Do an INTA w/o an accum */ - (dev_done & ~dev_disable); - iodata = int_req & (-int_req); - for (i = DEV_LOW; i <= DEV_HIGH; i++) { - if (iodata & dev_table[i].mask) { - iodev = i; - break; - } - } - - ventry = GetMap(vtable + iodev); /* Get Vector Entry */ - - if (!(ventry & 0100000)) { /* Direct bit = 0? */ - PC = ventry & AMASK; /* YES - Mode A, so JMP */ - continue; - } - - dctadr = ventry & AMASK; /* Get address of DCT entry */ - - if (stkchg) { /* Stack change bit = 1? */ - old40 = GetMap(040); /* Save stack info */ - old41 = GetMap(041); - old42 = GetMap(042); - old43 = GetMap(043); - PutMap(040, GetMap(004)); /* Loc 4 to stack ptr */ - PutMap(042, GetMap(006)); /* Loc 6 to stack limit */ - PutMap(043, GetMap(007)); /* Loc 7 into stack limit */ - PutMap(040, (GetMap(040) + 1)); /* Push old contents on new stk */ - PutMap(GetMap(040) & AMASK, old40); - PutMap(040, (GetMap(040) + 1)); - PutMap(GetMap(040) & AMASK, old41); - PutMap(040, (GetMap(040) + 1)); - PutMap(GetMap(040) & AMASK, old42); - PutMap(040, (GetMap(040) + 1)); - PutMap(GetMap(040) & AMASK, old43); - } - - t = GetMap(dctadr & AMASK); /* Get word 0 of DCT */ - - if (t & 0100000) { /* Push bit set ? */ - PutMap(040, (GetMap(040) + 1)); /* Push "Standard rtn block" */ - PutMap(GetMap(040) & AMASK, AC[0]); - PutMap(040, (GetMap(040) + 1)); - PutMap(GetMap(040) & AMASK, AC[1]); - PutMap(040, (GetMap(040) + 1)); - PutMap(GetMap(040) & AMASK, AC[2]); - PutMap(040, (GetMap(040) + 1)); - PutMap(GetMap(040) & AMASK, AC[3]); - PutMap(040, (GetMap(040) + 1)); - PutMap(GetMap(040) & AMASK, GetMap(0)); - if (GetMap(0) == 0 && Debug_Flags) { - printf("\n<>\n\r", PC); - reason = STOP_IBKPT; - } - if (C) PutMap(GetMap(040) & AMASK, (GetMap(GetMap(040) & AMASK) | 0100000)); - } - - /************************************************************************* - ** At this point, the instruction is not an Eclipse one. Therefore ** - ** decode it as a Nova instruction just like the Nova does. ** - *************************************************************************/ - - AC[2] = dctadr & AMASK; /* DCT Addr into AC2 */ - - PutMap(040, (GetMap(040) + 1)); /* Push pri int mask onto stack */ - PutMap(GetMap(040) & AMASK, pimask); - - AC[0] = GetMap(dctadr + 1) | pimask;/* Build new mask from word 1 of dct */ - PutMap(005, AC[0]); - - mask_out(pimask = AC[0]); /* Do a mask out inst */ - - PC = GetMap(dctadr) & AMASK; /* Finally, JMP to int routine */ - - continue; -} - -/* Memory reference instructions */ - -if (t < 014) { /* mem ref? */ - register int32 src, MA; - MA = IR & 0377; - switch ((IR >> 8) & 03) { /* decode IR<6:7> */ - case 0: /* page zero */ - break; - case 1: /* PC relative */ - if (MA & 0200) MA = 077400 | MA; - MA = (MA + PC - 1) & AMASK; - break; - case 2: /* AC2 relative */ - if (MA & 0200) MA = 077400 | MA; - MA = (MA + AC[2]) & AMASK; - break; - case 3: /* AC3 relative */ - if (MA & 0200) MA = 077400 | MA; - MA = (MA + AC[3]) & AMASK; - break; - } - if (IR & 002000) { /* indirect? */ - for (i = 0; i < (ind_max * 2); i++) { /* count indirects */ - if ((MA & 077770) == 020 && !(cpu_unit.flags & UNIT_MICRO)) - MA = (PutMap(MA & AMASK, (GetMap(MA & AMASK) + 1) & 0177777)); - else if ((MA & 077770) == 030 && !(cpu_unit.flags & UNIT_MICRO)) - MA = (PutMap(MA & AMASK, (GetMap(MA & AMASK) - 1) & 0177777)); - else MA = GetMap(MA & AMASK); - if (MapStat & 1) { /* Start MAP */ - Usermap = Enable; - Inhibit = 0; - } - if ((MA & 0100000) == 0) break; - if (i >= ind_max && (MapStat & 010) && Usermap) break; - } - if (i >= ind_max) { - if ((MapStat & 010) && Usermap) { - Fault = 04000; /* Map fault if IND prot */ - continue; - } - if (i >= (ind_max * 2) && !(Fault)) { - reason = STOP_IND; - break; - } - } - } - -/* Memory reference, continued */ - - switch (t) { /* decode IR<1:4> */ - case 001: /* JSR */ - AC[3] = PC; - case 000: /* JMP */ - old_PC = PC; - PC = MA; - break; - case 002: /* ISZ */ - src = (GetMap(MA) + 1) & 0177777; - if (MEM_ADDR_OK (MA)) PutMap(MA, src); - if (src == 0) PC = (PC + 1) & AMASK; - break; - case 003: /* DSZ */ - src = (GetMap(MA) - 1) & 0177777; - if (MEM_ADDR_OK (MA)) PutMap(MA, src); - if (src == 0) PC = (PC + 1) & AMASK; - break; - case 004: /* LDA 0 */ - if (SingleCycle) Usermap = SingleCycle; - AC[0] = GetMap(MA); - if (SingleCycle) { - Usermap = SingleCycle = 0; - if (Inhibit == 1) Inhibit = 3; - MapStat |= 02000; - MapStat &= 0177776; - } - break; - case 005: /* LDA 1 */ - if (SingleCycle) Usermap = SingleCycle; - AC[1] = GetMap(MA); - if (SingleCycle) { - Usermap = SingleCycle = 0; - if (Inhibit == 1) Inhibit = 3; - MapStat |= 02000; - MapStat &= 0177776; - } - break; - case 006: /* LDA 2 */ - if (SingleCycle) Usermap = SingleCycle; - AC[2] = GetMap(MA); - if (SingleCycle) { - Usermap = SingleCycle = 0; - if (Inhibit == 1) Inhibit = 3; - MapStat |= 02000; - MapStat &= 0177776; - } - break; - case 007: /* LDA 3 */ - if (SingleCycle) Usermap = SingleCycle; - AC[3] = GetMap(MA); - if (SingleCycle) { - Usermap = SingleCycle = 0; - if (Inhibit == 1) Inhibit = 3; - MapStat |= 02000; - MapStat &= 0177776; - } - break; - case 010: /* STA 0 */ - if (SingleCycle) - Usermap = SingleCycle; - if (MEM_ADDR_OK (MA)) PutMap(MA, AC[0]); - if (SingleCycle) { - Usermap = SingleCycle = 0; - if (Inhibit == 1) Inhibit = 3; - MapStat |= 02000; - MapStat &= 0177776; - } - break; - case 011: /* STA 1 */ - if (SingleCycle) - Usermap = SingleCycle; - if (MEM_ADDR_OK (MA)) PutMap(MA, AC[1]); - if (SingleCycle) { - Usermap = SingleCycle = 0; - if (Inhibit == 1) Inhibit = 3; - MapStat |= 02000; - MapStat &= 0177776; - } - break; - case 012: /* STA 2 */ - if (SingleCycle) - Usermap = SingleCycle; - if (MEM_ADDR_OK (MA)) PutMap(MA, AC[2]); - if (SingleCycle) { - Usermap = SingleCycle = 0; - if (Inhibit == 1) Inhibit = 3; - MapStat |= 02000; - MapStat &= 0177776; - } - break; - case 013: /* STA 3 */ - if (SingleCycle) - Usermap = SingleCycle; - if (MEM_ADDR_OK (MA)) PutMap(MA, AC[3]); - if (SingleCycle) { - Usermap = SingleCycle = 0; - if (Inhibit == 1) Inhibit = 3; - MapStat |= 02000; - MapStat &= 0177776; - } - break; } /* end switch */ - } /* end mem ref */ - -/* Operate instruction */ - -else if (t & 020) { /* operate? */ - register int32 src, srcAC, dstAC; - srcAC = (t >> 2) & 3; /* get reg decodes */ - dstAC = t & 03; - switch ((IR >> 4) & 03) { /* decode IR<10:11> */ - case 0: /* load */ - src = AC[srcAC] | C; - break; - case 1: /* clear */ - src = AC[srcAC]; - break; - case 2: /* set */ - src = AC[srcAC] | 0200000; - break; - case 3: /* complement */ - src = AC[srcAC] | (C ^ 0200000); - break; } /* end switch carry */ - switch ((IR >> 8) & 07) { /* decode IR<5:7> */ - case 0: /* COM */ - src = src ^ 0177777; - break; - case 1: /* NEG */ - src = ((src ^ 0177777) + 1) & 0377777; - break; - case 2: /* MOV */ - break; - case 3: /* INC */ - src = (src + 1) & 0377777; - break; - case 4: /* ADC */ - src = ((src ^ 0177777) + AC[dstAC]) & 0377777; - break; - case 5: /* SUB */ - src = ((src ^ 0177777) + AC[dstAC] + 1) & 0377777; - break; - case 6: /* ADD */ - src = (src + AC[dstAC]) & 0377777; - break; - case 7: /* AND */ - src = src & (AC[dstAC] | 0200000); - break; } /* end switch oper */ - -/* Operate, continued */ - - switch ((IR >> 6) & 03) { /* decode IR<8:9> */ - case 0: /* nop */ - break; - case 1: /* L */ - src = ((src << 1) | (src >> 16)) & 0377777; - break; - case 2: /* R */ - src = ((src >> 1) | (src << 16)) & 0377777; - break; - case 3: /* S */ - src = ((src & 0377) << 8) | ((src >> 8) & 0377) | - (src & 0200000); - break; } /* end switch shift */ - switch (IR & 07) { /* decode IR<13:15> */ - case 0: /* nop */ - break; - case 1: /* SKP */ - PC = (PC + 1) & AMASK; - break; - case 2: /* SZC */ - if (src < 0200000) PC = (PC + 1) & AMASK; - break; - case 3: /* SNC */ - if (src >= 0200000) PC = (PC + 1) & AMASK; - break; - case 4: /* SZR */ - if ((src & 0177777) == 0) PC = (PC + 1) & AMASK; - break; - case 5: /* SNR */ - if ((src & 0177777) != 0) PC = (PC + 1) & AMASK; - break; - case 6: /* SEZ */ - if (src <= 0200000) PC = (PC + 1) & AMASK; - break; - case 7: /* SBN */ - if (src > 0200000) PC = (PC + 1) & AMASK; - break; } /* end switch skip */ - if ((IR & 000010) == 0) { /* load? */ - AC[dstAC] = src & 0177777; - C = src & 0200000; } /* end if load */ - } /* end if operate */ - -/* IOT instruction */ - -else { /* IOT */ - register int32 dstAC, pulse, code, device, iodata; - char pulcode[4]; - - if ((MapStat & 0100) && Usermap) { /* We are in LEF Mode */ - AC[(IR >> 11) & 3] = LEFmode(PC - 1, (IR >> 8) & 3, IR & 0377, IR & 02000); - if (Debug_Flags & 020000) { - printf("\n\r<>\n\r", PC-1); - reason = STOP_IBKPT; - } - continue; - } - - dstAC = t & 03; /* decode fields */ - if ((MapStat & 040) && Usermap) { /* I/O protection fault */ - Fault = 020000; - continue; - } - code = (IR >> 8) & 07; - pulse = (IR >> 6) & 03; - device = IR & 077; - if (Debug_Flags && device == 0) { - printf("\n\r<>\n\r", PC-1); - reason = STOP_IBKPT; - } - if ((Debug_Flags & 0100) && (device == (Debug_Flags & 077))) { - printf("\n\r<>\n\r", device); - reason = STOP_IBKPT; - } - if (code == ioSKP) { /* IO skip? */ - switch (pulse) { /* decode IR<8:9> */ - case 0: /* skip if busy */ - if ((device == 077)? (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 == 077)? (int_req & INT_ION) == 0: - (dev_busy & dev_table[device].mask) == 0) - PC = (PC + 1) & AMASK; - break; - case 2: /* skip if done */ - if ((device == 077)? pwr_low != 0: - (dev_done & dev_table[device].mask) != 0) - PC = (PC + 1) & AMASK; - break; - case 3: /* skip if not done */ - if ((device == 077)? 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_CPU) { /* CPU control */ - switch (code) { /* decode IR<5:7> */ - case ioNIO: /* Get CPU ID */ - switch (model) { - case 280: /* S280 */ - AC[0] = 021102; - break; - case 380: - AC[0] = 013212; /* C380 */ - break; - default: - break; - } - break; /* Otherwise no-op */ - 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 IORST */ - reset_all (0); /* reset devices */ - Usermap = 0; /* reset MAP */ - MapStat &= 04; /* Reset MAP status */ - MapIntMode = 0; - Inhibit = 0; - Map31 = 037; - Check = SingleCycle = 0; - Fault = 0; - 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 (device == DEV_ECC) { - switch (code) { - case ioDIA: /* Read Fault Address */ - AC[dstAC] = 0; - break; - case ioDIB: /* Read fault code */ - AC[dstAC] = 0; - break; - case ioDOA: /* Enable ERCC */ - break; } - } - - else if (device == DEV_MAP) { /* MAP control */ - switch (code) { /* decode IR<5:7> */ - case ioNIO: /* No I/O -- Single */ - if (!Usermap || !(MapStat & 0140)) { - if ((Debug_Flags & 077) == 03) - fprintf(Trace, "%o NIO %o (No I/O, clear faults)\n", PC-1, dstAC); - MapStat &= ~036000; /* NIO Clears all faults */ - } else { - if ((Debug_Flags & 077) == 03) - fprintf(Trace, "%o NIO %o (No I/O, clear faults) NO EXEC(User mode)\n", PC-1, dstAC); - } - break; - case ioDIA: /* Read map status */ - if (!Usermap || !(MapStat & 0140)) { - if ((Debug_Flags & 077) == 03) - fprintf(Trace, "%o DIA %o=%o (Read Map Status)\n", PC-1, dstAC, MapStat); - AC[dstAC] = MapStat & 0xFFFE; - if (MapIntMode & 1) /* Bit 15 is mode asof last int */ - AC[dstAC] |= 1; - } else { - if ((Debug_Flags & 077) == 03) - fprintf(Trace, "%o DIA %o=%o (Read Map Status) NO EXEC(User mode)\n", PC-1, dstAC, MapStat); - } - break; - case ioDOA: /* Load map status */ - if (!Usermap || !(MapStat & 0140)) { - if ((Debug_Flags & 077) == 03) - fprintf(Trace, "%o DOA %o=%o (Load Map Status)\n", PC-1, dstAC, AC[dstAC]); - MapStat = AC[dstAC]; - MapIntMode = 0; - Enable = 1; - if (MapStat & 04) Enable = 2; - Check &= ~01600; - Check |= MapStat & 01600; - if (MapStat & 1) - Inhibit = 2; /* Inhibit interrupts */ - } else { - if ((Debug_Flags & 077) == 03) - fprintf(Trace, "%o DOA %o=%o (Load Map Status) NO EXEC(User mode)\n", PC-1, dstAC, AC[dstAC]); - } - break; - case ioDIB: /* not used */ - break; - case ioDOB: /* map block 31 */ - if (!Usermap || !(MapStat && 0140)) { - if ((Debug_Flags & 077) == 03) - fprintf(Trace, "%o DOB %o=%o (Map Blk 31)\n", PC-1, dstAC, AC[dstAC]); - Map31 = AC[dstAC] & PAGEMASK; - MapStat &= ~02000; - } else { - if ((Debug_Flags & 077) == 03) - fprintf(Trace, "%o DOB %o=%o (Map Blk 31) NO EXEC (User Mode)\n", PC-1, dstAC, AC[dstAC]); - } - break; - case ioDIC: /* Page Check */ - if (!Usermap || !(MapStat & 0140)) { - switch ((Check>>7) & 07) { - case 0: i=1; break; - case 1: i=6; break; - case 2: i=2; break; - case 3: i=7; break; - case 4: i=0; break; - case 5: i=4; break; - case 6: i=3; break; - case 7: i=5; break; - default: break; - } - j = (Check >> 10) & 037; - AC[dstAC] = Map[i][j] & 0101777; - AC[dstAC] |= ((Check << 5) & 070000); - if ((Debug_Flags & 077) == 03) - fprintf(Trace, "%o DIC %o=%o (Page Check)\n", PC-1, dstAC, AC[dstAC]); - MapStat &= ~02000; - } else { - if ((Debug_Flags & 077) == 03) - fprintf(Trace, "%o DIC %o=%o (Page Check) NO EXEC(User mode)\n", PC-1, dstAC, AC[dstAC]); - } - break; - case ioDOC: /* Init Page Check */ - if (!Usermap || !(MapStat & 0140)) { - if ((Debug_Flags & 077) == 03) - fprintf(Trace, "%o DOC %o=%o (Init Pg Chk)\n", PC-1, dstAC, AC[dstAC]); - Check = AC[dstAC]; - MapStat &= ~01600; - MapStat |= (Check & 01600); - MapStat &= ~02000; - } else { - if ((Debug_Flags & 077) == 03) - fprintf(Trace, "%o DOC %o=%o (Init Pg Chk) NO EXEC(User mode)\n", PC-1, dstAC, AC[dstAC]); - } - break; - } /* end switch code */ - switch (pulse) { - case iopP: - if ((Debug_Flags & 077) == 03) - fprintf(Trace, "%o xxxP (Single Cycle)\n", PC-1); - if (Usermap) { - MapStat &= 0177776; - Usermap = 0; - Inhibit = 0; - } else { - SingleCycle = Enable; - Inhibit = 1; /* Inhibit interrupts */ - } - break; } - } /* 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; - if ((Debug_Flags & 077) == device && Debug_Flags != 0) { - strcpy(pulcode, ""); - switch (pulse) { - case iopP: - strcpy(pulcode, "P"); - break; - case iopS: - strcpy(pulcode, "S"); - break; - case iopC: - strcpy(pulcode, "C"); - break; - default: - break; - } - switch(code) { - case ioNIO: - fprintf(Trace, "[%o] %o NIO%s %o\n", device, PC-1, pulcode, AC[dstAC]); - break; - case ioDIA: - fprintf(Trace, "[%o] %o DIA%s %o\n", device, PC-1, pulcode, iodata); - break; - case ioDIB: - fprintf(Trace, "[%o] %o DIB%s %o\n", device, PC-1, pulcode, iodata); - break; - case ioDIC: - fprintf(Trace, "[%o] %o DIC%s %o\n", device, PC-1, pulcode, iodata); - break; - case ioDOA: - fprintf(Trace, "[%o] %o DOA%s %o\n", device, PC-1, pulcode, AC[dstAC]); - break; - case ioDOB: - fprintf(Trace, "[%o] %o DOB%s %o\n", device, PC-1, pulcode, AC[dstAC]); - break; - case ioDOC: - fprintf(Trace, "[%o] %o DOC%s %o\n", device, PC-1, pulcode, AC[dstAC]); - break; - default: - break; - } /* end switch */ - } /* end if debug */ - } /* end else if */ - else reason = stop_dev; } /* end if IOT */ -} /* end while */ - -/* Simulation halted */ - -saved_PC = PC; -return reason; -} - -/* Computes and returns a 16-bit effective address, given a - program counter, index, and a displacement. -*/ - -int32 effective(int32 PC, int32 index, int32 disp) -{ - register int32 i, MA; - MA = disp & 077777; - switch (index) { /* decode IR<6:7> */ - case 0: /* page zero */ - break; - case 1: /* PC relative */ - MA = (MA + PC) & AMASK; - break; - case 2: /* AC2 relative */ - MA = (MA + AC[2]) & AMASK; - break; - case 3: /* AC3 relative */ - MA = (MA + AC[3]) & AMASK; - break; - } /* end switch mode */ - - if (disp & 0100000) { /* indirect? */ - for (i = 0; i < ind_max * 2; i++) { /* count indirects */ - MA = GetMap(MA & AMASK); - if (SingleCycle) Usermap = 0; - if (MapStat & 1) { /* Start MAP */ - Usermap = Enable; - Inhibit = 0; - } - if ((MA & 0100000) == 0) break; - if ((MapStat & 010) && Usermap && i >= ind_max) break; - } - if (i >= ind_max && (MapStat & 010) && Usermap) { - Fault = 04000; /* Map fault if IND prot */ - } - if (i >= (ind_max * 2) && !(Fault)) { - reason = STOP_IND_INT; /* Stop machine */ - } - } - return (MA & AMASK); -} - -/* Computes and returns a 16-bit effective address, given a - program counter, index, and a displacement. This is a - version supporting the LEF map mode instruction, as - opposed to the ELEF instruction. -*/ - -int32 LEFmode(int32 PC, int32 index, int32 disp, int32 indirect) -{ - register int32 i, MA; - int16 sMA; - MA = disp & 077777; - switch (index) { /* decode IR<6:7> */ - case 0: /* page zero */ - break; - case 1: /* PC relative */ - MA = (MA + PC) & AMASK; - break; - case 2: /* AC2 relative */ - sMA = MA; - if (MA & 0200) sMA |= 0xff00; - MA = (sMA + AC[2]) & AMASK; - break; - case 3: /* AC3 relative */ - sMA = MA; - if (MA & 0200) sMA |= 0xff00; - MA = (sMA + AC[3]) & AMASK; - break; - } /* end switch mode */ - - if (indirect) { /* indirect? */ - for (i = 0; i < (ind_max * 2); i++) { /* count indirects */ - if ((MA & 077770) == 020 && !(cpu_unit.flags & UNIT_MICRO)) - MA = (PutMap(MA & AMASK, (GetMap(MA & AMASK) + 1) & 0177777)); - else if ((MA & 077770) == 030 && !(cpu_unit.flags & UNIT_MICRO)) - MA = (PutMap(MA & AMASK, (GetMap(MA & AMASK) - 1) & 0177777)); - else MA = GetMap(MA & AMASK); - if (SingleCycle) Usermap = 0; - if (MapStat & 1) { /* Start MAP */ - Usermap = Enable; - Inhibit = 0; - } - if ((MA & 0100000) == 0) break; - if ((MapStat & 010) && Usermap && i >= ind_max) break; - } - if (i >= ind_max && (MapStat & 010) && Usermap) { - Fault = 04000; /* Map fault if IND prot */ - } - if (i >= (ind_max * 2) && !(Fault)) { - reason = STOP_IND_INT; /* Stop machine */ - } - } - return (MA & AMASK); -} - -/* Computes a "Byte pointer" for the Character Instruction set */ -/* This address in 'PC' must point to the displacement word of the instruction */ - -int32 Bytepointer(int32 PC, int32 index) -{ - register int32 MA; - switch (index) { /* decode IR<6:7> */ - case 0: /* page zero */ - MA = 0; - break; - case 1: /* PC relative */ - MA = PC & AMASK; - break; - case 2: /* AC2 relative */ - MA = AC[2] & AMASK; - break; - case 3: /* AC3 relative */ - MA = AC[3] & AMASK; - break; - } /* end switch mode */ - MA = (MA * 2) & 0177777; - MA = MA + M[PC]; - return (MA & 0177777); -} - -/* Given an address, returns either that address if bit 0 is 0, or - or follows an indirection chain until bit 0 is 0 -*/ - -int32 indirect(int32 d) -{ - int i; - - if (d & 0100000) { /* indirect? */ - for (i = 0; i < ind_max * 2; i++) { /* count indirects */ - if ((d & 077770) == 020 && !(cpu_unit.flags & UNIT_MICRO)) - d = (PutMap(d & AMASK, ((GetMap(d & AMASK) + 1) & 0177777))); - else if ((d & 077770) == 030 && !(cpu_unit.flags & UNIT_MICRO)) - d = (PutMap(d & AMASK, ((GetMap(d & AMASK) - 1) & 0177777))); - else d = GetMap(d & AMASK); - if (MapStat & 1) { /* Start MAP */ - Usermap = Enable; - Inhibit = 0; - } - if ((d & 0100000) == 0) break; - if ((MapStat & 010) && Usermap && i >= ind_max) break; - } - if (i >= ind_max && (MapStat & 010) && Usermap) { - Fault = 04000; /* Map fault if IND prot */ - } - if (i >= (ind_max * 2) && !(Fault)) { - reason = STOP_IND; /* Stop machine */ - } - } - return (d); -} - -/* Push a standard return block onto the stack */ - -int32 pushrtn(int32 pc) -{ - int32 t; - - t = (GetMap(040) + 1) & AMASK; - PutMap(t, AC[0]); - t++; - PutMap(t, AC[1]); - t++; - PutMap(t, AC[2]); - t++; - PutMap(t, AC[3]); - t++; - PutMap(t, pc); - if (C) PutMap(t, (GetMap(t) | 0100000)); - PutMap(040, t); - return 0; -} - - -/* Eclipse memory get/put - uses MAP if enabled */ - -int32 GetMap(int32 addr) -{ - int32 page; - uint32 paddr; - - switch (Usermap) { - case 0: - if (addr < 076000) - return M[addr]; - paddr = ((Map31 & PAGEMASK) << 10) | (addr & 001777); - if (paddr < MEMSIZE) - return M[paddr]; - else - return (0); - break; - case 1: - page = (addr >> 10) & 037; - paddr = ((Map[1][page] & 01777) << 10) | (addr & 001777); - if (Map[1][page] == INVALID && !SingleCycle) - Fault = 0100000; - if (paddr < MEMSIZE) - return M[paddr]; - else - return (0); - break; - case 2: - page = (addr >> 10) & 037; - paddr = ((Map[2][page] & PAGEMASK) << 10) | (addr & 001777); - if (Map[2][page] == INVALID && !SingleCycle) - Fault = 0100000; - if (paddr < MEMSIZE) - return M[paddr]; - else - return (0); - break; - case 6: - page = (addr >> 10) & 037; - paddr = ((Map[6][page] & PAGEMASK) << 10) | (addr & 001777); - if (Map[6][page] == INVALID && !SingleCycle) - Fault = 0100000; - if (paddr < MEMSIZE) - return M[paddr]; - else - return (0); - break; - case 7: - page = (addr >> 10) & 037; - paddr = ((Map[7][page] & PAGEMASK) << 10) | (addr & 001777); - if (Map[7][page] == INVALID && !SingleCycle) - Fault = 0100000; - if (paddr < MEMSIZE) - return M[paddr]; - else - return (0); - break; - default: - printf("\n\r<>\n\r"); - return M[addr]; - break; - } -} - -int32 PutMap(int32 addr, int32 data) -{ - int32 page; - uint32 paddr; - - switch (Usermap) { - case 0: - if (addr < 076000) { - M[addr] = data; - return (data); - } - paddr = ((Map31 & PAGEMASK) << 10) | (addr & 001777); - if (paddr < MEMSIZE) M[paddr] = data; - break; - case 1: - page = (addr >> 10) & 037; - paddr = ((Map[1][page] & PAGEMASK) << 10) | (addr & 001777); - if (((Map[1][page] & 0100000) && (MapStat & 020)) || Map[1][page] == INVALID) Fault = 010000; - else if (paddr < MEMSIZE) M[paddr] = data; - break; - case 2: - page = (addr >> 10) & 037; - paddr = ((Map[2][page] & PAGEMASK) << 10) | (addr & 001777); - if (((Map[2][page] & 0100000) && (MapStat & 020)) || Map[2][page] == INVALID) Fault = 010000; - else if (paddr < MEMSIZE) M[paddr] = data; - break; - case 6: - page = (addr >> 10) & 037; - paddr = ((Map[2][page] & PAGEMASK) << 10) | (addr & 001777); - if (((Map[6][page] & 0100000) && (MapStat & 020)) || Map[6][page] == INVALID) Fault = 010000; - else if (paddr < MEMSIZE) M[paddr] = data; - break; - case 7: - page = (addr >> 10) & 037; - paddr = ((Map[2][page] & PAGEMASK) << 10) | (addr & 001777); - if (((Map[7][page] & 0100000) && (MapStat & 020)) || Map[7][page] == INVALID) Fault = 010000; - else if (paddr < MEMSIZE) M[paddr] = data; - break; - default: - M[addr] = data; - break; - } - return (data); -} - -#if 0 -int16 GetDCHMap(int32 map, int32 addr) -{ - uint32 paddr; - if (!(MapStat & 02)) return M[addr]; - paddr = ((Map[map][(addr >> 10) & 037] & PAGEMASK) << 10) | (addr & 001777); - if (paddr < MEMSIZE) - return M[paddr]; - return (0); -} - -int16 PutDCHMap(int32 map, int32 addr, int16 data) -{ - uint32 paddr; - if (!(MapStat & 02)) { - M[addr] = data; - return (data); - } - paddr = ((Map[map][(addr >> 10) & 037] & PAGEMASK) << 10) | (addr & 001777); - if (paddr < MEMSIZE) - M[paddr] = data; - return (data); -} -#endif - -/* Given a map number and a logical, returns the physical address, unless - the map is not active, in which case logical = physical. This is - used primarily by the I/O routines to map data channel read/writes. -*/ - -int32 MapAddr(int32 map, int32 addr) -{ - int32 paddr; - if ((map == 0 || map > 2) && !(MapStat & 02)) return addr; - if (map > 0 && map < 3 && Usermap == 0) return addr; - paddr = ((Map[map][(addr >> 10) & 037] & PAGEMASK) << 10) | (addr & 001777); - return paddr; -} - -/* Loads a word into the Eclipse Maps */ - -int32 LoadMap(int32 w) -{ - int32 m; - - m = (w >> 10) & 037; - switch ((MapStat >> 7) & 07) { - case 0: /* Load user A Map */ - Map[1][m] = w & MAPMASK; - break; - case 1: /* Load user C Map */ - Map[6][m] = w & MAPMASK; - break; - case 2: /* Load user B Map */ - Map[2][m] = w & MAPMASK; - break; - case 3: /* Load user D Map */ - Map[7][m] = w & MAPMASK; - break; - case 4: /* Load DCH A Map */ - Map[0][m] = w & MAPMASK; - break; - case 5: /* Load DCH C Map */ - Map[4][m] = w; - break; - case 6: /* Load DCH B Map */ - Map[3][m] = w; - break; - case 7: /* Load DCH D Map */ - Map[5][m] = w; - break; - default: - break; - } - return 0; -} - -/* Displays an error on a unimplemented (in this sim) instr. */ - -int32 unimp(int32 PC) -{ - if (Debug_Flags) - printf("\n\r\007<<>>\n\r", PC - 1, GetMap(PC - 1)); - return 0; -} - -/* New priority mask out */ - -void mask_out (int32 newmask) -{ -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; } -int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable); -return; -} - -/* Reset routine */ - -t_stat cpu_reset (DEVICE *dptr) -{ -int_req = int_req & ~INT_ION; -pimask = 0; -dev_disable = 0; -pwr_low = 0; -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] & 0177777; -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 & 0177777; -return SCPE_OK; -} - -/* Alter memory size */ - -t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -int32 mc = 0; -uint32 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; -} - -/* MAP device services */ - -t_stat map_svc (UNIT *uptr) -{ -return SCPE_OK; -} - -/* Map examine */ - -t_stat map_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) -{ -if ((addr & 077) >= 037 || addr > 737) return SCPE_NXM; -uptr->u4 = -2; /* signal to print_sys in eclipse_sys.c: do not map */ -if (vptr != NULL) *vptr = Map[(addr >> 6) & 3][addr & 037] & 0177777; -return SCPE_OK; -} - -/* Memory deposit */ - -t_stat map_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw) -{ -if ((addr & 077) >= 037 || addr > 0737) return SCPE_NXM; -uptr->u4 = -2; /* signal to print_sys in eclipse_sys.c: do not map */ -Map[(addr >> 6) & 3][addr & 037] = val & 0177777; -return SCPE_OK; -} - -/* Bootstrap routine for CPU */ - -#define BOOT_START 00000 -#define BOOT_LEN (sizeof (boot_rom) / sizeof (int)) - -static const int32 boot_rom[] = { - 062677, /* IORST ;Reset all I/O */ - 060477, /* READS 0 ;Read SR into AC0 */ - 024026, /* LDA 1,C77 ;Get dev mask */ - 0107400, /* AND 0,1 ;Isolate dev code */ - 0124000, /* COM 1,1 ;- device code - 1 */ - 010014, /* LOOP: ISZ OP1 ;Device code to all */ - 010030, /* ISZ OP2 ;I/O instructions */ - 010032, /* ISZ OP3 */ - 0125404, /* INC 1,1,SZR ;done? */ - 000005, /* JMP LOOP ;No, increment again */ - 030016, /* LDA 2,C377 ;place JMP 377 into */ - 050377, /* STA 2,377 ;location 377 */ - 060077, /* OP1: 060077 ;start device (NIOS 0) */ - 0101102, /* MOVL 0,0,SZC ;Test switch 0, low speed? */ - 000377, /* C377: JMP 377 ;no - jmp 377 & wait */ - 004030, /* LOOP2: JSR GET+1 ;Get a frame */ - 0101065, /* MOVC 0,0,SNR ;is it non-zero? */ - 000017, /* JMP LOOP2 ;no, ignore */ - 004027, /* LOOP4: JSR GET ;yes, get full word */ - 046026, /* STA 1,@C77 ;store starting at 100 */ - /* ;2's complement of word ct */ - 010100, /* ISZ 100 ;done? */ - 000022, /* JMP LOOP4 ;no, get another */ - 000077, /* C77: JMP 77 ;yes location ctr and */ - /* ;jmp to last word */ - 0126420, /* GET: SUBZ 1,1 ; clr AC1, set carry */ - /* OP2: */ - 063577, /* LOOP3: 063577 ;done? (SKPDN 0) - 1 */ - 000030, /* JMP LOOP3 ;no -- wait */ - 060477, /* OP3: 060477 ;y--read in ac0 (DIAS 0,0) */ - 0107363, /* ADDCS 0,1,SNC ;add 2 frames swapped - got 2nd? */ - 000030, /* JMP LOOP3 ;no go back after it */ - 0125300, /* MOVS 1,1 ;yes swap them */ - 001400, /* JMP 0,3 ;rtn with full word */ - 0 /* 0 ;padding */ -}; - -t_stat cpu_boot (int32 unitno, DEVICE *dptr) -{ -int32 i; -extern int32 saved_PC; - -for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i]; -saved_PC = BOOT_START; -return SCPE_OK; -} - -int32 Debug_Entry(int32 PC, int32 inst, int32 inst2, int32 AC0, int32 AC1, int32 AC2, int32 AC3, int32 flags) -{ - hpc[hnext] = PC & 0xffff; - hinst[hnext] = inst & 0xffff; - hinst2[hnext] = inst2 & 0xffff; - hac0[hnext] = AC0 & 0xffff; - hac1[hnext] = AC1 & 0xffff; - hac2[hnext] = AC2 & 0xffff; - hac3[hnext] = AC3 & 0xffff; - hflags[hnext] = flags & 0xffff; - hnext++; - if (hnext >= hmax) { - hwrap = 1; - hnext = 0; - } - return 0; -} - -int32 Debug_Dump(UNIT *uptr, int32 val, char *cptr, void *desc) -{ - char debmap[4], debion[4]; - t_value simeval[20]; - int debcar; - FILE *Dumpf; - int start, end, ctr; - int count = 0; - - if (!Debug_Flags || Debug_Flags & 0100000) { - printf("History was not logged. Deposit a non-zero value\n"); - printf("in DEBUG with bit 0 being 1 to build history.\n"); - return SCPE_OK; - } - Dumpf = fopen("history.log", "w"); - if (!hwrap) { - start = 0; - end = hnext; - } else { - start = hnext; - end = hnext - 1; - if (end < 0) end = hmax; - } - ctr = start; - while (1) { - if (ctr == end) - break; - count++; - strcpy(debion, " "); - strcpy(debmap, " "); - debcar = 0; - if (hflags[ctr] & 0x80) { - fprintf(Dumpf, "--------- Interrupt %o (%o) to %6o ---------\n", - hinst[ctr], hac0[ctr], hac1[ctr]); - } else { - if (hflags[ctr] & 0x01) debcar = 1; - if (hflags[ctr] & 0x02) strcpy(debion, "I"); - if (hflags[ctr] & 0x04) strcpy(debmap, "A"); - if (hflags[ctr] & 0x08) strcpy(debmap, "B"); - if (hflags[ctr] & 0x10) strcpy(debmap, "C"); - if (hflags[ctr] & 0x20) strcpy(debmap, "D"); - fprintf(Dumpf, "%s%s%06o acs: %06o %06o %06o %06o %01o ", - debion, debmap, hpc[ctr], hac0[ctr], hac1[ctr], hac2[ctr], - hac3[ctr], debcar); - simeval[0] = hinst[ctr]; - simeval[1] = hinst2[ctr]; - fprint_sym (Dumpf, hpc[ctr], simeval, NULL, SWMASK('M')); - fprintf(Dumpf, "\n"); - } - ctr++; - if (ctr > hmax) - ctr = 0; - } - fclose(Dumpf); - printf("\n%d records dumped to history.log\n", count); - return SCPE_OK; -} - -/* Build dispatch table */ - -t_stat build_devtab (void) -{ -DEVICE *dptr; -DIB *dibp; -int32 i, dn; - -for (i = 0; i < 64; i++) { /* clr dev_table */ - dev_table[i].mask = 0; - dev_table[i].pi = 0; - dev_table[i].routine = NULL; } -for (i = 0; (dptr = sim_devices[i]) != NULL; i++) { /* loop thru dev */ - if (dibp = (DIB *) dptr->ctxt) { /* get DIB */ - dn = dibp->dnum; /* get dev num */ - dev_table[dn].mask = dibp->mask; /* copy entries */ - dev_table[dn].pi = dibp->pi; - dev_table[dn].routine = dibp->routine; } } -return SCPE_OK; -} diff --git a/NOVA/eclipse_tt.c b/NOVA/eclipse_tt.c deleted file mode 100644 index 972d80f7..00000000 --- a/NOVA/eclipse_tt.c +++ /dev/null @@ -1,395 +0,0 @@ -/* eclipse_tt.c: Eclipse console terminal simulator - - Copyright (c) 1998-2003, Charles E Owen - Portions copyright (c) 1993-2002, Robert M Supnik - Written by Charles Owen, used by gracious permission - Commercial use prohibited - - tti terminal input - tto terminal output - - 25-Apr-03 RMS Revised for extended file support - 03-Oct-02 RMS Added DIBs - 30-May-02 RMS Widened POS to 32b - 28-Jan-02 RMS Cleaned up compiler warnings -*/ - -#include "nova_defs.h" - -#define UNIT_V_DASHER (UNIT_V_UF + 0) /* Dasher mode */ -#define UNIT_DASHER (1 << UNIT_V_DASHER) - -extern int32 int_req, dev_busy, dev_done, dev_disable; - -int32 tti (int32 pulse, int32 code, int32 AC); -int32 tto (int32 pulse, int32 code, int32 AC); -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, char *cptr, void *desc); -void translate_in(); -int32 translate_out(int32 c); -int32 putseq(char *seq); - -/* TTI data structures - - tti_dev TTI device descriptor - tti_unit TTI unit descriptor - tti_reg TTI register list - ttx_mod TTI/TTO modifiers list -*/ - -DIB tti_dib = { DEV_TTI, INT_TTI, PI_TTI, &tti }; - -UNIT tti_unit = { UDATA (&tti_svc, 0, 0), KBD_POLL_WAIT }; - -REG tti_reg[] = { - { ORDATA (BUF, tti_unit.buf, 8) }, - { FLDATA (BUSY, dev_busy, INT_V_TTI) }, - { FLDATA (DONE, dev_done, INT_V_TTI) }, - { FLDATA (DISABLE, dev_disable, INT_V_TTI) }, - { FLDATA (INT, int_req, INT_V_TTI) }, - { DRDATA (POS, tti_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, tti_unit.wait, 24), REG_NZ + PV_LEFT }, - { NULL } }; - -MTAB ttx_mod[] = { - { UNIT_DASHER, 0, "ANSI", "ANSI", &ttx_setmod }, - { UNIT_DASHER, UNIT_DASHER, "Dasher", "DASHER", &ttx_setmod }, - { 0 } }; - -DEVICE tti_dev = { - "TTI", &tti_unit, tti_reg, ttx_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 descriptor - tto_reg TTO register list -*/ - -DIB tto_dib = { DEV_TTO, INT_TTO, PI_TTO, &tto }; - -UNIT tto_unit = { UDATA (&tto_svc, 0, 0), SERIAL_OUT_WAIT }; - -REG tto_reg[] = { - { ORDATA (BUF, tto_unit.buf, 8) }, - { FLDATA (BUSY, dev_busy, INT_V_TTO) }, - { FLDATA (DONE, dev_done, INT_V_TTO) }, - { FLDATA (DISABLE, dev_disable, INT_V_TTO) }, - { FLDATA (INT, int_req, INT_V_TTO) }, - { DRDATA (POS, tto_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, tto_unit.wait, 24), PV_LEFT }, - { NULL } }; - -DEVICE tto_dev = { - "TTO", &tto_unit, tto_reg, ttx_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &tto_reset, - NULL, NULL, NULL, - &tto_dib, 0 }; - - - -/* Terminal input: IOT routine */ - -int32 tti (int32 pulse, int32 code, int32 AC) -{ -int32 iodata; - -iodata = (code == ioDIA)? tti_unit.buf & 0377: 0; -switch (pulse) { /* decode IR<8:9> */ -case iopS: /* start */ - dev_busy = dev_busy | INT_TTI; /* set busy */ - dev_done = dev_done & ~INT_TTI; /* clear done, int */ - int_req = int_req & ~INT_TTI; - break; -case iopC: /* clear */ - dev_busy = dev_busy & ~INT_TTI; /* clear busy */ - dev_done = dev_done & ~INT_TTI; /* clear done, int */ - int_req = int_req & ~INT_TTI; - break; } /* end switch */ -return iodata; -} - -/* 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? */ -tti_unit.buf = temp & 0177; -/* --- BEGIN MODIFIED CODE --- */ -if (tti_unit.flags & UNIT_DASHER) /* translate input */ - translate_in(); -/* --- END MODIFIED CODE --- */ -dev_busy = dev_busy & ~INT_TTI; /* clear busy */ -dev_done = dev_done | INT_TTI; /* set done */ -int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable); -tti_unit.pos = tti_unit.pos + 1; -return SCPE_OK; -} - -/* -------------------- BEGIN INSERTION -----------------------*/ - -int curpos = 0; /* used by translate_out() */ -int row = 0, col = 0; /* ditto - for cursor positioning */ -int spec200 = 0; /* signals next char is 'special' */ - -/* Translation: Vt100 input to D200 keycodes. */ - -void translate_in() -{ - char rev = 0; - - if (tti_unit.buf == '\r') - rev = '\n'; - if (tti_unit.buf == '\n') - rev = '\r'; - if (rev) - tti_unit.buf = rev; -} - -/* -------------------- END INSERTION -----------------------*/ - -/* Reset routine */ - -t_stat tti_reset (DEVICE *dptr) -{ -tti_unit.buf = 0; -dev_busy = dev_busy & ~INT_TTI; /* clear busy */ -dev_done = dev_done & ~INT_TTI; /* clear done, int */ -int_req = int_req & ~INT_TTI; -sim_activate (&tti_unit, tti_unit.wait); /* activate unit */ -return SCPE_OK; -} - -/* Terminal output: IOT routine */ - -int32 tto (int32 pulse, int32 code, int32 AC) -{ -if (code == ioDOA) tto_unit.buf = AC & 0377; -switch (pulse) { /* decode IR<8:9> */ -case iopS: /* start */ - dev_busy = dev_busy | INT_TTO; /* set busy */ - dev_done = dev_done & ~INT_TTO; /* clear done, int */ - int_req = int_req & ~INT_TTO; - sim_activate (&tto_unit, tto_unit.wait); /* activate unit */ - break; -case iopC: /* clear */ - dev_busy = dev_busy & ~INT_TTO; /* clear busy */ - dev_done = dev_done & ~INT_TTO; /* clear done, int */ - int_req = int_req & ~INT_TTO; - sim_cancel (&tto_unit); /* deactivate unit */ - break; } /* end switch */ -return 0; -} - -/* Unit service */ - -t_stat tto_svc (UNIT *uptr) -{ -int32 c, temp; - -dev_busy = dev_busy & ~INT_TTO; /* clear busy */ -dev_done = dev_done | INT_TTO; /* set done */ -int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable); -c = tto_unit.buf & 0177; -/* --- BEGIN MODIFIED CODE --- */ -if (tto_unit.flags & UNIT_DASHER) { - if ((temp = translate_out(c)) != SCPE_OK) return temp; -} else { - if ((temp = sim_putchar (c)) != SCPE_OK) return temp; - tto_unit.pos = tto_unit.pos + 1; -} -/* --- END MODIFIED CODE --- */ -return SCPE_OK; -} - -/* -------------------- BEGIN INSERTION -----------------------*/ - -/* Translation routine - D200 screen controls to VT-100 controls. */ - -int32 translate_out(int32 c) -{ - int32 temp; - char outstr[32]; - - if (spec200 == 1) { /* Special terminal control seq */ - spec200 = 0; - switch (c) { - case 'C': /* read model ID */ - return SCPE_OK; - case 'E': /* Reverse video off */ - return SCPE_OK; - case 'D': /* Reverse video on */ - return SCPE_OK; - default: - return SCPE_OK; - } - } - if (curpos == 1) { /* 2nd char of cursor position */ - col = c & 0x7f; - curpos++; - return (SCPE_OK); - } - if (curpos == 2) { /* 3rd char of cursor position */ - row = c & 0x7f; - curpos = 0; - sprintf(outstr, "\033[%d;%dH", row+1, col+1); - if ((temp = putseq(outstr)) != SCPE_OK) return temp; - return (SCPE_OK); - } - switch (c) { /* Single-char command or data */ - case 003: /* Blink enable */ - break; - case 004: /* Blink disable */ - break; - case 005: /* Read cursor address */ - break; - case 010: /* Cursor home */ - sprintf(outstr, "\033[1;1H"); - if ((temp = putseq(outstr)) != SCPE_OK) return temp; - row = col = 0; - return (SCPE_OK); - case 012: /* Newline */ - if ((temp = sim_putchar('\r')) != SCPE_OK) return temp; - tto_unit.pos += 1; - if ((temp = sim_putchar(c)) != SCPE_OK) return temp; - tto_unit.pos += 1; - col = 1; - row++; - if (row > 24) row = 1; - return (SCPE_OK); - case 013: /* Erase EOL */ - sprintf(outstr, "\033[K"); - if ((temp = putseq(outstr)) != SCPE_OK) return temp; - return (SCPE_OK); - case 014: /* Erase screen */ - sprintf(outstr, "\033[1;1H\033[2J"); - if ((temp = putseq(outstr)) != SCPE_OK) return temp; - row = col = 0; - return (SCPE_OK); - case 015: /* CR */ - if ((temp = sim_putchar(c)) != SCPE_OK) return temp; - tto_unit.pos += 1; - col = 1; - return (SCPE_OK); - case 016: /* Blink On */ - sprintf(outstr, "\033[5m"); - if ((temp = putseq(outstr)) != SCPE_OK) return temp; - return (SCPE_OK); - case 017: /* Blink off */ - sprintf(outstr, "\033[25m"); - if ((temp = putseq(outstr)) != SCPE_OK) return temp; - return (SCPE_OK); - case 020: /* Write cursor address */ - curpos = 1; - return SCPE_OK; - case 024: /* underscore on */ - sprintf(outstr, "\033[4m"); - if ((temp = putseq(outstr)) != SCPE_OK) return temp; - return (SCPE_OK); - case 025: /* underscore off */ - sprintf(outstr, "\033[24m"); - if ((temp = putseq(outstr)) != SCPE_OK) return temp; - return (SCPE_OK); - break; - case 027: /* cursor up */ - sprintf(outstr, "\033[A"); - if ((temp = putseq(outstr)) != SCPE_OK) return temp; - row--; - if (row < 1) row = 24; - return (SCPE_OK); - case 030: /* cursor right */ - sprintf(outstr, "\033[C"); - if ((temp = putseq(outstr)) != SCPE_OK) return temp; - col++; - if (col > 80) { - col = 1; - row++; - if (row > 24) row = 1; - } - return (SCPE_OK); - case 031: /* Cursor left */ - sprintf(outstr, "\033[D"); - if ((temp = putseq(outstr)) != SCPE_OK) return temp; - tto_unit.pos += 1; - col--; - if (col < 1) { - col = 80; - row--; - if (row < 1) row = 24; - } - return (SCPE_OK); - case 032: /* Cursor down */ - sprintf(outstr, "\033[B"); - if ((temp = putseq(outstr)) != SCPE_OK) return temp; - row++; - if (row > 24) row = 1; - return (SCPE_OK); - case 034: /* Dim on */ - sprintf(outstr, "\033[22m"); - if ((temp = putseq(outstr)) != SCPE_OK) return temp; - return (SCPE_OK); - case 035: /* Dim off */ - sprintf(outstr, "\033[1m"); - if ((temp = putseq(outstr)) != SCPE_OK) return temp; - return (SCPE_OK); - case 036: /* Special sequence */ - spec200 = 1; - return SCPE_OK; - default: /* ..A character of data */ - if ((temp = sim_putchar(c)) != SCPE_OK) return temp; - tto_unit.pos += 1; - col++; - if (col > 80) { - col = 1; - row++; - if (row > 24) row = 24; - } - return (SCPE_OK); - } - return SCPE_OK; -} - -int32 putseq(char *seq) -{ - int i, len, temp; - - len = strlen(seq); - for (i = 0; i < len; i++) { - if ((temp = sim_putchar(seq[i])) != SCPE_OK) - return temp; - tto_unit.pos += 1; - } - return SCPE_OK; -} - -/* -------------------- END INSERTION -----------------------*/ - -/* Reset routine */ - -t_stat tto_reset (DEVICE *dptr) -{ -tto_unit.buf = 0; -dev_busy = dev_busy & ~INT_TTO; /* clear busy */ -dev_done = dev_done & ~INT_TTO; /* clear done, int */ -int_req = int_req & ~INT_TTO; -sim_cancel (&tto_unit); /* deactivate unit */ -return SCPE_OK; -} - -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; -return SCPE_OK; -} diff --git a/NOVA/nova_clk.c b/NOVA/nova_clk.c deleted file mode 100644 index 315e4050..00000000 --- a/NOVA/nova_clk.c +++ /dev/null @@ -1,163 +0,0 @@ -/* nova_clk.c: NOVA real-time clock simulator - - 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. - - clk real-time clock - - 01-Mar-03 RMS Added SET/SHOW CLK FREQ support - 03-Oct-02 RMS Added DIB - 17-Sep-01 RMS Added terminal multiplexor support - 17-Mar-01 RMS Moved function prototype - 05-Mar-01 RMS Added clock calibration - 24-Sep-97 RMS Fixed bug in unit service (found by Charles Owen) -*/ - -#include "nova_defs.h" - -extern int32 int_req, dev_busy, dev_done, dev_disable; - -int32 clk_sel = 0; /* selected freq */ -int32 clk_time[4] = { 16000, 100000, 10000, 1000 }; /* freq table */ -int32 clk_tps[4] = { 60, 10, 100, 1000 }; /* ticks per sec */ -int32 clk_adj[4] = { 1, -5, 2, 20 }; /* tmxr adjust */ -int32 tmxr_poll = 16000; /* tmxr poll */ - -int32 clk (int32 pulse, int32 code, int32 AC); -t_stat clk_svc (UNIT *uptr); -t_stat clk_reset (DEVICE *dptr); -t_stat clk_set_freq (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat clk_show_freq (FILE *st, UNIT *uptr, int32 val, void *desc); - -/* CLK data structures - - clk_dev CLK device descriptor - clk_unit CLK unit descriptor - clk_reg CLK register list -*/ - -DIB clk_dib = { DEV_CLK, INT_CLK, PI_CLK, &clk }; - -UNIT clk_unit = { UDATA (&clk_svc, 0, 0) }; - -REG clk_reg[] = { - { ORDATA (SELECT, clk_sel, 2) }, - { FLDATA (BUSY, dev_busy, INT_V_CLK) }, - { FLDATA (DONE, dev_done, INT_V_CLK) }, - { FLDATA (DISABLE, dev_disable, INT_V_CLK) }, - { FLDATA (INT, int_req, INT_V_CLK) }, - { DRDATA (TIME0, clk_time[0], 24), REG_NZ + PV_LEFT }, - { DRDATA (TIME1, clk_time[1], 24), REG_NZ + PV_LEFT }, - { DRDATA (TIME2, clk_time[2], 24), REG_NZ + PV_LEFT }, - { DRDATA (TIME3, clk_time[3], 24), REG_NZ + PV_LEFT }, - { DRDATA (TPS0, clk_tps[0], 6), PV_LEFT + REG_HRO }, - { NULL } }; - -MTAB clk_mod[] = { - { MTAB_XTD|MTAB_VDV, 50, NULL, "50HZ", - &clk_set_freq, NULL, NULL }, - { MTAB_XTD|MTAB_VDV, 60, NULL, "60HZ", - &clk_set_freq, NULL, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "LINE", NULL, - NULL, &clk_show_freq, NULL }, - { 0 } }; - -DEVICE clk_dev = { - "CLK", &clk_unit, clk_reg, clk_mod, - 1, 0, 0, 0, 0, 0, - NULL, NULL, &clk_reset, - NULL, NULL, NULL, - &clk_dib, 0 }; - -/* IOT routine */ - -int32 clk (int32 pulse, int32 code, int32 AC) -{ -if (code == ioDOA) { /* DOA */ - clk_sel = AC & 3; /* save select */ - sim_rtc_init (clk_time[clk_sel]); } /* init calibr */ -switch (pulse) { /* decode IR<8:9> */ -case iopS: /* start */ - dev_busy = dev_busy | INT_CLK; /* set busy */ - 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 */ - break; -case iopC: /* clear */ - dev_busy = dev_busy & ~INT_CLK; /* clear busy */ - dev_done = dev_done & ~INT_CLK; /* clear done, int */ - int_req = int_req & ~INT_CLK; - sim_cancel (&clk_unit); /* deactivate unit */ - break; } /* end switch */ -return 0; -} - -/* Unit service */ - -t_stat clk_svc (UNIT *uptr) -{ -int32 t; - -dev_done = dev_done | INT_CLK; /* set done */ -dev_busy = dev_busy & ~INT_CLK; /* clear busy */ -int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable); -t = sim_rtc_calb (clk_tps[clk_sel]); /* calibrate delay */ -sim_activate (&clk_unit, t); /* reactivate unit */ -if (clk_adj[clk_sel] > 0) /* clk >= 60Hz? */ - tmxr_poll = t * clk_adj[clk_sel]; /* poll is longer */ -else tmxr_poll = t / (-clk_adj[clk_sel]); /* poll is shorter */ -return SCPE_OK; -} - -/* Reset routine */ - -t_stat clk_reset (DEVICE *dptr) -{ -clk_sel = 0; -dev_busy = dev_busy & ~INT_CLK; /* clear busy */ -dev_done = dev_done & ~INT_CLK; /* clear done, int */ -int_req = int_req & ~INT_CLK; -sim_cancel (&clk_unit); /* deactivate unit */ -tmxr_poll = clk_time[0]; /* poll is default */ -return SCPE_OK; -} - -/* Set line frequency */ - -t_stat clk_set_freq (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -if (cptr) return SCPE_ARG; -if ((val != 50) && (val != 60)) return SCPE_IERR; -clk_tps[0] = val; -return SCPE_OK; -} - -/* Show line frequency */ - -t_stat clk_show_freq (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -fprintf (st, (clk_tps[0] == 50)? "50Hz": "60Hz"); -return SCPE_OK; -} diff --git a/NOVA/nova_cpu.c b/NOVA/nova_cpu.c deleted file mode 100644 index 864786d7..00000000 --- a/NOVA/nova_cpu.c +++ /dev/null @@ -1,900 +0,0 @@ -/* nova_cpu.c: NOVA CPU simulator - - 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. - - cpu Nova central processor - - 19-Jan-03 RMS Changed CMASK to CDMASK for Apple Dev Kit conflict - 03-Oct-02 RMS Added DIB infrastructure - 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 - 10-Aug-01 RMS Removed register in declarations - 17-Jul-01 RMS Moved function prototype - 26-Apr-01 RMS Added device enable/disable support - 05-Mar-01 RMS Added clock calibration - 22-Dec-00 RMS Added Bruce Ray's second terminal - 15-Dec-00 RMS Added Charles Owen's CPU bootstrap - 08-Dec-00 RMS Changes from Bruce Ray - -- fixed trap test to include Nova 3 - -- fixed DIV and DIVS divide by 0 - -- fixed RETN to set SP from FP - -- fixed IORST to preserve carry - -- added "secret" Nova 4 PSHN/SAVEN instructions - -- added plotter support - 15-Oct-00 RMS Fixed bug in MDV test, added stack, byte, trap instructions - 14-Apr-98 RMS Changed t_addr to unsigned - 15-Sep-97 RMS Added read and write breakpoints - - The register state for the NOVA CPU is: - - AC[0:3]<0:15> general registers - C carry flag - PC<0:14> program counter - - The NOVA has three instruction formats: memory reference, 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 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | 0| op | AC |in| mode| displacement | memory reference - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - <0:4> mnemonic action - - 00000 JMP PC = MA - 00001 JMS AC3 = PC, PC = MA - 00010 ISZ M[MA] = M[MA] + 1, skip if M[MA] == 0 - 00011 DSZ M[MA] = M[MA] - 1, skip if M[MA] == 0 - 001'n LDA ACn = M[MA] - 010'n STA M[MA] = ACn - - <5:7> mode action - - 000 page zero direct MA = zext (IR<8:15>) - 001 PC relative direct MA = PC + sext (IR<8:15>) - 010 AC2 relative direct MA = AC2 + sext (IR<8:15>) - 011 AC3 relative direct MA = AC3 + sext (IR<8:15>) - 100 page zero indirect MA = M[zext (IR<8:15>)] - 101 PC relative indirect MA = M[PC + sext (IR<8:15>)] - 110 AC2 relative indirect MA = M[AC2 + sext (IR<8:15>)] - 111 AC3 relative indirect MA = M[AC3 + sext (IR<8:15>)] - - Memory reference instructions can access an address space of 32K words. - An instruction can directly reference the first 256 words of memory - (called page zero), as well as 256 words relative to the PC, AC2, or - AC3; it can indirectly access all 32K words. If an indirect address - is in locations 00020-00027, the indirect address is incremented and - rewritten to memory before use; if in 00030-00037, decremented and - rewritten. -*/ - -/* The I/O transfer format is: - - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | 0 1 1| AC | opcode |pulse| device | I/O transfer - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - The IOT instruction sends the opcode, pulse, and specified AC to the - specified I/O device. The device may accept data, provide data, - initiate or cancel operations, or skip on status. - - The operate format is: - - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | 1|srcAC|dstAC| opcode |shift|carry|nl| skip | operate - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - \______/ \___/ \___/ | | | | - | | | | | | +--- reverse skip sense - | | | | | +--- skip if C == 0 - | | | | +--- skip if result == 0 - | | | +--- don't load result - | | +--- carry in (load as is, - | | set to Zero, - | | set to One, - | | load Complement) - | +--- shift (none, - | left one, - | right one, - | byte swap) - +--- operation (complement, - negate, - move, - increment, - add complement, - subtract, - add, - and) - - The operate instruction can be microprogrammed to perform operations - on the source and destination AC's and the Carry flag. - - Some notes from Bruce Ray: - - 1. DG uses the value of the autoindex location -before- the - modification to determine if additional indirect address - levels are to be performed. Most DG emulators conform to - this standard, but some vendor machines (i.e. Point 4 Mark 8) - do not. - - 2. Infinite indirect references may occur on unmapped systems - and can "hang" the hardware. Some DG diagnostics perform - 10,000s of references during a single instruction. - - 3. Nova 3 adds the following instructions to the standard Nova - instruction set: - - trap instructions - stack push/pop instructions - save/return instructions - stack register manipulation instructions - unsigned MUL/DIV - - 4. Nova 4 adds the following instructions to the Nova 3 instruction - set: - - signed MUL/DIV - load/store byte - secret (undocumented) stack instructions [PSHN, SAVN] - - 5. Nova, Nova 3 and Nova 4 unsigned mul/div instructions are the - same instruction code values on all machines. -*/ - -/* This routine is the instruction decode routine for the NOVA. - 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 - infinite indirection loop - unknown I/O device and STOP_DEV flag set - I/O error in I/O simulator - - 2. Interrupts. Interrupts are maintained by four parallel variables: - - dev_done device done flags - dev_disable device interrupt disable flags - dev_busy device busy flags - int_req interrupt requests - - In addition, int_req contains the interrupt enable and ION pending - flags. If ION and ION pending are set, and at least one interrupt - request is pending, then an interrupt occurs. Note that the 16b PIO - mask must be mapped to the simulator's device bit mapping. - - 3. Non-existent memory. On the NOVA, 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: - - nova_defs.h add interrupt request definition - nova_sys.c add sim_devices entry -*/ - -#include "nova_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 INCA(x) (((x) + 1) & AMASK) -#define DECA(x) (((x) - 1) & AMASK) -#define SEXT(x) (((x) & SIGN)? ((x) | ~DMASK): (x)) -#define STK_CHECK(x,y) if (((x) & 0377) < (y)) int_req = int_req | INT_STK -#define IND_STEP(x) M[x] & A_IND; \ - if (((x) & 077770) == AUTO_INC) \ - M[x] = (M[x] + 1) & 0177777; \ - else if (((x) & 077770) == AUTO_DEC) \ - M[x] = (M[x] - 1) & 0177777; \ - x = M[x] & AMASK - -#define UNIT_V_MDV (UNIT_V_UF + 0) /* MDV present */ -#define UNIT_V_STK (UNIT_V_UF + 1) /* stack instr */ -#define UNIT_V_BYT (UNIT_V_UF + 2) /* byte instr */ -#define UNIT_V_MSIZE (UNIT_V_UF + 3) /* dummy mask */ -#define UNIT_MDV (1 << UNIT_V_MDV) -#define UNIT_STK (1 << UNIT_V_STK) -#define UNIT_BYT (1 << UNIT_V_BYT) -#define UNIT_MSIZE (1 << UNIT_V_MSIZE) -#define UNIT_IOPT (UNIT_MDV | UNIT_STK | UNIT_BYT) -#define UNIT_NOVA3 (UNIT_MDV | UNIT_STK) -#define UNIT_NOVA4 (UNIT_MDV | UNIT_STK | UNIT_BYT) - -uint16 M[MAXMEMSIZE] = { 0 }; /* memory */ -int32 AC[4] = { 0 }; /* accumulators */ -int32 C = 0; /* carry flag */ -int32 saved_PC = 0; /* program counter */ -int32 SP = 0; /* stack pointer */ -int32 FP = 0; /* frame pointer */ -int32 SR = 0; /* switch register */ -int32 dev_done = 0; /* device done flags */ -int32 dev_busy = 0; /* device busy flags */ -int32 dev_disable = 0; /* int disable flags */ -int32 int_req = 0; /* interrupt requests */ -int32 pimask = 0; /* priority int mask */ -int32 pwr_low = 0; /* power fail flag */ -int32 ind_max = 16; /* iadr nest limit */ -int32 stop_dev = 0; /* stop on ill dev */ -uint16 pcq[PCQ_SIZE] = { 0 }; /* PC queue */ -int32 pcq_p = 0; /* PC queue ptr */ -REG *pcq_r = NULL; /* PC queue reg ptr */ -struct ndev dev_table[64]; /* dispatch table */ - -extern int32 sim_int_char; -extern int32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */ -extern DEVICE *sim_devices[]; - -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_boot (int32 unitno, DEVICE *dptr); -t_stat build_devtab (void); - -/* 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 + UNIT_MDV, - MAXMEMSIZE) }; - -REG cpu_reg[] = { - { ORDATA (PC, saved_PC, 15) }, - { ORDATA (AC0, AC[0], 16) }, - { ORDATA (AC1, AC[1], 16) }, - { ORDATA (AC2, AC[2], 16) }, - { ORDATA (AC3, AC[3], 16) }, - { FLDATA (C, C, 16) }, - { ORDATA (SP, SP, 16) }, - { ORDATA (FP, FP, 16) }, - { ORDATA (SR, SR, 16) }, - { ORDATA (PI, pimask, 16) }, - { FLDATA (ION, int_req, INT_V_ION) }, - { FLDATA (ION_DELAY, int_req, INT_V_NO_ION_PENDING) }, - { FLDATA (STKOVF, int_req, INT_V_STK) }, - { FLDATA (PWR, pwr_low, 0) }, - { ORDATA (INT, int_req, INT_V_ION+1), REG_RO }, - { ORDATA (BUSY, dev_busy, INT_V_ION+1), REG_RO }, - { ORDATA (DONE, dev_done, INT_V_ION+1), REG_RO }, - { ORDATA (DISABLE, dev_disable, INT_V_ION+1), REG_RO }, - { FLDATA (STOP_DEV, stop_dev, 0) }, - { DRDATA (INDMAX, ind_max, 16), REG_NZ + PV_LEFT }, - { BRDATA (PCQ, pcq, 8, 16, PCQ_SIZE), REG_RO+REG_CIRC }, - { ORDATA (PCQP, pcq_p, 6), REG_HRO }, - { ORDATA (WRU, sim_int_char, 8) }, - { NULL } }; - -MTAB cpu_mod[] = { - { UNIT_IOPT, UNIT_NOVA3, "NOVA3", "NOVA3", NULL }, - { UNIT_IOPT, UNIT_NOVA4, "NOVA4", "NOVA4", NULL }, - { UNIT_IOPT, UNIT_MDV, "MDV", "MDV", NULL }, - { UNIT_IOPT, 0, "none", "NONE", 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 }, - { 0 } }; - -DEVICE cpu_dev = { - "CPU", &cpu_unit, cpu_reg, cpu_mod, - 1, 8, 15, 1, 8, 16, - &cpu_ex, &cpu_dep, &cpu_reset, - NULL, NULL, NULL }; - -t_stat sim_instr (void) -{ -extern int32 sim_interval; -int32 PC, IR, i; -t_stat reason; -void mask_out (int32 mask); -extern int32 clk_sel, clk_time[4]; - -/* Restore register state */ - -if (build_devtab () != SCPE_OK) return SCPE_IERR; /* build dispatch */ -PC = saved_PC & AMASK; /* load local PC */ -C = C & CBIT; -mask_out (pimask); /* reset int system */ -reason = 0; -sim_rtc_init (clk_time[clk_sel]); /* init calibration */ - -/* Main instruction fetch/decode loop */ - -while (reason == 0) { /* loop until halted */ -if (sim_interval <= 0) { /* check clock queue */ - if (reason = sim_process_event ()) break; } - -if (int_req > INT_PENDING) { /* interrupt? */ - int32 MA, indf; - int_req = int_req & ~INT_ION; /* intr off */ - 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 */ - else MA = INT_JMP; /* intr: jmp @1 */ - for (i = 0, indf = 1; indf && (i < ind_max); i++) { - indf = IND_STEP (MA); } /* indirect loop */ - if (i >= ind_max) { - reason = STOP_IND_INT; - break; } - PC = MA; } /* end interrupt */ - -if (sim_brk_summ && sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */ - reason = STOP_IBKPT; /* stop simulation */ - break; } - -IR = M[PC]; /* fetch instr */ -PC = (PC + 1) & AMASK; -int_req = int_req | INT_NO_ION_PENDING; /* clear ION delay */ -sim_interval = sim_interval - 1; - -/* Operate instruction */ - -if (IR & I_OPR) { /* operate? */ - int32 src, srcAC, dstAC; - srcAC = I_GETSRC (IR); /* get reg decodes */ - dstAC = I_GETDST (IR); - switch (I_GETCRY (IR)) { /* decode carry */ - case 0: /* load */ - src = AC[srcAC] | C; - break; - case 1: /* clear */ - src = AC[srcAC]; - break; - case 2: /* set */ - src = AC[srcAC] | CBIT; - break; - case 3: /* complement */ - src = AC[srcAC] | (C ^ CBIT); - break; } /* end switch carry */ - switch (I_GETALU (IR)) { /* decode ALU */ - case 0: /* COM */ - src = src ^ DMASK; - break; - case 1: /* NEG */ - src = ((src ^ DMASK) + 1) & CDMASK; - break; - case 2: /* MOV */ - break; - case 3: /* INC */ - src = (src + 1) & CDMASK; - break; - case 4: /* ADC */ - src = ((src ^ DMASK) + AC[dstAC]) & CDMASK; - break; - case 5: /* SUB */ - src = ((src ^ DMASK) + AC[dstAC] + 1) & CDMASK; - break; - case 6: /* ADD */ - src = (src + AC[dstAC]) & CDMASK; - break; - case 7: /* AND */ - src = src & (AC[dstAC] | CBIT); - break; } /* end switch oper */ - -/* Operate, continued */ - - switch (I_GETSHF (IR)) { /* decode shift */ - case 0: /* nop */ - break; - case 1: /* L */ - src = ((src << 1) | (src >> 16)) & CDMASK; - break; - case 2: /* R */ - src = ((src >> 1) | (src << 16)) & CDMASK; - break; - case 3: /* S */ - 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; - case 1: /* SKP */ - PC = (PC + 1) & AMASK; - break; - case 2: /* SZC */ - if (src < CBIT) PC = (PC + 1) & AMASK; - break; - case 3: /* SNC */ - if (src >= CBIT) PC = (PC + 1) & AMASK; - break; - case 4: /* SZR */ - if ((src & DMASK) == 0) PC = (PC + 1) & AMASK; - break; - case 5: /* SNR */ - if ((src & DMASK) != 0) PC = (PC + 1) & AMASK; - break; - case 6: /* SEZ */ - if (src <= CBIT) PC = (PC + 1) & AMASK; - break; - case 7: /* SBN */ - 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 */ - } /* end if operate */ - -/* Memory reference instructions */ - -else if (IR < 060000) { /* mem ref? */ - int32 src, MA, indf; - MA = I_GETDISP (IR); /* get disp */ - switch (I_GETMODE (IR)) { /* decode mode */ - case 0: /* page zero */ - break; - case 1: /* PC relative */ - 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; - case 3: /* AC3 relative */ - 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; } } - -/* Memory reference, continued */ - - switch (I_GETOPAC (IR)) { /* decode op + AC */ - case 001: /* JSR */ - AC[3] = PC; - case 000: /* JMP */ - 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; - case 003: /* DSZ */ - 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; - case 005: /* LDA 1 */ - AC[1] = M[MA]; - break; - case 006: /* LDA 2 */ - AC[2] = M[MA]; - break; - case 007: /* LDA 3 */ - AC[3] = M[MA]; - break; - case 010: /* STA 0 */ - if (MEM_ADDR_OK (MA)) M[MA] = AC[0]; - break; - case 011: /* STA 1 */ - if (MEM_ADDR_OK (MA)) M[MA] = AC[1]; - break; - case 012: /* STA 2 */ - 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 */ - } /* end mem ref */ - -/* IOT instruction */ - -else { /* IOT */ - int32 dstAC, pulse, code, device, iodata; - dstAC = I_GETDST (IR); /* decode fields */ - code = I_GETIOT (IR); - 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 */ - -/* 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 = (uint32) AC[0]; - uAC1 = (uint32) AC[1]; - uAC2 = (uint32) 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 */ - 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; } - else reason = stop_dev; - } /* end if IOT */ -} /* end while */ - -/* Simulation halted */ - -saved_PC = PC; -pcq_r->qptr = pcq_p; /* update pc q ptr */ -return reason; -} - -/* New priority mask out */ - -void mask_out (int32 newmask) -{ -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; } -int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable); -return; -} - -/* Reset routine */ - -t_stat cpu_reset (DEVICE *dptr) -{ -int_req = int_req & ~(INT_ION | INT_STK); -pimask = 0; -dev_disable = 0; -pwr_low = 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] & DMASK; -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 & DMASK; -return SCPE_OK; -} - -/* Alter 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; -} - -/* Build dispatch table */ - -t_stat build_devtab (void) -{ -DEVICE *dptr; -DIB *dibp; -int32 i, dn; - -for (i = 0; i < 64; i++) { /* clr dev_table */ - dev_table[i].mask = 0; - dev_table[i].pi = 0; - dev_table[i].routine = NULL; } -for (i = 0; (dptr = sim_devices[i]) != NULL; i++) { /* loop thru dev */ - if (dibp = (DIB *) dptr->ctxt) { /* get DIB */ - dn = dibp->dnum; /* get dev num */ - dev_table[dn].mask = dibp->mask; /* copy entries */ - dev_table[dn].pi = dibp->pi; - dev_table[dn].routine = dibp->routine; } } -return SCPE_OK; -} - -/* Bootstrap routine for CPU */ - -#define BOOT_START 00000 -#define BOOT_LEN (sizeof (boot_rom) / sizeof (int)) - -static const int32 boot_rom[] = { - 0062677, /* IORST ;reset all I/O */ - 0060477, /* READS 0 ;read SR into AC0 */ - 0024026, /* LDA 1,C77 ;get dev mask */ - 0107400, /* AND 0,1 ;isolate dev code */ - 0124000, /* COM 1,1 ;- device code - 1 */ - 0010014, /* LOOP: ISZ OP1 ;device code to all */ - 0010030, /* ISZ OP2 ;I/O instructions */ - 0010032, /* ISZ OP3 */ - 0125404, /* INC 1,1,SZR ;done? */ - 0000005, /* JMP LOOP ;no, increment again */ - 0030016, /* LDA 2,C377 ;place JMP 377 into */ - 0050377, /* STA 2,377 ;location 377 */ - 0060077, /* OP1: 060077 ;start device (NIOS 0) */ - 00101102, /* MOVL 0,0,SZC ;test switch 0, low speed? */ - 0000377, /* C377: JMP 377 ;no - jmp 377 & wait */ - 0004030, /* LOOP2: JSR GET+1 ;get a frame */ - 0101065, /* MOVC 0,0,SNR ;is it non-zero? */ - 0000017, /* JMP LOOP2 ;no, ignore */ - 0004027, /* LOOP4: JSR GET ;yes, get full word */ - 0046026, /* STA 1,@C77 ;store starting at 100 */ - /* ;2's complement of word ct */ - 0010100, /* ISZ 100 ;done? */ - 0000022, /* JMP LOOP4 ;no, get another */ - 0000077, /* C77: JMP 77 ;yes location ctr and */ - /* ;jmp to last word */ - 0126420, /* GET: SUBZ 1,1 ; clr AC1, set carry */ - /* OP2: */ - 0063577, /* LOOP3: 063577 ;done? (SKPDN 0) - 1 */ - 0000030, /* JMP LOOP3 ;no -- wait */ - 0060477, /* OP3: 060477 ;y -- read in ac0 (DIAS 0,0) */ - 0107363, /* ADDCS 0,1,SNC ;add 2 frames swapped - got 2nd? */ - 0000030, /* JMP LOOP3 ;no go back after it */ - 0125300, /* MOVS 1,1 ;yes swap them */ - 0001400, /* JMP 0,3 ;rtn with full word */ - 0000000 /* 0 ;padding */ -}; - -t_stat cpu_boot (int32 unitno, DEVICE *dptr) -{ -int32 i; -extern int32 saved_PC; - -for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i]; -saved_PC = BOOT_START; -return SCPE_OK; -} - -/* 1-to-1 map for I/O devices */ - -int32 MapAddr (int32 map, int32 addr) -{ -return addr; -} diff --git a/NOVA/nova_defs.h b/NOVA/nova_defs.h deleted file mode 100644 index fdad7f22..00000000 --- a/NOVA/nova_defs.h +++ /dev/null @@ -1,271 +0,0 @@ -/* nova_defs.h: NOVA/Eclipse simulator definitions - - 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. - - 19-Jan-03 RMS Changed CMASK to CDMASK for Apple Dev kit conflict - 03-Oct-02 RMS Added device information structure - 22-Dec-00 RMS Added Bruce Ray's second terminal support - 10-Dec-00 RMS Added Charles Owen's Eclipse support - 08-Dec-00 RMS Added Bruce Ray's plotter support - 15-Oct-00 RMS Added stack, byte, trap instructions - 14-Apr-99 RMS Changed t_addr to unsigned - 16-Mar-95 RMS Added dynamic memory size - 06-Dec-95 RMS Added magnetic tape - - The author gratefully acknowledges the help of Tom West, Diana Englebart, - Carl Friend, Bruce Ray, and Charles Owen in resolving questions about - the NOVA. -*/ - -#include "sim_defs.h" /* simulator defns */ - -/* Simulator stop codes */ - -#define STOP_RSRV 1 /* must be 1 */ -#define STOP_HALT 2 /* HALT */ -#define STOP_IBKPT 3 /* breakpoint */ -#define STOP_IND 4 /* indirect loop */ -#define STOP_IND_INT 5 /* ind loop, intr */ -#define STOP_IND_TRP 6 /* ind loop, trap */ - -/* Memory */ - -#if defined (ECLIPSE) -#define MAXMEMSIZE 1048576 /* max memory size */ -#else -#define MAXMEMSIZE 32768 /* max memory size */ -#endif -#define AMASK 077777 /* logical addr mask */ -#define PAMASK (MAXMEMSIZE - 1) /* physical addr mask */ -#define MEMSIZE (cpu_unit.capac) /* actual memory size */ -#define A_V_IND 15 /* ind: indirect */ -#define A_IND (1 << A_V_IND) -#define MEM_ADDR_OK(x) (((uint32) (x)) < MEMSIZE) - -/* Architectural constants */ - -#define SIGN 0100000 /* sign */ -#define DMASK 0177777 /* data mask */ -#define CBIT (DMASK + 1) /* carry bit */ -#define CDMASK (CBIT | DMASK) /* carry + data */ - -/* Reserved memory locations */ - -#define INT_SAV 0 /* intr saved PC */ -#define INT_JMP 1 /* intr jmp @ */ -#define STK_JMP 3 /* stack jmp @ */ -#define TRP_SAV 046 /* trap saved PC */ -#define TRP_JMP 047 /* trap jmp @ */ -#define AUTO_INC 020 /* start autoinc */ -#define AUTO_DEC 030 /* start autodec */ - -/* Instruction format */ - -#define I_OPR 0100000 /* operate */ -#define I_M_SRC 03 /* OPR: src AC */ -#define I_V_SRC 13 -#define I_GETSRC(x) (((x) >> I_V_SRC) & I_M_SRC) -#define I_M_DST 03 /* dst AC */ -#define I_V_DST 11 -#define I_GETDST(x) (((x) >> I_V_DST) & I_M_DST) -#define I_M_ALU 07 /* OPR: ALU op */ -#define I_V_ALU 8 -#define I_GETALU(x) (((x) >> I_V_ALU) & I_M_ALU) -#define I_M_SHF 03 /* OPR: shift */ -#define I_V_SHF 6 -#define I_GETSHF(x) (((x) >> I_V_SHF) & I_M_SHF) -#define I_M_CRY 03 /* OPR: carry */ -#define I_V_CRY 4 -#define I_GETCRY(x) (((x) >> I_V_CRY) & I_M_CRY) -#define I_V_NLD 3 /* OPR: no load */ -#define I_NLD (1 << I_V_NLD) -#define I_M_SKP 07 /* OPR: skip */ -#define I_V_SKP 0 -#define I_GETSKP(x) (((x) >> I_V_SKP) & I_M_SKP) - -#define I_M_OPAC 017 /* MRF: opcode + AC */ -#define I_V_OPAC 11 -#define I_GETOPAC(x) (((x) >> I_V_OPAC) & I_M_OPAC) -#define I_V_IND 10 /* MRF: indirect */ -#define I_IND (1 << I_V_IND) -#define I_M_MODE 03 /* MRF: mode */ -#define I_V_MODE 8 -#define I_GETMODE(x) (((x) >> I_V_MODE) & I_M_MODE) -#define I_M_DISP 0377 /* MRF: disp */ -#define I_V_DISP 0 -#define I_GETDISP(x) (((x) >> I_V_DISP) & I_M_DISP) -#define DISPSIZE (I_M_DISP + 1) /* page size */ -#define DISPSIGN (DISPSIZE >> 1) /* page sign */ - -#define I_M_IOT 07 /* IOT: code */ -#define I_V_IOT 8 -#define I_GETIOT(x) (((x) >> I_V_IOT) & I_M_IOT) -#define I_M_PULSE 03 /* IOT pulse */ -#define I_V_PULSE 6 -#define I_GETPULSE(x) (((x) >> I_V_PULSE) & I_M_PULSE) -#define I_M_DEV 077 /* IOT: device */ -#define I_V_DEV 0 -#define I_GETDEV(x) (((x) >> I_V_DEV) & I_M_DEV) - -#define I_M_XOP 037 /* XOP: code */ -#define I_V_XOP 6 -#define I_GETXOP(x) (((x) >> I_V_XOP) & I_M_XOP) - -/* IOT return codes */ - -#define IOT_V_REASON 16 /* set reason */ -#define IORETURN(f,v) ((f)? (v): SCPE_OK) /* stop on error */ - -/* IOT fields */ - -#define ioNIO 0 /* opcode field */ -#define ioDIA 1 -#define ioDOA 2 -#define ioDIB 3 -#define ioDOB 4 -#define ioDIC 5 -#define ioDOC 6 -#define ioSKP 7 - -#define iopN 0 /* pulse field */ -#define iopS 1 -#define iopC 2 -#define iopP 3 - -/* Device numbers */ - -#define DEV_LOW 010 /* lowest intr dev */ -#define DEV_HIGH 051 /* highest intr dev */ -#define DEV_MDV 001 /* multiply/divide */ -#define DEV_ECC 002 /* ECC memory control */ -#define DEV_MAP 003 /* MMPU control */ -#define DEV_TTI 010 /* console input */ -#define DEV_TTO 011 /* console output */ -#define DEV_PTR 012 /* paper tape reader */ -#define DEV_PTP 013 /* paper tape punch */ -#define DEV_CLK 014 /* clock */ -#define DEV_PLT 015 /* plotter */ -#define DEV_CDR 016 /* card reader */ -#define DEV_LPT 017 /* line printer */ -#define DEV_DSK 020 /* fixed head disk */ -#define DEV_MTA 022 /* magtape */ -#define DEV_DCM 024 /* data comm mux */ -#define DEV_ADCV 030 /* A/D converter */ -#define DEV_DKP 033 /* disk pack */ -#define DEV_CAS 034 /* cassette */ -#define DEV_TTI1 050 /* second console input */ -#define DEV_TTO1 051 /* second console output */ -#define DEV_CPU 077 /* CPU control */ - -/* I/O structure - - The NOVA I/O structure is tied together by dev_table, indexed by - the device number. Each entry in dev_table consists of - - mask device mask for busy, done (simulator representation) - pi pi disable bit (hardware representation) - routine IOT action routine - - dev_table is populated at run time from the device information - blocks in each device. -*/ - -struct ndev { - int32 mask; /* done/busy mask */ - int32 pi; /* assigned pi bit */ - int32 (*routine)(); /* dispatch routine */ - }; - -struct nova_dib { - int32 dnum; /* device number */ - int32 mask; /* done/busy mask */ - int32 pi; /* assigned pi bit */ - int32 (*routine)(); /* dispatch routine */ - }; - -typedef struct nova_dib DIB; - -/* Device flags (simulator representation) - - Priority (for INTA) runs from low numbers to high -*/ - -#define INT_V_DKP 3 /* moving head disk */ -#define INT_V_DSK 4 /* fixed head disk */ -#define INT_V_MTA 5 /* magnetic tape */ -#define INT_V_LPT 6 /* line printer */ -#define INT_V_CLK 7 /* clock */ -#define INT_V_PTR 8 /* paper tape reader */ -#define INT_V_PTP 9 /* paper tape punch */ -#define INT_V_PLT 10 /* plotter */ -#define INT_V_TTI 11 /* keyboard */ -#define INT_V_TTO 12 /* terminal */ -#define INT_V_TTI1 13 /* second keyboard */ -#define INT_V_TTO1 14 /* second terminal */ -#define INT_V_STK 15 /* stack overflow */ -#define INT_V_NO_ION_PENDING 16 /* ion delay */ -#define INT_V_ION 17 /* interrupts on */ - -#define INT_DKP (1 << INT_V_DKP) -#define INT_DSK (1 << INT_V_DSK) -#define INT_MTA (1 << INT_V_MTA) -#define INT_LPT (1 << INT_V_LPT) -#define INT_CLK (1 << INT_V_CLK) -#define INT_PTR (1 << INT_V_PTR) -#define INT_PTP (1 << INT_V_PTP) -#define INT_PLT (1 << INT_V_PLT) -#define INT_TTI (1 << INT_V_TTI) -#define INT_TTO (1 << INT_V_TTO) -#define INT_TTI1 (1 << INT_V_TTI1) -#define INT_TTO1 (1 << INT_V_TTO1) -#define INT_STK (1 << INT_V_STK) -#define INT_NO_ION_PENDING (1 << INT_V_NO_ION_PENDING) -#define INT_ION (1 << INT_V_ION) -#define INT_DEV ((1 << INT_V_STK) - 1) /* device ints */ -#define INT_PENDING INT_ION+INT_NO_ION_PENDING - -/* PI disable bits */ - -#define PI_DKP 0000400 -#define PI_DSK 0000100 -#define PI_MTA 0000040 -#define PI_LPT 0000010 -#define PI_CLK 0000004 -#define PI_PTR 0000020 -#define PI_PTP 0000004 -#define PI_PLT 0000010 -#define PI_TTI 0000002 -#define PI_TTO 0000001 -#define PI_TTI1 PI_TTI -#define PI_TTO1 PI_TTO -/* #define PI_CDR 0000040 */ -/* #define PI_DCM 0100000 */ -/* #define PI_CAS 0000040 */ -/* #define PI_ADCV 0000002 */ - -/* Function prototypes */ - -int32 MapAddr (int32 map, int32 addr); -t_stat set_enb (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat set_dsb (UNIT *uptr, int32 val, char *cptr, void *desc); diff --git a/NOVA/nova_dkp.c b/NOVA/nova_dkp.c deleted file mode 100644 index 9dd91026..00000000 --- a/NOVA/nova_dkp.c +++ /dev/null @@ -1,723 +0,0 @@ -/* nova_dkp.c: NOVA moving head disk simulator - - 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. - - dkp moving head disk - - 25-Apr-03 RMS Revised autosizing - 08-Oct-02 RMS Added DIB - 06-Jan-02 RMS Revised enable/disable support - 30-Nov-01 RMS Added read only unit, extended SET/SHOW support - 24-Nov-01 RMS Changed FLG, CAPAC to arrays - 26-Apr-01 RMS Added device enable/disable support - 12-Dec-00 RMS Added Eclipse support from Charles Owen - 15-Oct-00 RMS Editorial changes - 14-Apr-99 RMS Changed t_addr to unsigned - 15-Sep-97 RMS Fixed bug in DIB/DOB for new disks - 15-Sep-97 RMS Fixed bug in cylinder extraction (found by Charles Owen) - 10-Sep-97 RMS Fixed bug in error reporting (found by Charles Owen) - 25-Nov-96 RMS Defaulted to autosize - 29-Jun-96 RMS Added unit disable support -*/ - -#include "nova_defs.h" - -#define DKP_NUMDR 4 /* #drives */ -#define DKP_NUMWD 256 /* words/sector */ -#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */ -#define UNIT_V_DTYPE (UNIT_V_UF + 1) /* disk type */ -#define UNIT_M_DTYPE 017 -#define UNIT_V_AUTO (UNIT_V_UF + 5) /* 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 FUNC u3 /* function */ -#define CYL u4 /* on cylinder */ -#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */ - -/* Unit, surface, sector, count register - - Original format: 2b, 6b, 4b, 4b - Revised format: 2b, 5b, 5b, 4b -*/ - -#define USSC_V_COUNT 0 /* count */ -#define USSC_M_COUNT 017 -#define USSC_V_OSECTOR 4 /* old: sector */ -#define USSC_M_OSECTOR 017 -#define USSC_V_OSURFACE 8 /* old: surface */ -#define USSC_M_OSURFACE 077 -#define USSC_V_NSECTOR 4 /* new: sector */ -#define USSC_M_NSECTOR 037 -#define USSC_V_NSURFACE 9 /* new: surface */ -#define USSC_M_NSURFACE 037 -#define USSC_V_UNIT 14 /* unit */ -#define USSC_M_UNIT 03 -#define USSC_UNIT (USSC_M_UNIT << USSC_V_UNIT) -#define GET_COUNT(x) (((x) >> USSC_V_COUNT) & USSC_M_COUNT) -#define GET_SECT(x,dt) ((drv_tab[dt].newf)? \ - (((x) >> USSC_V_NSECTOR) & USSC_M_NSECTOR): \ - (((x) >> USSC_V_OSECTOR) & USSC_M_OSECTOR) ) -#define GET_SURF(x,dt) ((drv_tab[dt].newf)? \ - (((x) >> USSC_V_NSURFACE) & USSC_M_NSURFACE): \ - (((x) >> USSC_V_OSURFACE) & USSC_M_OSURFACE) ) -#define GET_UNIT(x) (((x) >> USSC_V_UNIT) & USSC_M_UNIT) - -/* Flags, command, cylinder register - - Original format: 5b, 2b, 1b + 8b (surrounding command) - Revised format: 5b, 2b, 9b -*/ - -#define FCCY_V_OCYL 0 /* old: cylinder */ -#define FCCY_M_OCYL 0377 -#define FCCY_V_OCMD 8 /* old: command */ -#define FCCY_M_OCMD 3 -#define FCCY_V_OCEX 10 /* old: cyl extend */ -#define FCCY_OCEX (1 << FCCY_V_OCEX) -#define FCCY_V_NCYL 0 /* new: cylinder */ -#define FCCY_M_NCYL 0777 -#define FCCY_V_NCMD 9 /* new: command */ -#define FCCY_M_NCMD 3 -#define FCCY_READ 0 -#define FCCY_WRITE 1 -#define FCCY_SEEK 2 -#define FCCY_RECAL 3 -#define FCCY_FLAGS 0174000 /* flags */ -#define GET_CMD(x,dt) ((drv_tab[dt].newf)? \ - (((x) >> FCCY_V_NCMD) & FCCY_M_NCMD): \ - (((x) >> FCCY_V_OCMD) & FCCY_M_OCMD) ) -#define GET_CYL(x,dt) ((drv_tab[dt].newf)? \ - (((x) >> FCCY_V_NCYL) & FCCY_M_NCYL): \ - ((((x) >> FCCY_V_OCYL) & FCCY_M_OCYL) | \ - ((dt != TYPE_D44)? 0: \ - (((x) & FCCY_OCEX) >> (FCCY_V_OCEX - FCCY_V_OCMD)))) ) - -/* Status */ - -#define STA_ERR 0000001 /* error */ -#define STA_DLT 0000002 /* data late */ -#define STA_CRC 0000004 /* crc error */ -#define STA_UNS 0000010 /* unsafe */ -#define STA_XCY 0000020 /* cross cylinder */ -#define STA_CYL 0000040 /* nx cylinder */ -#define STA_DRDY 0000100 /* drive ready */ -#define STA_SEEK3 0000200 /* seeking unit 3 */ -#define STA_SEEK2 0000400 /* seeking unit 2 */ -#define STA_SEEK1 0001000 /* seeking unit 1 */ -#define STA_SEEK0 0002000 /* seeking unit 0 */ -#define STA_SKDN3 0004000 /* seek done unit 3 */ -#define STA_SKDN2 0010000 /* seek done unit 2 */ -#define STA_SKDN1 0020000 /* seek done unit 1 */ -#define STA_SKDN0 0040000 /* seek done unit 0 */ -#define STA_DONE 0100000 /* operation done */ - -#define STA_DYN (STA_DRDY | STA_CYL) /* set from unit */ -#define STA_EFLGS (STA_ERR | STA_DLT | STA_CRC | STA_UNS | \ - STA_XCY | STA_CYL) /* error flags */ -#define STA_DFLGS (STA_DONE | STA_SKDN0 | STA_SKDN1 | \ - STA_SKDN2 | STA_SKDN3) /* done flags */ - -#define GET_SA(cy,sf,sc,t) (((((cy)*drv_tab[t].surf)+(sf))* \ - drv_tab[t].sect)+(sc)) - -/* This controller supports many different disk drive types: - - type #sectors/ #surfaces/ #cylinders/ new format? - surface cylinder drive - - floppy 8 1 77 no - DS/DD floppy 16 2 77 yes - Diablo 31 12 2 203 no - 6225 20 2 245 yes - Century 111 6 10 203 no - Diablo 44 12 4 408 no - 6099 32 4 192 yes - 6227 20 6 245 yes - 6070 24 4 408 yes - Century 114 12 20 203 no - 6103 32 8 192 yes - 4231 23 19 411 yes - - 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. -*/ - -#define TYPE_FLP 0 -#define SECT_FLP 8 -#define SURF_FLP 1 -#define CYL_FLP 77 -#define SIZE_FLP (SECT_FLP * SURF_FLP * CYL_FLP * DKP_NUMWD) -#define NFMT_FLP FALSE - -#define TYPE_DSDD 1 -#define SECT_DSDD 16 -#define SURF_DSDD 2 -#define CYL_DSDD 77 -#define SIZE_DSDD (SECT_DSDD * SURF_DSDD * CYL_DSDD * DKP_NUMWD) -#define NFMT_DSDD TRUE - -#define TYPE_D31 2 -#define SECT_D31 12 -#define SURF_D31 2 -#define CYL_D31 203 -#define SIZE_D31 (SECT_D31 * SURF_D31 * CYL_D31 * DKP_NUMWD) -#define NFMT_D31 FALSE - -#define TYPE_6225 3 -#define SECT_6225 20 -#define SURF_6225 2 -#define CYL_6225 245 -#define SIZE_6225 (SECT_6225 * SURF_6225 * CYL_6225 * DKP_NUMWD) -#define NFMT_6225 TRUE - -#define TYPE_C111 4 -#define SECT_C111 6 -#define SURF_C111 10 -#define CYL_C111 203 -#define SIZE_C111 (SECT_C111 * SURF_C111 * CYL_C111 * DKP_NUMWD) -#define NFMT_C111 FALSE - -#define TYPE_D44 5 -#define SECT_D44 12 -#define SURF_D44 4 -#define CYL_D44 408 -#define SIZE_D44 (SECT_D44 * SURF_D44 * CYL_D44 * DKP_NUMWD) -#define NFMT_D44 FALSE - -#define TYPE_6099 6 -#define SECT_6099 32 -#define SURF_6099 4 -#define CYL_6099 192 -#define SIZE_6099 (SECT_6099 * SURF_6099 * CYL_6099 * DKP_NUMWD) -#define NFMT_6099 TRUE - -#define TYPE_6227 7 -#define SECT_6227 20 -#define SURF_6227 6 -#define CYL_6227 245 -#define SIZE_6227 (SECT_6227 * SURF_6227 * CYL_6227 * DKP_NUMWD) -#define NFMT_6227 TRUE - -#define TYPE_6070 8 -#define SECT_6070 24 -#define SURF_6070 4 -#define CYL_6070 408 -#define SIZE_6070 (SECT_6070 * SURF_6070 * CYL_6070 * DKP_NUMWD) -#define NFMT_6070 TRUE - -#define TYPE_C114 9 -#define SECT_C114 12 -#define SURF_C114 20 -#define CYL_C114 203 -#define SIZE_C114 (SECT_C114 * SURF_C114 * CYL_C114 * DKP_NUMWD) -#define NFMT_C114 FALSE - -#define TYPE_6103 10 -#define SECT_6103 32 -#define SURF_6103 8 -#define CYL_6103 192 -#define SIZE_6103 (SECT_6103 * SURF_6103 * CYL_6103 * DKP_NUMWD) -#define NFMT_6103 TRUE - -#define TYPE_4231 11 -#define SECT_4231 23 -#define SURF_4231 19 -#define CYL_4231 411 -#define SIZE_4231 (SECT_4231 * SURF_4231 * CYL_4231 * DKP_NUMWD) -#define NFMT_4231 TRUE - -struct drvtyp { - int32 sect; /* sectors */ - int32 surf; /* surfaces */ - int32 cyl; /* cylinders */ - int32 size; /* #blocks */ - int32 newf; /* new format flag */ -}; - -struct drvtyp drv_tab[] = { - { SECT_FLP, SURF_FLP, CYL_FLP, SIZE_FLP, NFMT_FLP }, - { SECT_DSDD, SURF_DSDD, CYL_DSDD, SIZE_DSDD, NFMT_DSDD }, - { SECT_D31, SURF_D31, CYL_D31, SIZE_D31, NFMT_D31 }, - { SECT_6225, SURF_6225, CYL_6225, SIZE_6225, NFMT_6225 }, - { SECT_C111, SURF_C111, CYL_C111, SIZE_C111, NFMT_C111 }, - { SECT_D44, SURF_D44, CYL_D44, SIZE_D44, NFMT_D44 }, - { SECT_6099, SURF_6099, CYL_6099, SIZE_6099, NFMT_6099 }, - { SECT_6227, SURF_6227, CYL_6227, SIZE_6227, NFMT_6227 }, - { SECT_6070, SURF_6070, CYL_6070, SIZE_6070, NFMT_6070 }, - { SECT_C114, SURF_C114, CYL_C114, SIZE_C114, NFMT_C114 }, - { SECT_6103, SURF_6103, CYL_6103, SIZE_6103, NFMT_6103 }, - { SECT_4231, SURF_4231, CYL_4231, SIZE_4231, NFMT_4231 }, - { 0 } }; - -extern uint16 M[]; -extern UNIT cpu_unit; -extern int32 int_req, dev_busy, dev_done, dev_disable; - -int32 dkp_ma = 0; /* memory address */ -int32 dkp_ussc = 0; /* unit/sf/sc/cnt */ -int32 dkp_fccy = 0; /* flags/cylinder */ -int32 dkp_sta = 0; /* status register */ -int32 dkp_swait = 100; /* seek latency */ -int32 dkp_rwait = 100; /* rotate latency */ - -DEVICE dkp_dev; -int32 dkp (int32 pulse, int32 code, int32 AC); -t_stat dkp_svc (UNIT *uptr); -t_stat dkp_reset (DEVICE *dptr); -t_stat dkp_boot (int32 unitno, DEVICE *dptr); -t_stat dkp_attach (UNIT *uptr, char *cptr); -t_stat dkp_go (void); -t_stat dkp_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); - -/* DKP data structures - - dkp_dev DKP device descriptor - dkp_unit DKP unit list - dkp_reg DKP register list - dkp_mod DKP modifier list -*/ - -DIB dkp_dib = { DEV_DKP, INT_DKP, PI_DKP, &dkp }; - -UNIT dkp_unit[] = { - { UDATA (&dkp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+ - UNIT_ROABLE+(TYPE_D31 << UNIT_V_DTYPE), SIZE_D31) }, - { UDATA (&dkp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+ - UNIT_ROABLE+(TYPE_D31 << UNIT_V_DTYPE), SIZE_D31) }, - { UDATA (&dkp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+ - UNIT_ROABLE+(TYPE_D31 << UNIT_V_DTYPE), SIZE_D31) }, - { UDATA (&dkp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+ - UNIT_ROABLE+(TYPE_D31 << UNIT_V_DTYPE), SIZE_D31) } }; - -REG dkp_reg[] = { - { ORDATA (FCCY, dkp_fccy, 16) }, - { ORDATA (USSC, dkp_ussc, 16) }, - { ORDATA (STA, dkp_sta, 16) }, - { ORDATA (MA, dkp_ma, 16) }, - { FLDATA (INT, int_req, INT_V_DKP) }, - { FLDATA (BUSY, dev_busy, INT_V_DKP) }, - { FLDATA (DONE, dev_done, INT_V_DKP) }, - { FLDATA (DISABLE, dev_disable, INT_V_DKP) }, - { DRDATA (STIME, dkp_swait, 24), PV_LEFT }, - { DRDATA (RTIME, dkp_rwait, 24), PV_LEFT }, - { URDATA (CAPAC, dkp_unit[0].capac, 10, T_ADDR_W, 0, - DKP_NUMDR, PV_LEFT | REG_HRO) }, - { NULL } }; - -MTAB dkp_mod[] = { - { UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL }, - { UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL }, - { (UNIT_DTYPE+UNIT_ATT), (TYPE_FLP << UNIT_V_DTYPE) + UNIT_ATT, - "6030 (floppy)", NULL, NULL }, - { (UNIT_DTYPE+UNIT_ATT), (TYPE_DSDD << UNIT_V_DTYPE) + UNIT_ATT, - "6097 (DS/DD floppy)", NULL, NULL }, - { (UNIT_DTYPE+UNIT_ATT), (TYPE_D31 << UNIT_V_DTYPE) + UNIT_ATT, - "4047 (Diablo 31)", NULL, NULL }, - { (UNIT_DTYPE+UNIT_ATT), (TYPE_D44 << UNIT_V_DTYPE) + UNIT_ATT, - "4234/6045 (Diablo 44)", NULL, NULL }, - { (UNIT_DTYPE+UNIT_ATT), (TYPE_C111 << UNIT_V_DTYPE) + UNIT_ATT, - "4048 (Century 111)", NULL, NULL }, - { (UNIT_DTYPE+UNIT_ATT), (TYPE_C114 << UNIT_V_DTYPE) + UNIT_ATT, - "2314/4057 (Century 114)", NULL, NULL }, - { (UNIT_DTYPE+UNIT_ATT), (TYPE_6225 << UNIT_V_DTYPE) + UNIT_ATT, - "6225", NULL, NULL }, - { (UNIT_DTYPE+UNIT_ATT), (TYPE_6227 << UNIT_V_DTYPE) + UNIT_ATT, - "6227", NULL, NULL }, - { (UNIT_DTYPE+UNIT_ATT), (TYPE_6099 << UNIT_V_DTYPE) + UNIT_ATT, - "6099", NULL, NULL }, - { (UNIT_DTYPE+UNIT_ATT), (TYPE_6103 << UNIT_V_DTYPE) + UNIT_ATT, - "6103", NULL, NULL }, - { (UNIT_DTYPE+UNIT_ATT), (TYPE_6070 << UNIT_V_DTYPE) + UNIT_ATT, - "6070", NULL, NULL }, - { (UNIT_DTYPE+UNIT_ATT), (TYPE_4231 << UNIT_V_DTYPE) + UNIT_ATT, - "4231/3330", NULL, NULL }, - { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (TYPE_FLP << UNIT_V_DTYPE), - "6030 (floppy)", NULL, NULL }, - { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (TYPE_DSDD << UNIT_V_DTYPE), - "6097 (DS/DD floppy)", NULL, NULL }, - { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (TYPE_D31 << UNIT_V_DTYPE), - "4047 (Diablo 31)", NULL, NULL }, - { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (TYPE_D44 << UNIT_V_DTYPE), - "4234/6045 (Diablo 44)", NULL, NULL }, - { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (TYPE_C111 << UNIT_V_DTYPE), - "4048 (Century 111)", NULL, NULL }, - { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (TYPE_C114 << UNIT_V_DTYPE), - "2314/4057 (Century 114)", NULL, NULL }, - { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (TYPE_6225 << UNIT_V_DTYPE), - "6225", NULL, NULL }, - { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (TYPE_6227 << UNIT_V_DTYPE), - "6227", NULL, NULL }, - { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (TYPE_6099 << UNIT_V_DTYPE), - "6099", NULL, NULL }, - { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (TYPE_6103 << UNIT_V_DTYPE), - "6103", NULL, NULL }, - { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (TYPE_6070 << UNIT_V_DTYPE), - "6070", NULL, NULL }, - { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (TYPE_4231 << UNIT_V_DTYPE), - "4231/3330", NULL, NULL }, - { (UNIT_AUTO+UNIT_ATT), UNIT_AUTO, "autosize", NULL, NULL }, - { UNIT_AUTO, UNIT_AUTO, NULL, "AUTOSIZE", NULL }, - { (UNIT_AUTO+UNIT_DTYPE), (TYPE_FLP << UNIT_V_DTYPE), - NULL, "FLOPPY", &dkp_set_size }, - { (UNIT_AUTO+UNIT_DTYPE), (TYPE_FLP << UNIT_V_DTYPE), - NULL, "6030", &dkp_set_size }, - { (UNIT_AUTO+UNIT_DTYPE), (TYPE_DSDD << UNIT_V_DTYPE), - NULL, "DSDDFLOPPY", &dkp_set_size }, - { (UNIT_AUTO+UNIT_DTYPE), (TYPE_DSDD << UNIT_V_DTYPE), - NULL, "6097", &dkp_set_size }, - { (UNIT_AUTO+UNIT_DTYPE), (TYPE_D31 << UNIT_V_DTYPE), - NULL, "D31", &dkp_set_size }, - { (UNIT_AUTO+UNIT_DTYPE), (TYPE_D31 << UNIT_V_DTYPE), - NULL, "4047", &dkp_set_size }, - { (UNIT_AUTO+UNIT_DTYPE), (TYPE_D44 << UNIT_V_DTYPE), - NULL, "D44", &dkp_set_size }, - { (UNIT_AUTO+UNIT_DTYPE), (TYPE_D44 << UNIT_V_DTYPE), - NULL, "4234", &dkp_set_size }, - { (UNIT_AUTO+UNIT_DTYPE), (TYPE_D44 << UNIT_V_DTYPE), - NULL, "6045", &dkp_set_size }, - { (UNIT_AUTO+UNIT_DTYPE), (TYPE_C111 << UNIT_V_DTYPE), - NULL, "C111", &dkp_set_size }, - { (UNIT_AUTO+UNIT_DTYPE), (TYPE_C111 << UNIT_V_DTYPE), - NULL, "4048", &dkp_set_size }, - { (UNIT_AUTO+UNIT_DTYPE), (TYPE_C114 << UNIT_V_DTYPE), - NULL, "C114", &dkp_set_size }, - { (UNIT_AUTO+UNIT_DTYPE), (TYPE_C114 << UNIT_V_DTYPE), - NULL, "2314", &dkp_set_size }, - { (UNIT_AUTO+UNIT_DTYPE), (TYPE_C114 << UNIT_V_DTYPE), - NULL, "4057", &dkp_set_size }, - { (UNIT_AUTO+UNIT_DTYPE), (TYPE_6225 << UNIT_V_DTYPE), - NULL, "6225", &dkp_set_size }, - { (UNIT_AUTO+UNIT_DTYPE), (TYPE_6227 << UNIT_V_DTYPE), - NULL, "6227", &dkp_set_size }, - { (UNIT_AUTO+UNIT_DTYPE), (TYPE_6099 << UNIT_V_DTYPE), - NULL, "6099", &dkp_set_size }, - { (UNIT_AUTO+UNIT_DTYPE), (TYPE_6103 << UNIT_V_DTYPE), - NULL, "6103", &dkp_set_size }, - { (UNIT_AUTO+UNIT_DTYPE), (TYPE_6070 << UNIT_V_DTYPE), - NULL, "6070", &dkp_set_size }, - { (UNIT_AUTO+UNIT_DTYPE), (TYPE_4231 << UNIT_V_DTYPE), - NULL, "4231", &dkp_set_size }, - { (UNIT_AUTO+UNIT_DTYPE), (TYPE_4231 << UNIT_V_DTYPE), - NULL, "3330", &dkp_set_size }, - { 0 } }; - -DEVICE dkp_dev = { - "DP", dkp_unit, dkp_reg, dkp_mod, - DKP_NUMDR, 8, 30, 1, 8, 16, - NULL, NULL, &dkp_reset, - &dkp_boot, &dkp_attach, NULL, - &dkp_dib, DEV_DISABLE }; - -/* IOT routine */ - -int32 dkp (int32 pulse, int32 code, int32 AC) -{ -UNIT *uptr; -int32 u, rval, dtype; - -rval = 0; -uptr = dkp_dev.units + GET_UNIT (dkp_ussc); /* select unit */ -dtype = GET_DTYPE (uptr->flags); /* get drive type */ -switch (code) { /* decode IR<5:7> */ -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? */ - 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); } - 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].newf? DMASK: AMASK); - break; -case ioDIC: /* DIC */ - rval = dkp_ussc; /* return unit, sect */ - break; -case ioDOC: /* DOC */ - if ((dev_busy & INT_DKP) == 0) dkp_ussc = AC; /* save unit, sect */ - break; } /* end switch code */ - -/* IOT, continued */ - -u = GET_UNIT(dkp_ussc); /* select unit */ -switch (pulse) { /* decode IR<8:9> */ -case iopS: /* start */ - dev_busy = dev_busy | INT_DKP; /* set busy */ - dev_done = dev_done & ~INT_DKP; /* clear done */ - int_req = int_req & ~INT_DKP; /* clear int */ - if (dkp_go ()) break; /* new cmd, error? */ - dev_busy = dev_busy & ~INT_DKP; /* clear busy */ - dev_done = dev_done | INT_DKP; /* set done */ - int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable); - dkp_sta = dkp_sta | STA_DONE; - break; -case iopC: /* clear */ - dev_busy = dev_busy & ~INT_DKP; /* clear busy */ - dev_done = dev_done & ~INT_DKP; /* clear done */ - int_req = int_req & ~INT_DKP; /* clear int */ - dkp_sta = dkp_sta & ~(STA_DFLGS + STA_EFLGS); - if (dkp_unit[u].FUNC != FCCY_SEEK) sim_cancel (&dkp_unit[u]); - break; -case iopP: /* pulse */ - dev_done = dev_done & ~INT_DKP; /* clear done */ - if (dkp_go ()) break; /* new seek command */ - dev_done = dev_done | INT_DKP; /* set done */ - int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable); - dkp_sta = dkp_sta | (STA_SKDN0 >> u); /* set seek done */ - break; } /* end case pulse */ -return rval; -} - -/* New command, start vs pulse handled externally - Returns true if command ok, false if error -*/ - -t_stat dkp_go (void) -{ -UNIT *uptr; -int32 newcyl, func, u, dtype; - -dkp_sta = dkp_sta & ~STA_EFLGS; /* clear errors */ -u = GET_UNIT (dkp_ussc); /* get unit number */ -uptr = dkp_dev.units + u; /* get unit */ -if (((uptr->flags & UNIT_ATT) == 0) || sim_is_active (uptr)) { - dkp_sta = dkp_sta | STA_ERR; /* attached or busy? */ - return FALSE; } -dtype = GET_DTYPE (uptr->flags); /* get drive type */ -func = GET_CMD (dkp_fccy, dtype); /* get function */ -newcyl = GET_CYL (dkp_fccy, dtype); /* get cylinder */ -switch (func) { /* decode command */ -case FCCY_READ: case FCCY_WRITE: - sim_activate (uptr, dkp_rwait); /* schedule */ - break; -case FCCY_RECAL: /* recalibrate */ - newcyl = 0; - func = FCCY_SEEK; -case FCCY_SEEK: /* seek */ - sim_activate (uptr, dkp_swait * abs (newcyl - uptr->CYL)); - dkp_sta = dkp_sta | (STA_SEEK0 >> u); /* set seeking */ - uptr->CYL = newcyl; /* on cylinder */ - break; } /* end case command */ -uptr->FUNC = func; /* save command */ -return TRUE; /* no error */ -} - -/* Unit service - - If seek done, put on cylinder; - else, do read or write - If controller was busy, clear busy, set done, interrupt - - Memory access: sectors are read into/written from an intermediate - buffer to allow word-by-word mapping of memory addresses on the - Eclipse. This allows each word written to memory to be tested - for out of range. -*/ - -t_stat dkp_svc (UNIT *uptr) -{ -int32 sc, sa, xcsa, bda; -int32 sx, dx, pa, u; -int32 dtype, err, newsect, newsurf; -uint32 awc; -t_stat rval; -static uint16 tbuf[DKP_NUMWD]; /* transfer buffer */ - -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; - 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 */ - return SCPE_OK; } - -if (((uptr->flags & UNIT_ATT) == 0) || /* not attached? */ - ((uptr->flags & UNIT_WPRT) && (uptr->FUNC == FCCY_WRITE))) - dkp_sta = dkp_sta | STA_DONE | STA_ERR; /* error */ - -else if ((uptr->CYL >= drv_tab[dtype].cyl) || /* bad cylinder */ - (GET_SURF (dkp_ussc, dtype) >= drv_tab[dtype].surf) || /* bad surface */ - (GET_SECT (dkp_ussc, dtype) >= drv_tab[dtype].sect)) /* or bad sector? */ - dkp_sta = dkp_sta | STA_DONE | STA_ERR | STA_UNS; - -else if (GET_CYL (dkp_fccy, dtype) != uptr->CYL) /* address error? */ - dkp_sta = dkp_sta | STA_DONE | STA_ERR | STA_UNS; - -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 */ - 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 */ - bda = sa * DKP_NUMWD * sizeof (short); /* to words, bytes */ - - err = fseek (uptr->fileref, bda, SEEK_SET); /* position drive */ - - if (uptr->FUNC == FCCY_READ) { /* read? */ - for (sx = 0; sx < sc; sx++) { /* loop thru sectors */ - awc = fxread (tbuf, sizeof(uint16), DKP_NUMWD, uptr->fileref); - for ( ; awc < DKP_NUMWD; awc++) tbuf[awc] = 0; - if (err = ferror (uptr->fileref)) break; - for (dx = 0; dx < DKP_NUMWD; dx++) { /* loop thru buffer */ - pa = MapAddr (0, dkp_ma); - if (MEM_ADDR_OK (pa)) M[pa] = tbuf[dx]; - dkp_ma = (dkp_ma + 1) & AMASK; } } } - - if (uptr->FUNC == FCCY_WRITE) { /* write? */ - for (sx = 0; sx < sc; sx++) { /* loop thru sectors */ - for (dx = 0; dx < DKP_NUMWD; dx++) { /* loop into buffer */ - pa = MapAddr (0, dkp_ma); - tbuf[dx] = M[pa]; - dkp_ma = (dkp_ma + 1) & AMASK; } - fxwrite (tbuf, sizeof(int16), DKP_NUMWD, uptr->fileref); - if (err = ferror (uptr->fileref)) break; } } - - if (err != 0) { - 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].newf)? - ((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 */ -dev_done = dev_done | INT_DKP; /* set done */ -int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable); -return rval; -} - -/* Reset routine */ - -t_stat dkp_reset (DEVICE *dptr) -{ -int32 u; -UNIT *uptr; - -dev_busy = dev_busy & ~INT_DKP; /* clear busy */ -dev_done = dev_done & ~INT_DKP; /* clear done, int */ -int_req = int_req & ~INT_DKP; -dkp_fccy = dkp_ussc = dkp_ma = dkp_sta = 0; /* clear registers */ -for (u = 0; u < DKP_NUMDR; u++) { /* loop thru units */ - uptr = dkp_dev.units + u; - sim_cancel (uptr); /* cancel activity */ - uptr->CYL = uptr->FUNC = 0; } -return SCPE_OK; -} - -/* Attach routine (with optional autosizing) */ - -t_stat dkp_attach (UNIT *uptr, char *cptr) -{ -int32 i, p; -t_stat r; - -uptr->capac = drv_tab[GET_DTYPE (uptr->flags)].size; -r = attach_unit (uptr, cptr); -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].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; } } -return SCPE_OK; -} - -/* Set size command validation routine */ - -t_stat dkp_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; -} - -/* Bootstrap routine */ - -#define BOOT_START 02000 -#define BOOT_UNIT 02021 -#define BOOT_SEEK 02022 -#define BOOT_LEN (sizeof (boot_rom) / sizeof (int)) - -static const int32 boot_rom[] = { - 060233, /* NIOC 0,DKP ; clear disk */ - 020420, /* LDA 0,USSC ; unit, sfc, sec, cnt */ - 063033, /* DOC 0,DKP ; select disk */ - 020417, /* LDA 0,SEKCMD ; command, cylinder */ - 061333, /* DOAP 0,DKP ; start seek */ - 024415, /* LDA 1,SEKDN */ - 060433, /* DIA 0,DKP ; get status */ - 0123415, /* AND# 1,0,SZR ; skip if done */ - 000776, /* JMP .-2 */ - 0102400, /* SUB 0,0 ; mem addr = 0 */ - 062033, /* DOB 0,DKP */ - 020411, /* LDA 0,REDCMD ; command, cylinder */ - 061133, /* DOAS 0,DKP ; start read */ - 060433, /* DIA 0, DKP ; get status */ - 0101113, /* MOVL# 0,0,SNC ; skip if done */ - 000776, /* JMP .-2 */ - 000377, /* JMP 377 */ - 000016, /* USSC: 0.B1+0.B7+0.B11+16 */ - 0175000, /* SEKCMD: 175000 */ - 074000, /* SEKDN: 074000 */ - 0174000 /* REDCMD: 174000 */ -}; - -t_stat dkp_boot (int32 unitno, DEVICE *dptr) -{ -int32 i, dtype; -extern int32 saved_PC; - -for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i]; -unitno = unitno & USSC_M_UNIT; -dtype = GET_DTYPE (dkp_unit[unitno].flags); -M[BOOT_UNIT] = M[BOOT_UNIT] | (unitno << USSC_V_UNIT); -if (drv_tab[dtype].newf) M[BOOT_SEEK] = 0176000; -saved_PC = BOOT_START; -return SCPE_OK; -} diff --git a/NOVA/nova_doc.txt b/NOVA/nova_doc.txt deleted file mode 100644 index b2bd632e..00000000 --- a/NOVA/nova_doc.txt +++ /dev/null @@ -1,594 +0,0 @@ -To: Users -From: Bob Supnik -Subj: Nova Simulator Usage -Date: 15-Mar-2003 - - COPYRIGHT NOTICE - -The following copyright notice applies to both the SIMH source and binary: - - 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"), - 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 Nova simulator. - - -1. Simulator Files - -sim/ sim_defs.h - sim_rev.h - sim_sock.h - sim_tape.h - sim_tmxr.h - scp.c - scp_tty.c - sim_sock.c - sim_tape.c - sim_tmxr.c - -sim/nova/ nova_defs.h - nova_cpu.c - nova_clk.c - nova_dkp.c - nova_dsk.c - nova_lp.c - nova_mta.c - nova_plt.c - nova_sys.c - nova_tt.c - nova_tt1.c - -2. Nova Features - -The Nova simulator is configured as follows: - -device simulates -name(s) - -CPU Nova CPU with 32KW of memory -- hardware multiply/divide -PTR,PTP paper tape reader/punch -TTI,TTO console terminal -TTI1,TTO1 second terminal -LPT line printer -PLT plotter -CLK real-time clock -DK head-per-track disk controller -DP moving head disk controller with four drives -MT magnetic tape controller with eight drives - -The Nova simulator implements these unique stop conditions: - - - reference to undefined I/O device, and STOP_DEV is set - - more than INDMAX indirect addresses are detected during - an interrupt - - more than INDMAX indirect addresses are detected during - memory reference address decoding - -The Nova loader supports standard binary format tapes. The DUMP command -is not implemented. - -Most devices can be disabled or enabled, by the commands: - - SET DISABLED - SET ENABLED - -All devices are enabled by default. - -2.1 CPU - -The only CPU options are the presence of the optional instructions -and the size of main memory. - - SET CPU MDV enable multiply/divide - SET CPU NOVA3 enable Nova3 instructions - SET CPU NOVA4 enable Nova4 instructions - SET CPU NONE disable all optional instructions - 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 - -(MDV = unsigned multiply/divide instructions) -(Nova 3 = unsigned multiply/divide, stack, trap instructions) -(Nova 4 = unsigned and signed multiply/divide, stack, byte, trap instructions) - -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 32K. - -CPU registers include the visible state of the processor as well as the -control registers for the interrupt system. - - name size comments - - PC 15 program counter - AC0..AC3 16 accumulators 0..3 - C 1 carry - SR 16 front panel switches - PI 16 priority interrupt mask - ION 1 interrupt enable - ION_DELAY 1 interrupt enable delay for ION - PWR 1 power fail interrupt - INT 15 interrupt pending flags - BUSY 15 device busy flags - DONE 15 device done flags - DISABLE 15 device interrupt disable flags - STOP_DEV 1 stop on undefined IOT - INDMAX 15 maximum number of nested indirects - PCQ[0:63] 15 PC prior to last JMP, JMS, or interrupt; - most recent PC change first - 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 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 8 last data item processed - BUSY 1 device busy flag - DONE 1 device done flag - DISABLE 1 interrupt disable flag - INT 1 interrupt pending 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 or paper - - end of file 1 report error and stop - 0 out of tape or paper - - 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 - BUSY 1 device busy flag - DONE 1 device done flag - DISABLE 1 interrupt disable flag - INT 1 interrupt pending 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 or paper - - OS I/O error x report error and stop - -2.2.3 Terminal Input (TTI) - -The terminal input polls the console keyboard for input. Terminal -input options include the ability to set ANSI mode or limited Dasher -compatibility mode: - - SET TTI ANSI normal mode - SET TTI DASHER Dasher mode - -Setting either TTI or TTO changes both devices. In Dasher mode, carriage -return is changed to newline on input, and ^X is changed to backspace. - -The terminal input implements these registers: - - name size comments - - BUF 8 last data item processed - BUSY 1 device busy flag - DONE 1 device done flag - DISABLE 1 interrupt disable flag - INT 1 interrupt pending flag - POS 32 number of characters input - TIME 24 keyboard polling interval - -2.2.4 Terminal Output (TTO) - -The terminal output writes to the simulator console window. Terminal -output options include the the ability to set ANSI mode or limited -Dasher compatibility mode: - - SET TTO ANSI normal mode - SET TTO DASHER Dasher mode - -Setting either TTI or TTO changes both devices. In Dasher mode, carriage -return is changed to newline on input, and ^X is changed to backspace. - -The terminal output implements these registers: - - name size comments - - BUF 8 last data item processed - BUSY 1 device busy flag - DONE 1 device done flag - DISABLE 1 interrupt disable flag - INT 1 interrupt pending flag - POS 32 number of characters output - TIME 24 time from I/O initiation to interrupt - -2.2.5 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 8 last data item processed - BUSY 1 device busy flag - DONE 1 device done flag - DISABLE 1 interrupt disable flag - INT 1 interrupt pending 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 paper - - OS I/O error x report error and stop - -2.2.6 Real-Time Clock (CLK) - -The real-time clock (CLK) line frequency can be adjusted as follows: - - SET CLK 60HZ set line frequency to 60Hz - SET CLK 50HZ set line frequency to 50Hz - -The default is 60Hz. - -The clock implements these registers: - - name size comments - - SELECT 2 selected clock interval - BUSY 1 device busy flag - DONE 1 device done flag - DISABLE 1 interrupt disable flag - INT 1 interrupt pending flag - TIME0 24 clock frequency, select = 0 - TIME1 24 clock frequency, select = 1 - TIME2 24 clock frequency, select = 2 - TIME3 24 clock frequency, select = 3 - -The real-time clock autocalibrates; the clock interval is adjusted up -or down so that the clock tracks actual elapsed time. - -2.2.7 Plotter (PTP) - -The plotter (PLT) 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 plotter. - -The plotter implements these registers: - - name size comments - - BUF 8 last data item processed - BUSY 1 device busy flag - DONE 1 device done flag - DISABLE 1 interrupt disable flag - INT 1 interrupt pending 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 or paper - - OS I/O error x report error and stop - -2.2.8 Second Terminal (TTI1, TTO1) - -The second terminal consists of two independent devices, TTI1 and TTO1. -The additional terminal performs input and output through a Telnet session -connecting into a user-specified port. The ATTACH command specifies the -port to be used: - - ATTACH TTI1 set up listening port - -where port is a decimal number between 1 and 65535 that is not being used -for other TCP/IP activities. - -Once TTI1 is attached and the simulator is running, the terminal listens -for a connection on the specified port. It assumes that the incoming -connection is a Telnet connection. The connection remain opens until -disconnected by the Telnet client, or by a DETACH TTI1 command. - -The second terminal has two options, recognized on both devices, for -setting limited Dasher-compatibility mode or ANSI mode: - - SET TTI1 ANSI normal mode - SET TTI1 DASHER Dasher mode - SET TTO1 ANSI normal mode - SET TTO1 DASHER Dasher mode - -Setting either TTI1 or TTO1 changes both devices. In Dasher mode, carriage -return is changed to newline on input, and ^X is changed to backspace. - -The SHOW TTI1 CONNECTIONS command displays the current connection to TTI1. -The SHOW TTI1 STATISTICS command displays statistics for the current connection. -The SET TTI1 DISCONNECT{=0} disconnects the current connection. - -The second terminal input implements these registers: - - name size comments - - BUF 8 last data item processed - BUSY 1 device busy flag - DONE 1 device done flag - DISABLE 1 interrupt disable flag - INT 1 interrupt pending flag - TIME 24 keyboard polling interval - -The second terminal output implements these registers: - - name size comments - - BUF 8 last data item processed - BUSY 1 device busy flag - DONE 1 device done flag - DISABLE 1 interrupt disable flag - INT 1 interrupt pending flag - TIME 24 time from I/O initiation to interrupt - -2.3 Fixed Head Disk (DK) - -Fixed head disk options include the ability to set the number of platters -to a fixed value between 1 and 8, or to autosize the number of platters -from the attached file: - - SET RF 1P one platter (256K) - SET RF 2P two platters (512K) - SET RF 3P three platters (768K) - SET RF 4P four platters (1024K) - SET RF 5P five platters (1280K) - SET RF 6P six platters (1536K) - SET RF 7P seven platters (1792K) - SET RF 8P eight platters (2048K) - SET RF AUTOSIZE autosized on attach - -The default is 1P (minimum size). - -The fixed head disk controller implements these registers: - - name size comments - - STAT 16 status - DA 16 disk address - MA 16 memory address - BUSY 1 device busy flag - DONE 1 device done flag - DISABLE 1 device disable flag - INT 1 interrupt pending flag - WLK 8 write lock switches - TIME 24 rotational delay, per sector - STOP_IOE 1 stop on I/O error - -The fixed head disk controller supports the BOOT command. - -Error handling is as follows: - - error STOP_IOE processed as - - not attached 1 report error and stop - 0 disk not ready - -Fixed head disk data files are buffered in memory; therefore, end of file -and OS I/O errors cannot occur. - -2.4 Moving Head Disk (DP) - -Moving head 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 FLOPPY set unit n to floppy disk - SET DPn D31 set unit n to Diablo 31 - SET DPn D44 set unit n to Diablo 44 - SET DPn C111 set unit n to Century 111 - SET DPn C114 set unit n to Century 114 - SET DPn 6225 set unit n to 6225 - SET DPn 6099 set unit n to 6099 - SET DPn 6227 set unit n to 6227 - SET DPn 6070 set unit n to 6070 - SET DPn 6103 set unit n to 6103 - SET DPn 4231 set unit n to 4231 - -Units can also be set ONLINE or OFFLINE. The moving head disk controller -supports the BOOT command. - -All drives have 256 16b words per sector. The other disk parameters are: - - drive cylinders surfaces sectors size (MW) DG models - - floppy 77 1 8 .158 6038 - D31 203 2 12 1.247 4047, 4237, 4238 - D44 408 4 12 5.014 4234, 6045 - C111 203 10 6 3.118 4048 - C114 203 20 12 12.472 4057, 2314 - 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: - - name size comments - - FCCY 16 flags, command, cylinder - USSC 16 unit, surface, sector, count - STAT 16 status - MA 16 memory address - BUSY 1 device busy flag - DONE 1 device done flag - DISABLE 1 interrupt disable flag - INT 1 interrupt pending flag - STIME 24 seek time, per cylinder - RTIME 24 rotational delay - -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.5 Magnetic Tape (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 controller -supports the BOOT command. - -The magnetic tape controller implements these registers: - - name size comments - - CU 16 command, unit - MA 16 memory address - WC 16 word count - STA1 16 status word 1 - STA2 16 status word 2 - EP 1 extended polling mode (not supported) - BUSY 1 device busy flag - DONE 1 device done flag - DISABLE 1 interrupt disable flag - INT 1 interrupt pending flag - STOP_IOE 1 stop on I/O error - CTIME 24 controller delay - RTIME 24 record delay - UST[0:7] 32 unit status, units 0-7 - POS[0:7] 31 position, units 0-7 - -Error handling is as follows: - - error processed as - - not attached tape not ready - - end of file bad tape - - OS I/O error report error and stop - -2.6 Symbolic Display and Input - -The Nova simulator implements symbolic display and input. Display is -controlled by command line switches: - - -a display as ASCII character - -c display as two character ASCII 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 ASCII string - alphabetic instruction mnemonic - numeric octal number - -Instruction input uses standard Nova assembler syntax. There are three -instruction classes: memory reference, IOT, and operate. - -Memory reference instructions have the format - - memref {ac,}{@}address{,index} - -LDA and STA require an initial register; ISZ, DSZ, JSR, and JMP do not. -The syntax for addresses and indices is as follows: - -syntax mode displacement comments - -0 <= n < 0400 0 n -{+/-}n >= 0400 1 {+/-}n - PC must be in range [-200, 177] - invalid on disk -.+/-n 1 {+/-}n must be in range [-200, 177] -{+/-}n,2 2 {+/-}n must be in range [-200, 177] -{+/-}n,3 3 {+/-}n must be in range [-200, 177] - -IOT instructions have one of four formats - - syntax example - - iot HALT - iot reg INTA - iot device SKPDN - iot reg,device DOAS - -Devices may be specified as mnemonics or as numbers in the range 0 - 077. - -Operate instructions have the format - - opcode{#} reg,reg{,skip} - -In all Nova instructions, blanks may be substituted for commas as field -delimiters. diff --git a/NOVA/nova_dsk.c b/NOVA/nova_dsk.c deleted file mode 100644 index d1fbc04a..00000000 --- a/NOVA/nova_dsk.c +++ /dev/null @@ -1,298 +0,0 @@ -/* nova_dsk.c: 4019 fixed head disk simulator - - 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. - - dsk fixed head disk - - 26-Jul-03 RMS Fixed bug in set size routine - 14-Mar-03 RMS Fixed variable capacity interaction with save/restore - 03-Mar-03 RMS Fixed variable capacity and autosizing - 03-Oct-02 RMS Added DIB - 06-Jan-02 RMS Revised enable/disable support - 23-Aug-01 RMS Fixed bug in write watermarking - 26-Apr-01 RMS Added device enable/disable support - 10-Dec-00 RMS Added Eclipse support - 15-Oct-00 RMS Editorial changes - 14-Apr-99 RMS Changed t_addr to unsigned - - The 4019 is a head-per-track disk. To minimize overhead, the entire disk - is buffered in memory. -*/ - -#include "nova_defs.h" -#include - -#define UNIT_V_AUTO (UNIT_V_UF + 0) /* autosize */ -#define UNIT_V_PLAT (UNIT_V_UF + 1) /* #platters - 1 */ -#define UNIT_M_PLAT 07 -#define UNIT_PLAT (UNIT_M_PLAT << UNIT_V_PLAT) -#define UNIT_GETP(x) ((((x) >> UNIT_V_PLAT) & UNIT_M_PLAT) + 1) -#define UNIT_AUTO (1 << UNIT_V_AUTO) -#define UNIT_PLAT (UNIT_M_PLAT << UNIT_V_PLAT) - -/* Constants */ - -#define DSK_NUMWD 256 /* words/sector */ -#define DSK_NUMSC 8 /* sectors/track */ -#define DSK_NUMTR 128 /* tracks/disk */ -#define DSK_DKSIZE (DSK_NUMTR*DSK_NUMSC*DSK_NUMWD) /* words/disk */ -#define DSK_AMASK ((DSK_NUMDK*DSK_NUMTR*DSK_NUMSC) - 1) /* address mask */ -#define DSK_NUMDK 8 /* disks/controller */ -#define GET_DISK(x) (((x) / (DSK_NUMSC * DSK_NUMTR)) & (DSK_NUMDK - 1)) - -/* Parameters in the unit descriptor */ - -#define FUNC u4 /* function */ - -/* Status register */ - -#define DSKS_WLS 020 /* write lock status */ -#define DSKS_DLT 010 /* data late error */ -#define DSKS_NSD 004 /* non-existent disk */ -#define DSKS_CRC 002 /* parity error */ -#define DSKS_ERR 001 /* error summary */ -#define DSKS_ALLERR (DSKS_WLS | DSKS_DLT | DSKS_NSD | DSKS_CRC | DSKS_ERR) - -/* Map logical sector numbers to physical sector numbers - (indexed by track<2:0>'sector) -*/ - -static const int32 sector_map[] = { - 0, 2, 4, 6, 1, 3, 5, 7, 1, 3, 5, 7, 2, 4, 6, 0, - 2, 4, 6, 0, 3, 5, 7, 1, 3, 5, 7, 1, 4, 6, 0, 2, - 4, 6, 0, 2, 5, 7, 1, 3, 5, 7, 1, 3, 6, 0, 2, 4, - 6, 0, 2, 4, 7, 1, 3, 5, 7, 1, 3, 5, 0, 2, 4, 6 }; - -#define DSK_MMASK 077 -#define GET_SECTOR(x) ((int) fmod (sim_gtime() / ((double) (x)), \ - ((double) DSK_NUMSC))) - -extern uint16 M[]; -extern UNIT cpu_unit; -extern int32 int_req, dev_busy, dev_done, dev_disable; - -int32 dsk_stat = 0; /* status register */ -int32 dsk_da = 0; /* disk address */ -int32 dsk_ma = 0; /* memory address */ -int32 dsk_wlk = 0; /* wrt lock switches */ -int32 dsk_stopioe = 1; /* stop on error */ -int32 dsk_time = 100; /* time per sector */ - -DEVICE dsk_dev; -int32 dsk (int32 pulse, int32 code, int32 AC); -t_stat dsk_svc (UNIT *uptr); -t_stat dsk_reset (DEVICE *dptr); -t_stat dsk_boot (int32 unitno, DEVICE *dptr); -t_stat dsk_attach (UNIT *uptr, char *cptr); -t_stat dsk_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); - -/* DSK data structures - - dsk_dev device descriptor - dsk_unit unit descriptor - dsk_reg register list -*/ - -DIB dsk_dib = { DEV_DSK, INT_DSK, PI_DSK, &dsk }; - -UNIT dsk_unit = - { UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+UNIT_MUSTBUF, - DSK_DKSIZE) }; - -REG dsk_reg[] = { - { ORDATA (STAT, dsk_stat, 16) }, - { ORDATA (DA, dsk_da, 16) }, - { ORDATA (MA, dsk_ma, 16) }, - { FLDATA (BUSY, dev_busy, INT_V_DSK) }, - { FLDATA (DONE, dev_done, INT_V_DSK) }, - { FLDATA (DISABLE, dev_disable, INT_V_DSK) }, - { FLDATA (INT, int_req, INT_V_DSK) }, - { ORDATA (WLK, dsk_wlk, 8) }, - { DRDATA (TIME, dsk_time, 24), REG_NZ + PV_LEFT }, - { FLDATA (STOP_IOE, dsk_stopioe, 0) }, - { NULL } }; - -MTAB dsk_mod[] = { - { UNIT_PLAT, (0 << UNIT_V_PLAT), NULL, "1P", &dsk_set_size }, - { UNIT_PLAT, (1 << UNIT_V_PLAT), NULL, "2P", &dsk_set_size }, - { UNIT_PLAT, (2 << UNIT_V_PLAT), NULL, "3P", &dsk_set_size }, - { UNIT_PLAT, (3 << UNIT_V_PLAT), NULL, "4P", &dsk_set_size }, - { UNIT_PLAT, (4 << UNIT_V_PLAT), NULL, "5P", &dsk_set_size }, - { UNIT_PLAT, (5 << UNIT_V_PLAT), NULL, "6P", &dsk_set_size }, - { UNIT_PLAT, (6 << UNIT_V_PLAT), NULL, "7P", &dsk_set_size }, - { UNIT_PLAT, (7 << UNIT_V_PLAT), NULL, "8P", &dsk_set_size }, - { UNIT_AUTO, UNIT_AUTO, "autosize", "AUTOSIZE", NULL }, - { 0 } }; - -DEVICE dsk_dev = { - "DK", &dsk_unit, dsk_reg, dsk_mod, - 1, 8, 21, 1, 8, 16, - NULL, NULL, &dsk_reset, - &dsk_boot, &dsk_attach, NULL, - &dsk_dib, DEV_DISABLE }; - -/* IOT routine */ - -int32 dsk (int32 pulse, int32 code, int32 AC) -{ -int32 t, rval; - -rval = 0; -switch (code) { /* decode IR<5:7> */ -case ioDIA: /* DIA */ - rval = dsk_stat & DSKS_ALLERR; /* read status */ - break; -case ioDOA: /* DOA */ - dsk_da = AC & DSK_AMASK; /* save disk addr */ - break; -case ioDIB: /* DIB */ - rval = dsk_ma & AMASK; /* read mem addr */ - break; -case ioDOB: /* DOB */ - dsk_ma = AC & AMASK; /* save mem addr */ - break; } /* end switch code */ - -if (pulse) { /* any pulse? */ - dev_busy = dev_busy & ~INT_DSK; /* clear busy */ - dev_done = dev_done & ~INT_DSK; /* clear done */ - int_req = int_req & ~INT_DSK; /* clear int */ - dsk_stat = 0; /* clear status */ - sim_cancel (&dsk_unit); } /* stop I/O */ - -if ((pulse == iopP) && ((dsk_wlk >> GET_DISK (dsk_da)) & 1)) { /* wrt lock? */ - dev_done = dev_done | INT_DSK; /* set done */ - int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable); - dsk_stat = DSKS_ERR + DSKS_WLS; /* set status */ - return rval; } - -if (pulse & 1) { /* read or write? */ - if (((uint32) (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 */ - 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); - if (t < 0) t = t + DSK_NUMSC; - sim_activate (&dsk_unit, t * dsk_time); } /* activate */ -return rval; -} - -/* Unit service */ - -t_stat dsk_svc (UNIT *uptr) -{ -int32 i, da, pa; - -dev_busy = dev_busy & ~INT_DSK; /* clear busy */ -dev_done = dev_done | INT_DSK; /* set done */ -int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable); - -if ((uptr->flags & UNIT_BUF) == 0) { /* not buf? abort */ - dsk_stat = DSKS_ERR + DSKS_NSD; /* set status */ - return IORETURN (dsk_stopioe, SCPE_UNATT); } - -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); } - 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]; } - if (((uint32) (da + i)) >= uptr->hwmark) /* past end? */ - uptr->hwmark = da + i + 1; /* upd hwmark */ - dsk_ma = (dsk_ma + DSK_NUMWD + 3) & AMASK; } - -dsk_stat = 0; /* set status */ -return SCPE_OK; -} - -/* Reset routine */ - -t_stat dsk_reset (DEVICE *dptr) -{ -dsk_stat = dsk_da = dsk_ma = 0; -dev_busy = dev_busy & ~INT_DSK; /* clear busy */ -dev_done = dev_done & ~INT_DSK; /* clear done */ -int_req = int_req & ~INT_DSK; /* clear int */ -sim_cancel (&dsk_unit); -return SCPE_OK; -} - -/* Bootstrap routine */ - -#define BOOT_START 2000 -#define BOOT_LEN (sizeof (boot_rom) / sizeof (int)) - -static const int32 boot_rom[] = { - 060220, /* NIOC DSK ; clear disk */ - 0102400, /* SUB 0,0 ; addr = 0 */ - 061020, /* DOA 0,DSK ; set disk addr */ - 062120, /* DOBS 0,DSK ; set mem addr, rd */ - 063620, /* SKPDN DSK ; done? */ - 000776, /* JMP .-2 */ - 000377, /* JMP 377 */ -}; - -t_stat dsk_boot (int32 unitno, DEVICE *dptr) -{ -int32 i; -extern int32 saved_PC; - -for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i]; -saved_PC = BOOT_START; -return SCPE_OK; -} - -/* Attach routine */ - -t_stat dsk_attach (UNIT *uptr, char *cptr) -{ -uint32 sz, p; -uint32 ds_bytes = DSK_DKSIZE * sizeof (int16); - -if ((uptr->flags & UNIT_AUTO) && (sz = sim_fsize (cptr))) { - p = (sz + ds_bytes - 1) / ds_bytes; - if (p >= DSK_NUMDK) p = DSK_NUMDK - 1; - uptr->flags = (uptr->flags & ~UNIT_PLAT) | - (p << UNIT_V_PLAT); } -uptr->capac = UNIT_GETP (uptr->flags) * DSK_DKSIZE; /* set capacity */ -return attach_unit (uptr, cptr); -} - -/* Change disk size */ - -t_stat dsk_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -if (val < 0) return SCPE_IERR; -if (uptr->flags & UNIT_ATT) return SCPE_ALATT; -uptr->capac = UNIT_GETP (val) * DSK_DKSIZE; -uptr->flags = uptr->flags & ~UNIT_AUTO; -return SCPE_OK; -} diff --git a/NOVA/nova_lp.c b/NOVA/nova_lp.c deleted file mode 100644 index 36817c27..00000000 --- a/NOVA/nova_lp.c +++ /dev/null @@ -1,124 +0,0 @@ -/* nova_lp.c: NOVA line printer simulator - - 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. - - lpt line printer - - 25-Apr-03 RMS Revised for extended file support - 30-May-02 RMS Widened POS to 32b -*/ - -#include "nova_defs.h" - -extern int32 int_req, dev_busy, dev_done, dev_disable; - -int32 lpt_stopioe = 0; /* stop on error */ - -int32 lpt (int32 pulse, int32 code, int32 AC); -t_stat lpt_svc (UNIT *uptr); -t_stat lpt_reset (DEVICE *dptr); - -/* LPT data structures - - lpt_dev LPT device descriptor - lpt_unit LPT unit descriptor - lpt_reg LPT register list -*/ - -DIB lpt_dib = { DEV_LPT, INT_LPT, PI_LPT, &lpt }; - -UNIT lpt_unit = { - UDATA (&lpt_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT }; - -REG lpt_reg[] = { - { ORDATA (BUF, lpt_unit.buf, 8) }, - { FLDATA (BUSY, dev_busy, INT_V_LPT) }, - { FLDATA (DONE, dev_done, INT_V_LPT) }, - { FLDATA (DISABLE, dev_disable, INT_V_LPT) }, - { FLDATA (INT, int_req, INT_V_LPT) }, - { DRDATA (POS, lpt_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, lpt_unit.wait, 24), PV_LEFT }, - { FLDATA (STOP_IOE, lpt_stopioe, 0) }, - { NULL } }; - -DEVICE lpt_dev = { - "LPT", &lpt_unit, lpt_reg, NULL, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &lpt_reset, - NULL, NULL, NULL, - &lpt_dib, DEV_DISABLE }; - -/* IOT routine */ - -int32 lpt (int32 pulse, int32 code, int32 AC) -{ - -if (code == ioDOA) lpt_unit.buf = AC & 0177; -switch (pulse) { /* decode IR<8:9> */ -case iopS: /* start */ - dev_busy = dev_busy | INT_LPT; /* set busy */ - dev_done = dev_done & ~INT_LPT; /* clear done, int */ - 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); - sim_activate (&lpt_unit, lpt_unit.wait); - break; -case iopC: /* clear */ - dev_busy = dev_busy & ~INT_LPT; /* clear busy */ - dev_done = dev_done & ~INT_LPT; /* clear done, int */ - int_req = int_req & ~INT_LPT; - sim_cancel (&lpt_unit); /* deactivate unit */ - break; } /* end switch */ -return 0; -} - -/* Unit service */ - -t_stat lpt_svc (UNIT *uptr) -{ -dev_busy = dev_busy & ~INT_LPT; /* clear busy */ -dev_done = dev_done | INT_LPT; /* set done */ -int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable); -if ((lpt_unit.flags & UNIT_ATT) == 0) /* attached? */ - return IORETURN (lpt_stopioe, SCPE_UNATT); -if (putc (lpt_unit.buf, lpt_unit.fileref) == EOF) { - perror ("LPT I/O error"); - clearerr (lpt_unit.fileref); - return SCPE_IOERR; } -lpt_unit.pos = lpt_unit.pos + 1; -return SCPE_OK; -} - -/* Reset routine */ - -t_stat lpt_reset (DEVICE *dptr) -{ -lpt_unit.buf = 0; -dev_busy = dev_busy & ~INT_LPT; /* clear busy */ -dev_done = dev_done & ~INT_LPT; /* clear done, int */ -int_req = int_req & ~INT_LPT; -sim_cancel (&lpt_unit); /* deactivate unit */ -return SCPE_OK; -} diff --git a/NOVA/nova_mta.c b/NOVA/nova_mta.c deleted file mode 100644 index e965da73..00000000 --- a/NOVA/nova_mta.c +++ /dev/null @@ -1,589 +0,0 @@ -/* nova_mta.c: NOVA magnetic tape simulator - - 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. - - mta magnetic tape - - 25-Apr-03 RMS Revised for extended file support - 28-Mar-03 RMS Added multiformat support - 28-Feb-03 RMS Revised for magtape library - 30-Oct-02 RMS Fixed BOT handling, added error record handling - 08-Oct-02 RMS Added DIB - 30-Sep-02 RMS Revamped error handling - 28-Aug-02 RMS Added end of medium support - 30-May-02 RMS Widened POS to 32b - 22-Apr-02 RMS Added maximum record length test - 06-Jan-02 RMS Revised enable/disable support - 30-Nov-01 RMS Added read only unit, extended SET/SHOW support - 24-Nov-01 RMS Changed POS, USTAT, FLG to an array - 26-Apr-01 RMS Added device enable/disable support - 18-Apr-01 RMS Changed to rewind tape before boot - 10-Dec-00 RMS Added Eclipse support from Charles Owen - 15-Oct-00 RMS Editorial changes - 11-Nov-98 CEO Removed clear of mta_ma on iopC - 04-Oct-98 RMS V2.4 magtape format - 18-Jan-97 RMS V2.3 magtape format - 29-Jun-96 RMS Added unit enable/disable support - - Magnetic tapes are represented as a series of variable records - of the form: - - 32b byte count byte count is little endian - byte 0 - byte 1 - : - byte n-2 - byte n-1 - 32b byte count - - If the byte count is odd, the record is padded with an extra byte - of junk. File marks are represented by a byte count of 0 and are - not duplicated; end of tape by end of file. -*/ - -#include "nova_defs.h" -#include "sim_tape.h" - -#define MTA_NUMDR 8 /* #drives */ -#define USTAT u3 /* unit status */ -#define MTA_MAXFR (1 << 16) /* max record lnt */ -#define WC_SIZE (1 << 14) /* max word count */ -#define WC_MASK (WC_SIZE - 1) - -/* Command/unit */ - -#define CU_CI 0100000 /* clear interrupt */ -#define CU_EP 0002000 /* poll enable */ -#define CU_DE 0001000 /* disable erase */ -#define CU_DA 0000400 /* disable autoretry */ -#define CU_PE 0000400 /* PE mode */ -#define CU_V_CMD 3 /* command */ -#define CU_M_CMD 027 -#define CU_READ 000 -#define CU_REWIND 001 -#define CU_CMODE 002 -#define CU_SPACEF 003 -#define CU_SPACER 004 -#define CU_WRITE 005 -#define CU_WREOF 006 -#define CU_ERASE 007 -#define CU_READNS 020 -#define CU_UNLOAD 021 -#define CU_DMODE 022 -#define CU_V_UNIT 0 /* unit */ -#define CU_M_UNIT 07 -#define GET_CMD(x) (((x) >> CU_V_CMD) & CU_M_CMD) -#define GET_UNIT(x) (((x) >> CU_V_UNIT) & CU_M_UNIT) - -/* Status 1 - stored in mta_sta<31:16> or (*) uptr->USTAT<31:16> */ - -#define STA_ERR1 (0100000u << 16) /* error */ -#define STA_DLT (0040000 << 16) /* data late */ -#define STA_REW (0020000 << 16) /* *rewinding */ -#define STA_ILL (0010000 << 16) /* illegal */ -#define STA_HDN (0004000 << 16) /* high density */ -#define STA_DAE (0002000 << 16) /* data error */ -#define STA_EOT (0001000 << 16) /* *end of tape */ -#define STA_EOF (0000400 << 16) /* *end of file */ -#define STA_BOT (0000200 << 16) /* *start of tape */ -#define STA_9TK (0000100 << 16) /* nine track */ -#define STA_BAT (0000040 << 16) /* bad tape */ -#define STA_CHG (0000010 << 16) /* status change */ -#define STA_WLK (0000004 << 16) /* *write lock */ -#define STA_ODD (0000002 << 16) /* odd character */ -#define STA_RDY (0000001 << 16) /* *drive ready */ - -/* Status 2 - stored in mta_sta<15:0> or (*) uptr->USTAT<15:0> */ - -#define STA_ERR2 0100000 /* error */ -#define STA_RWY 0040000 /* runaway tape */ -#define STA_FGP 0020000 /* false gap */ -#define STA_CDL 0004000 /* corrected dlt */ -#define STA_V_UNIT 8 -#define STA_M_UNIT 07 /* unit */ -#define STA_WCO 0000200 /* word count ovflo */ -#define STA_BDS 0000100 /* bad signal */ -#define STA_OVS 0000040 /* overskew */ -#define STA_CRC 0000020 /* check error */ -#define STA_STE 0000010 /* single trk error */ -#define STA_FPR 0000004 /* false preamble */ -#define STA_FMT 0000002 /* format error */ -#define STA_PEM 0000001 /* *PE mode */ - -#define STA_EFLGS1 (STA_DLT | STA_ILL | STA_DAE | STA_EOT | \ - STA_EOF | STA_BOT | STA_BAT | STA_ODD) -#define STA_EFLGS2 (STA_FGP | STA_CDL | STA_BDS | STA_OVS | \ - STA_CRC | STA_FPR | STA_FPR) /* set error 2 */ -#define STA_CLR ((020 << 16) | 0010000) /* always clear */ -#define STA_SET (STA_HDN | STA_9TK) /* always set */ -#define STA_DYN (STA_REW | STA_EOT | STA_EOF | STA_BOT | \ - STA_WLK | STA_RDY | STA_PEM) /* kept in USTAT */ -#define STA_MON (STA_REW | STA_BOT | STA_WLK | STA_RDY | \ - STA_PEM) /* set status chg */ - -extern uint16 M[]; -extern UNIT cpu_unit; -extern int32 int_req, dev_busy, dev_done, dev_disable; - -int32 mta_ma = 0; /* memory address */ -int32 mta_wc = 0; /* word count */ -int32 mta_cu = 0; /* command/unit */ -int32 mta_sta = 0; /* status register */ -int32 mta_ep = 0; /* enable polling */ -int32 mta_cwait = 100; /* command latency */ -int32 mta_rwait = 100; /* record latency */ -uint8 *mtxb = NULL; /* transfer buffer */ - -DEVICE mta_dev; -int32 mta (int32 pulse, int32 code, int32 AC); -t_stat mta_svc (UNIT *uptr); -t_stat mta_reset (DEVICE *dptr); -t_stat mta_boot (int32 unitno, DEVICE *dptr); -t_stat mta_attach (UNIT *uptr, char *cptr); -t_stat mta_detach (UNIT *uptr); -int32 mta_updcsta (UNIT *uptr); -void mta_upddsta (UNIT *uptr, int32 newsta); -t_stat mta_map_err (UNIT *uptr, t_stat st); -t_stat mta_vlock (UNIT *uptr, int32 val, char *cptr, void *desc); - -static const int ctype[32] = { /* c vs r timing */ - 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, - 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1 }; - -/* MTA data structures - - mta_dev MTA device descriptor - mta_unit MTA unit list - mta_reg MTA register list - mta_mod MTA modifier list -*/ - -DIB mta_dib = { DEV_MTA, INT_MTA, PI_MTA, &mta }; - -UNIT mta_unit[] = { - { UDATA (&mta_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) }, - { UDATA (&mta_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) }, - { UDATA (&mta_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) }, - { UDATA (&mta_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) }, - { UDATA (&mta_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) }, - { UDATA (&mta_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) }, - { UDATA (&mta_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) }, - { UDATA (&mta_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) } }; - -REG mta_reg[] = { - { ORDATA (CU, mta_cu, 16) }, - { ORDATA (MA, mta_ma, 16) }, - { ORDATA (WC, mta_wc, 16) }, - { GRDATA (STA1, mta_sta, 8, 16, 16) }, - { ORDATA (STA2, mta_sta, 16) }, - { FLDATA (EP, mta_ep, 0) }, - { FLDATA (BUSY, dev_busy, INT_V_MTA) }, - { FLDATA (DONE, dev_done, INT_V_MTA) }, - { FLDATA (DISABLE, dev_disable, INT_V_MTA) }, - { FLDATA (INT, int_req, INT_V_MTA) }, - { DRDATA (CTIME, mta_cwait, 24), PV_LEFT }, - { DRDATA (RTIME, mta_rwait, 24), PV_LEFT }, - { URDATA (UST, mta_unit[0].USTAT, 8, 32, 0, MTA_NUMDR, 0) }, - { URDATA (POS, mta_unit[0].pos, 8, T_ADDR_W, 0, - MTA_NUMDR, REG_RO | PV_LEFT) }, - { NULL } }; - -MTAB mta_mod[] = { - { MTUF_WLK, 0, "write enabled", "WRITEENABLED", &mta_vlock }, - { MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", &mta_vlock }, - { MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT", - &sim_tape_set_fmt, &sim_tape_show_fmt, NULL }, - { 0 } }; - -DEVICE mta_dev = { - "MT", mta_unit, mta_reg, mta_mod, - MTA_NUMDR, 10, 31, 1, 8, 8, - NULL, NULL, &mta_reset, - &mta_boot, &mta_attach, &mta_detach, - &mta_dib, DEV_DISABLE }; - -/* IOT routine */ - -int32 mta (int32 pulse, int32 code, int32 AC) -{ -UNIT *uptr; -int32 u, c, rval; - -rval = 0; -uptr = mta_dev.units + GET_UNIT(mta_cu); /* get unit */ -switch (code) { /* decode IR<5:7> */ -case ioDIA: /* DIA */ - rval = (mta_updcsta (uptr) >> 16) & DMASK; /* return status 1 */ - break; -case ioDOA: /* DOA */ -/* if (AC & CU_CI) ... clear ep int */ - mta_cu = AC; /* save cmd/unit */ - uptr = mta_dev.units + GET_UNIT(mta_cu); /* get unit */ - mta_updcsta (uptr); /* update status */ - break; -case ioDIB: /* DIB */ - rval = mta_ma & AMASK; /* return ma */ - break; -case ioDOB: /* DOB */ - mta_ma = AC & AMASK; /* save ma */ - break; -case ioDIC: /* DIC */ - rval = mta_updcsta (uptr) & DMASK; /* return status 2 */ - break; -case ioDOC: /* DOC */ - mta_wc = ((AC & 040000) << 1) | (AC & 077777); /* save wc */ - break; } /* end switch code */ - -/* IOT, continued */ - -switch (pulse) { /* decode IR<8:9> */ -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); } - 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_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); } } - dev_busy = dev_busy & ~INT_MTA; /* clear busy */ - dev_done = dev_done & ~INT_MTA; /* clear done */ - int_req = int_req & ~INT_MTA; /* clear int */ - mta_sta = mta_cu = 0; /* clear registers */ - mta_updcsta (&mta_unit[0]); /* update status */ - break; } /* end case pulse */ -return rval; -} - -/* Unit service - - If rewind done, reposition to start of tape, set status - else, do operation, clear busy, set done, interrupt -*/ - -t_stat mta_svc (UNIT *uptr) -{ -int32 c, p, pa, u; -t_mtrlnt i, cbc, tbc, wc; -uint16 c1, c2; -t_stat st, r = SCPE_OK; - -u = uptr - mta_dev.units; /* get unit number */ -c = GET_CMD (mta_cu); /* command */ -wc = WC_SIZE - (mta_wc & WC_MASK); /* io wc */ - -if (uptr->USTAT & STA_REW) { /* rewind? */ - sim_tape_rewind (uptr); /* update tape */ - mta_upddsta (uptr, (uptr->USTAT & ~STA_REW) | STA_BOT | STA_RDY); - if (u == GET_UNIT (mta_cu)) mta_updcsta (uptr); - return SCPE_OK; } - -if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */ - mta_upddsta (uptr, 0); /* unit off line */ - mta_sta = mta_sta | STA_ILL; } /* illegal operation */ -else switch (c) { /* case on command */ - -case CU_CMODE: /* controller mode */ - mta_ep = mta_cu & CU_EP; - break; -case CU_DMODE: /* drive mode */ - if (!sim_tape_bot (uptr)) 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); - break; - -/* Unit service, continued */ - -case CU_READ: /* read */ -case CU_READNS: /* read non-stop */ - st = sim_tape_rdrecf (uptr, mtxb, &tbc, MTA_MAXFR); /* read rec */ - if (st == MTSE_RECE) mta_sta = mta_sta | STA_DAE; /* rec in err? */ - else if (st != MTSE_OK) { /* other error? */ - r = mta_map_err (uptr, st); /* map error */ - break; } - 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 */ - for (i = p = 0; i < wc; i++) { /* copy buf to mem */ - c1 = mtxb[p++]; - c2 = mtxb[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; - mta_upddsta (uptr, uptr->USTAT | STA_RDY); - break; - -case CU_WRITE: /* write */ - tbc = wc * 2; /* io byte count */ - for (i = p = 0; i < wc; i++) { /* copy to buffer */ - pa = MapAddr (0, mta_ma); /* map address */ - mtxb[p++] = (M[pa] >> 8) & 0377; - mtxb[p++] = M[pa] & 0377; - mta_ma = (mta_ma + 1) & AMASK; } - if (st = sim_tape_wrrecf (uptr, mtxb, tbc)) { /* write rec, err? */ - r = mta_map_err (uptr, st); /* map error */ - mta_ma = (mta_ma - wc) & AMASK; } /* restore wc */ - else mta_wc = 0; /* clear wc */ - mta_upddsta (uptr, uptr->USTAT | STA_RDY); - break; - -/* Unit service, continued */ - -case CU_WREOF: /* write eof */ - if (st = sim_tape_wrtmk (uptr)) /* write tmk, err? */ - r = mta_map_err (uptr, st); /* map error */ - else mta_upddsta (uptr, uptr->USTAT | STA_EOF | STA_RDY); - break; - -case CU_ERASE: /* erase */ - if (sim_tape_wrp (uptr)) /* write protected? */ - r = mta_map_err (uptr, MTSE_WRP); /* map error */ - else mta_upddsta (uptr, uptr->USTAT | STA_RDY); - break; - -case CU_SPACEF: /* space forward */ - do { - mta_wc = (mta_wc + 1) & DMASK; /* incr wc */ - if (st = sim_tape_sprecf (uptr, &tbc)) { /* space rec fwd, err? */ - r = mta_map_err (uptr, st); /* map error */ - break; } - } - 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 (st = sim_tape_sprecr (uptr, &tbc)) { /* space rec rev, err? */ - r = mta_map_err (uptr, st); /* map error */ - break; } - } - while (mta_wc != 0); - mta_upddsta (uptr, uptr->USTAT | STA_RDY); - break; - -default: /* reserved */ - mta_sta = mta_sta | STA_ILL; - mta_upddsta (uptr, uptr->USTAT | STA_RDY); - break; } /* end case */ - -mta_updcsta (uptr); /* update status */ -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); -return r; -} - -/* Update controller status */ - -int32 mta_updcsta (UNIT *uptr) /* update ctrl */ -{ -mta_sta = (mta_sta & ~(STA_DYN | STA_CLR | STA_ERR1 | STA_ERR2)) | - (uptr->USTAT & STA_DYN) | STA_SET; -if (mta_sta & STA_EFLGS1) mta_sta = mta_sta | STA_ERR1; -if (mta_sta & STA_EFLGS2) mta_sta = mta_sta | STA_ERR2; -return mta_sta; -} - -/* Update drive status */ - -void mta_upddsta (UNIT *uptr, int32 newsta) /* drive status */ -{ -int32 change; - -if ((uptr->flags & UNIT_ATT) == 0) newsta = 0; /* offline? */ -change = (uptr->USTAT ^ newsta) & STA_MON; /* changes? */ -uptr->USTAT = newsta & STA_DYN; /* update status */ -if (change) { -/* if (mta_ep) { /* if polling */ -/* u = uptr - mta_dev.units; /* unit num */ -/* mta_sta = (mta_sta & ~STA_UNIT) | (u << STA_V_UNIT); -/* set polling interupt... } */ - mta_sta = mta_sta | STA_CHG; } /* flag change */ -return; -} - -/* Map tape error status */ - -t_stat mta_map_err (UNIT *uptr, t_stat st) -{ -switch (st) { -case MTSE_FMT: /* illegal fmt */ - mta_upddsta (uptr, uptr->USTAT | STA_WLK | STA_RDY); -case MTSE_UNATT: /* unattached */ - mta_sta = mta_sta | STA_ILL; -case MTSE_OK: /* no error */ - return SCPE_IERR; /* never get here! */ -case MTSE_TMK: /* end of file */ - mta_upddsta (uptr, uptr->USTAT | STA_RDY | STA_EOF); - break; -case MTSE_IOERR: /* IO error */ - mta_sta = mta_sta | STA_DAE; /* data error */ - mta_upddsta (uptr, uptr->USTAT | STA_RDY); /* ready */ - return SCPE_IOERR; -case MTSE_INVRL: /* invalid rec lnt */ - mta_sta = mta_sta | STA_DAE; /* data error */ - mta_upddsta (uptr, uptr->USTAT | STA_RDY); /* ready */ - return SCPE_MTRLNT; -case MTSE_RECE: /* record in error */ - mta_sta = mta_sta | STA_DAE; /* data error */ - mta_upddsta (uptr, uptr->USTAT | STA_RDY); /* ready */ - break; -case MTSE_EOM: /* end of medium */ - mta_sta = mta_sta | STA_BAT; /* bad tape */ - mta_upddsta (uptr, uptr->USTAT | STA_RDY); /* ready */ - break; -case MTSE_BOT: /* reverse into BOT */ - mta_upddsta (uptr, uptr->USTAT | STA_RDY | STA_BOT); - break; -case MTSE_WRP: /* write protect */ - mta_upddsta (uptr, uptr->USTAT | STA_WLK | STA_RDY); - mta_sta = mta_sta | STA_ILL; /* illegal operation */ - break; } -return SCPE_OK; -} - -/* Reset routine */ - -t_stat mta_reset (DEVICE *dptr) -{ -int32 u; -UNIT *uptr; - -dev_busy = dev_busy & ~INT_MTA; /* clear busy */ -dev_done = dev_done & ~INT_MTA; /* clear done, int */ -int_req = int_req & ~INT_MTA; -mta_cu = mta_wc = mta_ma = mta_sta = 0; /* clear registers */ -mta_ep = 0; -for (u = 0; u < MTA_NUMDR; u++) { /* loop thru units */ - uptr = mta_dev.units + u; - sim_tape_reset (uptr); /* clear pos flag */ - sim_cancel (uptr); /* cancel activity */ - if (uptr->flags & UNIT_ATT) uptr->USTAT = STA_RDY | - (uptr->USTAT & STA_PEM) | - (sim_tape_wrp (uptr)? STA_WLK: 0) | - (sim_tape_bot (uptr)? STA_BOT: 0); - else uptr->USTAT = 0; } -mta_updcsta (&mta_unit[0]); /* update status */ -if (mtxb == NULL) mtxb = calloc (MTA_MAXFR, sizeof (uint8)); -if (mtxb == NULL) return SCPE_MEM; -return SCPE_OK; -} - -/* Attach routine */ - -t_stat mta_attach (UNIT *uptr, char *cptr) -{ -t_stat r; - -r = sim_tape_attach (uptr, cptr); -if (r != SCPE_OK) return r; -if (!sim_is_active (uptr)) mta_upddsta (uptr, STA_RDY | STA_BOT | STA_PEM | - (sim_tape_wrp (uptr)? STA_WLK: 0)); -return r; -} - -/* Detach routine */ - -t_stat mta_detach (UNIT* uptr) -{ -if (!sim_is_active (uptr)) mta_upddsta (uptr, 0); -return sim_tape_detach (uptr); -} - -/* Write lock/unlock validate routine */ - -t_stat mta_vlock (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -if ((uptr->flags & UNIT_ATT) && (val || sim_tape_wrp (uptr))) - mta_upddsta (uptr, uptr->USTAT | STA_WLK); -else mta_upddsta (uptr, uptr->USTAT & ~STA_WLK); -return SCPE_OK; -} - -/* Bootstrap routine */ - -#define BOOT_START 02000 -#define BOOT_UNIT 02020 -#define BOOT_LEN (sizeof (boot_rom) / sizeof (int)) - -static const int32 boot_rom[] = { - 060222, /* NIOC 0,MTA ; clear disk */ - 020417, /* LDA 0,UNIT ; unit */ - 024417, /* LDA 1,REWIND ; cmd */ - 0107000, /* ADD 0,1 ; cmd + unit */ - 065122, /* DOAS 1,MTA ; start rewind */ - 070422, /* DIA 2,MTA ; get status */ - 0151213, /* MOVR# 2,2,SNC ; skip if done */ - 000776, /* JMP .-2 */ - 0126400, /* SUB 1,1 ; ma, wc = 0 */ - 066022, /* DOB 1,MTA */ - 067022, /* DOC 1,MTA */ - 061122, /* DOAS 0,MTA ; start read */ - 070422, /* DIA 2,MTA ; get status */ - 0151213, /* MOVR# 2,2,SNC ; skip if done */ - 000776, /* JMP .-2 */ - 000377, /* JMP 377 */ - 000000, /* UNIT: */ - 000010 /* REWIND: 10 */ -}; - -t_stat mta_boot (int32 unitno, DEVICE *dptr) -{ -int32 i; -extern int32 saved_PC; - -sim_tape_rewind (&mta_unit[unitno]); -for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i]; -M[BOOT_UNIT] = (unitno & CU_M_UNIT) << CU_V_UNIT; -saved_PC = BOOT_START; -return SCPE_OK; -} diff --git a/NOVA/nova_plt.c b/NOVA/nova_plt.c deleted file mode 100644 index f954733e..00000000 --- a/NOVA/nova_plt.c +++ /dev/null @@ -1,125 +0,0 @@ -/* nova_plt.c: NOVA plotter simulator - - Copyright (c) 2000-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 - 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. - - plt plotter - - 25-Apr-03 RMS Revised for extended file support - 03-Oct-02 RMS Added DIB - 30-May-02 RMS Widened POS to 32b - 06-Jan-02 RMS Revised enable/disable support - 26-Apr-01 RMS Added device enable/disable support -*/ - -#include "nova_defs.h" - -extern int32 int_req, dev_busy, dev_done, dev_disable; - -int32 plt_stopioe = 0; /* stop on error */ - -DEVICE plt_dev; -int32 plt (int32 pulse, int32 code, int32 AC); -t_stat plt_svc (UNIT *uptr); -t_stat plt_reset (DEVICE *dptr); - -/* PLT data structures - - plt_dev PLT device descriptor - plt_unit PLT unit descriptor - plt_reg PLT register list -*/ - -DIB plt_dib = { DEV_PLT, INT_PLT, PI_PLT, &plt }; - -UNIT plt_unit = { - UDATA (&plt_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT }; - -REG plt_reg[] = { - { ORDATA (BUF, plt_unit.buf, 8) }, - { FLDATA (BUSY, dev_busy, INT_V_PLT) }, - { FLDATA (DONE, dev_done, INT_V_PLT) }, - { FLDATA (DISABLE, dev_disable, INT_V_PLT) }, - { FLDATA (INT, int_req, INT_V_PLT) }, - { DRDATA (POS, plt_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, plt_unit.wait, 24), PV_LEFT }, - { FLDATA (STOP_IOE, plt_stopioe, 0) }, - { NULL } }; - -DEVICE plt_dev = { - "PLT", &plt_unit, plt_reg, NULL, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &plt_reset, - NULL, NULL, NULL, - &plt_dib, DEV_DISABLE }; - -/* plotter: IOT routine */ - -int32 plt (int32 pulse, int32 code, int32 AC) -{ -if (code == ioDOA) plt_unit.buf = AC & 0377; -switch (pulse) { /* decode IR<8:9> */ -case iopS: /* start */ - dev_busy = dev_busy | INT_PLT; /* set busy */ - dev_done = dev_done & ~INT_PLT; /* clear done, int */ - int_req = int_req & ~INT_PLT; - sim_activate (&plt_unit, plt_unit.wait); /* activate unit */ - break; -case iopC: /* clear */ - dev_busy = dev_busy & ~INT_PLT; /* clear busy */ - dev_done = dev_done & ~INT_PLT; /* clear done, int */ - int_req = int_req & ~INT_PLT; - sim_cancel (&plt_unit); /* deactivate unit */ - break; } /* end switch */ -return 0; -} - -/* Unit service */ - -t_stat plt_svc (UNIT *uptr) -{ -dev_busy = dev_busy & ~INT_PLT; /* clear busy */ -dev_done = dev_done | INT_PLT; /* set done */ -int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable); -if ((plt_unit.flags & UNIT_ATT) == 0) /* attached? */ - return IORETURN (plt_stopioe, SCPE_UNATT); -if (putc (plt_unit.buf, plt_unit.fileref) == EOF) { - perror ("PLT I/O error"); - clearerr (plt_unit.fileref); - return SCPE_IOERR; } -plt_unit.pos = plt_unit.pos + 1; -return SCPE_OK; -} - -/* Reset routine */ - -t_stat plt_reset (DEVICE *dptr) -{ -plt_unit.buf = 0; -dev_busy = dev_busy & ~INT_PLT; /* clear busy */ -dev_done = dev_done & ~INT_PLT; /* clear done, int */ -int_req = int_req & ~INT_PLT; -sim_cancel (&plt_unit); /* deactivate unit */ -return SCPE_OK; -} diff --git a/NOVA/nova_pt.c b/NOVA/nova_pt.c deleted file mode 100644 index 33333d91..00000000 --- a/NOVA/nova_pt.c +++ /dev/null @@ -1,215 +0,0 @@ -/* nova_pt.c: NOVA paper tape read/punch simulator - - 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. - - ptr paper tape reader - ptp paper tape punch - - 25-Apr-03 RMS Revised for extended file support - 03-Oct-02 RMS Added DIBs - 30-May-02 RMS Widened POS to 32b - 29-Nov-01 RMS Added read only unit support -*/ - -#include "nova_defs.h" - -extern int32 int_req, dev_busy, dev_done, dev_disable; - -int32 ptr_stopioe = 0, ptp_stopioe = 0; /* stop on error */ - -int32 ptr (int32 pulse, int32 code, int32 AC); -int32 ptp (int32 pulse, int32 code, int32 AC); -t_stat ptr_svc (UNIT *uptr); -t_stat ptp_svc (UNIT *uptr); -t_stat ptr_reset (DEVICE *dptr); -t_stat ptp_reset (DEVICE *dptr); - -/* PTR data structures - - ptr_dev PTR device descriptor - ptr_unit PTR unit descriptor - ptr_reg PTR register list -*/ - -DIB ptr_dib = { DEV_PTR, INT_PTR, PI_PTR, &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, 8) }, - { FLDATA (BUSY, dev_busy, INT_V_PTR) }, - { FLDATA (DONE, dev_done, INT_V_PTR) }, - { FLDATA (DISABLE, dev_disable, INT_V_PTR) }, - { FLDATA (INT, int_req, INT_V_PTR) }, - { DRDATA (POS, ptr_unit.pos, T_ADDR_W), 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, - NULL, NULL, NULL, - &ptr_dib, 0 }; - -/* PTP data structures - - ptp_dev PTP device descriptor - ptp_unit PTP unit descriptor - ptp_reg PTP register list -*/ - -DIB ptp_dib = { DEV_PTP, INT_PTP, PI_PTP, &ptp }; - -UNIT ptp_unit = { - UDATA (&ptp_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT }; - -REG ptp_reg[] = { - { ORDATA (BUF, ptp_unit.buf, 8) }, - { FLDATA (BUSY, dev_busy, INT_V_PTP) }, - { FLDATA (DONE, dev_done, INT_V_PTP) }, - { FLDATA (DISABLE, dev_disable, INT_V_PTP) }, - { FLDATA (INT, int_req, INT_V_PTP) }, - { DRDATA (POS, ptp_unit.pos, T_ADDR_W), 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, - &ptp_dib, 0 }; - -/* Paper tape reader: IOT routine */ - -int32 ptr (int32 pulse, int32 code, int32 AC) -{ -int32 iodata; - -iodata = (code == ioDIA)? ptr_unit.buf & 0377: 0; -switch (pulse) { /* decode IR<8:9> */ -case iopS: /* start */ - dev_busy = dev_busy | INT_PTR; /* set busy */ - dev_done = dev_done & ~INT_PTR; /* clear done, int */ - int_req = int_req & ~INT_PTR; - sim_activate (&ptr_unit, ptr_unit.wait); /* activate unit */ - break; -case iopC: /* clear */ - dev_busy = dev_busy & ~INT_PTR; /* clear busy */ - dev_done = dev_done & ~INT_PTR; /* clear done, int */ - int_req = int_req & ~INT_PTR; - sim_cancel (&ptr_unit); /* deactivate unit */ - break; } /* end switch */ -return iodata; -} - -/* 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; } -dev_busy = dev_busy & ~INT_PTR; /* clear busy */ -dev_done = dev_done | INT_PTR; /* set done */ -int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable); -ptr_unit.buf = temp & 0377; -ptr_unit.pos = ptr_unit.pos + 1; -return SCPE_OK; -} - -/* Reset routine */ - -t_stat ptr_reset (DEVICE *dptr) -{ -ptr_unit.buf = 0; -dev_busy = dev_busy & ~INT_PTR; /* clear busy */ -dev_done = dev_done & ~INT_PTR; /* clear done, int */ -int_req = int_req & ~INT_PTR; -sim_cancel (&ptr_unit); /* deactivate unit */ -return SCPE_OK; -} - -/* Paper tape punch: IOT routine */ - -int32 ptp (int32 pulse, int32 code, int32 AC) -{ -if (code == ioDOA) ptp_unit.buf = AC & 0377; -switch (pulse) { /* decode IR<8:9> */ -case iopS: /* start */ - dev_busy = dev_busy | INT_PTP; /* set busy */ - dev_done = dev_done & ~INT_PTP; /* clear done, int */ - int_req = int_req & ~INT_PTP; - sim_activate (&ptp_unit, ptp_unit.wait); /* activate unit */ - break; -case iopC: /* clear */ - dev_busy = dev_busy & ~INT_PTP; /* clear busy */ - dev_done = dev_done & ~INT_PTP; /* clear done, int */ - int_req = int_req & ~INT_PTP; - sim_cancel (&ptp_unit); /* deactivate unit */ - break; } /* end switch */ -return 0; -} - -/* Unit service */ - -t_stat ptp_svc (UNIT *uptr) -{ -dev_busy = dev_busy & ~INT_PTP; /* clear busy */ -dev_done = dev_done | INT_PTP; /* set done */ -int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable); -if ((ptp_unit.flags & UNIT_ATT) == 0) /* attached? */ - return IORETURN (ptp_stopioe, SCPE_UNATT); -if (putc (ptp_unit.buf, ptp_unit.fileref) == EOF) { - 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; -dev_busy = dev_busy & ~INT_PTP; /* clear busy */ -dev_done = dev_done & ~INT_PTP; /* clear done, int */ -int_req = int_req & ~INT_PTP; -sim_cancel (&ptp_unit); /* deactivate unit */ -return SCPE_OK; -} diff --git a/NOVA/nova_sys.c b/NOVA/nova_sys.c deleted file mode 100644 index 6198ad65..00000000 --- a/NOVA/nova_sys.c +++ /dev/null @@ -1,957 +0,0 @@ -/* nova_sys.c: NOVA simulator interface - - 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. - - 17-Sep-01 RMS Removed multiconsole support - 31-May-01 RMS Added multiconsole support - 14-Mar-01 RMS Revised load/dump interface (again) - 22-Dec-00 RMS Added second terminal support - 10-Dec-00 RMS Added Eclipse support - 08-Dec-00 BKR Added plotter support - 30-Oct-00 RMS Added support for examine to file - 15-Oct-00 RMS Added stack, byte, trap instructions - 14-Apr-99 RMS Changed t_addr to unsigned - 27-Oct-98 RMS V2.4 load interface - 24-Sep-97 RMS Fixed bug in device name table (found by Charles Owen) -*/ - -#include "nova_defs.h" -#include - -extern DEVICE cpu_dev; -extern UNIT cpu_unit; -#if defined (ECLIPSE) -extern DEVICE map_dev; -#endif -extern DEVICE ptr_dev, ptp_dev; -extern DEVICE plt_dev; -extern DEVICE tti_dev, tto_dev; -extern DEVICE tti1_dev, tto1_dev; -extern DEVICE clk_dev, lpt_dev; -extern DEVICE dkp_dev, dsk_dev; -extern DEVICE mta_dev; -extern UNIT tti_unit, tto_unit; -extern UNIT tti1_unit, tto1_unit; -extern REG cpu_reg[]; -extern uint16 M[]; -extern int32 saved_PC; - -/* SCP data structures - - sim_name simulator name string - sim_PC pointer to saved PC register descriptor - sim_emax number of words needed for examine - sim_devices array of pointers to simulated devices - sim_stop_messages array of pointers to stop messages - sim_load binary loader -*/ - -#if defined (ECLIPSE) -char sim_name[] = "ECLIPSE"; -#else -char sim_name[] = "NOVA"; -#endif - -REG *sim_PC = &cpu_reg[0]; - -int32 sim_emax = 4; - -DEVICE *sim_devices[] = { - &cpu_dev, -#if defined (ECLIPSE) - &map_dev, -#endif - &ptr_dev, &ptp_dev, - &tti_dev, &tto_dev, - &tti1_dev, &tto1_dev, - &clk_dev, &plt_dev, - &lpt_dev, &dsk_dev, - &dkp_dev, &mta_dev, - NULL }; - -const char *sim_stop_messages[] = { - "Unknown error", - "Unknown I/O instruction", - "HALT instruction", - "Breakpoint", - "Nested indirect address limit exceeded", - "Nested indirect interrupt address limit exceeded", - "Nested indirect trap address limit exceeded", - "Read breakpoint", - "Write breakpoint" }; - -/* Binary loader - - Loader format consists of blocks, optionally preceded, separated, and - followed by zeroes. Each block consists of: - - lo_count - hi_count - lo_origin - hi_origin - lo_checksum - hi_checksum - lo_data byte --- - hi_data byte | - : > -count words - lo_data byte | - hi_data byte --- - - If the word count is [0,-20], then the block is normal data. - If the word count is [-21,-n], then the block is repeated data. - If the word count is 1, the block is the start address. - If the word count is >1, the block is an error block. -*/ - -t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag) -{ -int32 data, csum, count, state, i; -uint32 origin; - -if ((*cptr != 0) || (flag != 0)) return SCPE_ARG; -state = 0; -while ((i = getc (fileref)) != EOF) { - switch (state) { - case 0: /* leader */ - count = i; - state = (count != 0); - break; - case 1: /* high count */ - csum = count = (i << 8) | count; - state = 2; - break; - case 2: /* low origin */ - origin = i; - state = 3; - break; - case 3: /* high origin */ - origin = (i << 8) | origin; - csum = csum + origin; - state = 4; - break; - case 4: /* low checksum */ - 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; - case 6: /* low data */ - 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; - case 8: /* error block */ - if (i == 0377) state = 0; - break; } /* end switch */ - } /* end while */ - -/* Ok to find end of tape between blocks or in error state */ - -return ((state == 0) || (state == 8))? SCPE_OK: SCPE_FMT; -} - -/* Symbol tables */ - -#define I_V_FL 18 /* flag bits */ -#define I_M_FL 037 /* flag width */ -#define I_V_NPN 000 /* no operands */ -#define I_V_R 001 /* reg */ -#define I_V_D 002 /* device */ -#define I_V_RD 003 /* reg,device */ -#define I_V_M 004 /* mem addr */ -#define I_V_RM 005 /* reg,mem addr */ -#define I_V_RR 006 /* operate */ -#define I_V_BY 007 /* Nova byte pointer */ -#define I_V_2AC 010 /* reg,reg */ -#define I_V_RSI 011 /* reg,short imm */ -#define I_V_LI 012 /* long imm */ -#define I_V_RLI 013 /* reg,long imm */ -#define I_V_LM 014 /* long mem addr */ -#define I_V_RLM 015 /* reg,long mem addr */ -#define I_V_FRM 016 /* flt reg,long mem addr */ -#define I_V_FST 017 /* flt long mem, status */ -#define I_V_XP 020 /* XOP */ -#define I_NPN (I_V_NPN << I_V_FL) -#define I_R (I_V_R << I_V_FL) -#define I_D (I_V_D << I_V_FL) -#define I_RD (I_V_RD << I_V_FL) -#define I_M (I_V_M << I_V_FL) -#define I_RM (I_V_RM << I_V_FL) -#define I_RR (I_V_RR << I_V_FL) -#define I_BY (I_V_BY << I_V_FL) -#define I_2AC (I_V_2AC << I_V_FL) -#define I_RSI (I_V_RSI << I_V_FL) -#define I_LI (I_V_LI << I_V_FL) -#define I_RLI (I_V_RLI << I_V_FL) -#define I_LM (I_V_LM << I_V_FL) -#define I_RLM (I_V_RLM << I_V_FL) -#define I_FRM (I_V_FRM << I_V_FL) -#define I_FST (I_V_FST << I_V_FL) -#define I_XP (I_V_XP << I_V_FL) - -static const int32 masks[] = { -0177777, 0163777, 0177700, 0163700, -0174000, 0160000, 0103770, 0163477, -0103777, 0103777, 0177777, 0163777, -0176377, 0162377, 0103777, 0163777, -0100077 }; - -static const char *opcode[] = { - "JMP", "JSR", "ISZ", "DSZ", - "LDA", "STA", -#if defined (ECLIPSE) - "ADI", "SBI", "DAD", "DSB", - "IOR", "XOR", "ANC", "XCH", - "SGT", "SGE", "LSH", "DLSH", - "HXL", "HXR", "DHXL", "DHXR", - "BTO", "BTZ", "SBZ", "SZBO", - "LOB", "LRB", "COB", "LDB", - "STB", "PSH", "POP", - "LMP", "SYSC", - "PSHR", "POPB", "BAM", "POPJ", - "RTN", "BLM", "DIVX", - "MUL", "MULS", "DIV", "DIVS", - "SAVE", "RSTR", - "XOP", - "FAS", "FAD", "FSS", "FSD", - "FMS", "FMD", "FDS", "FDD", - "FAMS", "FAMD", "FSMS", "FSMD", - "FMMS", "FMMD", "FDMS", "FDMD", - "FLDS", "FLDD", "FSTS", "FSTD", - "FLAS", "FLMD", "FFAS", "FFMD", - "FNOM", "FRH", "FAB", "FNEG", - "FSCAL", "FEXP", "FINT", "FHLV", - "FNS", "FSA", "FSEQ", "FSNE", - "FSLT", "FSGE", "FSLE", "FSGT", - "FSNM", "FSND", "FSNU", "FSNUD", - "FSNO", "FSNOD", "FSNUO", "FSNER", - "FSST", "FLST", - "FTE", "FTD", "FCLE", - "FPSH", "FPOP", - "FCMP", "FMOV", - "CMV", "CMP", "CTR", "CMT", - "EJMP", "EJSR", "EISZ", "EDSZ", - "ELDA", "ESTA", "ELEF", - "ELDB", "ESTB", "DSPA", - "PSHJ", "CLM", "SNB", - "MSP", "XCT", "HLV", - "IORI", "XORI", "ANDI", "ADDI", -#endif - "COM", "COMZ", "COMO", "COMC", - "COML", "COMZL", "COMOL", "COMCL", - "COMR", "COMZR", "COMOR", "COMCR", - "COMS", "COMZS", "COMOS", "COMCS", - "COM#", "COMZ#", "COMO#", "COMC#", - "COML#", "COMZL#", "COMOL#", "COMCL#", - "COMR#", "COMZR#", "COMOR#", "COMCR#", - "COMS#", "COMZS#", "COMOS#", "COMCS#", - "NEG", "NEGZ", "NEGO", "NEGC", - "NEGL", "NEGZL", "NEGOL", "NEGCL", - "NEGR", "NEGZR", "NEGOR", "NEGCR", - "NEGS", "NEGZS", "NEGOS", "NEGCS", - "NEG#", "NEGZ#", "NEGO#", "NEGC#", - "NEGL#", "NEGZL#", "NEGOL#", "NEGCL#", - "NEGR#", "NEGZR#", "NEGOR#", "NEGCR#", - "NEGS#", "NEGZS#", "NEGOS#", "NEGCS#", - "MOV", "MOVZ", "MOVO", "MOVC", - "MOVL", "MOVZL", "MOVOL", "MOVCL", - "MOVR", "MOVZR", "MOVOR", "MOVCR", - "MOVS", "MOVZS", "MOVOS", "MOVCS", - "MOV#", "MOVZ#", "MOVO#", "MOVC#", - "MOVL#", "MOVZL#", "MOVOL#", "MOVCL#", - "MOVR#", "MOVZR#", "MOVOR#", "MOVCR#", - "MOVS#", "MOVZS#", "MOVOS#", "MOVCS#", - "INC", "INCZ", "INCO", "INCC", - "INCL", "INCZL", "INCOL", "INCCL", - "INCR", "INCZR", "INCOR", "INCCR", - "INCS", "INCZS", "INCOS", "INCCS", - "INC#", "INCZ#", "INCO#", "INCC#", - "INCL#", "INCZL#", "INCOL#", "INCCL#", - "INCR#", "INCZR#", "INCOR#", "INCCR#", - "INCS#", "INCZS#", "INCOS#", "INCCS#", - "ADC", "ADCZ", "ADCO", "ADCC", - "ADCL", "ADCZL", "ADCOL", "ADCCL", - "ADCR", "ADCZR", "ADCOR", "ADCCR", - "ADCS", "ADCZS", "ADCOS", "ADCCS", - "ADC#", "ADCZ#", "ADCO#", "ADCC#", - "ADCL#", "ADCZL#", "ADCOL#", "ADCCL#", - "ADCR#", "ADCZR#", "ADCOR#", "ADCCR#", - "ADCS#", "ADCZS#", "ADCOS#", "ADCCS#", - "SUB", "SUBZ", "SUBO", "SUBC", - "SUBL", "SUBZL", "SUBOL", "SUBCL", - "SUBR", "SUBZR", "SUBOR", "SUBCR", - "SUBS", "SUBZS", "SUBOS", "SUBCS", - "SUB#", "SUBZ#", "SUBO#", "SUBC#", - "SUBL#", "SUBZL#", "SUBOL#", "SUBCL#", - "SUBR#", "SUBZR#", "SUBOR#", "SUBCR#", - "SUBS#", "SUBZS#", "SUBOS#", "SUBCS#", - "ADD", "ADDZ", "ADDO", "ADDC", - "ADDL", "ADDZL", "ADDOL", "ADDCL", - "ADDR", "ADDZR", "ADDOR", "ADDCR", - "ADDS", "ADDZS", "ADDOS", "ADDCS", - "ADD#", "ADDZ#", "ADDO#", "ADDC#", - "ADDL#", "ADDZL#", "ADDOL#", "ADDCL#", - "ADDR#", "ADDZR#", "ADDOR#", "ADDCR#", - "ADDS#", "ADDZS#", "ADDOS#", "ADDCS#", - "AND", "ANDZ", "ANDO", "ANDC", - "ANDL", "ANDZL", "ANDOL", "ANDCL", - "ANDR", "ANDZR", "ANDOR", "ANDCR", - "ANDS", "ANDZS", "ANDOS", "ANDCS", - "AND#", "ANDZ#", "ANDO#", "ANDC#", - "ANDL#", "ANDZL#", "ANDOL#", "ANDCL#", - "ANDR#", "ANDZR#", "ANDOR#", "ANDCR#", - "ANDS#", "ANDZS#", "ANDOS#", "ANDCS#", - "ION", "IOF", - "RDSW", "INTA", "MSKO", "IORST", "HALT", -#if !defined (ECLIPSE) - "MUL", "DIV", "MULS", "DIVS", - "PSHA", "POPA", "SAV", "RET", - "MTSP", "MTFP", "MFSP", "MFFP", - "LDB", "STB", -#endif - "NIO", "NIOS", "NIOC", "NIOP", - "DIA", "DIAS", "DIAC", "DIAP", - "DOA", "DOAS", "DOAC", "DOAP", - "DIB", "DIBS", "DIBC", "DIBP", - "DOB", "DOBS", "DOBC", "DOBP", - "DIC", "DICS", "DICC", "DICP", - "DOC", "DOCS", "DOCC", "DOCP", - "SKPBN", "SKPBZ", "SKPDN", "SKPDZ", - NULL }; - -static const opc_val[] = { - 0000000+I_M, 0004000+I_M, 0010000+I_M, 0014000+I_M, - 0020000+I_RM, 0040000+I_RM, -#if defined (ECLIPSE) - 0100010+I_RSI, 0100110+I_RSI, 0100210+I_2AC, 0100310+I_2AC, - 0100410+I_2AC, 0100510+I_2AC, 0100610+I_2AC, 0100710+I_2AC, - 0101010+I_2AC, 0101110+I_2AC, 0101210+I_RSI, 0101310+I_RSI, - 0101410+I_RSI, 0101510+I_RSI, 0101610+I_RSI, 0101710+I_RSI, - 0102010+I_2AC, 0102110+I_2AC, 0102210+I_2AC, 0102310+I_2AC, - 0102410+I_2AC, 0102510+I_2AC, 0102610+I_2AC, 0102710+I_2AC, - 0103010+I_2AC, 0103110+I_2AC, 0103210+I_2AC, - 0113410+I_NPN, 0103510+I_RSI, - 0103710+I_NPN, 0107710+I_NPN, 0113710+I_NPN, 0117710+I_NPN, - 0127710+I_NPN, 0133710+I_NPN, 0137710+I_NPN, - 0143710+I_NPN, 0147710+I_NPN, 0153710+I_NPN, 0157710+I_NPN, - 0163710+I_LI, 0167710+I_NPN, - 0100030+I_XP, - 0100050+I_2AC, 0100150+I_2AC, 0100250+I_2AC, 0100350+I_2AC, - 0100450+I_2AC, 0100550+I_2AC, 0100650+I_2AC, 0100750+I_2AC, - 0101050+I_FRM, 0101150+I_FRM, 0101250+I_FRM, 0101350+I_FRM, - 0101450+I_FRM, 0101550+I_FRM, 0101650+I_FRM, 0101750+I_FRM, - 0102050+I_FRM, 0102150+I_FRM, 0102250+I_FRM, 0102350+I_FRM, - 0102450+I_2AC, 0102550+I_FRM, 0102650+I_2AC, 0102750+I_FRM, - 0103050+I_R, 0123050+I_R, 0143050+I_R, 0163050+I_R, - 0103150+I_R, 0123150+I_R, 0143150+I_R, 0163150+I_R, - 0103250+I_NPN, 0107250+I_NPN, 0113250+I_NPN, 0117250+I_NPN, - 0123250+I_NPN, 0127250+I_NPN, 0133250+I_NPN, 0137250+I_NPN, - 0143250+I_NPN, 0147250+I_NPN, 0153250+I_NPN, 0157250+I_NPN, - 0163250+I_NPN, 0167250+I_NPN, 0173250+I_NPN, 0177250+I_NPN, - 0103350+I_FST, 0123350+I_FST, - 0143350+I_NPN, 0147350+I_NPN, 0153350+I_NPN, - 0163350+I_NPN, 0167350+I_NPN, - 0103450+I_2AC, 0103550+I_2AC, - 0153650+I_NPN, 0157650+I_NPN, 0163650+I_NPN, 0167650+I_NPN, - 0102070+I_LM, 0106070+I_LM, 0112070+I_LM, 0116070+I_LM, - 0122070+I_RLM, 0142070+I_RLM, 0162070+I_RLM, - 0102170+I_RLM, 0122170+I_RLM, 0142170+I_RLM, - 0102270+I_LM, 0102370+I_2AC, 0102770+I_2AC, - 0103370+I_R, 0123370+I_R, 0143370+I_R, - 0103770+I_RLI, 0123770+I_RLI, 0143770+I_RLI, 0163770+I_RLI, -#endif - 0100000+I_RR, 0100020+I_RR, 0100040+I_RR, 0100060+I_RR, - 0100100+I_RR, 0100120+I_RR, 0100140+I_RR, 0100160+I_RR, - 0100200+I_RR, 0100220+I_RR, 0100240+I_RR, 0100260+I_RR, - 0100300+I_RR, 0100320+I_RR, 0100340+I_RR, 0100360+I_RR, - 0100010+I_RR, 0100030+I_RR, 0100050+I_RR, 0100070+I_RR, - 0100110+I_RR, 0100130+I_RR, 0100150+I_RR, 0100170+I_RR, - 0100210+I_RR, 0100230+I_RR, 0100250+I_RR, 0100270+I_RR, - 0100310+I_RR, 0100330+I_RR, 0100350+I_RR, 0100370+I_RR, - 0100400+I_RR, 0100420+I_RR, 0100440+I_RR, 0100460+I_RR, - 0100500+I_RR, 0100520+I_RR, 0100540+I_RR, 0100560+I_RR, - 0100600+I_RR, 0100620+I_RR, 0100640+I_RR, 0100660+I_RR, - 0100700+I_RR, 0100720+I_RR, 0100740+I_RR, 0100760+I_RR, - 0100410+I_RR, 0100430+I_RR, 0100450+I_RR, 0100470+I_RR, - 0100510+I_RR, 0100530+I_RR, 0100550+I_RR, 0100570+I_RR, - 0100610+I_RR, 0100630+I_RR, 0100650+I_RR, 0100670+I_RR, - 0100710+I_RR, 0100730+I_RR, 0100750+I_RR, 0100770+I_RR, - 0101000+I_RR, 0101020+I_RR, 0101040+I_RR, 0101060+I_RR, - 0101100+I_RR, 0101120+I_RR, 0101140+I_RR, 0101160+I_RR, - 0101200+I_RR, 0101220+I_RR, 0101240+I_RR, 0101260+I_RR, - 0101300+I_RR, 0101320+I_RR, 0101340+I_RR, 0101360+I_RR, - 0101010+I_RR, 0101030+I_RR, 0101050+I_RR, 0101070+I_RR, - 0101110+I_RR, 0101130+I_RR, 0101150+I_RR, 0101170+I_RR, - 0101210+I_RR, 0101230+I_RR, 0101250+I_RR, 0101270+I_RR, - 0101310+I_RR, 0101330+I_RR, 0101350+I_RR, 0101370+I_RR, - 0101400+I_RR, 0101420+I_RR, 0101440+I_RR, 0101460+I_RR, - 0101500+I_RR, 0101520+I_RR, 0101540+I_RR, 0101560+I_RR, - 0101600+I_RR, 0101620+I_RR, 0101640+I_RR, 0101660+I_RR, - 0101700+I_RR, 0101720+I_RR, 0101740+I_RR, 0101760+I_RR, - 0101410+I_RR, 0101430+I_RR, 0101450+I_RR, 0101470+I_RR, - 0101510+I_RR, 0101530+I_RR, 0101550+I_RR, 0101570+I_RR, - 0101610+I_RR, 0101630+I_RR, 0101650+I_RR, 0101670+I_RR, - 0101710+I_RR, 0101730+I_RR, 0101750+I_RR, 0101770+I_RR, - 0102000+I_RR, 0102020+I_RR, 0102040+I_RR, 0102060+I_RR, - 0102100+I_RR, 0102120+I_RR, 0102140+I_RR, 0102160+I_RR, - 0102200+I_RR, 0102220+I_RR, 0102240+I_RR, 0102260+I_RR, - 0102300+I_RR, 0102320+I_RR, 0102340+I_RR, 0102360+I_RR, - 0102010+I_RR, 0102030+I_RR, 0102050+I_RR, 0102070+I_RR, - 0102110+I_RR, 0102130+I_RR, 0102150+I_RR, 0102170+I_RR, - 0102210+I_RR, 0102230+I_RR, 0102250+I_RR, 0102270+I_RR, - 0102310+I_RR, 0102330+I_RR, 0102350+I_RR, 0102370+I_RR, - 0102400+I_RR, 0102420+I_RR, 0102440+I_RR, 0102460+I_RR, - 0102500+I_RR, 0102520+I_RR, 0102540+I_RR, 0102560+I_RR, - 0102600+I_RR, 0102620+I_RR, 0102640+I_RR, 0102660+I_RR, - 0102700+I_RR, 0102720+I_RR, 0102740+I_RR, 0102760+I_RR, - 0102410+I_RR, 0102430+I_RR, 0102450+I_RR, 0102470+I_RR, - 0102510+I_RR, 0102530+I_RR, 0102550+I_RR, 0102570+I_RR, - 0102610+I_RR, 0102630+I_RR, 0102650+I_RR, 0102670+I_RR, - 0102710+I_RR, 0102730+I_RR, 0102750+I_RR, 0102770+I_RR, - 0103000+I_RR, 0103020+I_RR, 0103040+I_RR, 0103060+I_RR, - 0103100+I_RR, 0103120+I_RR, 0103140+I_RR, 0103160+I_RR, - 0103200+I_RR, 0103220+I_RR, 0103240+I_RR, 0103260+I_RR, - 0103300+I_RR, 0103320+I_RR, 0103340+I_RR, 0103360+I_RR, - 0103010+I_RR, 0103030+I_RR, 0103050+I_RR, 0103070+I_RR, - 0103110+I_RR, 0103130+I_RR, 0103150+I_RR, 0103170+I_RR, - 0103210+I_RR, 0103230+I_RR, 0103250+I_RR, 0103270+I_RR, - 0103310+I_RR, 0103330+I_RR, 0103350+I_RR, 0103370+I_RR, - 0103400+I_RR, 0103420+I_RR, 0103440+I_RR, 0103460+I_RR, - 0103500+I_RR, 0103520+I_RR, 0103540+I_RR, 0103560+I_RR, - 0103600+I_RR, 0103620+I_RR, 0103640+I_RR, 0103660+I_RR, - 0103700+I_RR, 0103720+I_RR, 0103740+I_RR, 0103760+I_RR, - 0103410+I_RR, 0103430+I_RR, 0103450+I_RR, 0103470+I_RR, - 0103510+I_RR, 0103530+I_RR, 0103550+I_RR, 0103570+I_RR, - 0103610+I_RR, 0103630+I_RR, 0103650+I_RR, 0103670+I_RR, - 0103710+I_RR, 0103730+I_RR, 0103750+I_RR, 0103770+I_RR, - 0060177+I_NPN, 0060277+I_NPN, - 0060477+I_R, 0061477+I_R, 0062077+I_R, 0062677+I_NPN, 0063077+I_NPN, -#if !defined (ECLIPSE) - 0073301+I_NPN, 0073101+I_NPN, 0077201+I_NPN, 0077001+I_NPN, - 0061401+I_R, 0061601+I_R, 0062401+I_NPN, 0062601+I_NPN, - 0061001+I_R, 0060001+I_R, 0061201+I_R, 0060201+I_R, - 0060401+I_BY, 0062001+I_BY, -#endif - 0060000+I_D, 0060100+I_D, 0060200+I_D, 0060300+I_D, - 0060400+I_RD, 0060500+I_RD, 0060600+I_RD, 0060700+I_RD, - 0061000+I_RD, 0061100+I_RD, 0061200+I_RD, 0061300+I_RD, - 0061400+I_RD, 0061500+I_RD, 0061600+I_RD, 0061700+I_RD, - 0062000+I_RD, 0062100+I_RD, 0062200+I_RD, 0062300+I_RD, - 0062400+I_RD, 0062500+I_RD, 0062600+I_RD, 0062700+I_RD, - 0063000+I_RD, 0063100+I_RD, 0063200+I_RD, 0063300+I_RD, - 0063400+I_D, 0063500+I_D, 0063600+I_D, 0063700+I_D, - -1 }; - -static const char *skip[] = { - "SKP", "SZC", "SNC", "SZR", "SNR", "SEZ", "SBN", - NULL }; - -static const char *device[] = { -#if defined (ECLIPSE) - "ERCC", "MAP", -#endif - "TTI", "TTO", "PTR", "PTP", "RTC", "PLT", "CDR", "LPT", - "DSK", "MTA", "DCM", "ADCV", "DKP", "CAS", - "TTI1", "TTO1", "CPU", - NULL }; - -static const int32 dev_val[] = { -#if defined (ECLIPSE) - 002, 003, -#endif - 010, 011, 012, 013, 014, 015, 016, 017, - 020, 022, 024, 030, 033, 034, - 050, 051, 077, - -1 }; - -/* Address decode - - Inputs: - *of = output stream - addr = current PC - ind = indirect flag - mode = addressing mode - disp = displacement - ext = true if extended address - cflag = true if decoding for CPU - Outputs: - return = error code -*/ - -t_stat fprint_addr (FILE *of, t_addr addr, int32 ind, int32 mode, - int32 disp, t_bool ext, int32 cflag) -{ -int32 dsign, dmax; - -if (ext) dmax = AMASK + 1; /* get max disp */ -else dmax = I_M_DISP + 1; -dsign = dmax >> 1; /* get disp sign */ -if (ind) fprintf (of, "@"); /* indirect? */ -switch (mode & 03) { /* mode */ -case 0: /* absolute */ - fprintf (of, "%-o", disp); - 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); } - break; -case 2: /* AC2 rel */ - if (disp & dsign) fprintf (of, "-%-o,2", dmax - disp); - else fprintf (of, "%-o,2", disp); - break; -case 3: /* AC3 rel */ - if (disp & dsign) fprintf (of, "-%-o,3", dmax - disp); - else fprintf (of, "%-o,3", disp); - break; } /* end switch */ -return SCPE_OK; -} - -/* Symbolic output - - Inputs: - *of = output stream - addr = current PC - *val = pointer to values - *uptr = pointer to unit - sw = switches - Outputs: - status = error code -*/ - -t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, - UNIT *uptr, int32 sw) -{ -int32 cflag, i, j, c1, c2, inst, dv, src, dst, skp; -int32 ind, mode, disp, dev; -int32 byac, extind, extdisp, xop; - -cflag = (uptr == NULL) || (uptr == &cpu_unit); -c1 = (val[0] >> 8) & 0177; -c2 = val[0] & 0177; -if (sw & SWMASK ('A')) { /* ASCII? */ - fprintf (of, (c2 < 040)? "<%03o>": "%c", c2); - return SCPE_OK; } -if (sw & SWMASK ('C')) { /* character? */ - fprintf (of, (c1 < 040)? "<%03o>": "%c", c1); - fprintf (of, (c2 < 040)? "<%03o>": "%c", c2); - return SCPE_OK; } -if (!(sw & SWMASK ('M'))) return SCPE_ARG; /* mnemonic? */ - -/* Instruction decode */ - -inst = val[0]; -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] & 0177777) == (inst & masks[j])) { /* match? */ - src = I_GETSRC (inst); /* opr fields */ - dst = I_GETDST (inst); - skp = I_GETSKP (inst); - ind = inst & I_IND; /* mem ref fields */ - mode = I_GETMODE (inst); - disp = I_GETDISP (inst); - dev = I_GETDEV (inst); /* IOT fields */ - byac = I_GETPULSE (inst); /* byte fields */ - xop = I_GETXOP (inst); /* XOP fields */ - extind = val[1] & A_IND; /* extended fields */ - extdisp = val[1] & AMASK; - for (dv = 0; (dev_val[dv] >= 0) && (dev_val[dv] != dev); dv++) ; - - switch (j) { /* switch on class */ - case I_V_NPN: /* no operands */ - fprintf (of, "%s", opcode[i]); /* opcode */ - break; - case I_V_R: /* reg only */ - 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; - 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; - case I_V_M: /* addr only */ - 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; - case I_V_RR: /* operate */ - 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; - case I_V_2AC: /* reg, reg */ - 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; - case I_V_LI: /* long imm */ - 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; - case I_V_LM: /* long addr */ - 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; - 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; - case I_V_FST: /* flt status */ - 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 */ - return SCPE_OK; } /* end if */ - } /* end for */ -return SCPE_ARG; -} - -/* Address parse - - Inputs: - *cptr = pointer to input string - addr = current PC - ext = extended address - cflag = true if parsing for CPU - val[3] = output array - Outputs: - optr = pointer to next char in input string - NULL if error -*/ - -#define A_FL 001 /* CPU flag */ -#define A_NX 002 /* index seen */ -#define A_PER 004 /* period seen */ -#define A_NUM 010 /* number seen */ -#define A_SI 020 /* sign seen */ -#define A_MI 040 /* - seen */ - -char *get_addr (char *cptr, t_addr addr, t_bool ext, int32 cflag, int32 *val) -{ -int32 d, r, x, pflag; -char gbuf[CBUFSIZE]; -int32 dmax, dsign; - -if (ext) dmax = AMASK + 1; /* get max disp */ -else dmax = I_M_DISP + 1; -dsign = dmax >> 1; /* get disp sign */ -val[0] = 0; /* no indirect */ -val[1] = 0; /* PC rel */ -val[2] = 0; /* no addr */ - -pflag = cflag & A_FL; /* isolate flag */ -if (*cptr == '@') { /* indirect? */ - val[0] = 1; - cptr++; } -if (*cptr == '.') { /* relative? */ - pflag = pflag | A_PER; - x = 1; /* "index" is PC */ - cptr++; } -if (*cptr == '+') { /* + sign? */ - pflag = pflag | A_SI; - cptr++; } -else if (*cptr == '-') { /* - sign? */ - pflag = pflag | A_MI | A_SI; - cptr++; } -if (*cptr != 0) { /* number? */ - cptr = get_glyph (cptr, gbuf, ','); /* get glyph */ - d = get_uint (gbuf, 8, AMASK, &r); - if (r != SCPE_OK) return NULL; - pflag = pflag | A_NUM; } -if (*cptr != 0) { /* index? */ - cptr = get_glyph (cptr, gbuf, 0); /* get glyph */ - x = get_uint (gbuf, 8, I_M_DST, &r); - if ((r != SCPE_OK) || (x < 2)) return NULL; - pflag = pflag | A_NX; } - -/* Address parse, continued */ - -switch (pflag) { /* case on flags */ -case A_NUM: case A_NUM+A_SI: /* ~CPU, (+)num */ - if (d < dmax) val[2] = d; - else return NULL; - break; -case A_NUM+A_FL: case A_NUM+A_SI+A_FL: /* CPU, (+)num */ - if (d < dmax) val[2] = d; - 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); } - else return NULL; - break; -case A_PER: case A_PER+A_FL: /* . */ -case A_PER+A_SI+A_NUM: case A_PER+A_SI+A_NUM+A_FL: /* . + num */ -case A_PER+A_SI+A_MI+A_NUM: /* . - num */ -case A_PER+A_SI+A_MI+A_NUM+A_FL: -case A_NX+A_NUM: case A_NX+A_NUM+A_FL: /* num, ndx */ -case A_NX+A_SI+A_NUM: case A_NX+A_SI+A_NUM+A_FL: /* +num, ndx */ -case A_NX+A_SI+A_MI+A_NUM: /* -num, ndx */ -case A_NX+A_SI+A_MI+A_NUM+A_FL: - val[1] = x; /* set mode */ - if (((pflag & A_MI) == 0) && (d < dsign)) val[2] = d; - else if ((pflag & A_MI) && (d <= dsign)) val[2] = (dmax - d); - else return NULL; - break; -default: - return NULL; } /* end case */ -return cptr; -} - -/* Parse two registers - - Inputs: - *cptr = input string - term = second terminating character - val = output array - Outputs: - optr = pointer to next char in input string - NULL if error -*/ - -char *get_2reg (char *cptr, char term, int32 *val) -{ -char gbuf[CBUFSIZE]; -t_stat r; - -cptr = get_glyph (cptr, gbuf, ','); /* get register */ -val[0] = get_uint (gbuf, 8, I_M_SRC, &r); -if (r != SCPE_OK) return NULL; -cptr = get_glyph (cptr, gbuf, term); /* get register */ -val[1] = get_uint (gbuf, 8, I_M_DST, &r); -if (r != SCPE_OK) return NULL; -return cptr; -} - -/* 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, amd[3]; -t_stat r, rtn; -char gbuf[CBUFSIZE]; - -cflag = (uptr == NULL) || (uptr == &cpu_unit); -while (isspace (*cptr)) cptr++; /* absorb spaces */ -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++)) { /* ASCII string? */ - if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */ - val[0] = ((t_value) cptr[0] << 8) + (t_value) cptr[1]; - return SCPE_OK; } - -/* Instruction parse */ - -rtn = SCPE_OK; /* assume 1 word */ -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] & 0177777; /* get value */ -j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */ - -switch (j) { /* case on class */ -case I_V_NPN: /* no operand */ - break; -case I_V_R: /* IOT reg */ - cptr = get_glyph (cptr, gbuf, 0); /* get register */ - d = get_uint (gbuf, 8, I_M_DST, &r); - if (r != SCPE_OK) return SCPE_ARG; - val[0] = val[0] | (d << I_V_DST); /* put in place */ - break; -case I_V_RD: /* IOT reg,dev */ - cptr = get_glyph (cptr, gbuf, ','); /* get register */ - d = get_uint (gbuf, 8, I_M_DST, &r); - if (r != SCPE_OK) return SCPE_ARG; - 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++); - 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); } - break; -case I_V_RM: /* reg, addr */ - cptr = get_glyph (cptr, gbuf, ','); /* get register */ - d = get_uint (gbuf, 8, I_M_DST, &r); - if (r != SCPE_OK) return SCPE_ARG; - val[0] = val[0] | (d << I_V_DST); /* put in place */ -case I_V_M: /* addr */ - cptr = get_addr (cptr, addr, FALSE, cflag, amd); - if (cptr == NULL) return SCPE_ARG; - val[0] = val[0] | (amd[0] << I_V_IND) | (amd[1] << I_V_MODE) | amd[2]; - break; -case I_V_RR: /* operate */ - cptr = get_2reg (cptr, ',', amd); /* get 2 reg */ - 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 */ - break; -case I_V_BY: /* byte */ - cptr = get_2reg (cptr, 0, amd); /* get 2 reg */ - if (cptr == NULL) return SCPE_ARG; - val[0] = val[0] | (amd[0] << I_V_PULSE) | (amd[1] << I_V_DST); - break; -case I_V_2AC: /* reg, reg */ - cptr = get_2reg (cptr, 0, amd); /* get 2 reg */ - if (cptr == NULL) return SCPE_ARG; - val[0] = val[0] | (amd[0] << I_V_SRC) | (amd[1] << I_V_DST); - break; -case I_V_RSI: /* reg, short imm */ - cptr = get_glyph (cptr, gbuf, ','); /* get immediate */ - d = get_uint (gbuf, 8, I_M_SRC + 1, &r); - if ((d == 0) || (r != SCPE_OK)) return SCPE_ARG; - val[0] = val[0] | ((d - 1) << I_V_SRC); /* put in place */ - cptr = get_glyph (cptr, gbuf, 0); /* get register */ - d = get_uint (gbuf, 8, I_M_DST, &r); - if (r != SCPE_OK) return SCPE_ARG; - val[0] = val[0] | (d << I_V_DST); /* put in place */ - break; -case I_V_RLI: /* reg, long imm */ - cptr = get_glyph (cptr, gbuf, ','); /* get immediate */ - val[1] = get_uint (gbuf, 8, DMASK, &r); - if (r != SCPE_OK) return SCPE_ARG; - cptr = get_glyph (cptr, gbuf, 0); /* get register */ - d = get_uint (gbuf, 8, I_M_DST, &r); - if (r != SCPE_OK) return SCPE_ARG; - val[0] = val[0] | (d << I_V_DST); /* put in place */ - rtn = -1; - break; -case I_V_LI: /* long imm */ - cptr = get_glyph (cptr, gbuf, 0); /* get immediate */ - val[1] = get_uint (gbuf, 8, DMASK, &r); - if (r != SCPE_OK) return SCPE_ARG; - rtn = -1; - break; -case I_V_RLM: /* reg, long mem */ - cptr = get_glyph (cptr, gbuf, ','); /* get register */ - d = get_uint (gbuf, 8, I_M_DST, &r); - if (r != SCPE_OK) return SCPE_ARG; - val[0] = val[0] | (d << I_V_DST); /* put in place */ -case I_V_LM: /* long mem */ - cptr = get_addr (cptr, addr, TRUE, cflag, amd); - if (cptr == NULL) return SCPE_ARG; - val[0] = val[0] | (amd[1] << I_V_MODE); - val[1] = (amd[0] << A_V_IND) | amd[2]; - rtn = -1; - break; -case I_V_FRM: /* flt reg, long mem */ - cptr = get_glyph (cptr, gbuf, ','); /* get register */ - d = get_uint (gbuf, 8, I_M_DST, &r); - if (r != SCPE_OK) return SCPE_ARG; - val[0] = val[0] | (d << I_V_DST); /* put in place */ - cptr = get_addr (cptr, addr, TRUE, cflag, amd); - if (cptr == NULL) return SCPE_ARG; - val[0] = val[0] | (amd[1] << I_V_SRC); - val[1] = (amd[0] << A_V_IND) | amd[2]; - rtn = -1; - break; -case I_V_FST: /* flt status */ - cptr = get_addr (cptr, addr, TRUE, cflag, amd); - if (cptr == NULL) return SCPE_ARG; - val[0] = val[0] | (amd[1] << I_V_DST); - val[1] = (amd[0] << A_V_IND) | amd[2]; - rtn = -1; - break; -case I_V_XP: /* XOP */ - cptr = get_2reg (cptr, ',', amd); /* get 2 reg */ - if (cptr == NULL) return SCPE_ARG; - val[0] = val[0] | (amd[0] << I_V_SRC) | (amd[1] << I_V_DST); - cptr = get_glyph (cptr, gbuf, 0); /* get argument */ - d = get_uint (gbuf, 8, I_M_XOP, &r); - if (r != SCPE_OK) return SCPE_ARG; - val[0] = val[0] | (d << I_V_XOP); - break; } /* end case */ -if (*cptr != 0) return SCPE_ARG; /* any leftovers? */ -return rtn; -} diff --git a/NOVA/nova_tt.c b/NOVA/nova_tt.c deleted file mode 100644 index f745b08e..00000000 --- a/NOVA/nova_tt.c +++ /dev/null @@ -1,220 +0,0 @@ -/* nova_tt.c: NOVA console terminal simulator - - 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. - - tti terminal input - tto terminal output - - 25-Apr-03 RMS Revised for extended file support - 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 - 17-Sep-01 RMS Removed multiconsole support - 07-Sep-01 RMS Moved function prototypes - 31-May-01 RMS Added multiconsole support -*/ - -#include "nova_defs.h" - -#define UNIT_V_DASHER (UNIT_V_UF + 0) /* Dasher mode */ -#define UNIT_DASHER (1 << UNIT_V_DASHER) -extern int32 int_req, dev_busy, dev_done, dev_disable; - -int32 tti (int32 pulse, int32 code, int32 AC); -int32 tto (int32 pulse, int32 code, int32 AC); -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, void *desc); - -/* TTI data structures - - tti_dev TTI device descriptor - tti_unit TTI unit descriptor - tti_reg TTI register list - ttx_mod TTI/TTO modifiers list -*/ - -DIB tti_dib = { DEV_TTI, INT_TTI, PI_TTI, &tti }; - -UNIT tti_unit = { UDATA (&tti_svc, 0, 0), KBD_POLL_WAIT }; - -REG tti_reg[] = { - { ORDATA (BUF, tti_unit.buf, 8) }, - { FLDATA (BUSY, dev_busy, INT_V_TTI) }, - { FLDATA (DONE, dev_done, INT_V_TTI) }, - { FLDATA (DISABLE, dev_disable, INT_V_TTI) }, - { FLDATA (INT, int_req, INT_V_TTI) }, - { DRDATA (POS, tti_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, tti_unit.wait, 24), REG_NZ + PV_LEFT }, - { NULL } }; - -MTAB ttx_mod[] = { - { UNIT_DASHER, 0, "ANSI", "ANSI", &ttx_setmod }, - { UNIT_DASHER, UNIT_DASHER, "Dasher", "DASHER", &ttx_setmod }, - { 0 } }; - -DEVICE tti_dev = { - "TTI", &tti_unit, tti_reg, ttx_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 descriptor - tto_reg TTO register list -*/ - -DIB tto_dib = { DEV_TTO, INT_TTO, PI_TTO, &tto }; - -UNIT tto_unit = { UDATA (&tto_svc, 0, 0), SERIAL_OUT_WAIT }; - -REG tto_reg[] = { - { ORDATA (BUF, tto_unit.buf, 8) }, - { FLDATA (BUSY, dev_busy, INT_V_TTO) }, - { FLDATA (DONE, dev_done, INT_V_TTO) }, - { FLDATA (DISABLE, dev_disable, INT_V_TTO) }, - { FLDATA (INT, int_req, INT_V_TTO) }, - { DRDATA (POS, tto_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, tto_unit.wait, 24), PV_LEFT }, - { NULL } }; - -DEVICE tto_dev = { - "TTO", &tto_unit, tto_reg, ttx_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &tto_reset, - NULL, NULL, NULL, - &tto_dib, 0 }; - -/* Terminal input: IOT routine */ - -int32 tti (int32 pulse, int32 code, int32 AC) -{ -int32 iodata; - -iodata = (code == ioDIA)? tti_unit.buf & 0377: 0; -switch (pulse) { /* decode IR<8:9> */ -case iopS: /* start */ - dev_busy = dev_busy | INT_TTI; /* set busy */ - dev_done = dev_done & ~INT_TTI; /* clear done, int */ - int_req = int_req & ~INT_TTI; - break; -case iopC: /* clear */ - dev_busy = dev_busy & ~INT_TTI; /* clear busy */ - dev_done = dev_done & ~INT_TTI; /* clear done, int */ - int_req = int_req & ~INT_TTI; - break; } /* end switch */ -return iodata; -} - -/* 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? */ -tti_unit.buf = temp & 0177; -if ((tti_unit.flags & UNIT_DASHER) && (tti_unit.buf == '\r')) - tti_unit.buf = '\n'; /* Dasher: cr -> nl */ -dev_busy = dev_busy & ~INT_TTI; /* clear busy */ -dev_done = dev_done | INT_TTI; /* set done */ -int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable); -tti_unit.pos = tti_unit.pos + 1; -return SCPE_OK; -} - -/* Reset routine */ - -t_stat tti_reset (DEVICE *dptr) -{ -tti_unit.buf = 0; -dev_busy = dev_busy & ~INT_TTI; /* clear busy */ -dev_done = dev_done & ~INT_TTI; /* clear done, int */ -int_req = int_req & ~INT_TTI; -sim_activate (&tti_unit, tti_unit.wait); /* activate unit */ -return SCPE_OK; -} - -/* Terminal output: IOT routine */ - -int32 tto (int32 pulse, int32 code, int32 AC) -{ -if (code == ioDOA) tto_unit.buf = AC & 0377; -switch (pulse) { /* decode IR<8:9> */ -case iopS: /* start */ - dev_busy = dev_busy | INT_TTO; /* set busy */ - dev_done = dev_done & ~INT_TTO; /* clear done, int */ - int_req = int_req & ~INT_TTO; - sim_activate (&tto_unit, tto_unit.wait); /* activate unit */ - break; -case iopC: /* clear */ - dev_busy = dev_busy & ~INT_TTO; /* clear busy */ - dev_done = dev_done & ~INT_TTO; /* clear done, int */ - int_req = int_req & ~INT_TTO; - sim_cancel (&tto_unit); /* deactivate unit */ - break; } /* end switch */ -return 0; -} - -/* Unit service */ - -t_stat tto_svc (UNIT *uptr) -{ -int32 c, temp; - -dev_busy = dev_busy & ~INT_TTO; /* clear busy */ -dev_done = dev_done | INT_TTO; /* set done */ -int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable); -c = tto_unit.buf & 0177; -if ((tto_unit.flags & UNIT_DASHER) && (c == 031)) c = '\b'; -if ((temp = sim_putchar (c)) != SCPE_OK) return temp; -tto_unit.pos = tto_unit.pos + 1; -return SCPE_OK; -} - -/* Reset routine */ - -t_stat tto_reset (DEVICE *dptr) -{ -tto_unit.buf = 0; -dev_busy = dev_busy & ~INT_TTO; /* clear busy */ -dev_done = dev_done & ~INT_TTO; /* clear done, int */ -int_req = int_req & ~INT_TTO; -sim_cancel (&tto_unit); /* deactivate unit */ -return SCPE_OK; -} - -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; -return SCPE_OK; -} diff --git a/NOVA/nova_tt1.c b/NOVA/nova_tt1.c deleted file mode 100644 index ea3f1bd3..00000000 --- a/NOVA/nova_tt1.c +++ /dev/null @@ -1,323 +0,0 @@ -/* nova_tt1.c: NOVA second terminal simulator - - 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 - 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. - - tti1 second terminal input - tto1 second terminal output - - 09-May-03 RMS Added network device flag - 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 - 06-Jan-02 RMS Revised enable/disable support - 30-Dec-01 RMS Added show statistics, set disconnect - 30-Nov-01 RMS Added extended SET/SHOW support - 17-Sep-01 RMS Changed to use terminal multiplexor library - 07-Sep-01 RMS Moved function prototypes - 31-May-01 RMS Added multiconsole support - 26-Apr-01 RMS Added device enable/disable support -*/ - -#include "nova_defs.h" -#include "sim_sock.h" -#include "sim_tmxr.h" - -#define UNIT_V_DASHER (UNIT_V_UF + 0) /* Dasher mode */ -#define UNIT_DASHER (1 << UNIT_V_DASHER) - -extern int32 int_req, dev_busy, dev_done, dev_disable; -extern int32 tmxr_poll; /* calibrated poll */ -TMLN tt1_ldsc = { 0 }; /* line descriptors */ -TMXR tt_desc = { 1, 0, 0, &tt1_ldsc }; /* mux descriptor */ - -DEVICE tti1_dev, tto1_dev; -int32 tti1 (int32 pulse, int32 code, int32 AC); -int32 tto1 (int32 pulse, int32 code, int32 AC); -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, 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); -t_stat tti1_show (FILE *st, UNIT *uptr, int32 val, void *desc); -void ttx1_enbdis (int32 dis); - -/* TTI1 data structures - - tti1_dev TTI1 device descriptor - tti1_unit TTI1 unit descriptor - tti1_reg TTI1 register list - ttx1_mod TTI1/TTO1 modifiers list -*/ - -DIB tti1_dib = { DEV_TTI1, INT_TTI1, PI_TTI1, &tti1 }; - -UNIT tti1_unit = { UDATA (&tti1_svc, UNIT_ATTABLE, 0), KBD_POLL_WAIT }; - -REG tti1_reg[] = { - { ORDATA (BUF, tti1_unit.buf, 8) }, - { FLDATA (BUSY, dev_busy, INT_V_TTI1) }, - { FLDATA (DONE, dev_done, INT_V_TTI1) }, - { FLDATA (DISABLE, dev_disable, INT_V_TTI1) }, - { FLDATA (INT, int_req, INT_V_TTI1) }, - { DRDATA (POS, tt1_ldsc.rxcnt, 32), PV_LEFT }, - { DRDATA (TIME, tti1_unit.wait, 24), REG_NZ + PV_LEFT }, - { NULL } }; - -MTAB tti1_mod[] = { - { UNIT_DASHER, 0, "ANSI", "ANSI", &ttx1_setmod }, - { UNIT_DASHER, UNIT_DASHER, "Dasher", "DASHER", &ttx1_setmod }, - { UNIT_ATT, UNIT_ATT, "summary", NULL, NULL, &tti1_summ }, - { MTAB_XTD | MTAB_VDV, 0, NULL, "DISCONNECT", - &tmxr_dscln, NULL, &tt_desc }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "CONNECTIONS", NULL, - NULL, &tti1_show, NULL }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "STATISTICS", NULL, - NULL, &tti1_show, NULL }, - { 0 } }; - -DEVICE tti1_dev = { - "TTI1", &tti1_unit, tti1_reg, tti1_mod, - 1, 10, 31, 1, 8, 8, - &tmxr_ex, &tmxr_dep, &tti1_reset, - NULL, &tti1_attach, &tti1_detach, - &tti1_dib, DEV_NET | DEV_DISABLE }; - -/* TTO1 data structures - - tto1_dev TTO1 device descriptor - tto1_unit TTO1 unit descriptor - tto1_reg TTO1 register list -*/ - -DIB tto1_dib = { DEV_TTO1, INT_TTO1, PI_TTO1, &tto1 }; - -UNIT tto1_unit = { UDATA (&tto1_svc, 0, 0), SERIAL_OUT_WAIT }; - -REG tto1_reg[] = { - { ORDATA (BUF, tto1_unit.buf, 8) }, - { FLDATA (BUSY, dev_busy, INT_V_TTO1) }, - { FLDATA (DONE, dev_done, INT_V_TTO1) }, - { FLDATA (DISABLE, dev_disable, INT_V_TTO1) }, - { FLDATA (INT, int_req, INT_V_TTO1) }, - { DRDATA (POS, tt1_ldsc.txcnt, 32), PV_LEFT }, - { DRDATA (TIME, tto1_unit.wait, 24), PV_LEFT }, - { NULL } }; - -MTAB tto1_mod[] = { - { UNIT_DASHER, 0, "ANSI", "ANSI", &ttx1_setmod }, - { UNIT_DASHER, UNIT_DASHER, "Dasher", "DASHER", &ttx1_setmod }, - { 0 } }; - -DEVICE tto1_dev = { - "TTO1", &tto1_unit, tto1_reg, tto1_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &tto1_reset, - NULL, NULL, NULL, - &tto1_dib, DEV_DISABLE }; - -/* Terminal input: IOT routine */ - -int32 tti1 (int32 pulse, int32 code, int32 AC) -{ -int32 iodata; - -iodata = (code == ioDIA)? tti1_unit.buf & 0377: 0; -switch (pulse) { /* decode IR<8:9> */ -case iopS: /* start */ - dev_busy = dev_busy | INT_TTI1; /* set busy */ - dev_done = dev_done & ~INT_TTI1; /* clear done, int */ - int_req = int_req & ~INT_TTI1; - break; -case iopC: /* clear */ - dev_busy = dev_busy & ~INT_TTI1; /* clear busy */ - dev_done = dev_done & ~INT_TTI1; /* clear done, int */ - int_req = int_req & ~INT_TTI1; - break; } /* end switch */ -return iodata; -} - -/* Unit service */ - -t_stat tti1_svc (UNIT *uptr) -{ -int32 temp, newln; - -if (tt1_ldsc.conn) { /* connected? */ - tmxr_poll_rx (&tt_desc); /* poll for input */ - if (temp = tmxr_getc_ln (&tt1_ldsc)) { /* get char */ - uptr->buf = temp & 0177; - if ((uptr->flags & UNIT_DASHER) && - (uptr->buf == '\r')) - uptr->buf = '\n'; /* Dasher: cr->nl */ - dev_busy = dev_busy & ~INT_TTI1; /* clear busy */ - dev_done = dev_done | INT_TTI1; /* set done */ - int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable); } - sim_activate (uptr, uptr->wait); } /* continue poll */ -if (uptr->flags & UNIT_ATT) { /* attached? */ - newln = tmxr_poll_conn (&tt_desc); /* poll connect */ - if (newln >= 0) { /* got one? */ - sim_activate (&tti1_unit, tti1_unit.wait); - tt1_ldsc.rcve = 1; } /* rcv enabled */ - sim_activate (uptr, tmxr_poll); } /* sched poll */ -return SCPE_OK; -} - -/* Reset routine */ - -t_stat tti1_reset (DEVICE *dptr) -{ -ttx1_enbdis (dptr->flags & DEV_DIS); /* sync devices */ -tti1_unit.buf = 0; -dev_busy = dev_busy & ~INT_TTI1; /* clear busy */ -dev_done = dev_done & ~INT_TTI1; /* clear done, int */ -int_req = int_req & ~INT_TTI1; -if (tt1_ldsc.conn) { /* if conn, */ - sim_activate (&tti1_unit, tti1_unit.wait); /* activate, */ - tt1_ldsc.rcve = 1; } /* enable */ -else if (tti1_unit.flags & UNIT_ATT) /* if attached, */ - sim_activate (&tti1_unit, tmxr_poll); /* activate */ -else sim_cancel (&tti1_unit); /* else stop */ -return SCPE_OK; -} - -/* Terminal output: IOT routine */ - -int32 tto1 (int32 pulse, int32 code, int32 AC) -{ -if (code == ioDOA) tto1_unit.buf = AC & 0377; -switch (pulse) { /* decode IR<8:9> */ -case iopS: /* start */ - dev_busy = dev_busy | INT_TTO1; /* set busy */ - dev_done = dev_done & ~INT_TTO1; /* clear done, int */ - int_req = int_req & ~INT_TTO1; - sim_activate (&tto1_unit, tto1_unit.wait); /* activate unit */ - break; -case iopC: /* clear */ - dev_busy = dev_busy & ~INT_TTO1; /* clear busy */ - dev_done = dev_done & ~INT_TTO1; /* clear done, int */ - int_req = int_req & ~INT_TTO1; - sim_cancel (&tto1_unit); /* deactivate unit */ - break; } /* end switch */ -return 0; -} - -/* Unit service */ - -t_stat tto1_svc (UNIT *uptr) -{ -int32 c; - -dev_busy = dev_busy & ~INT_TTO1; /* clear busy */ -dev_done = dev_done | INT_TTO1; /* set done */ -int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable); -c = tto1_unit.buf & 0177; -if ((tto1_unit.flags & UNIT_DASHER) && (c == 031)) c = '\b'; -if (tt1_ldsc.conn) { /* connected? */ - if (tt1_ldsc.xmte) { /* tx enabled? */ - tmxr_putc_ln (&tt1_ldsc, c); /* output char */ - tmxr_poll_tx (&tt_desc); } /* poll xmt */ - else { tmxr_poll_tx (&tt_desc); /* poll xmt */ - sim_activate (&tto1_unit, tmxr_poll); /* wait */ - return SCPE_OK; } } -return SCPE_OK; -} - -/* Reset routine */ - -t_stat tto1_reset (DEVICE *dptr) -{ -ttx1_enbdis (dptr->flags & DEV_DIS); /* sync devices */ -tto1_unit.buf = 0; -dev_busy = dev_busy & ~INT_TTO1; /* clear busy */ -dev_done = dev_done & ~INT_TTO1; /* clear done, int */ -int_req = int_req & ~INT_TTO1; -sim_cancel (&tto1_unit); /* deactivate unit */ -return SCPE_OK; -} - -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; -return SCPE_OK; -} - -/* Attach routine */ - -t_stat tti1_attach (UNIT *uptr, char *cptr) -{ -t_stat r; - -r = tmxr_attach (&tt_desc, uptr, cptr); /* attach */ -if (r != SCPE_OK) return r; /* error */ -sim_activate (uptr, tmxr_poll); /* start poll */ -return SCPE_OK; -} - -/* Detach routine */ - -t_stat tti1_detach (UNIT *uptr) -{ -t_stat r; - -r = tmxr_detach (&tt_desc, uptr); /* detach */ -tt1_ldsc.rcve = 0; /* disable rcv */ -sim_cancel (uptr); /* stop poll */ -return r; -} - -/* Show summary processor */ - -t_stat tti1_summ (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -if (tt1_ldsc.conn) fprintf (st, "connected"); -else fprintf (st, "disconnected"); -return SCPE_OK; -} - -/* SHOW CONN/STAT processor */ - -t_stat tti1_show (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -if (val) tmxr_fconns (st, &tt1_ldsc, -1); -else tmxr_fstats (st, &tt1_ldsc, -1); -return SCPE_OK; -} - -/* Enable/disable device */ - -void ttx1_enbdis (int32 dis) -{ -if (dis) { - tti1_dev.flags = tto1_dev.flags | DEV_DIS; - tto1_dev.flags = tto1_dev.flags | DEV_DIS; } -else { tti1_dev.flags = tti1_dev.flags & ~DEV_DIS; - tto1_dev.flags = tto1_dev.flags & ~DEV_DIS; } -return; -} diff --git a/PDP1/pdp1_cpu.c b/PDP1/pdp1_cpu.c deleted file mode 100644 index afe90b39..00000000 --- a/PDP1/pdp1_cpu.c +++ /dev/null @@ -1,853 +0,0 @@ -/* pdp1_cpu.c: PDP-1 CPU simulator - - 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. - - cpu PDP-1 central processor - - 07-Sep-03 RMS Added additional explanation on I/O simulation - 01-Sep-03 RMS Added address switches for hardware readin - 23-Jul-03 RMS Revised to detect I/O wait hang - 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 - 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 - IOS I/O syncronizer (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 TA = 0; /* address switches */ -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 ios = 0; /* I/O syncronizer */ -int32 cpls = 0; /* pending completions */ -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 dat); -extern int32 ptp (int32 inst, int32 dev, int32 dat); -extern int32 tti (int32 inst, int32 dev, int32 dat); -extern int32 tto (int32 inst, int32 dev, int32 dat); -extern int32 lpt (int32 inst, int32 dev, int32 dat); -extern int32 dt (int32 inst, int32 dev, int32 dat); -extern int32 drm (int32 inst, int32 dev, int32 dat); - -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 (TA, TA, ASIZE) }, - { 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 (IOS, ios, 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 == (OP_JMP+IA+1)) && ((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 { /* 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> */ - -/* 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 { /* 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 { /* 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 - - 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 - The simulator behaves functionally like a real PDP-1 but does not - use the same mechanisms or state bits. In particular, - - - If an IOT does not specify IO_WAIT, the IOT will be executed, and the - I/O halt flag (IOH) will not be disturbed. On the real PDP-1, IOH is - stored in IHS, IOH is cleared, the IOT is executed, and then IOH is - restored from IHS. Because IHS is not otherwise used, it is not - explicitly simulated. - - If an IOT does specify IO_WAIT, then IOH specifies whether an I/O halt - (wait) is already in progress. - > If already set, I/O wait is in progress. The simulator looks for - a completion pulse (IOS). If there is a pulse, IOH is cleared. If - not, the IOT is fetched again. In either case, execution of the - IOT is skipped. - > If not set, I/O wait must start. IOH is set, the PC is backed up, - and the IOT is executed. - On a real PDP-1, IOC is the I/O command enable and enables the IOT - pulses. In the simulator, the enabling of IOT pulses is done through - code flow, and IOC is not explicitly simulated. -*/ - -case 035: - if (IR & IO_WAIT) { /* wait? */ - if (ioh) { /* I/O halt? */ - if (ios) ioh = 0; /* comp pulse? done */ - else { /* wait more */ - PC = DECR_ADDR (PC); /* re-execute */ - if (cpls == 0) { /* any pending pulses? */ - reason = STOP_WAIT; /* no, CPU hangs */ - break; } - sim_interval = 0; } /* force event */ - 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 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; - default: /* undefined */ - 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 */ - 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 = ios = cpls = 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; -uint32 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/PDP1/pdp1_defs.h b/PDP1/pdp1_defs.h deleted file mode 100644 index e113db12..00000000 --- a/PDP1/pdp1_defs.h +++ /dev/null @@ -1,125 +0,0 @@ -/* pdp1_defs.h: 18b PDP simulator definitions - - 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. - - 22-Jul-03 RMS Updated for "hardware" RIM loader - Revised to detect I/O wait hang - 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 - 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 - Serial drum Type 24 - Line printer control Type 62 - Microtape (DECtape) control Type 550 -*/ - -#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 /* IO wait hang */ - -/* 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) (((uint32) (x)) < MEMSIZE) - -/* Architectural constants */ - -#define DMASK 0777777 /* data mask */ -#define DAMASK 0007777 /* direct addr */ -#define EPCMASK (AMASK & ~DAMASK) /* extended addr */ -#define IA 0010000 /* indirect flag */ -#define IO_WAIT 0010000 /* I/O sync wait */ -#define IO_CPLS 0004000 /* completion pulse */ -#define OP_DAC 0240000 /* DAC */ -#define OP_DIO 0320000 /* DIO */ -#define OP_JMP 0600000 /* JMP */ -#define GEN_CPLS(x) (((x) ^ ((x) << 1)) & IO_WAIT) /* completion pulse? */ - -/* IOT subroutine return codes */ - -#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 */ - -/* 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) - -/* Completion pulses */ - -#define CPLS_V_PTR 5 -#define CPLS_V_PTP 4 -#define CPLS_V_TTO 3 -#define CPLS_V_LPT 2 -#define CPLS_PTR (1 << CPLS_V_PTR) -#define CPLS_PTP (1 << CPLS_V_PTP) -#define CPLS_TTO (1 << CPLS_V_TTO) -#define CPLS_LPT (1 << CPLS_V_LPT) - -/* 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/PDP1/pdp1_doc.txt b/PDP1/pdp1_doc.txt deleted file mode 100644 index e0fda843..00000000 --- a/PDP1/pdp1_doc.txt +++ /dev/null @@ -1,516 +0,0 @@ -To: Users -From: Bob Supnik -Subj: PDP-1 Simulator Usage -Date: 15-Sep-2003 - - COPYRIGHT NOTICE - -The following copyright notice applies to both the SIMH source and binary: - - 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"), - 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_drm.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 -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: - - - an unimplemented instruction is decoded, and register - STOP_INST is set - - more than IND_MAX indirect addresses are detected during - memory reference address decoding - - more than XCT_MAX nested executes are detected during - instruction execution - - I/O wait, and no I/O operations outstanding (i.e, no I/O - completion will ever occur) - -The PDP-1 loader supports RIM format tapes and BLK format tapes. If -the file to be loaded has an extension of .BIN, or switch -B is specified, -the file is assumed to be BLK format; otherwise, it defaults to RIM -format. LOAD takes an optional argument which specifies the starting -address of the field to be loaded: - - LOAD lisp.rim -- load RIM format file lisp.rim - LOAD ddt.rim 70000 -- load RIM format file ddt.rim into - the field starting at 70000 - LOAD -B macro.blk -- load BLK format file macro.blk - -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> - TA 16 address switches - 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 - IOS 1 I/O synchronizer (completion) - 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 - XCT_MAX 8 maximum XCT chain - IND_MAX 8 maximum nested indirect addresses - 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. BOOT PTR loads into the -field selected by TA<0:3> (the high order four bits of the address -switches). - -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 Console Typewriter (TTY) - -The Typewriter is a half-duplex electric typewriter (originally a -Friden Flexowriter, later a Sorobon-modified IBM B). It has only a -single buffer and a single carriage state but distinct input and -output done and interrupt flags. The typewriter input (TTY unit 0) -polls the console keyboard for input. The typewriter output (TTY -unit 1) writes to the simulator console window. - -The typewriter implements these registers: - - name size comments - - BUF 6 typewriter buffer - UC 1 upper case/lower case state flag - RPLS 1 return restart pulse flag - KDONE 1 input ready flag - KPOS 32 number of characters input - KTIME 24 keyboard polling interval - TDONE 1 output done flag - TPOS 32 number of characters output - TTIME 24 time from I/O initiation to interrupt - -2.2.4 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 uses the Type 550 Microtape (later renamed DECtape), a programmed -I/O controller. PDP-1 DECtape format has 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 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: - - -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.6 Character Sets - -The PDP-1's first 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/PDP1/pdp1_drm.c b/PDP1/pdp1_drm.c deleted file mode 100644 index 1d396723..00000000 --- a/PDP1/pdp1_drm.c +++ /dev/null @@ -1,169 +0,0 @@ -/* pdp1_drm.c: PDP-1 drum 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 - - 23-Jul-03 RMS Fixed incorrect logical, missing activate - 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 dat) -{ -int32 t; -int32 pulse = (IR >> 6) & 037; - -if (drm_dev.flags & DEV_DIS) /* disabled? */ - return (stop_inst << IOT_V_REASON) | dat; /* stop if requested */ -if ((pulse != 001) && (pulse != 011)) /* invalid pulse? */ - return (stop_inst << IOT_V_REASON) | dat; /* stop if requested */ -switch (dev) { /* switch on device */ -case 061: /* DWR, DRD */ - drm_ma = dat & 0177777; /* load mem addr */ - drm_unit.FUNC = pulse & DRM_WRITE; /* save function */ - break; -case 062: /* DBL, DCN */ - if (pulse & 010) drm_da = dat & 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? */ - sim_activate (&drm_unit, t); /* start operation */ - break; -case 063: /* DTD */ - if (pulse == 011) return (stop_inst << IOT_V_REASON) | dat; - if (iosta & IOS_DRM) return (dat | IOT_SKP); /* skip if done */ - break; -case 064: /* DSE, DSP */ - if ((drm_err == 0) || (pulse & 010)) /* no error, par test? */ - return (dat | IOT_SKP); - } -return dat; -} - -/* Unit service - this code assumes the entire drum is buffered */ - -t_stat drm_svc (UNIT *uptr) -{ -uint32 i, 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 deleted file mode 100644 index bbafc553..00000000 --- a/PDP1/pdp1_dt.c +++ /dev/null @@ -1,983 +0,0 @@ -/* pdp1_dt.c: 18b DECtape simulator - - 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. - - dt Type 550/555 DECtape - - 25-Apr-03 RMS Revised for extended file support - 14-Mar-03 RMS Fixed variable size interaction with save/restore - 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, T_ADDR_W, 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 dat) -{ -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) | dat; /* 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 ^ dat) & DTA_UNIT) dt_deselect (dtsa); /* new unit? */ - dtsa = (dtsa & ~DTA_UNIT) | (dat & DTA_UNIT); - dtsb = dtsb & ~(DTB_DTF | DTB_BEF | DTB_ERF | DTB_ALLERR); } -if (pulse == 004) { /* MLC */ - dtsa = (dtsa & ~DTA_RW) | (dat & 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 */ - dat = (dat & ~DMASK) | dtdb; - dtsb = dtsb & ~(DTB_DTF | DTB_BEF); } -if (pulse == 006) { /* MWR */ - dtdb = dat & 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 */ - dat = (dat & ~DMASK) | dtsb; } -DT_UPDINT; -return dat; -} - -/* 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; -uint32 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 ba, sz, k, *bptr; -int32 u = uptr - dt_dev.units; -t_stat r; - -r = attach_unit (uptr, cptr); /* attach */ -if (r != SCPE_OK) return r; /* error? */ -if ((sim_switches & SIM_SW_REST) == 0) { /* not from rest? */ - 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? */ - (sz = sim_fsize (cptr))) { - if (sz == D8_FILSIZ) - uptr->flags = uptr->flags | UNIT_8FMT; - else if (sz == 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 */ -printf ("%s%d: ", sim_dname (&dt_dev), u); -if (uptr->flags & UNIT_8FMT) printf ("12b format"); -else if (uptr->flags & UNIT_11FMT) printf ("16b format"); -else printf ("18b/36b format"); -printf (", buffering file in memory\n"); -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 ba, k, *bptr; -int32 u = uptr - dt_dev.units; - -if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; -if (sim_is_active (uptr)) { - sim_cancel (uptr); - if ((u == 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 ("%s%d: writing buffer to file\n", sim_dname (&dt_dev), u); - 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/PDP1/pdp1_lp.c b/PDP1/pdp1_lp.c deleted file mode 100644 index d2c2fc2e..00000000 --- a/PDP1/pdp1_lp.c +++ /dev/null @@ -1,184 +0,0 @@ -/* pdp1_lp.c: PDP-1 line printer simulator - - 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. - - lpt Type 62 line printer for the PDP-1 - - 07-Sep-03 RMS Changed ioc to ios - 23-Jul-03 RMS Fixed bugs in instruction decoding, overprinting - Revised to detect I/O wait hang - 25-Apr-03 RMS Revised for extended file support - 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 */ - -int32 lpt_spc = 0; /* print (0) vs spc */ -int32 lpt_ovrpr = 0; /* overprint */ -int32 lpt_stopioe = 0; /* stop on error */ -int32 lpt_bptr = 0; /* buffer ptr */ -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','*','.','+',']','|','[' }; - -extern int32 ios, cpls, sbs, iosta; -extern int32 stop_inst; - -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, cpls, CPLS_V_LPT) }, - { DRDATA (BPTR, lpt_bptr, 6) }, - { ORDATA (LPT_STATE, lpt_spc, 6), REG_HRO }, - { FLDATA (LPT_OVRPR, lpt_ovrpr, 0), REG_HRO }, - { DRDATA (POS, lpt_unit.pos, T_ADDR_W), 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 dat) -{ -int32 i; - -if (lpt_dev.flags & DEV_DIS) /* disabled? */ - return (stop_inst << IOT_V_REASON) | dat; /* stop if requested */ -if ((inst & 07000) == 01000) { /* fill buf */ - if (lpt_bptr < BPTR_MAX) { /* limit test ptr */ - i = lpt_bptr * 3; /* cvt to chr ptr */ - lpt_buf[i] = lpt_trans[(dat >> 12) & 077]; - lpt_buf[i + 1] = lpt_trans[(dat >> 6) & 077]; - lpt_buf[i + 2] = lpt_trans[dat & 077]; } - lpt_bptr = (lpt_bptr + 1) & BPTR_MASK; - return dat; } -if ((inst & 07000) == 02000) { /* space */ - iosta = iosta & ~IOS_SPC; /* space, clear flag */ - lpt_spc = (inst >> 6) & 077; } /* state = space n */ -else if ((inst & 07000) == 00000) { /* print */ - iosta = iosta & ~IOS_PNT; /* clear flag */ - lpt_spc = 0; } /* state = print */ -else return (stop_inst << IOT_V_REASON) | dat; /* not implemented */ -if (GEN_CPLS (inst)) { /* comp pulse? */ - ios = 0; /* clear flop */ - cpls = cpls | CPLS_LPT; } /* request completion */ -else cpls = cpls & ~CPLS_LPT; -sim_activate (&lpt_unit, lpt_unit.wait); /* activate */ -return dat; -} - -/* Unit service, printer is in one of three states - - lpt_spc = 000 write buffer to file, set overprint - lpt_iot = 02x space command x, clear overprint -*/ - -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" }; - -if (cpls & CPLS_LPT) { /* completion pulse? */ - ios = 1; /* restart */ - cpls = cpls & ~CPLS_LPT; } /* clr pulse pending */ -sbs = sbs | SB_RQ; /* req seq break */ -if (lpt_spc) { /* 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_spc & 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_ovrpr = 0; } /* dont overprint */ -else { iosta = iosta | IOS_PNT; /* print */ - if ((lpt_unit.flags & UNIT_ATT) == 0) /* attached? */ - return IORETURN (lpt_stopioe, SCPE_UNATT); - if (lpt_ovrpr) fputc ('\r', lpt_unit.fileref); /* overprint? */ - 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; } - lpt_bptr = 0; - for (i = 0; i <= LPT_BSIZE; i++) lpt_buf[i] = 0; /* clear buffer */ - lpt_ovrpr = 1; } /* set overprint */ -lpt_unit.pos = ftell (lpt_unit.fileref); /* update position */ -return SCPE_OK; -} - -/* Reset routine */ - -t_stat lpt_reset (DEVICE *dptr) -{ -int32 i; - -lpt_bptr = 0; /* clear buffer ptr */ -for (i = 0; i <= LPT_BSIZE; i++) lpt_buf[i] = 0; /* clear buffer */ -lpt_spc = 0; /* clear state */ -lpt_ovrpr = 0; /* clear overprint */ -cpls = cpls & ~CPLS_LPT; -iosta = iosta & ~(IOS_PNT | IOS_SPC); /* clear flags */ -sim_cancel (&lpt_unit); /* deactivate unit */ -return SCPE_OK; -} diff --git a/PDP1/pdp1_stddev.c b/PDP1/pdp1_stddev.c deleted file mode 100644 index 98f95aa8..00000000 --- a/PDP1/pdp1_stddev.c +++ /dev/null @@ -1,455 +0,0 @@ -/* pdp1_stddev.c: PDP-1 standard devices - - 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. - - ptr paper tape reader - ptp paper tape punch - tti keyboard - tto teleprinter - - 07-Sep-03 RMS Changed ioc to ios - 30-Aug-03 RMS Revised PTR to conform to Maintenance Manual; - added deadlock prevention on errors - 23-Jul-03 RMS Revised to detect I/O wait hang - 25-Apr-03 RMS Revised for extended file support - 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 - 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_V 6 /* upper case */ -#define UC (1 << UC_V) -#define BOTH (1 << (UC_V + 1)) /* both cases */ -#define CW (1 << (UC_V + 2)) /* char waiting */ -#define TT_WIDTH 077 -#define TTI 0 -#define TTO 1 - -int32 ptr_state = 0; -int32 ptr_wait = 0; -int32 ptr_stopioe = 0; -int32 ptp_stopioe = 0; -int32 tti_hold = 0; /* tti hold buf */ -int32 tty_buf = 0; /* tty buffer */ -int32 tty_uc = 0; /* tty uc/lc */ - -extern int32 sbs, ios, ioh, cpls, iosta; -extern int32 PF, IO, PC, TA; -extern int32 M[]; - -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 tty_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, cpls, CPLS_V_PTR) }, - { ORDATA (STATE, ptr_state, 5), REG_HRO }, - { FLDATA (WAIT, ptr_wait, 0), REG_HRO }, - { DRDATA (POS, ptr_unit.pos, T_ADDR_W), 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, cpls, CPLS_V_PTP) }, - { DRDATA (POS, ptp_unit.pos, T_ADDR_W), 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 }; - -/* TTY data structures - - tty_dev TTY device descriptor - tty_unit TTY unit - tty_reg TTY register list -*/ - -UNIT tty_unit[] = { - { UDATA (&tti_svc, 0, 0), KBD_POLL_WAIT }, - { UDATA (&tto_svc, 0, 0), SERIAL_OUT_WAIT } }; - -REG tty_reg[] = { - { ORDATA (BUF, tty_buf, 6) }, - { FLDATA (UC, tty_uc, UC_V) }, - { FLDATA (RPLS, cpls, CPLS_V_TTO) }, - { ORDATA (HOLD, tti_hold, 9), REG_HRO }, - { FLDATA (KDONE, iosta, IOS_V_TTI) }, - { DRDATA (KPOS, tty_unit[TTI].pos, T_ADDR_W), PV_LEFT }, - { DRDATA (KTIME, tty_unit[TTI].wait, 24), REG_NZ + PV_LEFT }, - { FLDATA (TDONE, iosta, IOS_V_TTO) }, - { DRDATA (TPOS, tty_unit[TTO].pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TTIME, tty_unit[TTO].wait, 24), PV_LEFT }, - { NULL } }; - -DEVICE tty_dev = { - "TTY", tty_unit, tty_reg, NULL, - 2, 10, 31, 1, 8, 8, - NULL, NULL, &tty_reset, - NULL, NULL, NULL, - NULL, 0 }; - -/* Paper tape reader: IOT routine. Points to note: - - - RPA (but not RPB) complements the reader clutch control. Thus, - if the reader is running, RPA will stop it. - - The status bit indicates data in the reader buffer that has not - been transfered to IO. It is cleared by any RB->IO operation, - including RRB and the completion pulse. - - A reader error on a wait mode operation could hang the simulator. - IOH is set; any retry (without RESET) will be NOP'd. Accordingly, - the PTR service routine clears IOH on any error during a rpa/rpb i. -*/ - -int32 ptr (int32 inst, int32 dev, int32 dat) -{ -if (dev == 0030) { /* RRB */ - iosta = iosta & ~IOS_PTR; /* clear status */ - return ptr_unit.buf; } /* return data */ -if (dev == 0002) ptr_state = 18; /* RPB, mode = binary */ -else if (sim_is_active (&ptr_unit)) { /* RPA, running? */ - sim_cancel (&ptr_unit); /* stop reader */ - return dat; } -else ptr_state = 0; /* mode = alpha */ -ptr_unit.buf = 0; /* clear buffer */ -if (inst & IO_WAIT) ptr_wait = 1; /* set ptr wait */ -else ptr_wait = 0; /* from IR<5> */ -if (GEN_CPLS (inst)) { /* comp pulse? */ - ios = 0; - cpls = cpls | CPLS_PTR; } -else cpls = cpls & ~CPLS_PTR; -sim_activate (&ptr_unit, ptr_unit.wait); /* start reader */ -return dat; -} - -/* Unit service */ - -t_stat ptr_svc (UNIT *uptr) -{ -int32 temp; - -if ((ptr_unit.flags & UNIT_ATT) == 0) { /* attached? */ - if (ptr_wait) ptr_wait = ioh = 0; /* if wait, clr ioh */ - if ((cpls & CPLS_PTR) || ptr_stopioe) return SCPE_UNATT; - return SCPE_OK; } -if ((temp = getc (ptr_unit.fileref)) == EOF) { /* end of file? */ - if (ptr_wait) ptr_wait = ioh = 0; /* if wait, clr ioh */ - if (feof (ptr_unit.fileref)) { - if ((cpls & CPLS_PTR) || 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 (cpls & CPLS_PTR) { /* completion pulse? */ - iosta = iosta & ~IOS_PTR; /* clear flag */ - IO = ptr_unit.buf; /* fill IO */ - ios = 1; /* restart */ - cpls = cpls & ~CPLS_PTR; } - else { /* no, interrupt */ - iosta = iosta | IOS_PTR; /* set flag */ - sbs = sbs | SB_RQ; } } /* req seq break */ -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_wait = 0; -ptr_unit.buf = 0; -cpls = cpls & ~CPLS_PTR; -iosta = iosta & ~IOS_PTR; /* clear flag */ -sim_cancel (&ptr_unit); /* deactivate unit */ -return SCPE_OK; -} - -/* Bootstrap routine */ - -int32 ptr_getw (UNIT *uptr) -{ -int32 i, tmp, word; - -for (i = word = 0; i < 3;) { - if ((tmp = getc (uptr->fileref)) == EOF) return -1; - uptr->pos = uptr->pos + 1; - if (tmp & 0200) { - word = (word << 6) | (tmp & 077); - i++; } } -return word; -} - -t_stat ptr_boot (int32 unitno, DEVICE *dptr) -{ -int32 origin, val; -int32 fld = TA & EPCMASK; - -for (;;) { - if ((val = ptr_getw (&ptr_unit)) < 0) return SCPE_FMT; - if (((val & 0760000) == OP_DIO) || /* DIO? */ - ((val & 0760000) == OP_DAC)) { /* hack - Macro1 err */ - origin = val & DAMASK; - if ((val = ptr_getw (&ptr_unit)) < 0) return SCPE_FMT; - M[fld | origin] = val; } - else if ((val & 0760000) == OP_JMP) { /* JMP? */ - PC = fld | (val & DAMASK); - break; } - else return SCPE_FMT; /* bad instr */ - } -return SCPE_OK; /* done */ -} - -/* Paper tape punch: IOT routine */ - -int32 ptp (int32 inst, int32 dev, int32 dat) -{ -iosta = iosta & ~IOS_PTP; /* clear flag */ -ptp_unit.buf = (dev == 0006)? ((dat >> 12) | 0200): (dat & 0377); -if (GEN_CPLS (inst)) { /* comp pulse? */ - ios = 0; - cpls = cpls | CPLS_PTP; } -else cpls = cpls & ~CPLS_PTP; -sim_activate (&ptp_unit, ptp_unit.wait); /* start unit */ -return dat; -} - -/* Unit service */ - -t_stat ptp_svc (UNIT *uptr) -{ -if (cpls & CPLS_PTP) { /* completion pulse? */ - ios = 1; /* restart */ - cpls = cpls & ~CPLS_PTP; } -iosta = iosta | IOS_PTP; /* set flag */ -sbs = sbs | SB_RQ; /* req seq break */ -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 */ -cpls = cpls & ~CPLS_PTP; -iosta = iosta & ~IOS_PTP; /* clear flag */ -sim_cancel (&ptp_unit); /* deactivate unit */ -return SCPE_OK; -} - -/* Typewriter IOT routines */ - -int32 tti (int32 inst, int32 dev, int32 dat) -{ -iosta = iosta & ~IOS_TTI; /* clear flag */ -if (inst & (IO_WAIT | IO_CPLS)) /* wait or sync? */ - return (STOP_RSRV << IOT_V_REASON) | (tty_buf & 077); -return tty_buf & 077; -} - -int32 tto (int32 inst, int32 dev, int32 dat) -{ -iosta = iosta & ~IOS_TTO; /* clear flag */ -tty_buf = dat & TT_WIDTH; /* load buffer */ -if (GEN_CPLS (inst)) { /* comp pulse? */ - ios = 0; - cpls = cpls | CPLS_TTO; } -else cpls = cpls & ~CPLS_TTO; -sim_activate (&tty_unit[TTO], tty_unit[TTO].wait); /* activate unit */ -return dat; -} - -/* Unit service routines */ - -t_stat tti_svc (UNIT *uptr) -{ -int32 in, temp; - -sim_activate (uptr, uptr->wait); /* continue poll */ -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 */ - 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) == (tty_uc & UC))) - 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 */ -uptr->pos = uptr->pos + 1; -return SCPE_OK; -} - -t_stat tto_svc (UNIT *uptr) -{ -int32 out; - -if (cpls & CPLS_TTO) { /* completion pulse? */ - ios = 1; /* restart */ - cpls = cpls & ~CPLS_TTO; } -iosta = iosta | IOS_TTO; /* set flag */ -sbs = sbs | SB_RQ; /* req seq break */ -if (tty_buf == FIODEC_UC) { /* upper case? */ - tty_uc = UC; - return SCPE_OK; } -if (tty_buf == FIODEC_LC) { /* lower case? */ - tty_uc = 0; - return SCPE_OK; } -out = fiodec_to_ascii[tty_buf | tty_uc]; /* translate */ -if (out == 0) return SCPE_OK; /* no translation? */ -sim_putchar (out); -uptr->pos = uptr->pos + 1; -if (out == '\r') { /* cr? add lf */ - sim_putchar ('\n'); - uptr->pos = uptr->pos + 1; } -return SCPE_OK; -} - -/* Reset routine */ - -t_stat tty_reset (DEVICE *dptr) -{ -tty_buf = 0; /* clear buffer */ -tty_uc = 0; /* clear case */ -tti_hold = 0; /* clear hold buf */ -cpls = cpls & ~CPLS_TTO; -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 deleted file mode 100644 index 4a30a798..00000000 --- a/PDP1/pdp1_sys.c +++ /dev/null @@ -1,513 +0,0 @@ -/* pdp1_sys.c: PDP-1 simulator interface - - 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. - - 01-Sep-03 RMS Added support for loading in multiple fields - 22-Jul-03 RMS Updated for "hardware" RIM loader - 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 - 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; -extern DEVICE ptp_dev; -extern DEVICE tty_dev; -extern DEVICE lpt_dev; -extern DEVICE dt_dev; -extern DEVICE drm_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[]; -extern int32 sim_switches; - -/* 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, - &tty_dev, - &lpt_dev, - &dt_dev, - &drm_dev, - NULL }; - -const char *sim_stop_messages[] = { - "Unknown error", - "Undefined instruction", - "HALT instruction", - "Breakpoint", - "Nested XCT's", - "Nested indirect addresses", - "Infinite I/O wait state" }; - -/* Binary loader - supports both RIM format and Macro block format */ - -int32 getw (FILE *inf) -{ -int32 i, tmp, word; - -word = 0; -for (i = 0; i < 3;) { - if ((tmp = getc (inf)) == EOF) return -1; - if (tmp & 0200) { - word = (word << 6) | (tmp & 077); - i++; } } -return word; -} - -t_stat rim_load (FILE *inf, int32 fld) -{ -int32 origin, val; - -for (;;) { - if ((val = getw (inf)) < 0) return SCPE_FMT; - if (((val & 0760000) == OP_DIO) || /* DIO? */ - ((val & 0760000) == OP_DAC)) { /* hack - Macro1 err */ - origin = val & DAMASK; - if ((val = getw (inf)) < 0) return SCPE_FMT; - M[fld | origin] = val; } - else if ((val & 0760000) == OP_JMP) { /* JMP? */ - PC = fld | (val & DAMASK); - break; } - else return SCPE_FMT; /* bad instr */ - } -return SCPE_OK; /* done */ -} - -t_stat blk_load (FILE *inf, int32 fld) -{ -int32 val, start, count, csum; - -for (;;) { - if ((val = getw (inf)) < 0) return SCPE_FMT; /* get word, EOF? */ - if ((val & 0760000) == OP_DIO) { /* DIO? */ - csum = val; /* init checksum */ - start = val & DAMASK; /* starting addr */ - if ((val = getw (inf)) < 0) return SCPE_FMT; - if ((val & 0760000) != OP_DIO) return SCPE_FMT; - csum = csum + val; - if (csum > 0777777) csum = (csum + 1) & 0777777; - count = (val & DAMASK) - start + 1; /* block count */ - if (count <= 0) return SCPE_FMT; - while (count--) { /* loop on data */ - if ((val = getw (inf)) < 0) return SCPE_FMT; - csum = csum + val; - if (csum > 0777777) csum = (csum + 1) & 0777777; - M[fld | start] = val; - start = (start + 1) & DAMASK; } - if ((val = getw (inf)) < 0) return SCPE_FMT; - if (val != csum) return SCPE_CSUM; } - else if ((val & 0760000) == OP_JMP) { /* JMP? */ - PC = fld | (val & DAMASK); - break; } - else return SCPE_FMT; /* bad instr */ - } -return SCPE_OK; /* done */ -} - -t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag) -{ -t_stat sta; -int32 fld; - -if (flag != 0) return SCPE_ARG; -if (cptr) { - fld = get_uint (cptr, 8, AMASK, &sta); - if (sta != SCPE_OK) return sta; - fld = fld & EPCMASK; } -else fld = 0; -sta = rim_load (fileref, fld); -if (sta != SCPE_OK) return sta; -if ((sim_switches & SWMASK ('B')) || match_ext (fnam, "BIN")) - return blk_load (fileref, fld); -return SCPE_OK; -} - -/* 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/PDP10/pdp10_cpu.c b/PDP10/pdp10_cpu.c deleted file mode 100644 index 7ee895d8..00000000 --- a/PDP10/pdp10_cpu.c +++ /dev/null @@ -1,2102 +0,0 @@ -/* pdp10_cpu.c: PDP-10 CPU simulator - - 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. - - cpu KS10 central processor - - 08-Oct-02 RMS Revised to build dib_tab dynamically - Added SHOW IOSPACE - 30-Dec-01 RMS Added old PC queue - 25-Dec-01 RMS Cleaned up sim_inst declarations - 07-Dec-01 RMS Revised to use new breakpoint package - 21-Nov-01 RMS Implemented ITS 1-proceed hack - 31-Aug-01 RMS Changed int64 to t_int64 for Windoze - 10-Aug-01 RMS Removed register in declarations - 17-Jul-01 RMS Moved function prototype - 19-May-01 RMS Added workaround for TOPS-20 V4.1 boot bug - 29-Apr-01 RMS Fixed modifier naming conflict - Fixed XCTR/XCTRI, UMOVE/UMOVEM, BLTUB/BLTBU for ITS - Added CLRCSH for ITS - - The 36b system family had six different implementions: PDP-6, KA10, KI10, - L10, KL10 extended, and KS10. This simulator implements the KS10. - - The register state for the KS10 is: - - AC[8][16] accumulators - PC program counter - flags<0:11> state flags - pi_enb<1:7> enabled PI levels - pi_act<1:7> active PI levels - pi_prq<1:7> program PI requests - apr_enb<0:7> enabled system flags - apr_flg<0:7> system flags - ebr executive base register - ubr user base register - hsb halt status block address - spt SPT base - cst CST base - pur process use register - cstm CST mask - - The PDP-10 had just two instruction formats: memory reference - and I/O. - - 000000000 0111 1 1111 112222222222333333 - 012345678 9012 3 4567 890123456789012345 - +---------+----+-+----+------------------+ - | opcode | ac |i| idx| address | memory reference - +---------+----+-+----+------------------+ - - 000 0000000 111 1 1111 112222222222333333 - 012 3456789 012 3 4567 890123456789012345 - +---+-------+---+-+----+------------------+ - |111|device |iop|i| idx| address | I/O - +---+-------+---+-+----+------------------+ -*/ - -/* This routine is the instruction decode routine for the PDP-10. - It is called from the simulator control program to execute - instructions in simulated memory, starting at the simulated PC. - It runs until an abort occurs. - - General notes: - - 1. Reasons to stop. The simulator can be stopped by: - - HALT instruction - MUUO instruction in executive mode - pager error in interrupt sequence - invalid vector table in interrupt sequence - illegal instruction in interrupt sequence - breakpoint encountered - nested indirects exceeding limit - nested XCT's exceeding limit - I/O error in I/O simulator - - 2. Interrupts. PDP-10's have a seven level priority interrupt - system. Interrupt requests can come from internal sources, - such as APR program requests, or external sources, such as - I/O devices. The requests are stored in pi_prq for program - requests, pi_apr for other internal flags, and pi_ioq for - I/O device flags. Internal and device (but not program) - interrupts must be enabled on a level by level basis. When - an interrupt is granted on a level, interrupts at that level - and below are masked until the interrupt is dismissed. - - The I/O device interrupt system is taken from the PDP-11. - int_req stores the interrupt requests for Unibus I/O devices. - Routines in the Unibus adapter map requests in int_req to - PDP-10 levels. The Unibus adapter also calculates which - device to get a vector from when a PDP-10 interrupt is granted. - - 3. Arithmetic. The PDP-10 is a 2's complement system. - - 4. Adding I/O devices. These modules must be modified: - - pdp10_defs.h add device address and interrupt definitions - pdp10_sys.c add sim_devices table entry - - A note on ITS 1-proceed. The simulator follows the implementation - on the KS10, keeping 1-proceed as a side flag (its_1pr) rather than - as flags<8>. This simplifies the flag saving instructions, which - don't have to clear flags<8> before saving it. Instead, the page - fail and interrupt code must restore flags<8> from its_1pr. Unlike - the KS10, the simulator will not lose the 1-proceed trap if the - 1-proceeded instructions clears 1-proceed. -*/ - -#include "pdp10_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] = PC -#define UNIT_V_MSIZE (UNIT_V_T20V41 + 1) /* dummy mask */ -#define UNIT_MSIZE (1 << UNIT_V_MSIZE) - -d10 *M = NULL; /* memory */ -d10 acs[AC_NBLK * AC_NUM] = { 0 }; /* AC blocks */ -d10 *ac_cur, *ac_prv; /* AC cur, prv (dyn) */ -a10 epta, upta; /* proc tbl addr (dyn) */ -a10 saved_PC = 0; /* scp: saved PC */ -d10 pager_word = 0; /* pager: error word */ -a10 pager_PC = 0; /* pager: saved PC */ -int32 pager_flags = 0; /* pager: trap flags */ -t_bool pager_pi = FALSE; /* pager: in pi seq */ -t_bool pager_tc = FALSE; /* pager: trap cycle */ -d10 ebr = 0; /* exec base reg */ -d10 ubr = 0; /* user base reg */ -d10 hsb = 0; /* halt status block */ -d10 spt = 0; /* TOPS20 paging regs */ -d10 cst = 0; -d10 pur = 0; -d10 cstm = 0; -a10 dbr1 = 0; /* ITS paging regs */ -a10 dbr2 = 0; -a10 dbr3 = 0; -a10 dbr4 = 0; -d10 pcst = 0; /* ITS PC sampling */ -int32 pi_on = 0; /* pi system enable */ -int32 pi_enb = 0; /* pi enabled levels */ -int32 pi_act = 0; /* pi active levels */ -int32 pi_ioq = 0; /* pi io requests */ -int32 pi_apr = 0; /* pi apr requests */ -int32 pi_prq = 0; /* pi prog requests */ -int32 apr_enb = 0; /* apr enables */ -int32 apr_flg = 0; /* apr flags */ -int32 apr_lvl = 0; /* apr level */ -int32 qintr = 0; /* interrupt pending */ -int32 flags = 0; /* flags */ -int32 its_1pr = 0; /* ITS 1-proceed */ -int32 stop_op0 = 0; /* stop on 0 */ -int32 rlog = 0; /* extend fixup log */ -int32 ind_max = 32; /* nested ind limit */ -int32 xct_max = 32; /* nested XCT limit */ -a10 pcq[PCQ_SIZE] = { 0 }; /* PC queue */ -int32 pcq_p = 0; /* PC queue ptr */ -REG *pcq_r = NULL; /* PC queue reg ptr */ -jmp_buf save_env; - -extern int32 sim_int_char; -extern int32 sim_interval; -extern int32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */ -extern UNIT tim_unit; - -/* Forward and external declarations */ - -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); -d10 adjsp (d10 val, a10 ea); -void ibp (a10 ea, int32 pflgs); -d10 ldb (a10 ea, int32 pflgs); -void dpb (d10 val, a10 ea, int32 pflgs); -void adjbp (int32 ac, a10 ea, int32 pflgs); -d10 add (d10 val, d10 mb); -d10 sub (d10 val, d10 mb); -void dadd (int32 ac, d10 *rs); -void dsub (int32 ac, d10 *rs); -int32 jffo (d10 val); -d10 lsh (d10 val, a10 ea); -d10 rot (d10 val, a10 ea); -d10 ash (d10 val, a10 ea); -void lshc (int32 ac, a10 ea); -void rotc (int32 ac, a10 ea); -void ashc (int32 ac, a10 ea); -void circ (int32 ac, a10 ea); -void blt (int32 ac, a10 ea, int32 pflgs); -void bltu (int32 ac, a10 ea, int32 pflgs, int dir); -a10 calc_ea (d10 inst, int32 prv); -a10 calc_ioea (d10 inst, int32 prv); -d10 calc_jrstfea (d10 inst, int32 pflgs); -void pi_dismiss (void); -void set_newflags (d10 fl, t_bool jrst); -extern t_bool aprid (a10 ea, int32 prv); -t_bool wrpi (a10 ea, int32 prv); -t_bool rdpi (a10 ea, int32 prv); -t_bool czpi (a10 ea, int32 prv); -t_bool copi (a10 ea, int32 prv); -t_bool wrapr (a10 ea, int32 prv); -t_bool rdapr (a10 ea, int32 prv); -t_bool czapr (a10 ea, int32 prv); -t_bool coapr (a10 ea, int32 prv); -int32 pi_eval (void); -int32 test_int (void); -void set_ac_display (d10 *acbase); - -extern t_stat build_dib_tab (void); -extern t_stat show_iospace (FILE *st, UNIT *uptr, int32 val, void *desc); -extern d10 Read (a10 ea, int32 prv); /* read, read check */ -extern d10 ReadM (a10 ea, int32 prv); /* read, write check */ -extern d10 ReadE (a10 ea); /* read, exec */ -extern d10 ReadP (a10 ea); /* read, physical */ -extern void Write (a10 ea, d10 val, int32 prv); /* write */ -extern void WriteE (a10 ea, d10 val); /* write, exec */ -extern void WriteP (a10 ea, d10 val); /* write, physical */ -extern t_bool AccViol (a10 ea, int32 prv, int32 mode); /* access check */ -extern void set_dyn_ptrs (void); -extern a10 conmap (a10 ea, int32 mode, int32 sw); -extern void fe_intr (); -extern void dfad (int32 ac, d10 *rs, int32 inv); -extern void dfmp (int32 ac, d10 *rs); -extern void dfdv (int32 ac, d10 *rs); -extern void dmul (int32 ac, d10 *rs); -extern void ddiv (int32 ac, d10 *rs); -extern void fix (int32 ac, d10 mb, t_bool rnd); -extern d10 fad (d10 val, d10 mb, t_bool rnd, int32 inv); -extern d10 fmp (d10 val, d10 mb, t_bool rnd); -extern t_bool fdv (d10 val, d10 mb, d10 *rs, t_bool rnd); -extern d10 fsc (d10 val, a10 ea); -extern d10 fltr (d10 mb); -extern int xtend (int32 ac, a10 ea, int32 pflgs); -extern void xtcln (int32 rlog); -extern d10 map (a10 ea, int32 prv); -extern d10 imul (d10 val, d10 mb); -extern t_bool idiv (d10 val, d10 mb, d10 *rs); -extern void mul (d10 val, d10 mb, d10 *rs); -extern t_bool divi (int32 ac, d10 mb, d10 *rs); -extern t_bool io710 (int32 ac, a10 ea); -extern t_bool io711 (int32 ac, a10 ea); -extern d10 io712 (a10 ea); -extern void io713 (d10 val, a10 ea); -extern void io714 (d10 val, a10 ea); -extern void io715 (d10 val, a10 ea); -extern t_bool io720 (int32 ac, a10 ea); -extern t_bool io721 (int32 ac, a10 ea); -extern d10 io722 (a10 ea); -extern void io723 (d10 val, a10 ea); -extern void io724 (d10 val, a10 ea); -extern void io725 (d10 val, a10 ea); -extern t_bool clrcsh (a10 ea, int32 prv); -extern t_bool clrpt (a10 ea, int32 prv); -extern t_bool wrubr (a10 ea, int32 prv); -extern t_bool wrebr (a10 ea, int32 prv); -extern t_bool wrhsb (a10 ea, int32 prv); -extern t_bool wrspb (a10 ea, int32 prv); -extern t_bool wrcsb (a10 ea, int32 prv); -extern t_bool wrpur (a10 ea, int32 prv); -extern t_bool wrcstm (a10 ea, int32 prv); -extern t_bool ldbr1 (a10 ea, int32 prv); -extern t_bool ldbr2 (a10 ea, int32 prv); -extern t_bool ldbr3 (a10 ea, int32 prv); -extern t_bool ldbr4 (a10 ea, int32 prv); -extern t_bool rdubr (a10 ea, int32 prv); -extern t_bool rdebr (a10 ea, int32 prv); -extern t_bool rdhsb (a10 ea, int32 prv); -extern t_bool rdspb (a10 ea, int32 prv); -extern t_bool rdcsb (a10 ea, int32 prv); -extern t_bool rdpur (a10 ea, int32 prv); -extern t_bool rdcstm (a10 ea, int32 prv); -extern t_bool sdbr1 (a10 ea, int32 prv); -extern t_bool sdbr2 (a10 ea, int32 prv); -extern t_bool sdbr3 (a10 ea, int32 prv); -extern t_bool sdbr4 (a10 ea, int32 prv); -extern t_bool rdtim (a10 ea, int32 prv); -extern t_bool rdint (a10 ea, int32 prv); -extern t_bool wrtim (a10 ea, int32 prv); -extern t_bool wrint (a10 ea, int32 prv); -extern t_bool rdpcst (a10 ea, int32 prv); -extern t_bool wrpcst (a10 ea, int32 prv); -extern t_bool spm (a10 ea, int32 prv); -extern t_bool lpmr (a10 ea, int32 prv); -extern int32 pi_ub_vec (int32 lvl, int32 *uba); - -/* 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, MAXMEMSIZE) }; - -REG cpu_reg[] = { - { ORDATA (PC, saved_PC, VASIZE) }, - { ORDATA (FLAGS, flags, 18) }, - { ORDATA (AC0, acs[0], 36) }, /* addr in memory */ - { ORDATA (AC1, acs[1], 36) }, /* modified at exit */ - { ORDATA (AC2, acs[2], 36) }, /* to SCP */ - { ORDATA (AC3, acs[3], 36) }, - { ORDATA (AC4, acs[4], 36) }, - { ORDATA (AC5, acs[5], 36) }, - { ORDATA (AC6, acs[6], 36) }, - { ORDATA (AC7, acs[7], 36) }, - { ORDATA (AC10, acs[10], 36) }, - { ORDATA (AC11, acs[11], 36) }, - { ORDATA (AC12, acs[12], 36) }, - { ORDATA (AC13, acs[13], 36) }, - { ORDATA (AC14, acs[14], 36) }, - { ORDATA (AC15, acs[15], 36) }, - { ORDATA (AC16, acs[16], 36) }, - { ORDATA (AC17, acs[17], 36) }, - { ORDATA (PFW, pager_word, 36) }, - { ORDATA (EBR, ebr, EBR_N_EBR) }, - { FLDATA (PGON, ebr, EBR_V_PGON) }, - { FLDATA (T20P, ebr, EBR_V_T20P) }, - { ORDATA (UBR, ubr, 36) }, - { GRDATA (CURAC, ubr, 8, 3, UBR_V_CURAC), REG_RO }, - { GRDATA (PRVAC, ubr, 8, 3, UBR_V_PRVAC) }, - { ORDATA (SPT, spt, 36) }, - { ORDATA (CST, cst, 36) }, - { ORDATA (PUR, pur, 36) }, - { ORDATA (CSTM, cstm, 36) }, - { ORDATA (HSB, hsb, 36) }, - { ORDATA (DBR1, dbr1, PASIZE) }, - { ORDATA (DBR2, dbr2, PASIZE) }, - { ORDATA (DBR3, dbr3, PASIZE) }, - { ORDATA (DBR4, dbr4, PASIZE) }, - { ORDATA (PCST, pcst, 36) }, - { ORDATA (PIENB, pi_enb, 7) }, - { FLDATA (PION, pi_on, 0) }, - { ORDATA (PIACT, pi_act, 7) }, - { ORDATA (PIPRQ, pi_prq, 7) }, - { ORDATA (PIIOQ, pi_ioq, 7), REG_RO }, - { ORDATA (PIAPR, pi_apr, 7), REG_RO }, - { ORDATA (APRENB, apr_enb, 8) }, - { ORDATA (APRFLG, apr_flg, 8) }, - { ORDATA (APRLVL, apr_lvl, 3) }, - { ORDATA (RLOG, rlog, 10) }, - { FLDATA (F1PR, its_1pr, 0) }, - { BRDATA (PCQ, pcq, 8, VASIZE, PCQ_SIZE), REG_RO+REG_CIRC }, - { ORDATA (PCQP, pcq_p, 6), REG_HRO }, - { DRDATA (INDMAX, ind_max, 8), PV_LEFT + REG_NZ }, - { DRDATA (XCTMAX, xct_max, 8), PV_LEFT + REG_NZ }, - { ORDATA (WRU, sim_int_char, 8) }, - { FLDATA (STOP_ILL, stop_op0, 0) }, - { BRDATA (REG, acs, 8, 36, AC_NUM * AC_NBLK) }, - { NULL } }; - -MTAB cpu_mod[] = { - { UNIT_ITS+UNIT_T20V41, 0, "Standard microcode", "STANDARD", NULL }, - { UNIT_ITS+UNIT_T20V41, UNIT_T20V41, "TOPS-20 V4.1", "TOPS20V41", NULL }, - { UNIT_ITS+UNIT_T20V41, UNIT_ITS, "ITS microcode", "ITS", NULL }, - { MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, "IOSPACE", NULL, - NULL, &show_iospace }, - { 0 } }; - -DEVICE cpu_dev = { - "CPU", &cpu_unit, cpu_reg, cpu_mod, - 1, 8, PASIZE, 1, 8, 36, - &cpu_ex, &cpu_dep, &cpu_reset, - NULL, NULL, NULL }; - -/* Data arrays */ - -const int32 pi_l2bit[8] = { - 0, 0100, 0040, 0020, 0010, 0004, 0002, 0001 }; - -const int32 pi_m2lvl[128] = { - 0, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; - -const d10 bytemask[64] = { 0, - 01, 03, 07, 017, 037, 077, - 0177, 0377, 0777, 01777, 03777, 07777, - 017777, 037777, 077777, - 0177777, 0377777, 0777777, - 01777777, 03777777, 07777777, - 017777777, 037777777, 077777777, - 0177777777, 0377777777, 0777777777, - 01777777777, 03777777777, 07777777777, - 017777777777, 037777777777, 077777777777, - 0177777777777, 0377777777777, 0777777777777, - ONES, ONES, ONES, ONES, ONES, ONES, ONES, ONES, ONES, - ONES, ONES, ONES, ONES, ONES, ONES, ONES, ONES, ONES, - ONES, ONES, ONES, ONES, ONES, ONES, ONES, ONES, ONES }; - -static t_bool (*io700d[16])() = { - &aprid, NULL, NULL, NULL, &wrapr, &rdapr, &czapr, &coapr, - NULL, NULL, NULL, NULL, &wrpi, &rdpi, &czpi, &copi }; -static t_bool (*io701d[16])() = { - NULL, &rdubr, &clrpt, &wrubr, &wrebr, &rdebr, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; -static t_bool (*io702d[16])() = { - &rdspb, &rdcsb, &rdpur, &rdcstm, &rdtim, &rdint, &rdhsb, NULL, - &wrspb, &wrcsb, &wrpur, &wrcstm, &wrtim, &wrint, &wrhsb, NULL }; -#define io700i io700d -static t_bool (*io701i[16])() = { - &clrcsh, &rdubr, &clrpt, &wrubr, &wrebr, &rdebr, NULL, NULL, - NULL, &rdpcst, NULL, &wrpcst, NULL, NULL, NULL, NULL }; -static t_bool (*io702i[16])() = { - &sdbr1, &sdbr2, &sdbr3, &sdbr4, &rdtim, &rdint, &rdhsb, &spm, - &ldbr1, &ldbr2, &ldbr3, &ldbr4, &wrtim, &wrint, &wrhsb, &lpmr }; - -/* JRST classes and validation table */ - -#define JRST_U 1 /* ok anywhere */ -#define JRST_E 2 /* ok exec mode */ -#define JRST_UIO 3 /* ok user I/O mode */ - -static t_stat jrst_tab[16] = { - JRST_U, JRST_U, JRST_U, 0, JRST_E, JRST_U, JRST_E, JRST_E, - JRST_UIO, 0, JRST_UIO, 0, JRST_E, JRST_U, 0, 0 }; - -/* Address operations */ - -#define IM ((d10) ea) -#define IMS (((d10) ea) << 18) -#define JUMP(x) PCQ_ENTRY, PC = ((a10) (x)) & AMASK -#define SUBJ(x) CLRF (F_AFI | F_FPD | F_TR); JUMP (x) -#define INCPC PC = INCA (PC) - -/* AC operations */ - -#define AOBAC AC(ac) = AOB (AC(ac)) -#define SOBAC AC(ac) = SOB (AC(ac)) -#define G2AC rs[0] = AC(ac), rs[1] = AC(P1) -#define S1AC AC(ac) = rs[0] -#define S2AC S1AC, AC(P1) = rs[1] -#define LAC if (ac) AC(ac) = mb - -/* Memory operations */ - -#define RD mb = Read (ea, MM_OPND) -#define RDAC AC(ac) = Read (ea, MM_OPND) -#define RM mb = ReadM (ea, MM_OPND) -#define RMAC AC(ac) = ReadM (ea, MM_OPND) -#define RDP mb = Read (((a10) AC(ac)) & AMASK, MM_BSTK) -#define RD2 rs[0] = Read (ea, MM_OPND); \ - rs[1] = Read (INCA (ea), MM_OPND) -#define WR Write (ea, mb, MM_OPND) -#define WRAC Write (ea, AC(ac), MM_OPND) -#define WRP(x) Write (((a10) INCA (AC(ac))), (x), MM_BSTK) -#define WR1 Write (ea, rs[0], MM_OPND) -#define WR2 ReadM (INCA (ea), MM_OPND); \ - Write (ea, rs[0], MM_OPND); \ - Write (INCA (ea), rs[1], MM_OPND) - -/* Tests and compares */ - -#define TL(a) (TSTS (a) != 0) -#define TE(a) ((a) == 0) -#define TLE(a) (TL (a) || TE (a)) -#define TGE(a) (TSTS (a) == 0) -#define TN(a) ((a) != 0) -#define TG(a) (TGE (a) && TN (a)) -#define CL(a) ((TSTS (AC(ac) ^ a))? (a < AC(ac)): (AC(ac) < a)) -#define CE(a) (AC(ac) == a) -#define CLE(a) (CL (a) || CE (a)) -#define CGE(a) (!CL (a)) -#define CN(a) (AC(ac) != a) -#define CG(a) (CGE (a) && CN (a)) - -/* Word assemblies */ - -#define FLPC XWD (flags, PC) -#define UUOWORD (((d10) op) << INST_V_OP) | (((d10) ac) << INST_V_AC) | ea -#define APRHWORD ((apr_flg << APR_V_FLG) | (apr_lvl & APR_M_LVL) | \ - ((apr_flg & apr_enb)? APR_IRQ: 0)) -#define APRWORD ((apr_enb << (APR_V_FLG + 18)) | APRHWORD) -#define PIHWORD ((pi_act << PI_V_ACT) | (pi_on << PI_V_ON) | \ - (pi_enb << PI_V_ENB)) -#define PIWORD ((pi_prq << PI_V_PRQ) | PIHWORD) - -/* Instruction operations */ - -#define CIBP if (!TSTF (F_FPD)) { ibp (ea, pflgs); SETF (F_FPD); } -#define LDB AC(ac) = ldb (ea, pflgs) -#define DPB dpb (AC(ac), ea, pflgs) -#define FAD(s) fad (AC(ac), s, FALSE, 0) -#define FADR(s) fad (AC(ac), s, TRUE, 0) -#define FSB(s) fad (AC(ac), s, FALSE, 1) -#define FSBR(s) fad (AC(ac), s, TRUE, 1) -#define FMP(s) fmp (AC(ac), s, FALSE) -#define FMPR(s) fmp (AC(ac), s, TRUE) -#define FDV(s) fdv (AC(ac), s, rs, FALSE) -#define FDVR(s) fdv (AC(ac), s, rs, TRUE) -#define MOVN(s) NEG (s); MOVNF(s) -#define MOVM(s) ABS (s); MOVMF(s) -#define ADD(s) add (AC(ac), s) -#define SUB(s) sub (AC(ac), s) -#define IMUL(s) imul (AC(ac), s) -#define IDIV(s) idiv (AC(ac), s, rs) -#define MUL(s) mul (AC(ac), s, rs) -#define DIV(s) divi (ac, s, rs) -#define AOJ AC(ac) = INC (AC(ac)); INCF (AC(ac)) -#define AOS RM; mb = INC (mb); WR; INCF (mb); LAC -#define SOJ AC(ac) = DEC (AC(ac)); DECF (AC(ac)) -#define SOS RM; mb = DEC (mb); WR; DECF (mb); LAC -#define SETCA(s) ~AC(ac) & DMASK -#define SETCM(s) ~(s) & DMASK; -#define AND(s) AC(ac) & (s) -#define ANDCA(s) ~AC(ac) & (s) -#define ANDCM(s) AC(ac) & ~(s) -#define ANDCB(s) (~AC(ac) & ~(s)) & DMASK -#define IOR(s) AC(ac) | (s) -#define ORCA(s) (~AC(ac) | (s)) & DMASK -#define ORCM(s) (AC(ac) | ~(s)) & DMASK -#define ORCB(s) (~AC(ac) | ~(s)) & DMASK -#define XOR(s) AC(ac) ^ (s) -#define EQV(s) (~(AC(ac) ^ (s))) & DMASK -#define LL(s,d) ((s) & LMASK) | ((d) & RMASK) -#define RL(s,d) (((s) << 18) & LMASK) | ((d) & RMASK) -#define RR(s,d) ((s) & RMASK) | ((d) & LMASK) -#define LR(s,d) (((s) >> 18) & RMASK) | ((d) & LMASK) -#define LLO(s) ((s) & LMASK) | RMASK -#define RLO(s) (((s) << 18) & LMASK) | RMASK -#define RRO(s) ((s) & RMASK) | LMASK -#define LRO(s) (((s) >> 18) & RMASK) | LMASK -#define LLE(s) ((s) & LMASK) | (((s) & LSIGN)? RMASK: 0) -#define RLE(s) (((s) << 18) & LMASK) | (((s) & RSIGN)? RMASK: 0) -#define RRE(s) ((s) & RMASK) | (((s) & RSIGN)? LMASK: 0) -#define LRE(s) (((s) >> 18) & RMASK) | (((s) & LSIGN)? LMASK: 0) -#define TD_ RD -#define TS_ RD; mb = SWP (mb) -#define TL_ mb = IMS -#define TR_ mb = IM -#define T_Z AC(ac) = AC(ac) & ~mb -#define T_O AC(ac) = AC(ac) | mb -#define T_C AC(ac) = AC(ac) ^ mb -#define T__E if ((AC(ac) & mb) == 0) INCPC -#define T__N if ((AC(ac) & mb) != 0) INCPC -#define T__A INCPC -#define IOC if (TSTF (F_USR) && !TSTF (F_UIO)) goto MUUO; -#define IO7(x,y) IOC; fptr = ((ITS)? x[ac]: y[ac]); \ - if (fptr == NULL) goto MUUO; \ - if (fptr (ea, MM_OPND)) INCPC; break; -#define IOA IOC; if (!ITS) ea = calc_ioea (inst, pflgs) -#define IOAM IOC; ea = ((ITS)? ((a10) Read (ea, MM_OPND)): \ - calc_ioea (inst, pflgs)) - -/* Flag tests */ - -#define MOVNF(x) if ((x) == MAXNEG) SETF (F_C1 | F_AOV | F_T1); \ - else if ((x) == 0) SETF (F_C0 | F_C1) -#define MOVMF(x) if ((x) == MAXNEG) SETF (F_C1 | F_AOV | F_T1) -#define INCF(x) if ((x) == 0) SETF (F_C0 | F_C1); \ - else if ((x) == MAXNEG) SETF (F_C1 | F_AOV | F_T1) -#define DECF(x) if ((x) == MAXPOS) SETF (F_C0 | F_AOV | F_T1); \ - else if ((x) != ONES) SETF (F_C0 | F_C1) -#define PUSHF if (LRZ (AC(ac)) == 0) SETF (F_T2) -#define POPF if (LRZ (AC(ac)) == RMASK) SETF (F_T2) -#define DMOVNF if (rs[1] == 0) { MOVNF (rs[0]); } - -t_stat sim_instr (void) -{ -a10 PC; /* set by setjmp */ -int abortval = 0; /* abort value */ -t_stat r; - -/* Restore register state */ - -if ((r = build_dib_tab ()) != SCPE_OK) return r; /* build, chk dib_tab */ -pager_PC = PC = saved_PC & AMASK; /* load local PC */ -set_dyn_ptrs (); /* set up local ptrs */ -pager_tc = FALSE; /* not in trap cycle */ -pager_pi = FALSE; /* not in pi sequence */ -rlog = 0; /* not in extend */ -pi_eval (); /* eval pi system */ -sim_rtc_init (tim_unit.wait); /* init calibration */ -if (!ITS) its_1pr = 0; /* ~ITS, clr 1-proc */ - -/* Abort handling - - Aborts may come from within the simulator to stop simulation (values > 0), - for page fails (values < 0), or for an interrupt check (value = 0). -*/ - -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 */ - 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 */ - return abortval; } /* return to SCP */ - -/* Page fail - checked against KS10 ucode - All state variables MUST be declared global for GCC optimization to work -*/ - -else if (abortval == PAGE_FAIL) { /* page fail */ - d10 mb; - if (rlog) xtcln (rlog); /* clean up extend */ - 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)); } - JUMP (mb); /* set new PC */ - set_newflags (mb, FALSE); /* set new flags */ - pi_eval (); } /* eval pi system */ -else PC = pager_PC; /* intr, restore PC */ - -/* Main instruction fetch/decode loop: check clock queue, intr, trap, bkpt */ - -for ( ;; ) { /* loop until ABORT */ -int32 op, ac, i, st, xr, xct_cnt, its_2pr, pflgs; -a10 ea; -d10 inst, mb, indrct, rs[2]; -t_bool (*fptr)(); - -pager_PC = PC; /* update pager PC */ -pager_tc = FALSE; /* not in trap cycle */ -pflgs = 0; /* not in PXCT */ -xct_cnt = 0; /* count XCT's */ -if (sim_interval <= 0) { /* check clock queue */ - if (i = sim_process_event ()) ABORT (i); /* error? stop sim */ - pi_eval (); } /* eval pi system */ - -/* PI interrupt (Unibus or system flags). - On the KS10, only JSR and XPCW are allowed as interrupt instructions. - Because of exec mode addressing, and unconditional processing of flags, - they are explicitly emulated here. -*/ - -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); } - 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 */ - 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 */ - 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 */ - else ABORT (STOP_ILLINT); /* invalid instr */ - pi_act = pi_act | pi_l2bit[qintr]; /* set level active */ - pi_eval (); /* eval pi system */ - pager_pi = FALSE; /* end of sequence */ - if (sim_interval) sim_interval--; /* charge for instr */ - continue; } /* end if interrupt */ - -/* Traps fetch and execute an instruction from the current mode process table. - On the KS10, the fetch of the next instruction has started, and a page fail - trap on the instruction fetch takes precedence over the trap. During a trap, - flags are cleared before the execute, but if the execute aborts, they must - be restored. Also, the MUUO processor needs to know whether we are in a - trap sequence. Hence, trap in progress is recorded in pflgs, and the - traps for pager restoration are recorded in pager_flags. -*/ - -if (TSTF (F_T1 | F_T2) && PAGING) { - Read (pager_PC = PC, MM_CUR); /* test fetch */ - 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); - inst = ReadP (ea); /* get trap instr */ - CLRF (F_T1 | F_T2); } /* clear flags */ - -/* Test for instruction breakpoint */ - -else { if (sim_brk_summ && - sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */ - ABORT (STOP_IBKPT); } /* stop simulation */ - -/* Ready (at last) to get an instruction */ - - inst = Read (pager_PC = PC, MM_CUR); /* get instruction */ - INCPC; - sim_interval = sim_interval - 1; } - -its_2pr = its_1pr; /* save 1-proc flag */ - -/* Execute instruction. XCT and PXCT also return here. */ - -XCT: -op = GET_OP (inst); /* get opcode */ -ac = GET_AC (inst); /* get AC */ -for (indrct = inst, i = 0; i < ind_max; i++) { /* calc eff addr */ - ea = GET_ADDR (indrct); - xr = GET_XR (indrct); - if (xr) ea = (ea + ((a10) XR (xr, MM_EA))) & AMASK; - if (TST_IND (indrct)) indrct = Read (ea, MM_EA); - else break; } -if (i >= ind_max) - ABORT (STOP_IND); /* too many ind? stop */ -switch (op) { /* case on opcode */ - -/* UUO's (0000 - 0077) - checked against KS10 ucode */ - -case 0000: if (stop_op0) { ABORT (STOP_ILLEG); } - goto MUUO; -case 0001: /* local UUO's */ -case 0002: -case 0003: -case 0004: -case 0005: -case 0006: -case 0007: -case 0010: -case 0011: -case 0012: -case 0013: -case 0014: -case 0015: -case 0016: -case 0017: -case 0020: -case 0021: -case 0022: -case 0023: -case 0024: -case 0025: -case 0026: -case 0027: -case 0030: -case 0031: -case 0032: -case 0033: -case 0034: -case 0035: -case 0036: -case 0037: - Write (040, UUOWORD, MM_CUR); /* store op, ac, ea */ - inst = Read (041, MM_CUR); /* get new instr */ - goto XCT; -/* case 0040 - 0077: MUUO's, handled by default at end of case */ - -/* Floating point, bytes, multiple precision (0100 - 0177) */ - -/* 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; } - goto MUUO; -case 0103: if (ITS && !TSTF (F_USR)) { /* GFSB (KL), XCTR (ITS) */ - 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 */ -/* case 0106: MUUO /* GFMP (KL)*/ -/* case 0107: MUUO /* GFDV (KL) */ -case 0110: RD2; dfad (ac, rs, 0); break; /* DFAD */ -case 0111: RD2; dfad (ac, rs, 1); break; /* DFSB */ -case 0112: RD2; dfmp (ac, rs); break; /* DFMP */ -case 0113: RD2; dfdv (ac, rs); break; /* DFDV */ -case 0114: RD2; dadd (ac, rs); break; /* DADD */ -case 0115: RD2; dsub (ac, rs); break; /* DSUB */ -case 0116: RD2; dmul (ac, rs); break; /* DMUL */ -case 0117: RD2; ddiv (ac, rs); break; /* DDIV */ -case 0120: RD2; S2AC; break; /* DMOVE */ -case 0121: RD2; DMOVN (rs); S2AC; DMOVNF; break; /* DMOVN */ -case 0122: RD; fix(ac, mb, 0); break; /* FIX */ -case 0123: st = xtend (ac, ea, pflgs); /* EXTEND */ - rlog = 0; switch (st) { /* clear log */ - case XT_SKIP: INCPC; - case XT_NOSK: break; - default: goto MUUO; } - break; -case 0124: G2AC; WR2; break; /* DMOVEM */ -case 0125: G2AC; DMOVN (rs); WR2; DMOVNF; break; /* DMOVNM */ -case 0126: RD; fix (ac, mb, 1); break; /* FIXR */ -case 0127: RD; AC(ac) = fltr (mb); break; /* FLTR */ -/* case 0130: MUUO /* UFA */ -/* case 0131: MUUO /* DFN */ -case 0132: AC(ac) = fsc (AC(ac), ea); break; /* FSC */ -case 0133: if (!ac) ibp (ea, pflgs); /* IBP */ - else adjbp (ac, ea, pflgs); break; -case 0134: CIBP; LDB; CLRF (F_FPD); break; /* ILBP */ -case 0135: LDB; break; /* LDB */ -case 0136: CIBP; DPB; CLRF (F_FPD); break; /* IDBP */ -case 0137: DPB; break; /* DPB */ -case 0140: RD; AC(ac) = FAD (mb); break; /* FAD */ -/* case 0141: MUUO /* FADL */ -case 0142: RM; mb = FAD (mb); WR; break; /* FADM */ -case 0143: RM; AC(ac) = FAD (mb); WRAC; break; /* FADB */ -case 0144: RD; AC(ac) = FADR (mb); break; /* FADR */ -case 0145: AC(ac) = FADR (IMS); break; /* FADRI */ -case 0146: RM; mb = FADR (mb); WR; break; /* FADRM */ -case 0147: RM; AC(ac) = FADR (mb); WRAC; break; /* FADRB */ -case 0150: RD; AC(ac) = FSB (mb); break; /* FSB */ -/* case 0151: MUUO /* FSBL */ -case 0152: RM; mb = FSB (mb); WR; break; /* FSBM */ -case 0153: RM; AC(ac) = FSB (mb); WRAC; break; /* FSBB */ -case 0154: RD; AC(ac) = FSBR (mb); break; /* FSBR */ -case 0155: AC(ac) = FSBR (IMS); break; /* FSBRI */ -case 0156: RM; mb = FSBR (mb); WR; break; /* FSBRM */ -case 0157: RM; AC(ac) = FSBR (mb); WRAC; break; /* FSBRB */ -case 0160: RD; AC(ac) = FMP (mb); break; /* FMP */ -/* case 0161: MUUO /* FMPL */ -case 0162: RM; mb = FMP (mb); WR; break; /* FMPM */ -case 0163: RM; AC(ac) = FMP (mb); WRAC; break; /* FMPB */ -case 0164: RD; AC(ac) = FMPR (mb); break; /* FMPR */ -case 0165: AC(ac) = FMPR (IMS); break; /* FMPRI */ -case 0166: RM; mb = FMPR (mb); WR; break; /* FMPRM */ -case 0167: RM; AC(ac) = FMPR (mb); WRAC; break; /* FMPRB */ -case 0170: RD; if (FDV (mb)) S1AC; break; /* FDV */ -/* case 0171: MUUO /* FDVL */ -case 0172: RM; if (FDV (mb)) WR1; break; /* FDVM */ -case 0173: RM; if (FDV (mb)) { S1AC; WRAC; } break; /* FDVB */ -case 0174: RD; if (FDVR (mb)) S1AC; break; /* FDVR */ -case 0175: if (FDVR (IMS)) S1AC; break; /* FDVRI */ -case 0176: RM; if (FDVR (mb)) WR1; break; /* FDVRM */ -case 0177: RM; if (FDVR (mb)) { S1AC; WRAC; } break; /* FDVRB */ - -/* Move, arithmetic, shift, and jump (0200 - 0277) - - Note that instructions which modify the flags and store a - result in memory must prove the writeability of the result - location before modifying the flags. Also, 0247 and 0257, - if not implemented, are nops, not MUUO's. -*/ - -case 0200: RDAC; break; /* MOVE */ -case 0201: AC(ac) = ea; break; /* MOVEI */ -case 0202: WRAC; break; /* MOVEM */ -case 0203: RM; LAC; break; /* MOVES */ -case 0204: RD; AC(ac) = SWP (mb); break; /* MOVS */ -case 0205: AC(ac) = IMS; break; /* MOVSI */ -case 0206: mb = SWP (AC(ac)); WR; break; /* MOVSM */ -case 0207: RM; mb = SWP (mb); WR; LAC; break; /* MOVSS */ -case 0210: RD; AC(ac) = MOVN (mb); break; /* MOVN */ -case 0211: AC(ac) = MOVN (IM); break; /* MOVNI */ -case 0212: RM; mb = MOVN (AC(ac)); WR; break; /* MOVNM */ -case 0213: RM; mb = MOVN (mb); WR; LAC; break; /* MOVNS */ -case 0214: RD; AC(ac) = MOVM (mb); break; /* MOVM */ -case 0215: AC(ac) = ea; break; /* MOVMI */ -case 0216: RM; mb = MOVM (AC(ac)); WR; break; /* MOVMM */ -case 0217: RM; mb = MOVM (mb); WR; LAC; break; /* MOVMS */ -case 0220: RD; AC(ac) = IMUL (mb); break; /* IMUL */ -case 0221: AC(ac) = IMUL (IM); break; /* IMULI */ -case 0222: RM; mb = IMUL (mb); WR; break; /* IMULM */ -case 0223: RM; AC(ac) = IMUL (mb); WRAC; break; /* IMULB */ -case 0224: RD; MUL (mb); S2AC; break; /* MUL */ -case 0225: MUL (IM); S2AC; break; /* MULI */ -case 0226: RM; MUL (mb); WR1; break; /* MULM */ -case 0227: RM; MUL (mb); WR1; S2AC; break; /* MULB */ -case 0230: RD; if (IDIV (mb)) S2AC; break; /* IDIV */ -case 0231: if (IDIV (IM)) S2AC; break; /* IDIVI */ -case 0232: RM; if (IDIV (mb)) WR1; break; /* IDIVM */ -case 0233: RM; if (IDIV (mb)) { WR1; S2AC; } break; /* IDIVB */ -case 0234: RD; if (DIV (mb)) S2AC; break; /* DIV */ -case 0235: if (DIV (IM)) S2AC; break; /* DIVI */ -case 0236: RM; if (DIV (mb)) WR1; break; /* DIVM */ -case 0237: RM; if (DIV (mb)) { WR1; S2AC; } break; /* DIVB */ -case 0240: AC(ac) = ash (AC(ac), ea); break; /* ASH */ -case 0241: AC(ac) = rot (AC(ac), ea); break; /* ROT */ -case 0242: AC(ac) = lsh (AC(ac), ea); break; /* LSH */ -case 0243: AC(P1) = jffo (AC(ac)); /* JFFO */ - if (AC(ac)) JUMP (ea); break; -case 0244: ashc (ac, ea); break; /* ASHC */ -case 0245: rotc (ac, ea); break; /* ROTC */ -case 0246: lshc (ac, ea); break; /* LSHC */ -case 0247: if (ITS) circ (ac, ea); break; /* (ITS) CIRC */ -case 0250: RM; WRAC; AC(ac) = mb; break; /* EXCH */ -case 0251: blt (ac, ea, pflgs); break; /* BLT */ -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; -case 0256: if (xct_cnt++ >= xct_max) /* XCT */ - ABORT (STOP_XCT); - inst = Read (ea, MM_OPND); - if (ac && !TSTF (F_USR) && !ITS) pflgs = pflgs | ac; - goto XCT; -case 0257: if (ITS) goto MUUO; /* MAP */ - AC(ac) = map (ea, MM_OPND); break; -case 0260: WRP (FLPC); AOBAC; /* PUSHJ */ - SUBJ (ea); PUSHF; break; -case 0261: RD; WRP (mb); AOBAC; PUSHF; break; /* PUSH */ -case 0262: RDP; WR; SOBAC; POPF; break; /* POP */ -case 0263: RDP; JUMP (mb); SOBAC; POPF; break; /* POPJ */ -case 0264: Write (ea, FLPC, MM_OPND); /* JSR */ - SUBJ (INCR (ea)); break; -case 0265: AC(ac) = FLPC; SUBJ (ea); break; /* JSP */ -case 0266: WRAC; AC(ac) = XWD (ea, PC); /* JSA */ - JUMP (INCR (ea)); break; -case 0267: AC(ac) = Read ((a10) LRZ (AC(ac)), MM_OPND); /* JRA */ - JUMP (ea); break; -case 0270: RD; AC(ac) = ADD (mb); break; /* ADD */ -case 0271: AC(ac) = ADD (IM); break; /* ADDI */ -case 0272: RM; mb = ADD (mb); WR; break; /* ADDM */ -case 0273: RM; AC(ac) = ADD (mb); WRAC; break; /* ADDB */ -case 0274: RD; AC(ac) = SUB (mb); break; /* SUB */ -case 0275: AC(ac) = SUB (IM); break; /* SUBI */ -case 0276: RM; mb = SUB (mb); WR; break; /* SUBM */ -case 0277: RM; AC(ac) = SUB (mb); WRAC; break; /* SUBB */ - -/* Compare, jump, skip instructions (0300 - 0377) - checked against KS10 ucode */ - -case 0300: break; /* CAI */ -case 0301: if (CL (IM)) INCPC; break; /* CAIL */ -case 0302: if (CE (IM)) INCPC; break; /* CAIE */ -case 0303: if (CLE (IM)) INCPC; break; /* CAILE */ -case 0304: INCPC; break; /* CAIA */ -case 0305: if (CGE (IM)) INCPC; break; /* CAIGE */ -case 0306: if (CN (IM)) INCPC; break; /* CAIN */ -case 0307: if (CG (IM)) INCPC; break; /* CAIG */ -case 0310: RD; break; /* CAM */ -case 0311: RD; if (CL (mb)) INCPC; break; /* CAML */ -case 0312: RD; if (CE (mb)) INCPC; break; /* CAME */ -case 0313: RD; if (CLE (mb)) INCPC; break; /* CAMLE */ -case 0314: RD; INCPC; break; /* CAMA */ -case 0315: RD; if (CGE (mb)) INCPC; break; /* CAMGE */ -case 0316: RD; if (CN (mb)) INCPC; break; /* CAMN */ -case 0317: RD; if (CG (mb)) INCPC; break; /* CAMG */ -case 0320: break; /* JUMP */ -case 0321: if (TL (AC(ac))) JUMP (ea); break; /* JUMPL */ -case 0322: if (TE (AC(ac))) JUMP (ea); break; /* JUMPE */ -case 0323: if (TLE( AC(ac))) JUMP (ea); break; /* JUMPLE */ -case 0324: JUMP (ea); break; /* JUMPA */ -case 0325: if (TGE (AC(ac))) JUMP (ea); break; /* JUMPGE */ -case 0326: if (TN (AC(ac))) JUMP (ea); break; /* JUMPN */ -case 0327: if (TG (AC(ac))) JUMP (ea); break; /* JUMPG */ -case 0330: RD; LAC; break; /* SKIP */ -case 0331: RD; LAC; if (TL (mb)) INCPC; break; /* SKIPL */ -case 0332: RD; LAC; if (TE (mb)) INCPC; break; /* SKIPE */ -case 0333: RD; LAC; if (TLE (mb)) INCPC; break; /* SKIPLE */ -case 0334: RD; LAC; INCPC; break; /* SKIPA */ -case 0335: RD; LAC; if (TGE (mb)) INCPC; break; /* SKIPGE */ -case 0336: RD; LAC; if (TN (mb)) INCPC; break; /* SKIPN */ -case 0337: RD; LAC; if (TG (mb)) INCPC; break; /* SKIPG */ -case 0340: AOJ; break; /* AOJ */ -case 0341: AOJ; if (TL (AC(ac))) JUMP (ea); break; /* AOJL */ -case 0342: AOJ; if (TE (AC(ac))) JUMP (ea); break; /* AOJE */ -case 0343: AOJ; if (TLE (AC(ac))) JUMP (ea); break;/* AOJLE */ -case 0344: AOJ; JUMP(ea); break; /* AOJA */ -case 0345: AOJ; if (TGE (AC(ac))) JUMP (ea); break;/* AOJGE */ -case 0346: AOJ; if (TN (AC(ac))) JUMP (ea); break; /* AOJN */ -case 0347: AOJ; if (TG (AC(ac))) JUMP (ea); break; /* AOJG */ -case 0350: AOS; break; /* AOS */ -case 0351: AOS; if (TL (mb)) INCPC; break; /* AOSL */ -case 0352: AOS; if (TE (mb)) INCPC; break; /* AOSE */ -case 0353: AOS; if (TLE (mb)) INCPC; break; /* AOSLE */ -case 0354: AOS; INCPC; break; /* AOSA */ -case 0355: AOS; if (TGE (mb)) INCPC; break; /* AOSGE */ -case 0356: AOS; if (TN (mb)) INCPC; break; /* AOSN */ -case 0357: AOS; if (TG (mb)) INCPC; break; /* AOSG */ -case 0360: SOJ; break; /* SOJ */ -case 0361: SOJ; if (TL (AC(ac))) JUMP (ea); break; /* SOJL */ -case 0362: SOJ; if (TE (AC(ac))) JUMP (ea); break; /* SOJE */ -case 0363: SOJ; if (TLE (AC(ac))) JUMP (ea); break;/* SOJLE */ -case 0364: SOJ; JUMP(ea); break; /* SOJA */ -case 0365: SOJ; if (TGE (AC(ac))) JUMP (ea); break;/* SOJGE */ -case 0366: SOJ; if (TN (AC(ac))) JUMP (ea); break; /* SOJN */ -case 0367: SOJ; if (TG (AC(ac))) JUMP (ea); break; /* SOJG */ -case 0370: SOS; break; /* SOS */ -case 0371: SOS; if (TL (mb)) INCPC; break; /* SOSL */ -case 0372: SOS; if (TE (mb)) INCPC; break; /* SOSE */ -case 0373: SOS; if (TLE (mb)) INCPC; break; /* SOSLE */ -case 0374: SOS; INCPC; break; /* SOSA */ -case 0375: SOS; if (TGE (mb)) INCPC; break; /* SOSGE */ -case 0376: SOS; if (TN (mb)) INCPC; break; /* SOSN */ -case 0377: SOS; if (TG (mb)) INCPC; break; /* SOSG */ - -/* Boolean instructions (0400 - 0477) - checked against KS10 ucode - - Note that for boolean B, the initial read checks writeability of - the memory operand; hence, it is safe to modify the AC. -*/ - -case 0400: AC(ac) = 0; break; /* SETZ */ -case 0401: AC(ac) = 0; break; /* SETZI */ -case 0402: mb = 0; WR; break; /* SETZM */ -case 0403: mb = 0; WR; AC(ac) = 0; break; /* SETZB */ -case 0404: RD; AC(ac) = AND (mb); break; /* AND */ -case 0405: AC(ac) = AND (IM); break; /* ANDI */ -case 0406: RM; mb = AND (mb); WR; break; /* ANDM */ -case 0407: RM; AC(ac) = AND (mb); WRAC; break; /* ANDB */ -case 0410: RD; AC(ac) = ANDCA (mb); break; /* ANDCA */ -case 0411: AC(ac) = ANDCA (IM); break; /* ANDCAI */ -case 0412: RM; mb = ANDCA (mb); WR; break; /* ANDCAM */ -case 0413: RM; AC(ac) = ANDCA (mb); WRAC; break; /* ANDCAB */ -case 0414: RDAC; break; /* SETM */ -case 0415: AC(ac) = ea; break; /* SETMI */ -case 0416: RM; WR; break; /* SETMM */ -case 0417: RMAC; WRAC; break; /* SETMB */ -case 0420: RD; AC(ac) = ANDCM (mb); break; /* ANDCM */ -case 0421: AC(ac) = ANDCM (IM); break; /* ANDCMI */ -case 0422: RM; mb = ANDCM (mb); WR; break; /* ANDCMM */ -case 0423: RM; AC(ac) = ANDCM (mb); WRAC; break; /* ANDCMB */ -case 0424: break; /* SETA */ -case 0425: break; /* SETAI */ -case 0426: WRAC; break; /* SETAM */ -case 0427: WRAC; break; /* SETAB */ -case 0430: RD; AC(ac) = XOR (mb); break; /* XOR */ -case 0431: AC(ac) = XOR (IM); break; /* XORI */ -case 0432: RM; mb = XOR (mb); WR; break; /* XORM */ -case 0433: RM; AC(ac) = XOR (mb); WRAC; break; /* XORB */ -case 0434: RD; AC(ac) = IOR (mb); break; /* IOR */ -case 0435: AC(ac) = IOR (IM); break; /* IORI */ -case 0436: RM; mb = IOR (mb); WR; break; /* IORM */ -case 0437: RM; AC(ac) = IOR (mb); WRAC; break; /* IORB */ -case 0440: RD; AC(ac) = ANDCB (mb); break; /* ANDCB */ -case 0441: AC(ac) = ANDCB (IM); break; /* ANDCBI */ -case 0442: RM; mb = ANDCB (mb); WR; break; /* ANDCBM */ -case 0443: RM; AC(ac) = ANDCB (mb); WRAC; break; /* ANDCBB */ -case 0444: RD; AC(ac) = EQV (mb); break; /* EQV */ -case 0445: AC(ac) = EQV (IM); break; /* EQVI */ -case 0446: RM; mb = EQV (mb); WR; break; /* EQVM */ -case 0447: RM; AC(ac) = EQV (mb); WRAC; break; /* EQVB */ -case 0450: RD; AC(ac) = SETCA (mb); break; /* SETCA */ -case 0451: AC(ac) = SETCA (IM); break; /* SETCAI */ -case 0452: RM; mb = SETCA (mb); WR; break; /* SETCAM */ -case 0453: RM; AC(ac) = SETCA (mb); WRAC; break; /* SETCAB */ -case 0454: RD; AC(ac) = ORCA (mb); break; /* ORCA */ -case 0455: AC(ac) = ORCA (IM); break; /* ORCAI */ -case 0456: RM; mb = ORCA (mb); WR; break; /* ORCAM */ -case 0457: RM; AC(ac) = ORCA (mb); WRAC; break; /* ORCAB */ -case 0460: RD; AC(ac) = SETCM (mb); break; /* SETCM */ -case 0461: AC(ac) = SETCM (IM); break; /* SETCMI */ -case 0462: RM; mb = SETCM (mb); WR; break; /* SETCMM */ -case 0463: RM; AC(ac) = SETCM (mb); WRAC; break; /* SETCMB */ -case 0464: RD; AC(ac) = ORCM (mb); break; /* ORCM */ -case 0465: AC(ac) = ORCM (IM); break; /* ORCMI */ -case 0466: RM; mb = ORCM (mb); WR; break; /* ORCMM */ -case 0467: RM; AC(ac) = ORCM (mb); WRAC; break; /* ORCMB */ -case 0470: RD; AC(ac) = ORCB (mb); break; /* ORCB */ -case 0471: AC(ac) = ORCB (IM); break; /* ORCBI */ -case 0472: RM; mb = ORCB (mb); WR; break; /* ORCBM */ -case 0473: RM; AC(ac) = ORCB (mb); WRAC; break; /* ORCBB */ -case 0474: AC(ac) = ONES; break; /* SETO */ -case 0475: AC(ac) = ONES; break; /* SETOI */ -case 0476: mb = ONES; WR; break; /* SETOM */ -case 0477: mb = ONES; WR; AC(ac) = ONES; break; /* SETOB */ - -/* Halfword instructions (0500 - 0577) - checked against KS10 ucode */ - -case 0500: RD; AC(ac) = LL (mb, AC(ac)); break; /* HLL */ -case 0501: AC(ac) = LL (IM, AC(ac)); break; /* HLLI */ -case 0502: RM; mb = LL (AC(ac), mb); WR; break; /* HLLM */ -case 0503: RM; mb = LL (mb, mb); WR; LAC; break; /* HLLS */ -case 0504: RD; AC(ac) = RL (mb, AC(ac)); break; /* HRL */ -case 0505: AC(ac) = RL (IM, AC(ac)); break; /* HRLI */ -case 0506: RM; mb = RL (AC(ac), mb); WR; break; /* HRLM */ -case 0507: RM; mb = RL (mb, mb); WR; LAC; break; /* HRLS */ -case 0510: RD; AC(ac) = LLZ (mb); break; /* HLLZ */ -case 0511: AC(ac) = LLZ (IM); break; /* HLLZI */ -case 0512: mb = LLZ (AC(ac)); WR; break; /* HLLZM */ -case 0513: RM; mb = LLZ (mb); WR; LAC; break; /* HLLZS */ -case 0514: RD; AC(ac) = RLZ (mb); break; /* HRLZ */ -case 0515: AC(ac) = RLZ (IM); break; /* HRLZI */ -case 0516: mb = RLZ (AC(ac)); WR; break; /* HRLZM */ -case 0517: RM; mb = RLZ (mb); WR; LAC; break; /* HRLZS */ -case 0520: RD; AC(ac) = LLO (mb); break; /* HLLO */ -case 0521: AC(ac) = LLO (IM); break; /* HLLOI */ -case 0522: mb = LLO (AC(ac)); WR; break; /* HLLOM */ -case 0523: RM; mb = LLO (mb); WR; LAC; break; /* HLLOS */ -case 0524: RD; AC(ac) = RLO (mb); break; /* HRLO */ -case 0525: AC(ac) = RLO (IM); break; /* HRLOI */ -case 0526: mb = RLO (AC(ac)); WR; break; /* HRLOM */ -case 0527: RM; mb = RLO (mb); WR; LAC; break; /* HRLOS */ -case 0530: RD; AC(ac) = LLE (mb); break; /* HLLE */ -case 0531: AC(ac) = LLE (IM); break; /* HLLEI */ -case 0532: mb = LLE (AC(ac)); WR; break; /* HLLEM */ -case 0533: RM; mb = LLE (mb); WR; LAC; break; /* HLLES */ -case 0534: RD; AC(ac) = RLE (mb); break; /* HRLE */ -case 0535: AC(ac) = RLE (IM); break; /* HRLEI */ -case 0536: mb = RLE (AC(ac)); WR; break; /* HRLEM */ -case 0537: RM; mb = RLE (mb); WR; LAC; break; /* HRLES */ -case 0540: RD; AC(ac) = RR (mb, AC(ac)); break; /* HRR */ -case 0541: AC(ac) = RR (IM, AC(ac)); break; /* HRRI */ -case 0542: RM; mb = RR (AC(ac), mb); WR; break; /* HRRM */ -case 0543: RM; mb = RR (mb, mb); WR; LAC; break; /* HRRS */ -case 0544: RD; AC(ac) = LR (mb, AC(ac)); break; /* HLR */ -case 0545: AC(ac) = LR (IM, AC(ac)); break; /* HLRI */ -case 0546: RM; mb = LR (AC(ac), mb); WR; break; /* HLRM */ -case 0547: RM; mb = LR (mb, mb); WR; LAC; break; /* HLRS */ -case 0550: RD; AC(ac) = RRZ (mb); break; /* HRRZ */ -case 0551: AC(ac) = RRZ (IM); break; /* HRRZI */ -case 0552: mb = RRZ (AC(ac)); WR; break; /* HRRZM */ -case 0553: RM; mb = RRZ(mb); WR; LAC; break; /* HRRZS */ -case 0554: RD; AC(ac) = LRZ (mb); break; /* HLRZ */ -case 0555: AC(ac) = LRZ (IM); break; /* HLRZI */ -case 0556: mb = LRZ (AC(ac)); WR; break; /* HLRZM */ -case 0557: RM; mb = LRZ (mb); WR; LAC; break; /* HLRZS */ -case 0560: RD; AC(ac) = RRO (mb); break; /* HRRO */ -case 0561: AC(ac) = RRO (IM); break; /* HRROI */ -case 0562: mb = RRO (AC(ac)); WR; break; /* HRROM */ -case 0563: RM; mb = RRO (mb); WR; LAC; break; /* HRROS */ -case 0564: RD; AC(ac) = LRO (mb); break; /* HLRO */ -case 0565: AC(ac) = LRO (IM); break; /* HLROI */ -case 0566: mb = LRO (AC(ac)); WR; break; /* HLROM */ -case 0567: RM; mb = LRO (mb); WR; LAC; break; /* HLROS */ -case 0570: RD; AC(ac) = RRE (mb); break; /* HRRE */ -case 0571: AC(ac) = RRE (IM); break; /* HRREI */ -case 0572: mb = RRE (AC(ac)); WR; break; /* HRREM */ -case 0573: RM; mb = RRE (mb); WR; LAC; break; /* HRRES */ -case 0574: RD; AC(ac) = LRE (mb); break; /* HLRE */ -case 0575: AC(ac) = LRE (IM); break; /* HLREI */ -case 0576: mb = LRE (AC(ac)); WR; break; /* HLREM */ -case 0577: RM; mb = LRE (mb); WR; LAC; break; /* HLRES */ - -/* Test instructions (0600 - 0677) - checked against KS10 ucode - In the KS10 ucode, TDN and TSN do not fetch an operand; the Processor - Reference Manual describes them as NOPs that reference memory. -*/ - -case 0600: break; /* TRN */ -case 0601: break; /* TLN */ -case 0602: TR_; T__E; break; /* TRNE */ -case 0603: TL_; T__E; break; /* TLNE */ -case 0604: T__A; break; /* TRNA */ -case 0605: T__A; break; /* TLNA */ -case 0606: TR_; T__N; break; /* TRNN */ -case 0607: TL_; T__N; break; /* TLNN */ -case 0610: TD_; break; /* TDN */ -case 0611: TS_; break; /* TSN */ -case 0612: TD_; T__E; break; /* TDNE */ -case 0613: TS_; T__E; break; /* TSNE */ -case 0614: TD_; T__A; break; /* TDNA */ -case 0615: TS_; T__A; break; /* TSNA */ -case 0616: TD_; T__N; break; /* TDNN */ -case 0617: TS_; T__N; break; /* TSNN */ -case 0620: TR_; T_Z; break; /* TRZ */ -case 0621: TL_; T_Z; break; /* TLZ */ -case 0622: TR_; T__E; T_Z; break; /* TRZE */ -case 0623: TL_; T__E; T_Z; break; /* TLZE */ -case 0624: TR_; T__A; T_Z; break; /* TRZA */ -case 0625: TL_; T__A; T_Z; break; /* TLZA */ -case 0626: TR_; T__N; T_Z; break; /* TRZN */ -case 0627: TL_; T__N; T_Z; break; /* TLZN */ -case 0630: TD_; T_Z; break; /* TDZ */ -case 0631: TS_; T_Z; break; /* TSZ */ -case 0632: TD_; T__E; T_Z; break; /* TDZE */ -case 0633: TS_; T__E; T_Z; break; /* TSZE */ -case 0634: TD_; T__A; T_Z; break; /* TDZA */ -case 0635: TS_; T__A; T_Z; break; /* TSZA */ -case 0636: TD_; T__N; T_Z; break; /* TDZN */ -case 0637: TS_; T__N; T_Z; break; /* TSZN */ -case 0640: TR_; T_C; break; /* TRC */ -case 0641: TL_; T_C; break; /* TLC */ -case 0642: TR_; T__E; T_C; break; /* TRCE */ -case 0643: TL_; T__E; T_C; break; /* TLCE */ -case 0644: TR_; T__A; T_C; break; /* TRCA */ -case 0645: TL_; T__A; T_C; break; /* TLCA */ -case 0646: TR_; T__N; T_C; break; /* TRCN */ -case 0647: TL_; T__N; T_C; break; /* TLCN */ -case 0650: TD_; T_C; break; /* TDC */ -case 0651: TS_; T_C; break; /* TSC */ -case 0652: TD_; T__E; T_C; break; /* TDCE */ -case 0653: TS_; T__E; T_C; break; /* TSCE */ -case 0654: TD_; T__A; T_C; break; /* TDCA */ -case 0655: TS_; T__A; T_C; break; /* TSCA */ -case 0656: TD_; T__N; T_C; break; /* TDCN */ -case 0657: TS_; T__N; T_C; break; /* TSCN */ -case 0660: TR_; T_O; break; /* TRO */ -case 0661: TL_; T_O; break; /* TLO */ -case 0662: TR_; T__E; T_O; break; /* TROE */ -case 0663: TL_; T__E; T_O; break; /* TLOE */ -case 0664: TR_; T__A; T_O; break; /* TROA */ -case 0665: TL_; T__A; T_O; break; /* TLOA */ -case 0666: TR_; T__N; T_O; break; /* TRON */ -case 0667: TL_; T__N; T_O; break; /* TLON */ -case 0670: TD_; T_O; break; /* TDO */ -case 0671: TS_; T_O; break; /* TSO */ -case 0672: TD_; T__E; T_O; break; /* TDOE */ -case 0673: TS_; T__E; T_O; break; /* TSOE */ -case 0674: TD_; T__A; T_O; break; /* TDOA */ -case 0675: TS_; T__A; T_O; break; /* TSOA */ -case 0676: TD_; T__N; T_O; break; /* TDON */ -case 0677: TS_; T__N; T_O; break; /* TSON */ - -/* I/O instructions (0700 - 0777) - - Only the defined I/O instructions have explicit case labels; - the rest default to unimplemented (monitor UUO). Note that - 710-715 and 720-725 have different definitions under ITS and - use normal effective addresses instead of the special address - calculation required by TOPS-10 and TOPS-20. -*/ - -case 0700: IO7 (io700i, io700d); break; /* I/O 0 */ -case 0701: IO7 (io701i, io701d); break; /* I/O 1 */ -case 0702: IO7 (io702i, io702d); break; /* I/O 2 */ -case 0704: IOC; AC(ac) = Read (ea, OPND_PXCT); break; /* UMOVE */ -case 0705: IOC; Write (ea, AC(ac), OPND_PXCT); break; /* UMOVEM */ -case 0710: IOA; if (io710 (ac, ea)) INCPC; break; /* TIOE, IORDI */ -case 0711: IOA; if (io711 (ac, ea)) INCPC; break; /* TION, IORDQ */ -case 0712: IOAM; AC(ac) = io712 (ea); break; /* RDIO, IORD */ -case 0713: IOAM; io713 (AC(ac), ea); break; /* WRIO, IOWR */ -case 0714: IOA; io714 (AC(ac), ea); break; /* BSIO, IOWRI */ -case 0715: IOA; io715 (AC(ac), ea); break; /* BCIO, IOWRQ */ -case 0716: IOC; bltu (ac, ea, pflgs, 0); break; /* BLTBU */ -case 0717: IOC; bltu (ac, ea, pflgs, 1); break; /* BLTUB */ -case 0720: IOA; if (io720 (ac, ea)) INCPC; break; /* TIOEB, IORDBI */ -case 0721: IOA; if (io721 (ac, ea)) INCPC; break; /* TIONB, IORDBQ */ -case 0722: IOAM; AC(ac) = io722 (ea); break; /* RDIOB, IORDB */ -case 0723: IOAM; io723 (AC(ac), ea); break; /* WRIOB, IOWRB */ -case 0724: IOA; io724 (AC(ac), ea); break; /* BSIOB, IOWRBI */ -case 0725: IOA; io725 (AC(ac), ea); break; /* BCIOB, IOWRBQ */ - -/* If undefined, monitor UUO - checked against KS10 ucode - The KS10 implements a much more limited version of MUUO flag handling. - In the KS10, the trap ucode checks for opcodes 000-077. If the opcode - is in that range, the trap flags are not cleared. Instead, the MUUO - microcode stores the flags with traps cleared, and uses the trap flags - to determine how to vector. Thus, MUUO's >= 100 will vector incorrectly. -*/ - -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 { /* 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 */ - JUMP (mb); /* set new PC */ - if (TSTF (F_USR)) mb = mb | XWD (F_UIO, 0); /* set PCU */ - set_newflags (mb, FALSE); /* set new flags */ - break; - -/* JRST - checked against KS10 ucode - Differences from the KS10: the KS10 - - (JRSTF, JEN) refetches the base instruction from PC - 1 - - (XJEN) dismisses interrupt before reading the new flags and PC - - (XPCW) writes the old flags and PC before reading the new - ITS microcode includes extended JRST's, although they are not used -*/ - -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 */ - switch (ac) { /* case on subopcode */ - case 000: /* JRST 0 = jump */ - case 001: /* JRST 1 = portal */ - 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; - 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; - case 005: /* JRST 5 = XJRSTF */ - 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; - 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; - case 010: /* JRST 10 = dismiss */ - 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; - case 014: /* JRST 14 = SFM */ - 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 */ - 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 */ - } /* end if 2-proc */ -} /* end for */ - -/* Should never get here */ - -ABORT (STOP_UNKNOWN); -} - -/* Single word integer routines */ - -/* Integer add - - Truth table for integer add - - case a b r flags - 1 + + + none - 2 + + - AOV + C1 - 3 + - + C0 + C1 - 4 + - - - - 5 - + + C0 + C1 - 6 - + - - - 7 - - + AOV + C0 - 8 - - - C0 + C1 -*/ - -d10 add (d10 a, d10 b) -{ -d10 r; - -r = (a + b) & DMASK; -if (TSTS (a & b)) { /* cases 7,8 */ - if (TSTS (r)) SETF (F_C0 | F_C1); /* case 8 */ - else SETF (F_C0 | F_AOV | F_T1); /* case 7 */ - return r; } -if (!TSTS (a | b)) { /* cases 1,2 */ - if (TSTS (r)) SETF (F_C1 | F_AOV | F_T1); /* case 2 */ - return r; } /* case 1 */ -if (!TSTS (r)) SETF (F_C0 | F_C1); /* cases 3,5 */ -return r; -} - -/* Integer subtract - actually ac + ~op + 1 */ - -d10 sub (d10 a, d10 b) -{ -d10 r; - -r = (a - b) & DMASK; -if (TSTS (a & ~b)) { /* cases 7,8 */ - if (TSTS (r)) SETF (F_C0 | F_C1); /* case 8 */ - else SETF (F_C0 | F_AOV | F_T1); /* case 7 */ - return r; } -if (!TSTS (a | ~b)) { /* cases 1,2 */ - if (TSTS (r)) SETF (F_C1 | F_AOV | F_T1); /* case 2 */ - return r; } /* case 1 */ -if (!TSTS (r)) SETF (F_C0 | F_C1); /* cases 3,5 */ -return r; -} - - -/* Logical shift */ - -d10 lsh (d10 val, a10 ea) -{ -int32 sc = LIT8 (ea); - -if (sc > 35) return 0; -if (ea & RSIGN) return (val >> sc); -return ((val << sc) & DMASK); -} - -/* Rotate */ - -d10 rot (d10 val, a10 ea) -{ -int32 sc = LIT8 (ea) % 36; - -if (sc == 0) return val; -if (ea & RSIGN) sc = 36 - sc; -return (((val << sc) | (val >> (36 - sc))) & DMASK); -} - -/* Double word integer instructions */ - -/* Double add - see case table for single add */ - -void dadd (int32 ac, d10 *rs) -{ -d10 r; -int32 p1 = ADDAC (ac, 1); - -AC(p1) = CLRS (AC(p1)) + CLRS (rs[1]); /* add lo */ -r = (AC(ac) + rs[0] + (TSTS (AC(p1))? 1: 0)) & DMASK; /* add hi+cry */ -if (TSTS (AC(ac) & rs[0])) { /* cases 7,8 */ - if (TSTS (r)) SETF (F_C0 | F_C1); /* case 8 */ - else SETF (F_C0 | F_AOV | F_T1); } /* case 7 */ -else if (!TSTS (AC(ac) | rs[0])) { /* cases 1,2 */ - if (TSTS (r)) SETF (F_C1 | F_AOV | F_T1); } /* case 2 */ -else if (!TSTS (r)) SETF (F_C0 | F_C1); /* cases 3,5 */ -AC(ac) = r; -AC(p1) = TSTS (r)? SETS (AC(p1)): CLRS (AC(p1)); -return; -} - -/* Double subtract - see comments for single subtract */ - -void dsub (int32 ac, d10 *rs) -{ -d10 r; -int32 p1 = ADDAC (ac, 1); - -AC(p1) = CLRS (AC(p1)) - CLRS (rs[1]); /* sub lo */ -r = (AC(ac) - rs[0] - (TSTS (AC(p1))? 1: 0)) & DMASK; /* sub hi,borrow */ -if (TSTS (AC(ac) & ~rs[0])) { /* cases 7,8 */ - if (TSTS (r)) SETF (F_C0 | F_C1); /* case 8 */ - else SETF (F_C0 | F_AOV | F_T1); } /* case 7 */ -else if (!TSTS (AC(ac) | ~rs[0])) { /* cases 1,2 */ - if (TSTS (r)) SETF (F_C1 | F_AOV | F_T1); } /* case 2 */ -else if (!TSTS (r)) SETF (F_C0 | F_C1); /* cases 3,5 */ -AC(ac) = r; -AC(p1) = (TSTS (r)? SETS (AC(p1)): CLRS (AC(p1))) & DMASK; -return; -} - - -/* Logical shift combined */ - -void lshc (int32 ac, a10 ea) -{ -int32 p1 = ADDAC (ac, 1); -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; } } -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; } } -return; -} - -/* Rotate combined */ - -void rotc (int32 ac, a10 ea) -{ -int32 p1 = ADDAC (ac, 1); -int32 sc = LIT8 (ea) % 72; -d10 t = AC(ac); - -if (sc == 0) return; -if (ea & RSIGN) sc = 72 - sc; -if (sc >= 36) { - AC(ac) = ((AC(p1) << (sc - 36)) | (t >> (72 - sc))) & DMASK; - AC(p1) = ((t << (sc - 36)) | (AC(p1) >> (72 - sc))) & DMASK; } -else { AC(ac) = ((t << sc) | (AC(p1) >> (36 - sc))) & DMASK; - AC(p1) = ((AC(p1) << sc) | (t >> (36 - sc))) & DMASK; } -return; -} - -/* Arithmetic shifts */ - -d10 ash (d10 val, a10 ea) -{ -int32 sc = LIT8 (ea); -d10 sign = TSTS (val); -d10 fill = sign? ONES: 0; -d10 so; - -if (sc == 0) return val; -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 */ -if (so != (sign? bytemask[sc + 1]: 0)) SETF (F_AOV | F_T1); -return (sign | ((val << sc) & MMASK)); -} - -void ashc (int32 ac, a10 ea) -{ -int32 sc = LIT8 (ea); -int32 p1 = ADDAC (ac, 1); -d10 sign = TSTS (AC(ac)); -d10 fill = sign? ONES: 0; -d10 so; - -if (sc == 0) return; -if (sc > 70) sc = 70; /* cap sc at 70 */ -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; } } -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); } } -return; -} - -/* Effective address routines */ - -/* Calculate effective address - used by byte instructions, extended - instructions, and interrupts to get a different mapping context from - the main loop. prv is either EABP_PXCT or MM_CUR. -*/ - -a10 calc_ea (d10 inst, int32 prv) -{ -int32 i, ea, xr; -d10 indrct; - -for (indrct = inst, i = 0; i < ind_max; i++) { - ea = GET_ADDR (indrct); - xr = GET_XR (indrct); - if (xr) ea = (ea + ((a10) XR (xr, prv))) & AMASK; - if (TST_IND (indrct)) indrct = Read (ea, prv); - else break; } -if (i >= ind_max) ABORT (STOP_IND); -return ea; -} - -/* Calculate I/O effective address. Cases: - - No index or indirect, return addr from instruction - - Index only, index >= 0, return 36b sum of addr + index - - Index only, index <= 0, return 18b sum of addr + index - - Indirect, calculate 18b sum of addr + index, return - entire word fetch (single level) -*/ - -a10 calc_ioea (d10 inst, int32 pflgs) -{ -int32 xr; -a10 ea; - -xr = GET_XR (inst); -ea = GET_ADDR (inst); -if (TST_IND (inst)) { /* indirect? */ - if (xr) ea = (ea + ((a10) XR (xr, MM_EA))) & AMASK; - ea = (a10) Read (ea, MM_EA); } -else if (xr) { /* direct + idx? */ - ea = ea + ((a10) XR (xr, MM_EA)); - if (TSTS (XR (xr, MM_EA))) ea = ea & AMASK; } -return ea; -} - -/* Calculate JRSTF effective address. This routine preserves - the left half of the effective address, to be the new flags. -*/ - -d10 calc_jrstfea (d10 inst, int32 pflgs) -{ -int32 i, xr; -d10 mb; - -for (i = 0; i < ind_max; i++) { - mb = inst; - xr = GET_XR (inst); - if (xr) mb = (mb & AMASK) + XR (xr, MM_EA); - if (TST_IND (inst)) inst = Read (((a10) mb) & AMASK, MM_EA); - else break; } -if (i >= ind_max) ABORT (STOP_IND); -return (mb & DMASK); -} - -/* Byte pointer routines */ - -/* Increment byte pointer - checked against KS10 ucode */ - -void ibp (a10 ea, int32 pflgs) -{ -int32 p, s; -d10 bp; - -bp = ReadM (ea, MM_OPND); /* get byte ptr */ -p = GET_P (bp); /* get P and S */ -s = GET_S (bp); -p = p - s; /* adv P */ -if (p < 0) { /* end of word? */ - bp = (bp & LMASK) | (INCR (bp)); /* incr addr */ - p = (36 - s) & 077; } /* reset P */ -bp = PUT_P (bp, p); /* store new P */ -Write (ea, bp, MM_OPND); /* store byte ptr */ -return; -} - -/* Load byte */ - -d10 ldb (a10 ea, int32 pflgs) -{ -a10 ba; -int32 p, s; -d10 bp, wd; - -bp = Read (ea, MM_OPND); /* get byte ptr */ -p = GET_P (bp); /* get P and S */ -s = GET_S (bp); -ba = calc_ea (bp, MM_EABP); /* get addr of byte */ -wd = Read (ba, MM_BSTK); /* read word */ -wd = (wd >> p); /* align byte */ -wd = wd & bytemask[s]; /* mask to size */ -return wd; -} - -/* Deposit byte - must use read and write to get page fail correct */ - -void dpb (d10 val, a10 ea, int32 pflgs) -{ -a10 ba; -int32 p, s; -d10 bp, wd, mask; - -bp = Read (ea, MM_OPND); /* get byte ptr */ -p = GET_P (bp); /* get P and S */ -s = GET_S (bp); -ba = calc_ea (bp, MM_EABP); /* get addr of byte */ -wd = Read (ba, MM_BSTK); /* read word */ -mask = bytemask[s] << p; /* shift mask, val */ -val = val << p; -wd = (wd & ~mask) | (val & mask); /* insert byte */ -Write (ba, wd & DMASK, MM_BSTK); -return; -} - -/* Adjust byte pointer - checked against KS10 ucode - The KS10 divide checks if the bytes per word = 0, which is a simpler - formulation of the processor reference manual check. -*/ - -void adjbp (int32 ac, a10 ea, int32 pflgs) -{ -int32 p, s; -d10 bp, newby, left, byadj, bywrd, val, wdadj; - -val = AC(ac); /* get adjustment */ -bp = Read (ea, MM_OPND); /* get byte pointer */ -p = GET_P (bp); /* get p */ -s = GET_S (bp); /* get s */ -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 */ - 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; } - p = (36 - ((int32) byadj) * s) - ((36 - p) % s); /* new p */ - bp = (PUT_P (bp, p) & LMASK) | ((bp + wdadj) & RMASK); } -AC(ac) = bp; -return; -} - -/* Block transfer - checked against KS10 ucode - The KS10 uses instruction specific recovery code in page fail - to set the AC properly for restart. Lacking this mechanism, - the simulator must test references in advance. - The clocking test guarantees forward progress under single step. -*/ - -void blt (int32 ac, a10 ea, int32 pflgs) -{ -a10 srca = (a10) LRZ (AC(ac)); -a10 dsta = (a10) RRZ (AC(ac)); -a10 lnt = ea - dsta + 1; -d10 srcv; -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); } - 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 */ - 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 */ - srcv = Read (srca & AMASK, MM_BSTK); /* read */ - Write (dsta & AMASK, srcv, MM_OPND); /* write */ - srca = srca + 1; /* incr addr */ - dsta = dsta + 1; } -return; -} - -/* I/O block transfers - byte to Unibus (0) and Unibus to byte (1) */ - -#define BYTE1 0776000000000 -#define BYTE2 0001774000000 -#define BYTE3 0000003770000 -#define BYTE4 0000000007760 -/* unused 0000000000017 */ - -void bltu (int32 ac, a10 ea, int32 pflgs, int dir) -{ -a10 srca = (a10) LRZ (AC(ac)); -a10 dsta = (a10) RRZ (AC(ac)); -a10 lnt = ea - dsta + 1; -d10 srcv, dstv; -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); } - 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 */ - 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 */ - srcv = Read (srca & AMASK, MM_BSTK); /* read */ - if (dir) dstv = ((srcv << 10) & BYTE1) | ((srcv >> 6) & BYTE2) | - ((srcv << 12) & BYTE3) | ((srcv >> 4) & BYTE4); - else dstv = ((srcv & BYTE1) >> 10) | ((srcv & BYTE2) << 6) | - ((srcv & BYTE3) >> 12) | ((srcv & BYTE4) << 4); - Write (dsta & AMASK, dstv, MM_OPND); /* write */ - srca = srca + 1; /* incr addr */ - dsta = dsta + 1; } -return; -} - -/* Utility routine to test for I/O event and interrupt */ - -int32 test_int (void) -{ -int32 t; - -if (sim_interval <= 0) { /* check queue */ - if (t = sim_process_event ()) return t; /* IO event? */ - if (pi_eval ()) return (INTERRUPT); } /* interrupt? */ -else sim_interval--; /* count clock */ -return 0; -} - -/* Miscellaneous routines */ - -/* Adjust stack pointer - - The reference manual says to trap on: - 1) E < 0, left changes from + to - - 2) E >= 0, left changes from - to + - This is the same as trap on: - 1) E and left result have same signs - 2) initial value and left result have different signs - */ - -d10 adjsp (d10 val, a10 ea) -{ -d10 imm = ea; -d10 left, right; - -left = ADDL (val, imm); -right = ADDR (val, imm); -if (TSTS ((val ^ left) & (~left ^ RLZ (imm)))) SETF (F_T2); -return (left | right); -} - -/* Jump if find first ones - Takes advantage of 7 bit find first table for priority interrupts. -*/ - -int32 jffo (d10 val) -{ -int32 i, by; - -if ((val & DMASK) == 0) return 0; -for (i = 0; i <= 28; i = i + 7) { /* scan five bytes */ - by = (int32) ((val >> (29 - i)) & 0177); - if (by) return (pi_m2lvl[by] + i - 1); } -return 35; /* must be bit 35 */ -} - -/* Circulate - ITS only instruction - - Bits rotated out of AC are rotated into the opposite end of AC+1 - why? - No attempt is made to optimize this instruction. -*/ - -void circ (int32 ac, int32 ea) -{ -int32 sc = LIT8 (ea) % 72; -int32 p1 = ADDAC (ac,1); -int32 i; -d10 val; - -if (sc == 0) return; /* any shift? */ -if (ea & RSIGN) sc = 72 - sc; /* if right, make left */ -for (i = 0; i < sc; i++) { /* one bit at a time */ - val = TSTS (AC(ac)); /* shift out */ - AC(ac) = ((AC(ac) << 1) | (AC(p1) & 1)) & DMASK; - AC(p1) = (AC(p1) >> 1) | val; } /* shift in */ -return; -} - -/* Arithmetic processor (APR) - - The APR subsystem includes miscellaneous interrupts that are individually - maskable but which interrupt on a single, selectable level - - Instructions for the arithmetic processor: - APRID read system id - WRAPR (CONO APR) write system flags - RDAPR (CONI APR) read system flags - (CONSO APR) test system flags - (CONSZ APR) test system flags -*/ - -t_bool aprid (a10 ea, int32 prv) -{ -Write (ea, (ITS)? UC_AIDITS: UC_AIDDEC, prv); -return FALSE; -} - -/* Checked against KS10 ucode */ - -t_bool wrapr (a10 ea, int32 prv) -{ -int32 bits = APR_GETF (ea); - -apr_lvl = ea & APR_M_LVL; -if (ea & APR_SENB) apr_enb = apr_enb | bits; /* set enables? */ -if (ea & APR_CENB) apr_enb = apr_enb & ~bits; /* clear enables? */ -if (ea & APR_CFLG) apr_flg = apr_flg & ~bits; /* clear flags? */ -if (ea & APR_SFLG) apr_flg = apr_flg | bits; /* set flags? */ -if (apr_flg & APRF_ITC) { /* interrupt console? */ - fe_intr (); /* explicit callout */ - apr_flg = apr_flg & ~APRF_ITC; } /* interrupt clears */ -pi_eval (); /* eval pi system */ -return FALSE; -} - -t_bool rdapr (a10 ea, int32 prv) -{ -Write (ea, (d10) APRWORD, prv); -return FALSE; -} - -t_bool czapr (a10 ea, int32 prv) -{ -return ((APRHWORD & ea)? FALSE: TRUE); -} - -t_bool coapr (a10 ea, int32 prv) -{ -return ((APRHWORD & ea)? TRUE: FALSE); -} - -/* Routine to change the processor flags, called from JRST, MUUO, interrupt. - If jrst is TRUE, must munge flags for executive security. - Because the KS10 lacks the public flag, these checks are simplified. -*/ - -void set_newflags (d10 newf, t_bool jrst) -{ -int32 fl = (int32) LRZ (newf); - -if (jrst && TSTF (F_USR)) { /* if in user now */ - fl = fl | F_USR; /* can't clear user */ - if (!TSTF (F_UIO)) fl = fl & ~F_UIO; } /* if !UIO, can't set */ -if (ITS && (fl & F_1PR)) { /* ITS 1-proceed? */ - its_1pr = 1; /* set flag */ - fl = fl & ~F_1PR; } /* vanish bit */ -flags = fl & F_MASK; /* set new flags */ -set_dyn_ptrs (); /* set new ptrs */ -return; -} - -/* Priority interrupt system (PI) - - The priority interrupt system has three sources of requests - (pi_apr) system flags - synthesized on the fly - (pi_ioq) I/O interrupts - synthesized on the fly - pi_prq program requests - APR and I/O requests are masked with the PI enable mask; the program - requests are not. If priority interrupts are enabled, and there is - a request at a level exceeding the currently active level, then an - interrupt occurs. - - Instructions for the priority interrupt system: - WRPI (CONO PI) write pi system - RDPI (CONI PI) read pi system - (CONSO PI) test pi system - (CONSZ PI) test pi system - - Routines for the priority interrupt system: - pi_eval return level number of highest interrupt - pi_dismiss dismiss highest outstanding interrupt - - Checked against KS10 ucode - KS10 UUO's if <18:21> are non-zero -*/ - -t_bool wrpi (a10 ea, int32 prv) -{ -int32 lvl = ea & PI_M_LVL; - -if (ea & PI_INIT) pi_on = pi_enb = pi_act = pi_prq = 0; -if (ea & PI_CPRQ) pi_prq = pi_prq & ~lvl; /* clear prog reqs? */ -if (ea & PI_SPRQ) pi_prq = pi_prq | lvl; /* set prog reqs? */ -if (ea & PI_SENB) pi_enb = pi_enb | lvl; /* enable levels? */ -if (ea & PI_CENB) pi_enb = pi_enb & ~lvl; /* disable levels? */ -if (ea & PI_SON) pi_on = 1; /* enable pi? */ -if (ea & PI_CON) pi_on = 0; /* disable pi? */ -pi_eval (); /* eval pi system */ -return FALSE; -} - -t_bool rdpi (a10 ea, int32 prv) -{ -Write (ea, (d10) PIWORD, prv); -return FALSE; -} - -t_bool czpi (a10 ea, int32 prv) -{ -return ((PIHWORD & ea)? FALSE: TRUE); -} - -t_bool copi (a10 ea, int32 prv) -{ -return ((PIHWORD & ea)? TRUE: FALSE); -} - -/* Priority interrupt evaluation - - The Processor Reference Manuals says that program interrupt - requests occur whether the corresponding level is enabled or - not. However, the KS10, starting with microcode edit 47, - masked program requests under the enable mask, just like APR - and I/O requests. This is not formally documented but appears - to be necessary for the TOPS20 console port to run correclty. -*/ - -int32 pi_eval (void) -{ -int32 reqlvl, actlvl; -extern int32 pi_ub_eval (); - -qintr = 0; -if (pi_on) { - pi_apr = (apr_flg & apr_enb)? pi_l2bit[apr_lvl]: 0; - pi_ioq = pi_ub_eval (); - reqlvl = pi_m2lvl[((pi_apr | pi_ioq | pi_prq) & pi_enb)]; - actlvl = pi_m2lvl[pi_act]; - if ((actlvl == 0) || (reqlvl < actlvl)) qintr = reqlvl; } -return qintr; -} - -void pi_dismiss (void) -{ -pi_act = pi_act & ~pi_l2bit[pi_m2lvl[pi_act]]; /* clr left most bit */ -pi_eval (); /* eval pi system */ -return; -} - -/* Reset routine */ - -t_stat cpu_reset (DEVICE *dptr) -{ -flags = 0; /* clear flags */ -its_1pr = 0; /* clear 1-proceed */ -ebr = ubr = 0; /* clear paging */ -pi_enb = pi_act = pi_prq = 0; /* clear PI */ -apr_enb = apr_flg = apr_lvl = 0; /* clear APR */ -pcst = 0; /* clear PC samp */ -rlog = 0; /* clear reg log */ -hsb = (ITS)? UC_HSBITS: UC_HSBDEC; /* set HSB */ -set_dyn_ptrs (); -set_ac_display (ac_cur); -pi_eval (); -if (M == NULL) M = calloc (MAXMEMSIZE, sizeof (d10)); -if (M == NULL) return SCPE_MEM; -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 ea, UNIT *uptr, int32 sw) -{ -if (vptr == NULL) return SCPE_ARG; -if (ea < AC_NUM) *vptr = AC(ea) & DMASK; -else { if (sw & SWMASK ('V')) { - ea = conmap (ea, PTF_CON, sw); - if (ea >= MAXMEMSIZE) return SCPE_REL; } - if (ea >= MEMSIZE) return SCPE_NXM; - *vptr = M[ea] & DMASK; } -return SCPE_OK; -} - -/* Memory deposit */ - -t_stat cpu_dep (t_value val, t_addr ea, UNIT *uptr, int32 sw) -{ -if (ea < AC_NUM) AC(ea) = val & DMASK; -else { if (sw & SWMASK ('V')) { - ea = conmap (ea, PTF_CON | PTF_WR, sw); - if (ea >= MAXMEMSIZE) return SCPE_REL; } - if (ea >= MEMSIZE) return SCPE_NXM; - M[ea] = val & DMASK; } -return SCPE_OK; -} - -/* Set current AC pointers for SCP */ - -void set_ac_display (d10 *acbase) -{ -extern REG *find_reg (char *cptr, char **optr, DEVICE *dptr); -REG *rptr; -int i; - -rptr = find_reg ("AC0", NULL, &cpu_dev); -if (rptr == NULL) return; -for (i = 0; i < AC_NUM; i++, rptr++) rptr->loc = (void *) (acbase + i); -return; -} diff --git a/PDP10/pdp10_defs.h b/PDP10/pdp10_defs.h deleted file mode 100644 index a92ef0d0..00000000 --- a/PDP10/pdp10_defs.h +++ /dev/null @@ -1,749 +0,0 @@ -/* pdp10_defs.h: PDP-10 simulator definitions - - 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. - - 19-May-03 RMS Revised for new conditional compilation scheme - 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 - 23-Oct-01 RMS New IO page address constants - 19-Oct-01 RMS Added DZ11 definitions - 07-Sep-01 RMS Revised for PDP-11 multi-level interrupts - 31-Aug-01 RMS Changed int64 to t_int64 for Windoze - 29-Aug-01 RMS Corrected models and dates (found by Lars Brinkhoff) - 01-Jun-01 RMS Updated DZ11 vector definitions - 19-May-01 RMS Added workaround for TOPS-20 V4.1 boot bug -*/ - -#ifndef _PDP10_DEFS_H_ -#define _PDP10_DEFS_H_ 0 - -#ifndef VM_PDP10 -#define VM_PDP10 0 -#endif - -#include "sim_defs.h" /* simulator defns */ - -/* Digital Equipment Corporation's 36b family had six implementations: - - name mips comments - - PDP-6 0.25 Original 36b implementation, 1964 - KA10 0.38 First PDP-10, flip chips, 1967 - KI10 0.72 First paging system, flip chip + MSI, 1972 - KL10 1.8 First ECL system, ECL 10K, 1975 - KL10B 1.8 Expanded addressing, ECL 10K, 1978 - KS10 0.3 Last 36b system, 2901 based, 1979 - - In addition, it ran four major (incompatible) operating systems: - - name company comments - - TOPS-10 DEC Original timesharing system - ITS MIT "Incompatible Timesharing System" - TENEX BBN ARPA-sponsored, became - TOPS-20 DEC Commercial version of TENEX - - All of the implementations differ from one another, in instruction set, - I/O structure, and memory management. Further, each of the operating - systems customized the microcode of the paging systems (KI10, KL10, KS10) - for additional instructions and specialized memory management. As a - result, there is no "reference implementation" for the 36b family that - will run all programs and all operating systems. The conditionalization - and generality needed to support the full matrix of models and operating - systems, and to support 36b hardware on 32b data types, is beyond the - scope of this project. - - Instead, this simulator emulates one model -- the KS10. It has the best - documentation and allows reuse of some of the Unibus peripheral emulators - written for the PDP-11 simulator. Further, the simulator requires that - the underlying compiler support 64b integer data types, allowing 36b data - to be maintained in a single data item. Lastly, the simulator implements - the maximum memory size, so that NXM's never happen. -*/ - -/* Data types */ - -typedef int32 a10; /* PDP-10 addr (30b) */ -typedef t_int64 d10; /* PDP-10 data (36b) */ - -/* Abort codes, used to sort out longjmp's back to the main loop - Codes > 0 are simulator stop codes - Codes < 0 are internal aborts - Code = 0 stops execution for an interrupt check -*/ - -#define STOP_HALT 1 /* halted */ -#define STOP_IBKPT 2 /* breakpoint */ -#define STOP_ILLEG 3 /* illegal instr */ -#define STOP_ILLINT 4 /* illegal intr inst */ -#define STOP_PAGINT 5 /* page fail in intr */ -#define STOP_ZERINT 6 /* zero vec in intr */ -#define STOP_NXMPHY 7 /* nxm on phys ref */ -#define STOP_IND 8 /* indirection loop */ -#define STOP_XCT 9 /* XCT loop */ -#define STOP_ILLIOC 10 /* invalid UBA num */ -#define STOP_ASTOP 11 /* address stop */ -#define STOP_UNKNOWN 12 /* unknown stop */ -#define PAGE_FAIL -1 /* page fail */ -#define INTERRUPT -2 /* interrupt */ -#define ABORT(x) longjmp (save_env, (x)) /* abort */ -#define IORETURN(f,v) ((f)? (v): SCPE_OK) /* cond error return */ - -/* Return codes from eXTEND */ - -#define XT_MUUO 0 /* invalid operation */ -#define XT_SKIP 1 /* skip return */ -#define XT_NOSK 2 /* no skip return */ - -/* Operating system flags, kept in cpu_unit.flags */ - -#define UNIT_V_ITS (UNIT_V_UF) /* ITS */ -#define UNIT_ITS (1 << UNIT_V_ITS) -#define UNIT_V_T20V41 (UNIT_V_UF + 1) /* TOPS-20 V4.1 */ -#define UNIT_T20V41 (1 << UNIT_V_T20V41) -#define ITS (cpu_unit.flags & UNIT_ITS) - -/* Architectural constants */ - -#define PASIZE 20 /* phys addr width */ -#define MAXMEMSIZE (1 << PASIZE) /* maximum memory */ -#define PAMASK ((1 << PASIZE) - 1) -#define MEMSIZE MAXMEMSIZE /* fixed, KISS */ -#define MEM_ADDR_NXM(x) ((x) >= MEMSIZE) -#define VASIZE 18 /* virtual addr width */ -#define AMASK ((1 << VASIZE) - 1) /* virtual addr mask */ -#define LMASK 0777777000000 /* left mask */ -#define LSIGN 0400000000000 /* left sign */ -#define RMASK 0000000777777 /* right mask */ -#define RSIGN 0000000400000 /* right sign */ -#define DMASK 0777777777777 /* data mask */ -#define SIGN 0400000000000 /* sign */ -#define MMASK 0377777777777 /* magnitude mask */ -#define ONES 0777777777777 -#define MAXPOS 0377777777777 -#define MAXNEG 0400000000000 - -/* Instruction format */ - -#define INST_V_OP 27 /* opcode */ -#define INST_M_OP 0777 -#define INST_V_DEV 26 -#define INST_M_DEV 0177 /* device */ -#define INST_V_AC 23 /* AC */ -#define INST_M_AC 017 -#define INST_V_IND 22 /* indirect */ -#define INST_IND (1 << INST_V_IND) -#define INST_V_XR 18 /* index */ -#define INST_M_XR 017 -#define OP_JRST 0254 /* JRST */ -#define AC_XPCW 07 /* XPCW */ -#define OP_JSR 0264 /* JSR */ -#define GET_OP(x) ((int32) (((x) >> INST_V_OP) & INST_M_OP)) -#define GET_DEV(x) ((int32) (((x) >> INST_V_DEV) & INST_M_DEV)) -#define GET_AC(x) ((int32) (((x) >> INST_V_AC) & INST_M_AC)) -#define TST_IND(x) ((x) & INST_IND) -#define GET_XR(x) ((int32) (((x) >> INST_V_XR) & INST_M_XR)) -#define GET_ADDR(x) ((a10) ((x) & AMASK)) - -/* Byte pointer format */ - -#define BP_V_P 30 /* position */ -#define BP_M_P 077 -#define BP_P 0770000000000 -#define BP_V_S 24 /* size */ -#define BP_M_S 077 -#define BP_S 0007700000000 -#define GET_P(x) ((int32) (((x) >> BP_V_P) & BP_M_P)) -#define GET_S(x) ((int32) (((x) >> BP_V_S) & BP_M_S)) -#define PUT_P(b,x) (((b) & ~BP_P) | ((((t_int64) (x)) & BP_M_P) << BP_V_P)) - -/* Flags (stored in their own halfword) */ - -#define F_V_AOV 17 /* arithmetic ovflo */ -#define F_V_C0 16 /* carry 0 */ -#define F_V_C1 15 /* carry 1 */ -#define F_V_FOV 14 /* floating ovflo */ -#define F_V_FPD 13 /* first part done */ -#define F_V_USR 12 /* user mode */ -#define F_V_UIO 11 /* user I/O mode */ -#define F_V_PUB 10 /* public mode */ -#define F_V_AFI 9 /* addr fail inhibit */ -#define F_V_T2 8 /* trap 2 */ -#define F_V_T1 7 /* trap 1 */ -#define F_V_FXU 6 /* floating exp unflo */ -#define F_V_DCK 5 /* divide check */ -#define F_AOV (1 << F_V_AOV) -#define F_C0 (1 << F_V_C0) -#define F_C1 (1 << F_V_C1) -#define F_FOV (1 << F_V_FOV) -#define F_FPD (1 << F_V_FPD) -#define F_USR (1 << F_V_USR) -#define F_UIO (1 << F_V_UIO) -#define F_PUB (1 << F_V_PUB) -#define F_AFI (1 << F_V_AFI) -#define F_T2 (1 << F_V_T2) -#define F_T1 (1 << F_V_T1) -#define F_TR (F_T1 | F_T2) -#define F_FXU (1 << F_V_FXU) -#define F_DCK (1 << F_V_DCK) -#define F_1PR (F_AFI) /* ITS: 1-proceed */ -#define F_MASK 0777740 /* all flags */ -#define SETF(x) flags = flags | (x) -#define CLRF(x) flags = flags & ~(x) -#define TSTF(x) (flags & (x)) -#define GET_TRAPS(x) (((x) & (F_T2 | F_T1)) >> F_V_T1) - -/* Priority interrupt system */ - -#define PI_CPRQ 020000 /* drop prog req */ -#define PI_INIT 010000 /* clear pi system */ -#define PI_SPRQ 004000 /* set prog req */ -#define PI_SENB 002000 /* set enables */ -#define PI_CENB 001000 /* clear enables */ -#define PI_CON 000400 /* turn off pi system */ -#define PI_SON 000200 /* turn on pi system */ -#define PI_M_LVL 000177 /* level mask */ -#define PI_V_PRQ 18 /* in CONI */ -#define PI_V_ACT 8 -#define PI_V_ON 7 -#define PI_V_ENB 0 - -/* Arithmetic processor flags */ - -#define APR_SENB 0100000 /* set enable */ -#define APR_CENB 0040000 /* clear enable */ -#define APR_CFLG 0020000 /* clear flag */ -#define APR_SFLG 0010000 /* set flag */ -#define APR_IRQ 0000010 /* int request */ -#define APR_M_LVL 0000007 /* pi level */ -#define APR_V_FLG 4 /* system flags */ -#define APR_M_FLG 0377 -#define APRF_ITC (002000 >> APR_V_FLG) /* int console flag */ -#define APRF_NXM (000400 >> APR_V_FLG) /* nxm flag */ -#define APRF_TIM (000040 >> APR_V_FLG) /* timer request */ -#define APRF_CON (000020 >> APR_V_FLG) /* console int */ -#define APR_GETF(x) (((x) >> APR_V_FLG) & APR_M_FLG) - -/* Virtual address, DEC paging */ - -#define PAG_V_OFF 0 /* offset - must be 0 */ -#define PAG_N_OFF 9 /* page offset width */ -#define PAG_SIZE 01000 /* page offset size */ -#define PAG_M_OFF 0777 /* mask for offset */ -#define PAG_V_PN PAG_N_OFF /* page number */ -#define PAG_N_PPN (PASIZE - PAG_N_OFF) /* phys pageno width */ -#define PAG_M_PPN 03777 /* phys pageno mask */ -#define PAG_PPN 03777000 -#define PAG_N_VPN (VASIZE - PAG_N_OFF) /* virt pageno width */ -#define PAG_M_VPN 0777 /* virt pageno mask */ -#define PAG_VPN 0777000 -#define PAG_GETOFF(x) ((x) & PAG_M_OFF) -#define PAG_GETVPN(x) (((x) >> PAG_V_PN) & PAG_M_VPN) -#define PAG_XPTEPA(p,x) (((p) + PAG_GETOFF (x)) & PAMASK) -#define PAG_PTEPA(p,x) (((((int32) (p)) & PTE_PPMASK) << PAG_V_PN) + PAG_GETOFF (x)) - -/* Page table entry, TOPS-10 paging */ - -#define PTE_T10_A 0400000 /* T10: access */ -#define PTE_T10_P 0200000 /* T10: public */ -#define PTE_T10_W 0100000 /* T10: writeable */ -#define PTE_T10_S 0040000 /* T10: software */ -#define PTE_T10_C 0020000 /* T10: cacheable */ -#define PTE_PPMASK PAG_M_PPN - -/* Page table entry, TOPS-20 paging */ - -#define PTE_T20_V_TYP 33 /* T20: pointer type */ -#define PTE_T20_M_TYP 07 -#define T20_NOA 0 /* no access */ -#define T20_IMM 1 /* immediate */ -#define T20_SHR 2 /* shared */ -#define T20_IND 3 /* indirect */ -#define PTE_T20_W 0020000000000 /* T20: writeable */ -#define PTE_T20_C 0004000000000 /* T20: cacheable */ -#define PTE_T20_STM 0000077000000 /* T20: storage medium */ -#define PTE_T20_V_PMI 18 /* page map index */ -#define PTE_T20_M_PMI 0777 -#define T20_GETTYP(x) ((int32) (((x) >> PTE_T20_V_TYP) & PTE_T20_M_TYP)) -#define T20_GETPMI(x) ((int32) (((x) >> PTE_T20_V_PMI) & PTE_T20_M_PMI)) - -/* CST entry, TOPS-20 paging */ - -#define CST_AGE 0770000000000 /* age field */ -#define CST_M 0000000000001 /* modified */ - -/* Page fail word, DEC paging */ - -#define PF_USER 0400000000000 /* user mode */ -#define PF_HARD 0200000000000 /* nx I/O reg */ -#define PF_NXM 0370000000000 /* nx memory */ -#define PF_T10_A 0100000000000 /* T10: pte A bit */ -#define PF_T10_W 0040000000000 /* T10: pte W bit */ -#define PF_T10_S 0020000000000 /* T10: pte S bit */ -#define PF_T20_DN 0100000000000 /* T20: eval done */ -#define PF_T20_M 0040000000000 /* T20: modified */ -#define PF_T20_W 0020000000000 /* T20: writeable */ -#define PF_WRITE 0010000000000 /* write reference */ -#define PF_PUB 0004000000000 /* pte public bit */ -#define PF_C 0002000000000 /* pte C bit */ -#define PF_VIRT 0001000000000 /* pfl: virt ref */ -#define PF_NXMP 0001000000000 /* nxm: phys ref */ -#define PF_IO 0000200000000 /* I/O reference */ -#define PF_BYTE 0000020000000 /* I/O byte ref */ - -/* Virtual address, ITS paging */ - -#define ITS_V_OFF 0 /* offset - must be 0 */ -#define ITS_N_OFF 10 /* page offset width */ -#define ITS_SIZE 02000 /* page offset size */ -#define ITS_M_OFF 01777 /* mask for offset */ -#define ITS_V_PN ITS_N_OFF /* page number */ -#define ITS_N_PPN (PASIZE- ITS_N_OFF) /* phys pageno width */ -#define ITS_M_PPN 01777 /* phys pageno mask */ -#define ITS_PPN 03776000 -#define ITS_N_VPN (VASIZE - ITS_N_OFF) /* virt pageno width */ -#define ITS_M_VPN 0377 /* virt pageno mask */ -#define ITS_VPN 0776000 -#define ITS_GETVPN(x) (((x) >> ITS_V_PN) & ITS_M_VPN) - -/* Page table entry, ITS paging */ - -#define PTE_ITS_V_ACC 16 /* access field */ -#define PTE_ITS_M_ACC 03 -#define ITS_ACC_NO 0 /* no access */ -#define ITS_ACC_RO 1 /* read only */ -#define ITS_ACC_RWF 2 /* read-write first */ -#define ITS_ACC_RW 3 /* read write */ -#define PTE_ITS_AGE 0020000 /* age */ -#define PTE_ITS_C 0010000 /* cacheable */ -#define PTE_ITS_PPMASK ITS_M_PPN -#define ITS_GETACC(x) (((x) >> PTE_ITS_V_ACC) & PTE_ITS_M_ACC) - -/* Page fail word, ITS paging */ - -#define PF_ITS_WRITE 0010000000000 /* write reference */ -#define PF_ITS_V_ACC 28 /* access from PTE */ - -/* Page table fill operations */ - -#define PTF_RD 0 /* read check */ -#define PTF_WR 1 /* write check */ -#define PTF_MAP 2 /* map instruction */ -#define PTF_CON 4 /* console access */ - -/* User base register */ - -#define UBR_SETACB 0400000000000 /* set AC blocks */ -#define UBR_SETUBR 0100000000000 /* set UBR */ -#define UBR_V_CURAC 27 /* current AC block */ -#define UBR_V_PRVAC 24 /* previous AC block */ -#define UBR_M_AC 07 -#define UBR_ACBMASK 0007700000000 -#define UBR_V_UBR 0 /* user base register */ -#define UBR_N_UBR 11 -#define UBR_M_UBR 03777 -#define UBR_UBRMASK 0000000003777 -#define UBR_GETCURAC(x) ((int32) (((x) >> UBR_V_CURAC) & UBR_M_AC)) -#define UBR_GETPRVAC(x) ((int32) (((x) >> UBR_V_PRVAC) & UBR_M_AC)) -#define UBR_GETUBR(x) ((int32) (((x) >> UBR_V_UBR) & PAG_M_PPN)) -#define UBRWORD (ubr | UBR_SETACB | UBR_SETUBR) - -/* Executive base register */ - -#define EBR_V_T20P 14 /* TOPS20 paging */ -#define EBR_T20P (1u << EBR_V_T20P) -#define EBR_V_PGON 13 /* enable paging */ -#define EBR_PGON (1u << EBR_V_PGON) -#define EBR_V_EBR 0 /* exec base register */ -#define EBR_N_EBR 11 -#define EBR_M_EBR 03777 -#define EBR_MASK (EBR_T20P | EBR_PGON | (EBR_M_EBR << EBR_V_EBR)) -#define EBR_GETEBR(x) ((int32) (((x) >> EBR_V_EBR) & PAG_M_PPN)) -#define PAGING (ebr & EBR_PGON) -#define T20 (ebr & EBR_T20P) - -/* AC and mapping contexts - - There are only two real contexts for selecting the AC block and - the memory map: current and previous. However, PXCT allows the - choice of current versus previous to be made selectively for - various parts of an instruction. The PXCT flags are kept in a - dynamic CPU variable. -*/ - -#define EA_PXCT 010 /* eff addr calc */ -#define OPND_PXCT 004 /* operand, bdst */ -#define EABP_PXCT 002 /* bp eff addr calc */ -#define BSTK_PXCT 001 /* stk, bp op, bsrc */ -#define XSRC_PXCT 002 /* extend source */ -#define XDST_PXCT 001 /* extend destination */ -#define MM_CUR 000 /* current context */ -#define MM_EA (pflgs & EA_PXCT) -#define MM_OPND (pflgs & OPND_PXCT) -#define MM_EABP (pflgs & EABP_PXCT) -#define MM_BSTK (pflgs & BSTK_PXCT) - -/* Accumulator access. The AC blocks are kept in array acs[AC_NBLK * AC_NUM]. - Two pointers are provided to the bases of the current and previous blocks. - Macro AC selects the current AC block; macro XR selects current or previous, - depending on whether the selected bit in the "pxct in progress" flag is set. -*/ - -#define AC_NUM 16 /* # AC's/block */ -#define AC_NBLK 8 /* # AC blocks */ -#define AC(r) (ac_cur[r]) /* AC select current */ -#define XR(r,prv) ((prv)? ac_prv[r]: ac_cur[r]) /* AC select context */ -#define ADDAC(x,i) (((x) + (i)) & INST_M_AC) -#define P1 ADDAC (ac, 1) - -/* User process table entries */ - -#define UPT_T10_UMAP 0000 /* T10: user map */ -#define UPT_T10_X340 0400 /* T10: exec 340-377 */ -#define UPT_TRBASE 0420 /* trap base */ -#define UPT_MUUO 0424 /* MUUO block */ -#define UPT_MUPC 0425 /* caller's PC */ -#define UPT_T10_CTX 0426 /* T10: context */ -#define UPT_T20_UEA 0426 /* T20: address */ -#define UPT_T20_CTX 0427 /* T20: context */ -#define UPT_ENPC 0430 /* MUUO new PC, exec */ -#define UPT_1PO 0432 /* ITS 1-proc: old PC */ -#define UPT_1PN 0433 /* ITS 1-proc: new PC */ -#define UPT_UNPC 0434 /* MUUO new PC, user */ -#define UPT_NPCT 1 /* PC offset if trap */ -#define UPT_T10_PAG 0500 /* T10: page fail blk */ -#define UPT_T20_PFL 0500 /* T20: page fail wd */ -#define UPT_T20_OFL 0501 /* T20: flags */ -#define UPT_T20_OPC 0502 /* T20: old PC */ -#define UPT_T20_NPC 0503 /* T20: new PC */ -#define UPT_T20_SCTN 0540 /* T20: section 0 ptr */ - -/* Exec process table entries */ - -#define EPT_PIIT 0040 /* PI interrupt table */ -#define EPT_UBIT 0100 /* Unibus intr table */ -#define EPT_T10_X400 0200 /* T10: exec 400-777 */ -#define EPT_TRBASE 0420 /* trap base */ -#define EPT_ITS_PAG 0440 /* ITS: page fail blk */ -#define EPT_T20_SCTN 0540 /* T20: section 0 ptr */ -#define EPT_T10_X000 0600 /* T10: exec 0 - 337 */ - -/* Microcode constants */ - -#define UC_INHCST 0400000000000 /* inhibit CST update */ -#define UC_UBABLT 0040000000000 /* BLTBU and BLTUB */ -#define UC_KIPAGE 0020000000000 /* "KI" paging */ -#define UC_KLPAGE 0010000000000 /* "KL" paging */ -#define UC_VERDEC (0130 << 18) /* ucode version */ -#define UC_VERITS (262u << 18) -#define UC_SERDEC 4097 /* serial number */ -#define UC_SERITS 1729 -#define UC_AIDDEC (UC_INHCST | UC_UBABLT | UC_KIPAGE | UC_KLPAGE | \ - UC_VERDEC | UC_SERDEC) -#define UC_AIDITS (UC_KIPAGE | UC_VERITS | UC_SERITS) -#define UC_HSBDEC 0376000 /* DEC initial HSB */ -#define UC_HSBITS 0000500 /* ITS initial HSB */ - -/* Front end communications region */ - -#define FE_SWITCH 030 /* halt switch */ -#define FE_KEEPA 031 /* keep alive */ -#define FE_CTYIN 032 /* console in */ -#define FE_CTYOUT 033 /* console out */ -#define FE_KLININ 034 /* KLINIK in */ -#define FE_KLINOUT 035 /* KLINIK out */ -#define FE_RHBASE 036 /* boot: RH11 addr */ -#define FE_UNIT 037 /* boot: unit num */ -#define FE_MTFMT 040 /* boot: magtape params */ -#define FE_CVALID 0400 /* char valid flag */ - -/* Halfword operations */ - -#define ADDL(x,y) (((x) + ((y) << 18)) & LMASK) -#define ADDR(x,y) (((x) + (y)) & RMASK) -#define INCL(x) ADDL (x, 1) -#define INCR(x) ADDR (x, 1) -#define AOB(x) (INCL (x) | INCR(x)) -#define SUBL(x,y) (((x) - ((y) << 18)) & LMASK) -#define SUBR(x,y) (((x) - (y)) & RMASK) -#define DECL(x) SUBL (x, 1) -#define DECR(x) SUBR (x, 1) -#define SOB(x) (DECL (x) | DECR(x)) -#define LLZ(x) ((x) & LMASK) -#define RLZ(x) (((x) << 18) & LMASK) -#define RRZ(x) ((x) & RMASK) -#define LRZ(x) (((x) >> 18) & RMASK) -#define LIT8(x) (((x) & RSIGN)? \ - (((x) & 0377)? (-(x) & 0377): 0400): ((x) & 0377)) - -/* Fullword operations */ - -#define INC(x) (((x) + 1) & DMASK) -#define DEC(x) (((x) - 1) & DMASK) -#define SWP(x) ((((x) << 18) & LMASK) | (((x) >> 18) & RMASK)) -#define XWD(x,y) (((((d10) (x)) << 18) & LMASK) | (((d10) (y)) & RMASK)) -#define SETS(x) ((x) | SIGN) -#define CLRS(x) ((x) & ~SIGN) -#define TSTS(x) ((x) & SIGN) -#define NEG(x) (-(x) & DMASK) -#define ABS(x) (TSTS (x)? NEG(x): (x)) -#define SXT(x) (TSTS (x)? (x) | ~DMASK: (x)) - -/* Doubleword operations (on 2-word arrays) */ - -#define DMOVN(rs) rs[1] = (-rs[1]) & MMASK; \ - rs[0] = (~rs[0] + (rs[1] == 0)) & DMASK -#define MKDNEG(rs) rs[1] = SETS (-rs[1]) & DMASK; \ - rs[0] = (~rs[0] + (rs[1] == MAXNEG)) & DMASK -#define DCMPGE(a,b) ((a[0] > b[0]) || ((a[0] == b[0]) && (a[1] >= b[1]))) - -/* Address operations */ - -#define ADDA(x,i) (((x) + (i)) & AMASK) -#define INCA(x) ADDA (x, 1) - -/* Unibus adapter control/status register */ - -#define UBCS_TMO 0400000 /* timeout */ -#define UBCS_BMD 0200000 /* bad mem data NI */ -#define UBCS_PAR 0100000 /* parity error NI */ -#define UBCS_NXD 0040000 /* nx device */ -#define UBCS_HI 0004000 /* irq on BR7 or BR6 */ -#define UBCS_LO 0002000 /* irq on BR5 or BR4 */ -#define UBCS_PWR 0001000 /* power low NI */ -#define UBCS_DXF 0000200 /* disable xfer NI*/ -#define UBCS_INI 0000100 /* Unibus init */ -#define UBCS_RDZ 0030500 /* read as zero */ -#define UBCS_RDW 0000277 /* read/write bits */ -#define UBCS_V_LHI 3 /* hi pri irq level */ -#define UBCS_V_LLO 0 /* lo pri irq level */ -#define UBCS_M_PRI 07 -#define UBCS_GET_HI(x) (((x) >> UBCS_V_LHI) & UBCS_M_PRI) -#define UBCS_GET_LO(x) (((x) >> UBCS_V_LLO) & UBCS_M_PRI) - -/* Unibus adapter page map */ - -#define UBANUM 2 /* # of Unibus adapters */ -#define UMAP_ASIZE 6 /* address size */ -#define UMAP_MEMSIZE (1 << UMAP_ASIZE) /* length */ -#define UMAP_AMASK (UMAP_MEMSIZE - 1) -#define UMAP_V_RRV 30 /* read reverse */ -#define UMAP_V_DSB 29 /* 16b on NPR read */ -#define UMAP_V_FST 28 /* fast transfer */ -#define UMAP_V_VLD 27 /* valid flag */ -#define UMAP_RRV (1 << UMAP_V_RRV) -#define UMAP_DSB (1 << UMAP_V_DSB) -#define UMAP_FST (1 << UMAP_V_FST) -#define UMAP_VLD (1 << UMAP_V_VLD) -#define UMAP_V_FLWR 14 /* flags as written */ -#define UMAP_V_FLRD 27 /* flags as stored */ -#define UMAP_M_FL 017 -#define UMAP_V_PNWR 0 /* page num, write */ -#define UMAP_V_PNRD 9 /* page num, read */ -#define UMAP_M_PN 03777 -#define UMAP_MASK ((UMAP_M_FL << UMAP_V_FLRD) | (UMAP_M_PN << UMAP_V_PNRD)) -#define UMAP_POSFL(x) (((x) & (UMAP_M_FL << UMAP_V_FLWR)) \ - << (UMAP_V_FLRD - UMAP_V_FLWR)) -#define UMAP_POSPN(x) (((x) & (UMAP_M_PN << UMAP_V_PNWR)) \ - << (UMAP_V_PNRD - UMAP_V_PNWR)) - -/* Unibus I/O constants */ - -#define READ 0 /* PDP11 compatible */ -/* #define READC 1 /* console read */ -#define WRITE 2 -/* #define WRITEC 3 /* console write */ -#define WRITEB 4 -#define IO_V_UBA 18 /* UBA in I/O addr */ -#define IO_N_UBA 16 /* max num of UBA's */ -#define IO_M_UBA (IO_N_UBA - 1) -#define IO_UBA1 (1 << IO_V_UBA) -#define IO_UBA3 (3 << IO_V_UBA) -#define GET_IOUBA(x) (((x) >> IO_V_UBA) & IO_M_UBA) - -/* Device information block */ - -#define VEC_DEVMAX 8 /* max device vec */ - -struct pdp_dib { - uint32 ba; /* base addr */ - uint32 lnt; /* length */ - t_stat (*rd)(int32 *dat, int32 ad, int32 md); - t_stat (*wr)(int32 dat, int32 ad, int32 md); - int32 vnum; /* vectors: number */ - int32 vloc; /* locator */ - int32 vec; /* value */ - int32 (*ack[VEC_DEVMAX])(void); /* ack routines */ -}; - -typedef struct pdp_dib DIB; - -/* I/O system parameters */ - -#define DZ_MUXES 4 /* max # of muxes */ -#define DZ_LINES 8 /* lines per mux */ -#define DIB_MAX 100 /* max DIBs */ - -#define DEV_V_UBUS (DEV_V_UF + 0) /* Unibus */ -#define DEV_V_QBUS (DEV_V_UF + 1) /* Qbus */ -#define DEV_V_FLTA (DEV_V_UF + 2) /* float addr */ -#define DEV_UBUS (1u << DEV_V_UBUS) -#define DEV_QBUS (1u << DEV_V_QBUS) -#define DEV_FLTA (1u << DEV_V_FLTA) - -#define UNIBUS TRUE /* 18b only */ - -#define FST 0 /* Unibus 1 */ -#define MAP 1 /* Unibus 3 */ - -#define DEV_RDX 8 /* default device radix */ - -/* I/O page layout */ - -#define IOPAGEBASE 0760000 /* I/O page base */ -#define IOBA_UBMAP 0763000 - -#define IOBA_UBMAP1 (IO_UBA1 + IOBA_UBMAP) /* Unibus 1 map */ -#define IOLN_UBMAP1 0100 -#define IOBA_UBCS1 (IO_UBA1 + 0763100) /* Unibus 1 c/s reg */ -#define IOLN_UBCS1 001 -#define IOBA_UBMNT1 (IO_UBA1 + 0763101) /* Unibus 1 maint reg */ -#define IOLN_UBMNT1 001 -#define IOBA_RP (IO_UBA1 + 0776700) /* RH11/disk */ -#define IOLN_RP 050 - -#define IOBA_DZ (IO_UBA3 + 0760010) /* DZ11 */ -#define IOLN_DZ 010 -#define IOBA_TCU (IO_UBA3 + 0760770) /* TCU150 */ -#define IOLN_TCU 006 -#define IOBA_UBMAP3 (IO_UBA3 + IOBA_UBMAP) /* Unibus 3 map */ -#define IOLN_UBMAP3 0100 -#define IOBA_UBCS3 (IO_UBA3 + 0763100) /* Unibus 3 c/s reg */ -#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 */ -#define IOLN_TU 034 -#define IOBA_LP20 (IO_UBA3 + 0775400) /* LP20 */ -#define IOLN_LP20 020 -#define IOBA_PTR (IO_UBA3 + 017550) /* PC11 reader */ -#define IOLN_PTR 004 -#define IOBA_PTP (IO_UBA3 + 017554) /* PC11 punch */ -#define IOLN_PTP 004 - -/* Common Unibus CSR flags */ - -#define CSR_V_GO 0 /* go */ -#define CSR_V_IE 6 /* interrupt enable */ -#define CSR_V_DONE 7 /* done */ -#define CSR_V_BUSY 11 /* busy */ -#define CSR_V_ERR 15 /* error */ -#define CSR_GO (1u << CSR_V_GO) -#define CSR_IE (1u << CSR_V_IE) -#define CSR_DONE (1u << CSR_V_DONE) -#define CSR_BUSY (1u << CSR_V_BUSY) -#define CSR_ERR (1u << CSR_V_ERR) - -/* I/O system definitions, lifted from the PDP-11 simulator - Interrupt assignments, priority is right to left - - <3:0> = BR7 - <7:4> = BR6 - <19:8> = BR5 - <30:20> = BR4 -*/ - -#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 */ -#define INT_V_PTR 24 /* PC11 */ -#define INT_V_PTP 25 -#define INT_V_LP20 26 /* LPT20 */ - -#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) -#define INT_PTR (1u << INT_V_PTR) -#define INT_PTP (1u << INT_V_PTP) -#define INT_LP20 (1u << INT_V_LP20) - -#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 -#define IPL_PTR 4 -#define IPL_PTP 4 -#define IPL_LP20 4 - -#define INT_UB1 INT_RP /* on Unibus 1 */ -#define INT_UB3 (0xFFFFFFFFu & ~INT_UB1) /* on Unibus 3 */ - -#define INT_IPL7 0x0000000F /* int level masks */ -#define INT_IPL6 0x000000F0 -#define INT_IPL5 0x000FFF00 -#define INT_IPL4 0x3FF00000 - -#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 -#define VEC_DZRX 0340 -#define VEC_DZTX 0344 -#define VEC_LP20 0754 - -#define IVCL(dv) (INT_V_##dv) -#define IREQ(dv) int_req -#define SET_INT(dv) IREQ(dv) = IREQ(dv) | (INT_##dv) -#define CLR_INT(dv) IREQ(dv) = IREQ(dv) & ~(INT_##dv) - -/* Function prototypes */ - -int32 Map_ReadB (uint32 ba, int32 bc, uint8 *buf, t_bool ub); -int32 Map_ReadW (uint32 ba, int32 bc, uint16 *buf, t_bool ub); -int32 Map_WriteB (uint32 ba, int32 bc, uint8 *buf, t_bool ub); -int32 Map_WriteW (uint32 ba, int32 bc, uint16 *buf, t_bool ub); -t_stat set_addr (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat show_addr (FILE *st, UNIT *uptr, int32 val, void *desc); -t_stat set_vec (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat show_vec (FILE *st, UNIT *uptr, int32 val, void *desc); -t_stat auto_config (uint32 rank, uint32 num); - -#endif diff --git a/PDP10/pdp10_diag.txt b/PDP10/pdp10_diag.txt deleted file mode 100644 index 3f9a18a6..00000000 --- a/PDP10/pdp10_diag.txt +++ /dev/null @@ -1,25 +0,0 @@ -Bugs Found ----------- - -1. pushj cleared T2 after setting it -2. if timer autoadjust is enabled, timer diagnostic may fail, - depending on host CPU speed -3. DFAD/DFSB should use FP_ONES instead of ONES -4. TLB physical address max = 1MW, tested in diagnostic -5. DPB does read/write, not read-modify/write -6. Fetch error takes priority over traps, due to prefetching - of next instruction -7. HSB is 36b, was 32b -8. CPU and PAG devices had mismatched types -9. non-zero sections in Tops-20 paging section indirect may - cause non-existent memory error, due to microcode "error" -10. PXCT test for user mode was backward -11. Timer interrupts were not implemented in Tops-20 indirect - chains -12. epta/upta hit known bug in VC++ implementation of 64b - data types -13. final W calculation in Tops-20 paging was incorrect -14. Timer representation lost sub msec values -15. UBA initialization reset the UBA itself -16. RHCS1: writing IE cannot trigger an interrupt -17. Tape bootstrap was set to 800bpi instead of 1600bpi diff --git a/PDP10/pdp10_doc.txt b/PDP10/pdp10_doc.txt deleted file mode 100644 index fb31fe4e..00000000 --- a/PDP10/pdp10_doc.txt +++ /dev/null @@ -1,623 +0,0 @@ -To: Users -From: Bob Supnik -Subj: PDP-10 Simulator Usage -Date: 15-May-2003 - - COPYRIGHT NOTICE - -The following copyright notice applies to both the SIMH source and binary: - - 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"), - 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-10 simulator. - - -1. Simulator Files - -To compile the PDP-10, you must define VM_PDP10 and USE_INT64 as part of the -compilation command line. - -sim/ sim_defs.h - sim_ether.h - sim_rev.h - sim_sock.h - sim_tape.h - sim_tmxr.h - scp.c - scp_tty.c - sim_ether.c - sim_sock.c - sim_tape.c - sim_tmxr.c - -sim/pdp10/ pdp10_defs.h - pdp10_cpu.c - pdp10_fe.c - pdp10_ksio.c - pdp10_lp20.c - pdp10_mdfp.c - pdp10_pag.c - pdp10_rp.c - pdp10_sys.c - pdp10_tu.c - pdp10_xtnd.c - -sim/pdp11/ pdp11_dz.c - pdp11_pt.c - pdp11_ry.c - pdp11_xu.c - -2. PDP-10 Features - -The PDP-10 simulator is configured as follows: - -device simulates -name(s) - -CPU KS10 CPU with 1MW of memory -PAG paging unit (translation maps) -UBA Unibus adapters (translation maps) -FE console -TIM timer -PTR,PTP PC11 paper tape reader/punch -RY RX211/RX02 floppy disk and two drives -DZ DZ11 8-line terminal multiplexor (up to 4) -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 -allows the I/O page address of the device to be changed, and the SET VECTOR -command, which allows the vector of the device to be changed. All devices -support the SHOW ADDRESS and SHOW VECTOR commands, which display the device -address and vector, respectively. - -The PDP-10 simulator implements several unique stop condition: - - - illegal instruction (000) in kernel mode - - indirect addressing nesting exceeds limit - - execute chaining exceeds limit - - page fail or other error in interrupt sequence - - illegal instruction in interrupt sequence - - invalid vector pointer in interrupt sequence - - invalid Unibus adapter number - - non-existent exec or user page table address - -The PDP-10 loader supports RIM10B format paper tapes, SAV binary files, and -EXE binary files. LOAD switches -r, -s, -e specify RIM10, SAV, EXE format, -respectively. If no switch is specified, the LOAD command checks the file -extension; .RIM, .SAV, .EXE specify RIM10, SAV, EXE format, respectively. -If no switch is specified, and no extension matches, the LOAD command checks -the file format to try to determine the file type. - -2.1 CPU - -The CPU options allow the user to specify standard microcode, standard -microcode with a bug fix for a boostrap problem in TOPS-20 V4.1, or ITS -microcode: - - SET CPU STANDARD Standard microcode - SET CPU TOPS20V41 Standard microcode with TOPS-20 V4.1 bug fix - SET CPU ITS ITS compatible microcode - -The CPU implements a SHOW command to display the I/O space address map: - - SHOW CPU IOSPACE show I/O space address map - -CPU registers include the visible state of the processor as well as the -control registers for the interrupt system. - - name size comments - - PC 18 program counter - FLAGS 18 processor flags (<13:17> unused) - AC0..AC17 36 accumulators - IR 36 instruction register - EBR 18 executive base register - PGON 1 paging enabled flag - T20P 1 TOPS-20 paging - UBR 18 user base register - CURAC 3 current AC block - PRVAC 3 previous AC block - SPT 36 shared pointer table - CST 36 core status table - PUR 36 process update register - CSTM 36 CST mask - HSB 18 halt status block address - DBR1 18 descriptor base register 1 (ITS) - DBR2 18 descriptor base register 2 (ITS) - DBR3 18 descriptor base register 3 (ITS) - DBR4 18 descriptor base register 4 (ITS) - PIENB 7 PI levels enabled - PIACT 7 PI levels active - PIPRQ 7 PI levels with program requests - PIIOQ 7 PI levels with IO requests - PIAPR 7 PI levels with APR requests - APRENB 8 APR flags enabled - APRFLG 8 APR flags active - APRLVL 3 PI level for APR interrupt - IND_MAX 8 indirect address nesting limit - XCT_MAX 8 execute chaining limit - PCQ[0:63] 18 PC prior to last jump or interrupt; - most recent PC change first - WRU 8 interrupt character - REG[0:127] 36 fast memory blocks - -2.2 Pager - -The pager contains the page maps for executive and user mode. The -executive page map is the memory space for unit 0, the user page map the -memory space for unit 1. A page map entry is 32 bits wide and has the -following format: - - bit content - --- ------- - 31 page is writeable - 30 entry is valid - 29:19 mbz - 18:9 physical page base address - 8:0 mbz - -The pager has no registers. - -2.3 Unibus Adapters - -The Unibus adapters link the system I/O devices to the CPU. Unibus -adapter 1 (UBA1) is unit 0, and Unibus adapter 3 is unit 1. The -adapter's Unibus map is the memory space of the corresponding unit. - -The Unibus adapter has the following registers: - - name size comments - - INTREQ 32 interrupt requests - UB1CS 16 Unibus adapter 1 control/status - UB3CS 16 Unibus adapter 3 control/status - -2.4 Front End (FE) - -The front end is the system console. The keyboard input is unit 0, -the console output is unit 1. It supports two options: - - SET FE STOP halts the PDP-10 operating system - SET FE CTLC simulates typing ^C - -The front end has the following registers: - - name size comments - - IBUF 8 input buffer - ICOUNT 32 count of input characters - ITIME 24 keyboard polling interval - OBUF 8 output buffer - OCOUNT 32 count of output characters - OTIME 24 console output response time - -2.5 Timer (TIM) - -The timer (TIM) implements the system timer, the interval timer, and -the time of day clock used to get the date and time at system startup. -Because most PDP-10 software is not Y2K compliant, the timer implements -one option: - - SET TIM NOY2K software not Y2K compliant, limit time - of day clock to 1999 (default) - SET TIM Y2K software is Y2K compliant - -The timer has the following registers: - - name size comments - - TIMBASE 59 time base (double precision) - TTG 36 time to go (remaining time) for interval - PERIOD 36 reset value for interval - QUANT 36 quantum timer (ITS only) - TIME 24 tick delay - DIAG 1 use fixed tick delay instead of autocalibration - -Unless the DIAG flag is set, the timer autocalibrates; the tick delay -is adjusted up or down so that the time base tracks actual elapsed time. -This may cause time-dependent diagnostics to report errors. - -2.6 PC11 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 requires an unsupported driver under TOPS-10 -and is not supported under TOPS-20 or ITS. - -The paper tape reader implements these registers: - - name size comments - - BUF 8 last data item processed - CSR 16 control/status register - INT 1 interrupt pending flag - ERR 1 error flag (CSR<15>) - BUSY 1 busy flag (CSR<11>) - DONE 1 device done flag (CSR<7>) - IE 1 interrupt enable flag (CSR<6>) - 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.7 PC11 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 requires an unsupported driver under TOPS-10 -and is not supported under TOPS-20 or ITS. - -The paper tape punch implements these registers: - - name size comments - - BUF 8 last data item processed - CSR 16 control/status register - INT 1 interrupt pending flag - ERR 1 error flag (CSR<15>) - DONE 1 device done flag (CSR<7>) - IE 1 interrupt enable flag (CSR<6>) - POS 32 position in the input or 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.8 DZ11 Terminal Multiplexor (DZ) - -The DZ11 is an 8-line terminal multiplexor. Up to 4 DZ11's (32 lines) -are supported. The number of lines can be changed with the command - - SET DZ LINES=n set line count to n - -The line count must be a multiple of 8, with a maximum of 32. - -The DZ11 can support 8-bit input and output of characters. 8-bit -output is incompatible with TOPS-20 and is off by default. The command - - SET DZ 8B - -allows output characters to be 8 bits. - -The terminal lines perform input and output through Telnet sessions -connected to a user-specified port. The ATTACH command specifies -the port to be used: - - ATTACH {-am} DZ set up listening port - -where port is a decimal number between 1 and 65535 that is not being used -for other TCP/IP activities. The optional switch -m turns on the DZ11's -modem controls; the optional switch -a turns on active disconnects -(disconnect session if computer clears Data Terminal Ready). Without -modem control, the DZ behaves as though terminals were directly connected; -disconnecting the Telnet session does not cause any operating system- -visible change in line status. - -Once the DZ is attached and the simulator is running, the DZ will listen -for connections on the specified port. It assumes that the incoming -connections are Telnet connections. The connection remains open until -disconnected by the simulated program, the Telnet client, a SET DZ -DISCONNECT command, or a DETACH DZ command. - -The SHOW DZ CONNECTIONS command displays the current connections to the DZ. -The SHOW DZ STATISTICS command displays statistics for active connections. -The SET DZ DISCONNECT=linenumber disconnects the specified line. - -The DZ11 implements these registers: - - name size comments - - CSR[0:3] 16 control/status register, boards 0-3 - RBUF[0:3] 16 receive buffer, boards 0-3 - LPR[0:3] 16 line parameter register, boards 0-3 - TCR[0:3] 16 transmission control register, boards 0-3 - MSR[0:3] 16 modem status register, boards 0-3 - TDR[0:3] 16 transmit data register, boards 0-3 - SAENB[0:3] 1 silo alarm enabled, boards 0-3 - RXINT 4 receive interrupts, boards 3..0 - TXINT 4 transmit interrupts, boards 3..0 - MDMTCL 1 modem control enabled - AUTODS 1 autodisconnect enabled - -The DZ11 does not support save and restore. All open connections are -lost when the simulator shuts down or the DZ is detached. - -2.9 RH11 Adapter, RM02/03/05/80, RP04/05/06/07 drives (RP) - -The RP controller implements the Massbus 18b (RH11) direct interface for -large disk drives. It is more abstract than other device simulators, with -just enough detail to run operating system drivers. In addition, the RP -controller conflates the details of the RM series controllers with the RP -series controllers, although there were detailed differences. - -RP options include the ability to set units write enabled or write locked, -to set the drive type to one of six disk types, or autosize: - - SET RPn LOCKED set unit n write locked - SET RPn WRITEENABLED set unit n write enabled - SET RPn RM03 set type to RM03 - SET RPn RM05 set type to RM05 - SET RPn RM80 set type to RM80 - SET RPn RP04 set type to RP04 - SET RPn RP06 set type to RP06 - SET RPn RP07 set type to RP07 - SET RPn AUTOSIZE set type based on file size at attach - -The type options can be used only when a unit is not attached to a file. -Note that TOPS-10 V7.03 supported only the RP06 and RM03; V7.04 added -support for the RP07. TOPS-20 V4.1 also supported only the RP06 and -RM03. Units can be set ONLINE or OFFLINE. - -The RP controller implements these registers: - - name size comments - - RPCS1 16 control/status 1 - RPWC 16 word count - RPBA 16 bus address - RPDA 16 desired surface, sector - RPCS2 16 control/status 2 - RPDS[0:7] 16 drive status, drives 0-7 - RPER1[0:7] 16 drive errors, drives 0-7 - RPOF 16 offset - RPDC 8 desired cylinder - RPER2 16 error status 2 - RPER3 16 error status 3 - RPEC1 16 ECC syndrome 1 - RPEC2 16 ECC syndrome 2 - RPMR 16 maintenance register - RPDB 16 data buffer - IFF 1 transfer complete interrupt request flop - INT 1 interrupt pending flag - SC 1 special condition (CSR1<15>) - DONE 1 device done flag (CSR1<7>) - IE 1 interrupt enable flag (CSR1<6>) - STIME 24 seek time, per cylinder - RTIME 24 rotational delay - 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 - -2.10 RH11 Adapter, TM02 Formatter, TU45 Magnetic Tape (TU) - -The magnetic tape simulator simulates an RH11 Massbus adapter with one -TM02 formatter and up to eight TU45 drives. Magnetic tape options include -the ability to make units write enabled or locked. - - SET TUn LOCKED set unit n write locked - SET TUn WRITEENABLED set unit n write enabled - -Units can also be set ONLINE or OFFLINE. - -The magnetic tape controller implements these registers: - - name size comments - - MTCS1 16 control/status 1 - MTBA 16 memory address - MTWC 16 word count - MTFC 16 frame count - MTCS2 16 control/status 2 - MTFS 16 formatter status - MTER 16 error status - MTCC 16 check character - MTDB 16 data buffer - MTMR 16 maintenance register - MTTC 16 tape control register - INT 1 interrupt pending flag - DONE 1 device done flag - IE 1 interrupt enable flag - STOP_IOE 1 stop on I/O error - TIME 24 delay - UST[0:7] 16 unit status, units 0-7 - POS[0:7] 32 position, units 0-7 - -Error handling is as follows: - - error processed as - - not attached tape not ready; if STOP_IOE, stop - - end of file operation incomplete - - OS I/O error parity error; if STOP_IOE, stop - -2.11 LP20 DMA Line Printer (LP20) - -The LP20 is a DMA-based line printer controller. There is one -line printer option to clear the vertical forms unit (VFU): - - SET LP20 VFUCLEAR clear the vertical forms unit - -The LP20 implements these registers: - - name size comments - - LPCSA 16 control/status register A - LPCSB 16 control/status register B - LPBA 16 bus address register - LPBC 12 byte count register - LPPAGC 12 page count register - LPRDAT 12 RAM data register - LPCBUF 8 character buffer register - LPCOLC 8 column counter register - LPPDAT 8 printer data register - LPCSUM 8 checksum register - DVPTR 7 vertical forms unit pointer - DVLNT 7 vertical forms unit length - INT 1 interrupt request - ERR 1 error flag - DONE 1 done flag - IE 1 interrupt enable flag - POS 32 position in output file - TIME 24 response time - STOP_IOE 1 stop on I/O error - TXRAM[0:255] 12 translation RAM - DAVFU[0:142] 12 vertical forms unit array - -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.12 RX211/RX02 Floppy Disk (RY) - -RX211 options include the ability to set units write enabled or write -locked, single or double density, or autosized: - - SET RYn LOCKED set unit n write locked - SET RYn WRITEENABLED set unit n write enabled - SET RYn SINGLE set unit n single density - SET RYn DOUBLE set unit n double density (default) - SET RYn AUTOSIZE set unit n autosized - -The floppy disk requires an unsupported driver under TOPS-10 and -is not supported under TOPS-20 or ITS. - -The RX211 implements these registers: - - name size comments - - RYCS 16 status - RYBA 16 buffer address - RYWC 8 word count - RYDB 16 data buffer - RYES 12 error status - RYERR 8 error code - RYTA 8 current track - RYSA 8 current sector - STAPTR 4 controller state - INT 1 interrupt pending flag - ERR 1 error flag (CSR<15>) - TR 1 transfer ready flag (CSR<7>) - IE 1 interrupt enable flag (CSR<6>) - DONE 1 device done flag (CSR<5>) - CTIME 24 command completion time - STIME 24 seek time, per track - XTIME 24 transfer ready delay - STOP_IOE 1 stop on I/O error - SBUF[0:255] 8 sector buffer array - -Error handling is as follows: - - error STOP_IOE processed as - - not attached 1 report error and stop - 0 disk not ready - -RX02 data files are buffered in memory; therefore, end of file and OS -I/O errors cannot occur. - -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: - - -a display as ASCII character - -c display as (sixbit) character string - -p display as packed (seven bit) string - -m display instruction mnemonics - -v interpret address as virtual - -e force executive mode - -u force user mode - -Input parsing is controlled by the first character typed in or by command -line switches: - - ' or -a ASCII character - " or -c sixbit string - # or -p packed seven bit string - alphabetic instruction mnemonic - numeric octal number - -Instruction input uses standard PDP-10 assembler syntax. There are three -instruction classes: memory reference, memory reference with AC, and I/O. - -Memory reference instructions have the format - - memref {@}address{(index)} - -memory reference with AC instructions have the format - - memac ac,{@}address{(index)} - -and I/O instructions have the format - - io device,{@}address{(index)} - -where @ signifies indirect. The address is a signed octal number in the -range 0 - 0777777. The ac and index are unsigned octal numbers in the -range 0-17. The device is either a recognized device mnemonic (APR, PI, -TIM) or an octal number in the range 0 - 0177. - -The simulator recognizes the standard MACRO alternate mnemonics (CLEAR -for SETZ, OR for IORI), the individual definitions for JRST and JFCL -variants, and the extended instruction mnemonics. diff --git a/PDP10/pdp10_fe.c b/PDP10/pdp10_fe.c deleted file mode 100644 index e0f9d1cf..00000000 --- a/PDP10/pdp10_fe.c +++ /dev/null @@ -1,168 +0,0 @@ -/* pdp10_fe.c: PDP-10 front end (console terminal) simulator - - 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. - - fe KS10 console front end - - 25-Apr-03 RMS Revised for extended file support - 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 - 07-Sep-01 RMS Moved function prototypes -*/ - -#include "pdp10_defs.h" -#define UNIT_DUMMY (1 << UNIT_V_UF) - -extern d10 *M; -extern int32 apr_flg; -t_stat fei_svc (UNIT *uptr); -t_stat feo_svc (UNIT *uptr); -t_stat fe_reset (DEVICE *dptr); -t_stat fe_stop_os (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat fe_ctrl_c (UNIT *uptr, int32 val, char *cptr, void *desc); - -/* FE data structures - - fe_dev FE device descriptor - fe_unit FE unit descriptor - fe_reg FE register list -*/ - -#define fei_unit fe_unit[0] -#define feo_unit fe_unit[1] - -UNIT fe_unit[] = { - { UDATA (&fei_svc, 0, 0), KBD_POLL_WAIT }, - { UDATA (&feo_svc, 0, 0), SERIAL_OUT_WAIT } }; - -REG fe_reg[] = { - { ORDATA (IBUF, fei_unit.buf, 8) }, - { DRDATA (ICOUNT, fei_unit.pos, T_ADDR_W), REG_RO + PV_LEFT }, - { DRDATA (ITIME, fei_unit.wait, 24), REG_NZ + PV_LEFT }, - { ORDATA (OBUF, feo_unit.buf, 8) }, - { DRDATA (OCOUNT, feo_unit.pos, T_ADDR_W), REG_RO + PV_LEFT }, - { DRDATA (OTIME, feo_unit.wait, 24), REG_NZ + PV_LEFT }, - { NULL } }; - -MTAB fe_mod[] = { - { UNIT_DUMMY, 0, NULL, "STOP", &fe_stop_os }, - { UNIT_DUMMY, 0, NULL, "CTRL-C", &fe_ctrl_c }, - { 0 } }; - -DEVICE fe_dev = { - "FE", fe_unit, fe_reg, fe_mod, - 2, 10, 31, 1, 8, 8, - NULL, NULL, &fe_reset, - NULL, NULL, NULL }; - -/* Front end processor (console terminal) - - Communications between the KS10 and its front end is based on an in-memory - status block and two interrupt lines: interrupt-to-control (APR_ITC) and - interrupt-from-console (APR_CON). When the KS10 wants to print a character - on the terminal, - - 1. It places a character, plus the valid flag, in FE_CTYOUT. - 2. It interrupts the front end processor. - 3. The front end processor types the character and then zeroes FE_CTYOUT. - 4. The front end procesor interrupts the KS10. - - When the front end wants to send an input character to the KS10, - - 1. It places a character, plus the valid flag, in FE_CTYIN. - 2. It interrupts the KS10. - 3. It waits for the KS10 to take the character and clear the valid flag. - 4. It can then send more input (the KS10 may signal this by interrupting - the front end). - - Note that the protocol has both ambiguity (interrupt to the KS10 may mean - character printed, or input character available, or both) and lack of - symmetry (the KS10 does not inform the front end that it has taken an - input character). -*/ - -void fe_intr (void) -{ -if (M[FE_CTYOUT] & FE_CVALID) { /* char to print? */ - feo_unit.buf = (int32) M[FE_CTYOUT] & 0177; /* pick it up */ - sim_putchar (feo_unit.buf); /* type it */ - feo_unit.pos = feo_unit.pos + 1; - sim_activate (&feo_unit, feo_unit.time); } /* sched completion */ -else if ((M[FE_CTYIN] & FE_CVALID) == 0) { /* input char taken? */ - sim_cancel (&fei_unit); /* sched immediate */ - sim_activate (&fei_unit, 0); }; /* keyboard poll */ -return; -} - -t_stat feo_svc (UNIT *uptr) -{ -M[FE_CTYOUT] = 0; /* clear char */ -apr_flg = apr_flg | APRF_CON; /* interrupt KS10 */ -return SCPE_OK; -} - -t_stat fei_svc (UNIT *uptr) -{ -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 */ -apr_flg = apr_flg | APRF_CON; /* interrupt KS10 */ -return SCPE_OK; -} - -/* Reset */ - -t_stat fe_reset (DEVICE *dptr) -{ -fei_unit.buf = feo_unit.buf = 0; -M[FE_CTYIN] = M[FE_CTYOUT] = 0; -apr_flg = apr_flg & ~(APRF_ITC | APRF_CON); -sim_activate (&fei_unit, fei_unit.wait); /* start input poll */ -return SCPE_OK; -} - -/* Stop operating system */ - -t_stat fe_stop_os (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -M[FE_SWITCH] = IOBA_RP; /* tell OS to stop */ -return SCPE_OK; -} - -/* Enter control-C for Windoze */ - -t_stat fe_ctrl_c (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -fei_unit.buf = 003; /* control-C */ -M[FE_CTYIN] = fei_unit.buf | FE_CVALID; /* put char in mem */ -apr_flg = apr_flg | APRF_CON; /* interrupt KS10 */ -return SCPE_OK; -} diff --git a/PDP10/pdp10_ksio.c b/PDP10/pdp10_ksio.c deleted file mode 100644 index ec54d729..00000000 --- a/PDP10/pdp10_ksio.c +++ /dev/null @@ -1,797 +0,0 @@ -/* pdp10_ksio.c: PDP-10 KS10 I/O subsystem simulator - - 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. - - uba Unibus adapters - - 12-Mar-03 RMS Added logical name support - 10-Oct-02 RMS Revised for dynamic table generation - Added SHOW IOSPACE routine - 29-Sep-02 RMS Added variable vector, central map support - 25-Jan-02 RMS Revised for multiple DZ11's - 06-Jan-02 RMS Revised enable/disable support - 23-Sep-01 RMS New IO page address constants - 07-Sep-01 RMS Revised device disable mechanism - 25-Aug-01 RMS Enabled DZ11 - 21-Aug-01 RMS Updated DZ11 disable - 01-Jun-01 RMS Updated DZ11 vectors - 12-May-01 RMS Fixed typo - - The KS10 uses the PDP-11 Unibus for its I/O, via adapters. While - nominally four adapters are supported, in practice only 1 and 3 - are implemented. The disks are placed on adapter 1, the rest of - the I/O devices on adapter 3. - - In theory, we should maintain completely separate Unibuses, with - distinct PI systems. In practice, this simulator has so few devices - that we can get away with a single PI system, masking for which - devices are on adapter 1, and which on adapter 3. The Unibus - implementation is modeled on the Qbus in the PDP-11 simulator and - is described there. - - The I/O subsystem is programmed by I/O instructions which create - Unibus operations (read, read pause, write, write byte). DMA is - the responsibility of the I/O device simulators, which also implement - Unibus to physical memory mapping. - - The priority interrupt subsystem (and other privileged functions) - is programmed by I/O instructions with internal devices codes - (opcodes 700-702). These are dispatched here, although many are - handled in the memory management unit or elsewhere. - - The ITS instructions are significantly different from the TOPS-10/20 - instructions. They do not use the extended address calculation but - instead provide instruction variants (Q for Unibus adapter 1, I for - Unibus adapter 3) which insert the Unibus adapter number into the - effective address. -*/ - -#include "pdp10_defs.h" -#include - -#define XBA_MBZ 0400000 /* ba mbz */ -#define eaRB (ea & ~1) -#define GETBYTE(ea,x) ((((ea) & 1)? (x) >> 8: (x)) & 0377) -#define UBNXM_FAIL(pa,op) \ - n = iocmap[GET_IOUBA (pa)]; \ - if (n >= 0) ubcs[n] = ubcs[n] | UBCS_TMO | UBCS_NXD; \ - pager_word = PF_HARD | PF_VIRT | PF_IO | \ - ((op == WRITEB)? PF_BYTE: 0) | \ - (TSTF (F_USR)? PF_USER: 0) | (pa); \ - ABORT (PAGE_FAIL) - -/* Unibus adapter data */ - -int32 ubcs[UBANUM] = { 0 }; /* status registers */ -int32 ubmap[UBANUM][UMAP_MEMSIZE] = { 0 }; /* Unibus maps */ -int32 int_req = 0; /* interrupt requests */ - -/* Map IO controller numbers to Unibus adapters: -1 = non-existent */ - -static int iocmap[IO_N_UBA] = { /* map I/O ext to UBA # */ - -1, 0, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }; - -static const int32 ubabr76[UBANUM] = { - INT_UB1 & (INT_IPL7 | INT_IPL6), INT_UB3 & (INT_IPL7 | INT_IPL6) }; -static const int32 ubabr54[UBANUM] = { - INT_UB1 & (INT_IPL5 | INT_IPL4), INT_UB3 & (INT_IPL5 | INT_IPL4) }; -static const int32 ubashf[4] = { 18, 26, 0, 8 }; - -extern d10 *M; /* main memory */ -extern d10 *ac_cur; -extern d10 pager_word; -extern int32 flags, pi_l2bit[8]; -extern UNIT cpu_unit; -extern FILE *sim_log; -extern jmp_buf save_env; -extern DEVICE *sim_devices[]; - -extern d10 Read (a10 ea); -extern void pi_eval (); -extern int32 rp_inta (void); -extern int32 tu_inta (void); -extern int32 lp20_inta (void); -extern int32 dz_rxinta (void); -extern int32 dz_txinta (void); - -t_stat ubmap_rd (int32 *data, int32 addr, int32 access); -t_stat ubmap_wr (int32 data, int32 addr, int32 access); -t_stat ubs_rd (int32 *data, int32 addr, int32 access); -t_stat ubs_wr (int32 data, int32 addr, int32 access); -t_stat rd_zro (int32 *data, int32 addr, int32 access); -t_stat wr_nop (int32 data, int32 addr, int32 access); -t_stat uba_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw); -t_stat uba_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw); -t_stat uba_reset (DEVICE *dptr); -d10 ReadIO (a10 ea); -void WriteIO (a10 ea, d10 val, int32 mode); - -/* Unibus adapter data structures - - uba_dev UBA device descriptor - uba_unit UBA units - uba_reg UBA register list -*/ - -DIB ubmp1_dib = { IOBA_UBMAP1, IOLN_UBMAP1, &ubmap_rd, &ubmap_wr, 0 }; -DIB ubmp3_dib = { IOBA_UBMAP3, IOLN_UBMAP3, &ubmap_rd, &ubmap_wr, 0 }; -DIB ubcs1_dib = { IOBA_UBCS1, IOLN_UBCS1, &ubs_rd, &ubs_wr, 0 }; -DIB ubcs3_dib = { IOBA_UBCS3, IOLN_UBCS3, &ubs_rd, &ubs_wr, 0 }; -DIB ubmn1_dib = { IOBA_UBMNT1, IOLN_UBMNT1, &rd_zro, &wr_nop, 0 }; -DIB ubmn3_dib = { IOBA_UBMNT3, IOLN_UBMNT3, &rd_zro, &wr_nop, 0 }; -DIB msys_dib = { 00100000, 1, &rd_zro, &wr_nop, 0 }; - -UNIT uba_unit[] = { - { UDATA (NULL, UNIT_FIX, UMAP_MEMSIZE) }, - { UDATA (NULL, UNIT_FIX, UMAP_MEMSIZE) } }; - -REG uba_reg[] = { - { ORDATA (INTREQ, int_req, 32), REG_RO }, - { ORDATA (UB1CS, ubcs[0], 18) }, - { ORDATA (UB3CS, ubcs[1], 18) }, - { NULL } }; - -DEVICE uba_dev = { - "UBA", uba_unit, uba_reg, NULL, - UBANUM, 8, UMAP_ASIZE, 1, 8, 32, - &uba_ex, &uba_dep, &uba_reset, - NULL, NULL, NULL, - NULL, 0 }; - -/* PDP-11 I/O structures */ - -DIB *dib_tab[DIB_MAX]; /* run-time DIBs */ - -int32 (*int_ack[32])(void); /* int ack routines */ - -int32 int_vec[32]; /* int vectors */ - -DIB *std_dib[] = { /* standard DIBs */ - &ubmp1_dib, - &ubmp3_dib, - &ubcs1_dib, - &ubcs3_dib, - &ubmn1_dib, - &ubmn3_dib, - &msys_dib, - NULL }; - -/* IO 710 (DEC) TIOE - test I/O word, skip if zero - (ITS) IORDI - read word from Unibus 3 - returns TRUE if skip, FALSE otherwise -*/ - -t_bool io710 (int32 ac, a10 ea) -{ -d10 val; - -if (ITS) AC(ac) = ReadIO (IO_UBA3 | ea); /* IORDI */ -else { /* TIOE */ - val = ReadIO (ea); /* read word */ - if ((AC(ac) & val) == 0) return TRUE; } -return FALSE; -} - -/* IO 711 (DEC) TION - test I/O word, skip if non-zero - (ITS) IORDQ - read word from Unibus 1 - returns TRUE if skip, FALSE otherwise -*/ - -t_bool io711 (int32 ac, a10 ea) -{ -d10 val; - -if (ITS) AC(ac) = ReadIO (IO_UBA1 | ea); /* IORDQ */ -else { /* TION */ - val = ReadIO (ea); /* read word */ - if ((AC(ac) & val) != 0) return TRUE; } -return FALSE; -} - -/* IO 712 (DEC) RDIO - read I/O word, addr in ea - (ITS) IORD - read I/O word, addr in M[ea] -*/ - -d10 io712 (a10 ea) -{ -return ReadIO (ea); /* RDIO, IORD */ -} - -/* IO 713 (DEC) WRIO - write I/O word, addr in ea - (ITS) IOWR - write I/O word, addr in M[ea] -*/ - -void io713 (d10 val, a10 ea) -{ -WriteIO (ea, val & 0177777, WRITE); /* WRIO, IOWR */ -return; -} - -/* IO 714 (DEC) BSIO - set bit in I/O address - (ITS) IOWRI - write word to Unibus 3 -*/ - -void io714 (d10 val, a10 ea) -{ -d10 temp; - -val = val & 0177777; -if (ITS) WriteIO (IO_UBA3 | ea, val, WRITE); /* IOWRI */ -else { - temp = ReadIO (ea); /* BSIO */ - temp = temp | val; - WriteIO (ea, temp, WRITE); } -return; -} - -/* IO 715 (DEC) BCIO - clear bit in I/O address - (ITS) IOWRQ - write word to Unibus 1 -*/ - -void io715 (d10 val, a10 ea) -{ -d10 temp; - -val = val & 0177777; -if (ITS) WriteIO (IO_UBA1 | ea, val, WRITE); /* IOWRQ */ -else { - temp = ReadIO (ea); /* BCIO */ - temp = temp & ~val; - WriteIO (ea, temp, WRITE); } -return; -} - -/* IO 720 (DEC) TIOEB - test I/O byte, skip if zero - (ITS) IORDBI - read byte from Unibus 3 - returns TRUE if skip, FALSE otherwise -*/ - -t_bool io720 (int32 ac, a10 ea) -{ -d10 val; - -if (ITS) { /* IORDBI */ - val = ReadIO (IO_UBA3 | eaRB); - AC(ac) = GETBYTE (ea, val); } -else { /* TIOEB */ - val = ReadIO (eaRB); - val = GETBYTE (ea, val); - if ((AC(ac) & val) == 0) return TRUE; } -return FALSE; -} - -/* IO 721 (DEC) TIONB - test I/O word, skip if non-zero - (ITS) IORDBQ - read word from Unibus 1 - returns TRUE if skip, FALSE otherwise -*/ - -t_bool io721 (int32 ac, a10 ea) -{ -d10 val; - -if (ITS) { /* IORDBQ */ - val = ReadIO (IO_UBA1 | eaRB); - AC(ac) = GETBYTE (ea, val); } -else { /* TIONB */ - val = ReadIO (eaRB); - val = GETBYTE (ea, val); - if ((AC(ac) & val) != 0) return TRUE; } -return FALSE; -} - -/* IO 722 (DEC) RDIOB - read I/O byte, addr in ea - (ITS) IORDB - read I/O byte, addr in M[ea] -*/ - -d10 io722 (a10 ea) -{ -d10 val; - -val = ReadIO (eaRB); /* RDIOB, IORDB */ -return GETBYTE (ea, val); -} - -/* IO 723 (DEC) WRIOB - write I/O byte, addr in ea - (ITS) IOWRB - write I/O byte, addr in M[ea] -*/ - -void io723 (d10 val, a10 ea) -{ -WriteIO (ea, val & 0377, WRITEB); /* WRIOB, IOWRB */ -return; -} - -/* IO 724 (DEC) BSIOB - set bit in I/O byte address - (ITS) IOWRBI - write byte to Unibus 3 -*/ - -void io724 (d10 val, a10 ea) -{ -d10 temp; - -val = val & 0377; -if (ITS) WriteIO (IO_UBA3 | ea, val, WRITEB); /* IOWRBI */ -else { - temp = ReadIO (eaRB); /* BSIOB */ - temp = GETBYTE (ea, temp); - temp = temp | val; - WriteIO (ea, temp, WRITEB); } -return; -} - -/* IO 725 (DEC) BCIOB - clear bit in I/O byte address - (ITS) IOWRBQ - write byte to Unibus 1 -*/ - -void io725 (d10 val, a10 ea) -{ -d10 temp; - -val = val & 0377; -if (ITS) WriteIO (IO_UBA1 | ea, val, WRITEB); /* IOWRBQ */ -else { - temp = ReadIO (eaRB); /* BCIOB */ - temp = GETBYTE (ea, temp); - temp = temp & ~val; - WriteIO (ea, temp, WRITEB); } -return; -} - -/* Read and write I/O devices. - These routines are the linkage between the 64b world of the main - simulator and the 32b world of the device simulators. -*/ - -d10 ReadIO (a10 ea) -{ -uint32 pa = (uint32) ea; -int32 i, n, val; -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); } } -UBNXM_FAIL (pa, READ); -} - -void WriteIO (a10 ea, d10 val, int32 mode) -{ -uint32 pa = (uint32) ea; -int32 i, n; -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; } } -UBNXM_FAIL (pa, mode); -} - -/* Mapped read and write routines - used by word-oriented Unibus devices */ - -a10 Map_Addr10 (a10 ba, int32 ub) -{ -a10 pa10; -int32 vpn = PAG_GETVPN (ba >> 2); /* get PDP-10 page number */ - -if ((vpn >= UMAP_MEMSIZE) || (ba & XBA_MBZ) || - ((ubmap[ub][vpn] & UMAP_VLD) == 0)) return -1; /* invalid map? */ -pa10 = (ubmap[ub][vpn] + PAG_GETOFF (ba >> 2)) & PAMASK; -return pa10; -} - -int32 Map_ReadB (uint32 ba, int32 bc, uint8 *buf, t_bool ub) -{ -uint32 lim; -a10 pa10; - -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 */ - *buf++ = (uint8) ((M[pa10] >> ubashf[ba & 3]) & 0377); - } -return 0; -} - -int32 Map_ReadW (uint32 ba, int32 bc, uint16 *buf, t_bool ub) -{ -uint32 lim; -a10 pa10; - -ba = ba & ~01; /* align start */ -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 */ - *buf++ = (uint16) ((M[pa10] >> ((ba & 2)? 0: 18)) & 0177777); - } -return 0; -} - -int32 Map_WriteB (uint32 ba, int32 bc, uint8 *buf, t_bool ub) -{ -uint32 lim; -a10 pa10; -static d10 mask = 0377; - -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 */ - M[pa10] = (M[pa10] & ~(mask << ubashf[ba & 3])) | - (((d10) *buf++) << ubashf[ba & 3]); } -return 0; -} - -int32 Map_WriteW (uint32 ba, int32 bc, uint16 *buf, t_bool ub) -{ -uint32 lim; -a10 pa10; -d10 val; - -ba = ba & ~01; /* align start */ -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 */ - val = *buf++; /* get data */ - if (ba & 2) M[pa10] = (M[pa10] & 0777777600000) | val; - else M[pa10] = (M[pa10] & 0600000777777) | (val << 18); - } -return 0; -} - -/* Evaluate Unibus priority interrupts */ - -int32 pi_ub_eval () -{ -int32 i, lvl; - -for (i = lvl = 0; i < UBANUM; i++) { - if (int_req & ubabr76[i]) - lvl = lvl | pi_l2bit[UBCS_GET_HI (ubcs[i])]; - if (int_req & ubabr54[i]) - lvl = lvl | pi_l2bit[UBCS_GET_LO (ubcs[i])]; } -return lvl; -} - -/* Return Unibus device vector - - Takes as input the request level calculated by pi_eval - If there is an interrupting Unibus device at that level, return its vector, - otherwise, returns 0 -*/ - -int32 pi_ub_vec (int32 rlvl, int32 *uba) -{ -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; - if ((rlvl == UBCS_GET_LO (ubcs[i])) && /* req on lo level? */ - (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 */ -return 0; -} - -/* Unibus adapter map routines */ - -t_stat ubmap_rd (int32 *val, int32 pa, int32 mode) -{ -int32 n = iocmap[GET_IOUBA (pa)]; - -if (n < 0) ABORT (STOP_ILLIOC); -*val = ubmap[n][pa & UMAP_AMASK]; -return SCPE_OK; -} - -t_stat ubmap_wr (int32 val, int32 pa, int32 mode) -{ -int32 n = iocmap[GET_IOUBA (pa)]; - -if (n < 0) ABORT (STOP_ILLIOC); -ubmap[n][pa & UMAP_AMASK] = UMAP_POSFL (val) | UMAP_POSPN (val); -return SCPE_OK; -} - -/* Unibus adapter control/status routines */ - -t_stat ubs_rd (int32 *val, int32 pa, int32 mode) -{ -int32 n = iocmap[GET_IOUBA (pa)]; - -if (n < 0) ABORT (STOP_ILLIOC); -if (int_req & ubabr76[n]) ubcs[n] = ubcs[n] | UBCS_HI; -if (int_req & ubabr54[n]) ubcs[n] = ubcs[n] | UBCS_LO; -*val = ubcs[n] = ubcs[n] & ~UBCS_RDZ; -return SCPE_OK; -} - -t_stat ubs_wr (int32 val, int32 pa, int32 mode) -{ -int32 n = iocmap[GET_IOUBA (pa)]; - -if (n < 0) ABORT (STOP_ILLIOC); -if (val & UBCS_INI) { - reset_all (5); /* start after UBA */ - ubcs[n] = val & UBCS_DXF; } -else ubcs[n] = val & UBCS_RDW; -if (int_req & ubabr76[n]) ubcs[n] = ubcs[n] | UBCS_HI; -if (int_req & ubabr54[n]) ubcs[n] = ubcs[n] | UBCS_LO; -return SCPE_OK; -} - -/* Unibus adapter read zero/write ignore routines */ - -t_stat rd_zro (int32 *val, int32 pa, int32 mode) -{ -*val = 0; -return SCPE_OK; -} - -t_stat wr_nop (int32 val, int32 pa, int32 mode) -{ -return SCPE_OK; -} - -t_stat uba_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) -{ -int32 uba = uptr - uba_unit; - -if (addr >= UMAP_MEMSIZE) return SCPE_NXM; -*vptr = ubmap[uba][addr]; -return SCPE_OK; -} - -t_stat uba_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw) -{ -int32 uba = uptr - uba_unit; - -if (addr >= UMAP_MEMSIZE) return SCPE_NXM; -ubmap[uba][addr] = (int32) val & UMAP_MASK; -return SCPE_OK; -} - -t_stat uba_reset (DEVICE *dptr) -{ -int32 i, uba; - -int_req = 0; -for (uba = 0; uba < UBANUM; uba++) { - ubcs[uba] = 0; - for (i = 0; i < UMAP_MEMSIZE; i++) ubmap[uba][i] = 0; } -pi_eval (); -return SCPE_OK; -} - -/* Change device address */ - -t_stat set_addr (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -DEVICE *dptr; -DIB *dibp; -uint32 newba; -t_stat r; - -if (cptr == NULL) return SCPE_ARG; -if ((val == 0) || (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; -newba = (uint32) get_uint (cptr, 8, PAMASK, &r); /* get new */ -if ((r != SCPE_OK) || (newba == dibp->ba)) return r; -if (GET_IOUBA (newba) != GET_IOUBA (dibp->ba)) return SCPE_ARG; -if (newba % ((uint32) val)) return SCPE_ARG; /* check modulus */ -if (GET_IOUBA (newba) != GET_IOUBA (dibp->ba)) return SCPE_ARG; -dibp->ba = newba; /* store */ -return SCPE_OK; -} - -/* Show device address */ - -t_stat show_addr (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->ba <= IOPAGEBASE)) return SCPE_IERR; -fprintf (st, "address=%07o", dibp->ba); -if (dibp->lnt > 1) - fprintf (st, "-%07o", dibp->ba + dibp->lnt - 1); -return SCPE_OK; -} - -/* Change device vector */ - -t_stat set_vec (UNIT *uptr, int32 arg, char *cptr, void *desc) -{ -DEVICE *dptr; -DIB *dibp; -uint32 newvec; -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; -newvec = (uint32) get_uint (cptr, 8, VEC_Q + 01000, &r); -if ((r != SCPE_OK) || (newvec <= VEC_Q) || - ((newvec + (dibp->vnum * 4)) >= (VEC_Q + 01000)) || - (newvec & ((dibp->vnum > 1)? 07: 03))) return SCPE_ARG; -dibp->vec = newvec; -return SCPE_OK; -} - -/* Show device vector */ - -t_stat show_vec (FILE *st, UNIT *uptr, int32 arg, void *desc) -{ -DEVICE *dptr; -DIB *dibp; -uint32 vec, numvec; - -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; -vec = dibp->vec; -if (arg) numvec = arg; -else numvec = dibp->vnum; -if (vec == 0) fprintf (st, "no vector"); -else { fprintf (st, "vector=%o", vec); - if (numvec > 1) fprintf (st, "-%o", vec + (4 * (numvec - 1))); } -return SCPE_OK; -} - -/* Test for conflict in device addresses */ - -t_bool dev_conflict (DIB *curr) -{ -uint32 i, end; -DEVICE *dptr; -DIB *dibp; - -end = curr->ba + curr->lnt - 1; /* get end */ -for (i = 0; (dptr = sim_devices[i]) != NULL; i++) { /* loop thru dev */ - dibp = (DIB *) dptr->ctxt; /* get DIB */ - if ((dibp == NULL) || (dibp == curr) || - (dptr->flags & DEV_DIS)) continue; - if (((curr->ba >= dibp->ba) && /* overlap start? */ - (curr->ba < (dibp->ba + dibp->lnt))) || - ((end >= dibp->ba) && /* overlap end? */ - (end < (dibp->ba + dibp->lnt)))) { - printf ("Device %s address conflict at %08o\n", - sim_dname (dptr), dibp->ba); - if (sim_log) fprintf (sim_log, - "Device %s address conflict at %08o\n", - sim_dname (dptr), dibp->ba); - return TRUE; } } -return FALSE; -} - -/* Build interrupt tables */ - -void build_int_vec (int32 vloc, int32 ivec, int32 (*iack)(void) ) -{ -if (iack != NULL) int_ack[vloc] = iack; -else int_vec[vloc] = ivec; -return; -} - -/* Build dib_tab from device list */ - -t_bool build_dib_tab (void) -{ -int32 i, j, k; -DEVICE *dptr; -DIB *dibp; - -for (i = 0; i < 32; i++) { /* clear intr tables */ - int_vec[i] = 0; - int_ack[i] = NULL; } -for (i = j = 0; (dptr = sim_devices[i]) != NULL; i++) { /* loop thru dev */ - dibp = (DIB *) dptr->ctxt; /* get DIB */ - if (dibp && !(dptr->flags & DEV_DIS)) { /* defined, enabled? */ - if (dibp->vnum > VEC_DEVMAX) return SCPE_IERR; - for (k = 0; k < dibp->vnum; k++) /* loop thru vec */ - build_int_vec (dibp->vloc + k, /* add vector */ - dibp->vec + (k * 4), dibp->ack[k]); - if (dibp->lnt != 0) { /* I/O addresses? */ - dib_tab[j++] = dibp; /* add DIB to dib_tab */ - if (j >= DIB_MAX) return SCPE_IERR; } /* too many? */ - } /* end if enabled */ - } /* end for */ -for (i = 0; (dibp = std_dib[i]) != NULL; i++) { /* loop thru std */ - dib_tab[j++] = dibp; /* add to dib_tab */ - if (j >= DIB_MAX) return SCPE_IERR; } /* too many? */ -dib_tab[j] = NULL; /* end with NULL */ -for (i = 0; (dibp = dib_tab[i]) != NULL; i++) { /* test built dib_tab */ - if (dev_conflict (dibp)) return SCPE_STOP; } /* for conflicts */ -return SCPE_OK; -} - -/* Show dib_tab */ - -t_stat show_iospace (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -int32 i, j, done = 0; -DEVICE *dptr; -DIB *dibt; - -build_dib_tab (); /* build table */ -while (done == 0) { /* sort ascending */ - done = 1; /* assume done */ - for (i = 0; dib_tab[i + 1] != NULL; i++) { /* check table */ - if (dib_tab[i]->ba > dib_tab[i + 1]->ba) { /* out of order? */ - dibt = dib_tab[i]; /* interchange */ - dib_tab[i] = dib_tab[i + 1]; - dib_tab[i + 1] = dibt; - done = 0; } } /* not done */ - } /* end while */ -for (i = 0; dib_tab[i] != NULL; i++) { /* print table */ - for (j = 0, dptr = NULL; sim_devices[j] != NULL; j++) { - if (((DIB*) sim_devices[j]->ctxt) == dib_tab[i]) { - dptr = sim_devices[j]; - break; } } - fprintf (st, "%07o - %07o\t%s\n", dib_tab[i]->ba, - dib_tab[i]->ba + dib_tab[i]->lnt - 1, - dptr? sim_dname (dptr): "CPU"); - } -return SCPE_OK; -} - -/* Stub auto-configure */ - -t_stat auto_config (uint32 rank, uint32 num) -{ -return SCPE_OK; -} diff --git a/PDP10/pdp10_lp20.c b/PDP10/pdp10_lp20.c deleted file mode 100644 index 343994ae..00000000 --- a/PDP10/pdp10_lp20.c +++ /dev/null @@ -1,599 +0,0 @@ -/* pdp10_lp20.c: PDP-10 LP20 line printer simulator - - 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. - - lp20 line printer - - 25-Apr-03 RMS Revised for extended file support - 29-Sep-02 RMS Added variable vector support - Modified to use common Unibus routines - New data structures - 30-May-02 RMS Widened POS to 32b - 06-Jan-02 RMS Added enable/disable support - 30-Nov-01 RMS Added extended SET/SHOW support -*/ - -#include "pdp10_defs.h" - -#define UNIT_DUMMY (1 << UNIT_V_UF) -#define LP_WIDTH 132 /* printer width */ - -/* DAVFU RAM */ - -#define DV_SIZE 143 /* DAVFU size */ -#define DV_DMASK 077 /* data mask per byte */ -#define DV_TOF 0 /* top of form channel */ -#define DV_MAX 11 /* max channel number */ - -/* Translation RAM */ - -#define TX_SIZE 256 /* translation RAM */ -#define TX_AMASK (TX_SIZE - 1) -#define TX_DMASK 07777 -#define TX_V_FL 8 /* flags */ -#define TX_M_FL 017 -/* define TX_INTR 04000 /* interrupt */ -#define TX_DELH 02000 /* delimiter */ -/* define TX_XLAT 01000 /* translate */ -/* define TX_DVFU 00400 /* DAVFU */ -#define TX_SLEW 00020 /* chan vs slew */ -#define TX_VMASK 00017 /* spacing mask */ -#define TX_CHR 0 /* states: pr char */ -#define TX_RAM 1 /* pr translation */ -#define TX_DVU 2 /* DAVFU action */ -#define TX_INT 3 /* interrupt */ -#define TX_GETFL(x) (((x) >> TX_V_FL) & TX_M_FL) - -/* LPCSRA (765400) */ - -#define CSA_GO 0000001 /* go */ -#define CSA_PAR 0000002 /* parity enable NI */ -#define CSA_V_FNC 2 /* function */ -#define CSA_M_FNC 03 -#define FNC_PR 0 /* print */ -#define FNC_TST 1 /* test */ -#define FNC_DVU 2 /* load DAVFU */ -#define FNC_RAM 3 /* load translation RAM */ -#define FNC_INTERNAL 1 /* internal function */ -#define CSA_FNC (CSA_M_FNC << CSA_V_FNC) -#define CSA_V_UAE 4 /* Unibus addr extension */ -#define CSA_UAE (03 << CSA_V_UAE) -#define CSA_IE 0000100 /* interrupt enable */ -#define CSA_DONE 0000200 /* done */ -#define CSA_INIT 0000400 /* init */ -#define CSA_ECLR 0001000 /* clear errors */ -#define CSA_DELH 0002000 /* delimiter hold */ -#define CSA_ONL 0004000 /* online */ -#define CSA_DVON 0010000 /* DAVFU online */ -#define CSA_UNDF 0020000 /* undefined char */ -#define CSA_PZRO 0040000 /* page counter zero */ -#define CSA_ERR 0100000 /* error */ -#define CSA_RW (CSA_DELH | CSA_IE | CSA_UAE | CSA_FNC | CSA_PAR | CSA_GO) -#define CSA_MBZ (CSA_ECLR | CSA_INIT) -#define CSA_GETUAE(x) (((x) & CSA_UAE) << (16 - CSA_V_UAE)) -#define CSA_GETFNC(x) (((x) >> CSA_V_FNC) & CSA_M_FNC) - -/* LPCSRB (765402) */ - -#define CSB_GOE 0000001 /* go error */ -#define CSB_DTE 0000002 /* DEM timing error NI */ -#define CSB_MTE 0000004 /* MSYN error (Ubus timeout) */ -#define CSB_RPE 0000010 /* RAM parity error NI */ -#define CSB_MPE 0000020 /* MEM parity error NI */ -#define CSB_LPE 0000040 /* LPT parity error NI */ -#define CSB_DVOF 0000100 /* DAVFU not ready */ -#define CSB_OFFL 0000200 /* offline */ -#define CSB_TEST 0003400 /* test mode */ -#define CSB_OVFU 0004000 /* optical VFU NI */ -#define CSB_PBIT 0010000 /* data parity bit NI */ -#define CSB_NRDY 0020000 /* printer error NI */ -#define CSB_LA180 0040000 /* LA180 printer NI */ -#define CSB_VLD 0100000 /* valid data NI */ -#define CSB_ECLR (CSB_GOE | CSB_DTE | CSB_MTE | CSB_RPE | CSB_MPE | CSB_LPE) -#define CSB_ERR (CSB_ECLR | CSB_DVOF | CSB_OFFL) -#define CSB_RW CSB_TEST -#define CSB_MBZ (CSB_DTE | CSB_RPE | CSB_MPE | CSB_LPE | CSB_OVFU |\ - CSB_PBIT | CSB_NRDY | CSB_LA180 | CSB_VLD) - -/* LPBA (765404) */ - -/* LPBC (765506) */ - -#define BC_MASK 0007777 /* <15:12> MBZ */ - -/* LPPAGC (765510) */ - -#define PAGC_MASK 0007777 /* <15:12> MBZ */ - -/* LPRDAT (765512) */ - -#define RDAT_MASK 0007777 /* <15:12> MBZ */ - -/* LPCOLC/LPCBUF (765514) */ - -/* LPCSUM/LPPDAT (765516) */ - -extern d10 *M; /* main memory */ -extern int32 int_req; -extern int32 int_vec[32]; -extern int32 ubcs[UBANUM]; /* UBA csr */ -extern int32 ubmap[UBANUM][UMAP_MEMSIZE]; /* UBA map */ - -int32 lpcsa = 0; /* control/status A */ -int32 lpcsb = 0; /* control/status B */ -int32 lpba = 0; /* bus address */ -int32 lpbc = 0; /* byte count */ -int32 lppagc = 0; /* page count */ -int32 lprdat = 0; /* RAM data */ -int32 lpcbuf = 0; /* character buffer */ -int32 lpcolc = 0; /* column count */ -int32 lppdat = 0; /* printer data */ -int32 lpcsum = 0; /* checksum */ -int32 dvptr = 0; /* davfu pointer */ -int32 dvlnt = 0; /* davfu length */ -int32 lp20_irq = 0; /* int request */ -int32 lp20_stopioe = 0; /* stop on error */ -int16 txram[TX_SIZE] = { 0 }; /* translation RAM */ -int16 davfu[DV_SIZE] = { 0 }; /* DAVFU */ - -DEVICE lp20_dev; -t_stat lp20_rd (int32 *data, int32 pa, int32 access); -t_stat lp20_wr (int32 data, int32 pa, int32 access); -int32 lp20_inta (void); -t_stat lp20_svc (UNIT *uptr); -t_stat lp20_reset (DEVICE *dptr); -t_stat lp20_attach (UNIT *uptr, char *ptr); -t_stat lp20_detach (UNIT *uptr); -t_stat lp20_clear_vfu (UNIT *uptr, int32 val, char *cptr, void *desc); -t_bool lp20_print (int32 c); -t_bool lp20_adv (int32 c, t_bool advdvu); -t_bool lp20_davfu (int32 c); -void update_lpcs (int32 flg); - -/* LP data structures - - lp20_dev LPT device descriptor - lp20_unit LPT unit descriptor - lp20_reg LPT register list -*/ - -DIB lp20_dib = { IOBA_LP20, IOLN_LP20, &lp20_rd, &lp20_wr, - 1, IVCL (LP20), VEC_LP20, { &lp20_inta } }; - -UNIT lp20_unit = { - UDATA (&lp20_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT }; - -REG lp20_reg[] = { - { ORDATA (LPCSA, lpcsa, 16) }, - { ORDATA (LPCSB, lpcsb, 16) }, - { ORDATA (LPBA, lpba, 16) }, - { ORDATA (LPBC, lpbc, 12) }, - { ORDATA (LPPAGC, lppagc, 12) }, - { ORDATA (LPRDAT, lprdat, 12) }, - { ORDATA (LPCBUF, lpcbuf, 8) }, - { ORDATA (LPCOLC, lpcolc, 8) }, - { ORDATA (LPPDAT, lppdat, 8) }, - { ORDATA (LPCSUM, lpcsum, 8) }, - { ORDATA (DVPTR, dvptr, 7) }, - { ORDATA (DVLNT, dvlnt, 7), REG_RO + REG_NZ }, - { FLDATA (INT, int_req, INT_V_LP20) }, - { FLDATA (IRQ, lp20_irq, 0) }, - { FLDATA (ERR, lpcsa, CSR_V_ERR) }, - { FLDATA (DONE, lpcsa, CSR_V_DONE) }, - { FLDATA (IE, lpcsa, CSR_V_IE) }, - { DRDATA (POS, lp20_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, lp20_unit.wait, 24), PV_LEFT }, - { FLDATA (STOP_IOE, lp20_stopioe, 0) }, - { BRDATA (TXRAM, txram, 8, 12, TX_SIZE) }, - { BRDATA (DAVFU, davfu, 8, 12, DV_SIZE) }, - { ORDATA (DEVADDR, lp20_dib.ba, 32), REG_HRO }, - { ORDATA (DEVVEC, lp20_dib.vec, 16), REG_HRO }, - { NULL } }; - -MTAB lp20_mod[] = { - { UNIT_DUMMY, 0, NULL, "VFUCLEAR", &lp20_clear_vfu }, - { MTAB_XTD|MTAB_VDV, 004, "ADDRESS", "ADDRESS", - &set_addr, &show_addr, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "VECTOR", "VECTOR", - &set_vec, &show_vec, NULL }, - { 0 } }; - -DEVICE lp20_dev = { - "LP20", &lp20_unit, lp20_reg, lp20_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &lp20_reset, - NULL, &lp20_attach, &lp20_detach, - &lp20_dib, DEV_DISABLE | DEV_UBUS }; - -/* Line printer routines - - lp20_rd I/O page read - lp20_wr I/O page write - lp20_svc process event (printer ready) - lp20_reset process reset - lp20_attach process attach - lp20_detach process detach -*/ - -t_stat lp20_rd (int32 *data, int32 pa, int32 access) -{ -update_lpcs (0); /* update csr's */ -switch ((pa >> 1) & 07) { /* case on PA<3:1> */ -case 00: /* LPCSA */ - *data = lpcsa = lpcsa & ~CSA_MBZ; - break; -case 01: /* LPCSB */ - *data = lpcsb = lpcsb & ~CSB_MBZ; - break; -case 02: /* LPBA */ - *data = lpba; - break; -case 03: /* LPBC */ - *data = lpbc = lpbc & BC_MASK; - break; -case 04: /* LPPAGC */ - *data = lppagc = lppagc & PAGC_MASK; - break; -case 05: /* LPRDAT */ - *data = lprdat = lprdat & RDAT_MASK; - break; -case 06: /* LPCOLC/LPCBUF */ - *data = (lpcolc << 8) | lpcbuf; - break; -case 07: /* LPCSUM/LPPDAT */ - *data = (lpcsum << 8) | lppdat; - break; } /* end case PA */ -return SCPE_OK; -} - -t_stat lp20_wr (int32 data, int32 pa, int32 access) -{ -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; - 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 */ - 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); } } - else sim_cancel (&lp20_unit); /* go clr, stop DMA */ - lpcsa = (lpcsa & ~CSA_RW) | (data & CSA_RW); - break; -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 = data; - break; -case 03: /* LPBC */ - if (access == WRITEB) data = (pa & 1)? - (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 = data & PAGC_MASK; - break; -case 05: /* LPRDAT */ - if (access == WRITEB) data = (pa & 1)? - (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; } - break; -case 07: /* LPCSUM/LPPDAT */ - break; } /* read only */ -update_lpcs (0); -return SCPE_OK; -} - -/* Line printer service - - The translation RAM case table is derived from the LP20 spec and - verified against the LP20 RAM simulator in TOPS10 7.04 LPTSPL. - The equations are: - - flags := inter, delim, xlate, paper, delim_hold (from CSRA) - actions : = print_input, print_xlate, davfu_action, interrupt - - if (inter) { - if (!xlate || delim || delim_hold) interrupt; - else if (paper) davfu_action; - else print_xlate; } - else if (paper) { - if (xlate || delim || delim_hold) davfu_action; - else print_input; } - else { - if (xlate || delim || delim_hold) print_xlate; - else print_input; } -*/ - -t_stat lp20_svc (UNIT *uptr) -{ -int32 fnc, i, tbc, temp, txst; -int32 dvld = -2; /* must be even */ -int32 err = 0; -uint16 wd10; -t_bool cont; -a10 ba; - -static const uint32 txcase[32] = { - TX_CHR, TX_RAM, TX_CHR, TX_DVU, TX_RAM, TX_RAM, TX_DVU, TX_DVU, - TX_RAM, TX_RAM, TX_DVU, TX_DVU, TX_RAM, TX_RAM, TX_DVU, TX_DVU, - TX_INT, TX_INT, TX_INT, TX_INT, TX_RAM, TX_INT, TX_DVU, TX_INT, - TX_INT, TX_INT, TX_INT, TX_INT, TX_INT, TX_INT, TX_INT, TX_INT }; - -lpcsa = lpcsa & ~CSA_GO; -ba = CSA_GETUAE (lpcsa) | lpba; -fnc = CSA_GETFNC (lpcsa); -tbc = 010000 - lpbc; -if (((fnc & FNC_INTERNAL) == 0) && ((lp20_unit.flags & UNIT_ATT) == 0)) { - update_lpcs (CSA_ERR); - IORETURN (lp20_stopioe, SCPE_UNATT); } -if ((fnc == FNC_PR) && (dvlnt == 0)) { - update_lpcs (CSA_ERR); - return SCPE_OK; } - -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; } - lpcbuf = (wd10 >> ((ba & 1)? 8: 0)) & 0377; /* get character */ - lpcsum = (lpcsum + lpcbuf) & 0377; /* add into checksum */ - switch (fnc) { /* switch on function */ - -/* Translation RAM load */ - - case FNC_RAM: /* RAM load */ - 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 - loaded is odd, or no bytes are loaded, the DAVFU is invalid. -*/ - - 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; - -/* 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 */ - break; - case FNC_TST: /* test */ - break; } /* end case function */ - } /* end for */ -lpba = ba & 0177777; -lpcsa = (lpcsa & ~CSA_UAE) | ((ba >> (16 - CSA_V_UAE)) & CSA_UAE); -lpbc = (lpbc + i) & BC_MASK; -if (lpbc) update_lpcs (CSA_MBZ); /* intr, but not done */ -else update_lpcs (CSA_DONE); /* intr and done */ -if ((fnc == FNC_PR) && ferror (lp20_unit.fileref)) { - perror ("LP I/O error"); - clearerr (uptr->fileref); - return SCPE_IOERR; } -return SCPE_OK; -} - -/* Print routines - - lp20_print print a character - lp20_adv advance n lines - lp20_davfu advance to channel on VFU - - Return TRUE to continue printing, FALSE to stop -*/ - -t_bool lp20_print (int32 c) -{ -t_bool r = TRUE; -int32 i, rpt = 1; - -lppdat = c & 0177; /* mask char to 7b */ -if (lppdat == 000) return TRUE; /* NUL? no op */ -if (lppdat == 012) return lp20_adv (1, TRUE); /* LF? adv carriage */ -if (lppdat == 014) return lp20_davfu (DV_TOF); /* FF? top of form */ -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 */ - 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 */ -for (i = 0; i < rpt; i++) putc (lppdat, lp20_unit.fileref); -lp20_unit.pos = lp20_unit.pos + rpt; -lpcolc = lpcolc + rpt; -return r; -} - -t_bool lp20_adv (int32 cnt, t_bool dvuadv) -{ -int32 i; - -if (cnt == 0) return TRUE; -lpcolc = 0; /* reset col cntr */ -for (i = 0; i < cnt; i++) putc ('\n', lp20_unit.fileref); -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; } } -return TRUE; -} - -t_bool lp20_davfu (int32 cnt) -{ -int i; - -if (cnt > DV_MAX) cnt = 7; /* inval chan? */ -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; } } - } /* end for */ -dvlnt = 0; /* DAVFU error */ -return FALSE; -} - -/* Update LPCSA, optionally request interrupt */ - -void update_lpcs (int32 flg) -{ -if (flg) lp20_irq = 1; /* set int req */ -lpcsa = (lpcsa | flg) & ~(CSA_MBZ | CSA_ERR | CSA_ONL | CSA_DVON); -lpcsb = (lpcsb | CSB_OFFL | CSB_DVOF) & ~CSB_MBZ; -if (lp20_unit.flags & UNIT_ATT) { - lpcsa = lpcsa | CSA_ONL; - lpcsb = lpcsb & ~CSB_OFFL; } -else lpcsa = lpcsa & ~CSA_DONE; -if (dvlnt) { - lpcsa = lpcsa | CSA_DVON; - lpcsb = lpcsb & ~CSB_DVOF; } -if (lpcsb & CSB_ERR) lpcsa = lpcsa | CSA_ERR; -if ((lpcsa & CSA_IE) && lp20_irq) int_req = int_req | INT_LP20; -else int_req = int_req & ~INT_LP20; -return; -} - -/* Acknowledge interrupt (clear internal request) */ - -int32 lp20_inta (void) -{ -lp20_irq = 0; /* clear int req */ -return lp20_dib.vec; -} - -t_stat lp20_reset (DEVICE *dptr) -{ -lpcsa = CSA_DONE; -lpcsb = 0; -lpba = lpbc = lppagc = lpcolc = 0; /* clear registers */ -lprdat = lppdat = lpcbuf = lpcsum = 0; -lp20_irq = 0; /* clear int req */ -dvptr = 0; /* reset davfu ptr */ -sim_cancel (&lp20_unit); /* deactivate unit */ -update_lpcs (0); /* update status */ -return SCPE_OK; -} - -t_stat lp20_attach (UNIT *uptr, char *cptr) -{ -t_stat reason; - -reason = attach_unit (uptr, cptr); /* attach file */ -if (lpcsa & CSA_ONL) return reason; /* just file chg? */ -if (sim_is_active (&lp20_unit)) update_lpcs (0); /* busy? no int */ -else update_lpcs (CSA_MBZ); /* interrupt */ -return reason; -} - -t_stat lp20_detach (UNIT *uptr) -{ -t_stat reason; - -reason = detach_unit (uptr); -sim_cancel (&lp20_unit); -lpcsa = lpcsa & ~CSA_GO; -update_lpcs (CSA_MBZ); -return reason; -} - -t_stat lp20_clear_vfu (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -int i; - -if (!get_yn ("Clear DAVFU? [N]", FALSE)) return SCPE_OK; -for (i = 0; i < DV_SIZE; i++) davfu[i] = 0; -dvlnt = dvptr = 0; -update_lpcs (0); -return SCPE_OK; -} diff --git a/PDP10/pdp10_mdfp.c b/PDP10/pdp10_mdfp.c deleted file mode 100644 index 5c3e1ad9..00000000 --- a/PDP10/pdp10_mdfp.c +++ /dev/null @@ -1,688 +0,0 @@ -/* pdp10_mdfp.c: PDP-10 multiply/divide and floating point simulator - - 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. - - Instructions handled in this module: - imul integer multiply - idiv integer divide - mul multiply - div divide - dmul double precision multiply - ddiv double precision divide - fad(r) floating add (and round) - fsb(r) floating subtract (and round) - fmp(r) floating multiply (and round) - fdv(r) floating divide and round - fsc floating scale - fix(r) floating to fixed (and round) - fltr fixed to floating and round - dfad double precision floating add/subtract - dfmp double precision floating multiply - dfdv double precision floating divide - - The PDP-10 stores double (quad) precision integers in sequential - AC's or memory locations. Integers are stored in 2's complement - form. Only the sign of the high order word matters; the signs - in low order words are ignored on input and set to the sign of - the result on output. Quad precision integers exist only in the - AC's as the result of a DMUL or the dividend of a DDIV. - - 0 00000000011111111112222222222333333 - 0 12345678901234567890123456789012345 - +-+-----------------------------------+ - |S| high order integer | AC(n), A - +-+-----------------------------------+ - |S| low order integer | AC(n + 1), A + 1 - +-+-----------------------------------+ - |S| low order integer | AC(n + 2) - +-+-----------------------------------+ - |S| low order integer | AC(n + 3) - +-+-----------------------------------+ - - The PDP-10 supports two floating point formats: single and double - precision. In both, the exponent is 8 bits, stored in excess - 128 notation. The fraction is expected to be normalized. A - single precision floating point number has 27 bits of fraction; - a double precision number has 62 bits of fraction (the sign - bit of the second word is ignored and is set to zero). - - In a negative floating point number, the exponent is stored in - one's complement form, the fraction in two's complement form. - - 0 00000000 011111111112222222222333333 - 0 12345678 901234567890123456789012345 - +-+--------+---------------------------+ - |S|exponent| high order fraction | AC(n), A - +-+--------+---------------------------+ - |0| low order fraction | AC(n + 1), A + 1 - +-+------------------------------------+ - - Note that treatment of the sign is different for double precision - integers and double precision floating point. DMOVN (implemented - as an inline macro) follows floating point conventions. - - The original PDP-10 CPU (KA10) used a different format for double - precision numbers and included certain instructions to make - software support easier. These instructions were phased out in - the KL10 and KS10 and are treated as MUUO's. - - The KL10 added extended precision (11-bit exponent) floating point - format (so-called G floating). These instructions were not - implemented in the KS10 and are treated as MUUO's. - - 31-Aug-01 RMS Changed int64 to t_int64 for Windoze - 10-Aug-01 RMS Removed register in declarations -*/ - -#include "pdp10_defs.h" -#include - -struct ufp { /* unpacked fp number */ - int32 sign; /* sign */ - int32 exp; /* exponent */ - t_uint64 fhi; /* fraction high */ - t_uint64 flo; }; /* for double prec */ - -typedef struct ufp UFP; - -#define MSK32 0xFFFFFFFF -#define FIT27 (DMASK - 0x07FFFFFF) -#define FIT32 (DMASK - MSK32) -#define SFRC TRUE /* frac 2's comp */ -#define AFRC FALSE /* frac abs value */ - -/* In packed floating point number */ - -#define FP_BIAS 0200 /* exponent bias */ -#define FP_N_FHI 27 /* # of hi frac bits */ -#define FP_V_FHI 0 /* must be zero */ -#define FP_M_FHI 0000777777777 -#define FP_N_EXP 8 /* # of exp bits */ -#define FP_V_EXP (FP_V_FHI + FP_N_FHI) -#define FP_M_EXP 0377 -#define FP_V_SIGN (FP_V_EXP + FP_N_EXP) /* sign */ -#define FP_N_FLO 35 /* # of lo frac bits */ -#define FP_V_FLO 0 /* must be zero */ -#define FP_M_FLO 0377777777777 -#define GET_FPSIGN(x) ((int32) (((x) >> FP_V_SIGN) & 1)) -#define GET_FPEXP(x) ((int32) (((x) >> FP_V_EXP) & FP_M_EXP)) -#define GET_FPHI(x) ((x) & FP_M_FHI) -#define GET_FPLO(x) ((x) & FP_M_FLO) - -/* In unpacked floating point number */ - -#define FP_N_GUARD 1 /* # of guard bits */ -#define FP_V_UFLO FP_N_GUARD /* <35:1> */ -#define FP_V_URNDD (FP_V_UFLO - 1) /* dp round bit */ -#define FP_V_UFHI (FP_V_UFLO + FP_N_FLO) /* <62:36> */ -#define FP_V_URNDS (FP_V_UFHI - 1) /* sp round bit */ -#define FP_V_UCRY (FP_V_UFHI + FP_N_FHI) /* <63> */ -#define FP_V_UNORM (FP_V_UCRY - 1) /* normalized bit */ -#define FP_UFHI 0x7FFFFFF000000000 -#define FP_UFLO 0x0000000FFFFFFFFE -#define FP_UFRAC 0x7FFFFFFFFFFFFFFE -#define FP_URNDD 0x0000000000000001 -#define FP_URNDS 0x0000000800000000 -#define FP_UNORM 0x4000000000000000 -#define FP_UCRY 0x8000000000000000 -#define FP_ONES 0xFFFFFFFFFFFFFFFF - -#define UNEG(x) ((~x) + 1) -#define DUNEG(x) x.flo = UNEG (x.flo); x.fhi = ~x.fhi + (x.flo == 0) - -extern d10 *ac_cur; /* current AC block */ -extern int32 flags; /* flags */ -void mul (d10 a, d10 b, d10 *rs); -void funpack (d10 h, d10 l, UFP *r, t_bool sgn); -void fnorm (UFP *r, t_int64 rnd); -d10 fpack (UFP *r, d10 *lo, t_bool fdvneg); - -/* Integer multiply - checked against KS-10 ucode */ - -d10 imul (d10 a, d10 b) -{ -d10 rs[2]; - -if ((a == SIGN) && (b == SIGN)) { /* KS10 hack */ - SETF (F_AOV | F_T1); /* -2**35 squared */ - return SIGN; } -mul (a, b, rs); /* mpy, dprec result */ -if (rs[0] && (rs[0] != ONES)) { /* high not all sign? */ - rs[1] = TSTS (a ^ b)? SETS (rs[1]): CLRS (rs[1]); /* set sign */ - SETF (F_AOV | F_T1); } /* overflow */ -return rs[1]; -} - -/* Integer divide, return quotient, remainder - checked against KS10 ucode - The KS10 does not recognize -2^35/-1 as an error. Instead, it produces - 2^35 (that is, -2^35) as the incorrect result. -*/ - -t_bool idiv (d10 a, d10 b, d10 *rs) -{ -d10 dvd = ABS (a); /* make ops positive */ -d10 dvr = ABS (b); - -if (dvr == 0) { /* divide by 0? */ - SETF (F_DCK | F_AOV | F_T1); /* set flags, return */ - return FALSE; } -rs[0] = dvd / dvr; /* get quotient */ -rs[1] = dvd % dvr; /* get remainder */ -if (TSTS (a ^ b)) rs[0] = NEG (rs[0]); /* sign of result */ -if (TSTS (a)) rs[1] = NEG (rs[1]); /* sign of remainder */ -return TRUE; -} - -/* Multiply, return double precision result - checked against KS10 ucode */ - -void mul (d10 s1, d10 s2, d10 *rs) -{ -t_uint64 a = ABS (s1); -t_uint64 b = ABS (s2); -t_uint64 t, u, r; - -if ((a == 0) || (b == 0)) { /* operand = 0? */ - rs[0] = rs[1] = 0; /* result 0 */ - return; } -if ((a & FIT32) || (b & FIT32)) { /* fit in 64b? */ - t = a >> 18; /* no, split in half */ - a = a & RMASK; /* "dp" multiply */ - u = b >> 18; - b = b & RMASK; - r = (a * b) + (((a * u) + (b * t)) << 18); /* low is only 35b */ - rs[0] = ((t * u) << 1) + (r >> 35); /* so lsh hi 1 */ - rs[1] = r & MMASK; } -else { r = a * b; /* fits, native mpy */ - rs[0] = r >> 35; /* split at bit 35 */ - rs[1] = r & MMASK; } - -if (TSTS (s1 ^ s2)) { MKDNEG (rs); } /* result -? */ -else if (TSTS (rs[0])) { /* result +, 2**70? */ - SETF (F_AOV | F_T1); /* overflow */ - rs[1] = SETS (rs[1]); } /* consistent - */ -return; -} - -/* Divide, return quotient and remainder - checked against KS10 ucode - Note that the initial divide check catches the case -2^70/-2^35; - thus, the quotient can have at most 35 bits. -*/ - -t_bool divi (int32 ac, d10 b, d10 *rs) -{ -int32 p1 = ADDAC (ac, 1); -d10 dvr = ABS (b); /* make divr positive */ -t_int64 t; -int32 i; -d10 dvd[2]; - -dvd[0] = AC(ac); /* divd high */ -dvd[1] = CLRS (AC(p1)); /* divd lo, clr sgn */ -if (TSTS (AC(ac))) { DMOVN (dvd); } /* make divd positive */ -if (dvd[0] >= dvr) { /* divide fail? */ - SETF (F_AOV | F_DCK | F_T1); /* set flags, return */ - 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; } } - rs[1] = dvd[0]; } /* store remainder */ -else { t = (dvd[0] << 35) | dvd[1]; /* concatenate */ - rs[0] = t / dvr; /* quotient */ - rs[1] = t % dvr; } /* remainder */ -if (TSTS (AC(ac) ^ b)) rs[0] = NEG (rs[0]); /* sign of result */ -if (TSTS (AC(ac))) rs[1] = NEG (rs[1]); /* sign of remainder */ -return TRUE; -} - -/* Double precision multiply. This is done the old fashioned way. Cross - product multiplies would be a lot faster but would require more code. -*/ - -void dmul (int32 ac, d10 *mpy) -{ -int32 p1 = ADDAC (ac, 1); -int32 p2 = ADDAC (ac, 2); -int32 p3 = ADDAC (ac, 3); -int32 i; -d10 mpc[2], sign; - -mpc[0] = AC(ac); /* mplcnd hi */ -mpc[1] = CLRS (AC(p1)); /* mplcnd lo, clr sgn */ -sign = mpc[0] ^ mpy[0]; /* sign of result */ -if (TSTS (mpc[0])) { DMOVN (mpc); } /* get abs (mpcnd) */ -if (TSTS (mpy[0])) { DMOVN (mpy); } /* get abs (mpyer) */ -else mpy[1] = CLRS (mpy[1]); /* clear mpy lo sign */ -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; } - 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)); } } -if (TSTS (sign)) { /* result minus? */ - AC(p3) = (-AC(p3)) & MMASK; /* quad negate */ - AC(p2) = (~AC(p2) + (AC(p3) == 0)) & MMASK; - AC(p1) = (~AC(p1) + (AC(p2) == 0)) & MMASK; - AC(ac) = (~AC(ac) + (AC(p1) == 0)) & DMASK; } -else if (TSTS (AC(ac))) SETF (F_AOV | F_T1); /* wrong sign */ -if (TSTS (AC(ac))) { /* if result - */ - AC(p1) = SETS (AC(p1)); /* make signs consistent */ - AC(p2) = SETS (AC(p2)); - AC(p3) = SETS (AC(p3)); } -return; -} - -/* Double precision divide - checked against KS10 ucode */ - -void ddiv (int32 ac, d10 *dvr) -{ -int32 i, cryin; -d10 sign, qu[2], dvd[4]; - -dvd[0] = AC(ac); /* save dividend */ -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[0] = (~dvd[0] + cryin) & DMASK; } -if (TSTS (dvr[0])) { DMOVN (dvr); } /* get abs (divisor) */ -else dvr[1] = CLRS (dvr[1]); -if (DCMPGE (dvd, dvr)) { /* will divide work? */ - SETF (F_AOV | F_DCK | F_T1); /* no, set flags */ - return; } -qu[0] = qu[1] = 0; /* clear quotient */ -for (i = 0; i < 70; i++) { /* 70 quotient bits */ - dvd[0] = ((dvd[0] << 1) | ((dvd[1] >> 34) & 1)) & DMASK;; - dvd[1] = ((dvd[1] << 1) | ((dvd[2] >> 34) & 1)) & MMASK; - dvd[2] = ((dvd[2] << 1) | ((dvd[3] >> 34) & 1)) & MMASK; - dvd[3] = (dvd[3] << 1) & MMASK; /* shift dividend */ - 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 */ -if (TSTS (sign) && (qu[0] | qu[1])) { MKDNEG (qu); } -if (TSTS (AC(ac)) && (dvd[0] | dvd[1])) { MKDNEG (dvd); } -AC(ac) = qu[0]; /* quotient */ -AC(ADDAC(ac, 1)) = qu[1]; -AC(ADDAC(ac, 2)) = dvd[0]; /* remainder */ -AC(ADDAC(ac, 3)) = dvd[1]; -return; -} - -/* Single precision floating add - checked against KS10 ucode - The KS10 shifts the smaller operand regardless of the exponent diff. - This code will not shift more than 63 places; shifts beyond that - cannot change the value of the smaller operand. - - If the signs of the operands are the same, the result sign is the - same as the source sign; the sign of the result fraction is actually - part of the data. If the signs of the operands are different, the - result sign is determined by the fraction sign. -*/ - -d10 fad (d10 op1, d10 op2, t_bool rnd, int32 inv) -{ -int32 ediff; -UFP a, b, t; - -if (inv) op2 = NEG (op2); /* subtract? -b */ -if (op1 == 0) funpack (op2, 0, &a, AFRC); /* a = 0? result is b */ -else if (op2 == 0) funpack (op1, 0, &a, AFRC); /* b = 0? result is a */ -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; } - 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; } } } -fnorm (&a, (rnd? FP_URNDS: 0)); /* normalize, round */ -return fpack (&a, NULL, FALSE); -} - -/* Single precision floating multiply. Because the fractions are 27b, - a 64b multiply can be used for the fraction multiply. The 27b - fractions are positioned 0'frac'0000, resulting in 00'hifrac'0..0. - The extra 0 is accounted for by biasing the result exponent. -*/ - -#define FP_V_SPM (FP_V_UFHI - (32 - FP_N_FHI - 1)) -d10 fmp (d10 op1, d10 op2, t_bool rnd) -{ -UFP a, b; - -funpack (op1, 0, &a, AFRC); /* unpack operands */ -funpack (op2, 0, &b, AFRC); /* fracs are abs val */ -if ((a.fhi == 0) || (b.fhi == 0)) return 0; /* either 0? */ -a.sign = a.sign ^ b.sign; /* result sign */ -a.exp = a.exp + b.exp - FP_BIAS + 1; /* result exponent */ -a.fhi = (a.fhi >> FP_V_SPM) * (b.fhi >> FP_V_SPM); /* high 27b of result */ -fnorm (&a, (rnd? FP_URNDS: 0)); /* normalize, round */ -return fpack (&a, NULL, FALSE); -} - -/* Single precision floating divide. Because the fractions are 27b, a - 64b divide can be used for the fraction divide. Note that 28b-29b - of fraction are developed; the code will do one special normalize to - make sure that the 28th bit is not lost. Also note the special - treatment of negative quotients with non-zero remainders; this - implements the note on p2-23 of the Processor Reference Manual. -*/ - -t_bool fdv (d10 op1, d10 op2, d10 *rs, t_bool rnd) -{ -UFP a, b; -t_uint64 savhi; -t_bool rem = FALSE; - -funpack (op1, 0, &a, AFRC); /* unpack operands */ -funpack (op2, 0, &b, AFRC); /* fracs are abs val */ -if (a.fhi >= 2 * b.fhi) { /* will divide work? */ - SETF (F_AOV | F_DCK | F_FOV | F_T1); - return FALSE; } -if (savhi = 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 */ - 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 */ - 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 & (FP_UFHI | FP_URNDS); } /* mask quo to 28b */ -fnorm (&a, (rnd? FP_URNDS: 0)); /* normalize, round */ -*rs = fpack (&a, NULL, rem); /* pack result */ -return TRUE; -} - -/* Single precision floating scale. */ - -d10 fsc (d10 val, a10 ea) -{ -int32 sc = LIT8 (ea); -UFP a; - -if (val == 0) return 0; -funpack (val, 0, &a, AFRC); /* unpack operand */ -if (ea & RSIGN) a.exp = a.exp - sc; /* adjust exponent */ -else a.exp = a.exp + sc; -fnorm (&a, 0); /* renormalize */ -return fpack (&a, NULL, FALSE); /* pack result */ -} - -/* Float integer operand and round */ - -d10 fltr (d10 mb) -{ -UFP a; -d10 val = ABS (mb); - -a.sign = GET_FPSIGN (mb); /* get sign */ -a.exp = FP_BIAS + 36; /* initial exponent */ -a.fhi = val << (FP_V_UNORM - 35); /* left justify op */ -a.flo = 0; -fnorm (&a, FP_URNDS); /* normalize, round */ -return fpack (&a, NULL, FALSE); /* pack result */ -} - -/* Fix and truncate/round floating operand */ - -void fix (int32 ac, d10 mb, t_bool rnd) -{ -int32 sc; -t_uint64 so; -UFP a; - -funpack (mb, 0, &a, AFRC); /* unpack operand */ -if (a.exp > (FP_BIAS + FP_N_FHI + FP_N_EXP)) SETF (F_AOV | F_T1); -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; } - if (a.sign) AC(ac) = NEG (AC(ac)); } -return; -} - -/* Double precision floating add/subtract - Since a.flo is 0, adding b.flo is just a copy - this is incorporated into - the denormalization step. If there's no denormalization, bflo is zero too. -*/ - -void dfad (int32 ac, d10 *rs, int32 inv) -{ -int32 p1 = ADDAC (ac, 1); -int32 ediff; -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 */ -else if ((rs[0] | rs[1]) == 0) funpack (AC(ac), AC(p1), &a, AFRC); - /* 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; } - 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 */ - 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.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; } } } -fnorm (&a, FP_URNDD); /* normalize, round */ -AC(ac) = fpack (&a, &AC(p1), FALSE); /* pack result */ -return; -} - -/* Double precision floating multiply - The 62b fractions are multiplied, with cross products, to produce a - 124b fraction with two leading and two trailing 0's. Because the - product has 2 leading 0's, instead of the normal 1, an extra - normalization step is needed. Accordingly, the exponent calculation - increments the result exponent, to compensate for normalization. -*/ - -void dfmp (int32 ac, d10 *rs) -{ -int32 p1 = ADDAC (ac, 1); -t_uint64 xh, xl, yh, yl, mid; -UFP a, b; - -funpack (AC(ac), AC(p1), &a, AFRC); /* unpack operands */ -funpack (rs[0], rs[1], &b, AFRC); -if ((a.fhi == 0) || (b.fhi == 0)) { /* either 0? result 0 */ - AC(ac) = AC(p1) = 0; - return; } -a.sign = a.sign ^ b.sign; /* result sign */ -a.exp = a.exp + b.exp - FP_BIAS + 1; /* result exponent */ -xh = a.fhi >> 32; /* split 62b fracs */ -xl = a.fhi & MSK32; /* into 32b halves */ -yh = b.fhi >> 32; -yl = b.fhi & MSK32; -a.fhi = xh * yh; /* hi xproduct */ -a.flo = xl * yl; /* low xproduct */ -mid = (xh * yl) + (yh * xl); /* fits in 64b */ -a.flo = a.flo + (mid << 32); /* add mid lo to lo */ -a.fhi = a.fhi + ((mid >> 32) & MSK32) + (a.flo < (mid << 32)); -fnorm (&a, FP_URNDD); /* normalize, round */ -AC(ac) = fpack (&a, &AC(p1), FALSE); /* pack result */ -return; -} - -/* Double precision floating divide - This algorithm develops a full 62 bits of quotient, plus one rounding - bit, in the low order 63b of a 64b number. To do this, we must assure - that the initial divide step generates a 1. If it would fail, shift - the dividend left and decrement the result exponent accordingly. -*/ - -void dfdv (int32 ac, d10 *rs) -{ -int32 p1 = ADDAC (ac, 1); -int32 i; -t_uint64 qu = 0; -UFP a, b; - -funpack (AC(ac), AC(p1), &a, AFRC); /* unpack operands */ -funpack (rs[0], rs[1], &b, AFRC); -if (a.fhi >= 2 * b.fhi) { /* will divide work? */ - SETF (F_AOV | F_DCK | F_FOV | F_T1); - return; } -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; } - 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 */ - a.fhi = qu; } -fnorm (&a, FP_URNDD); /* normalize, round */ -AC(ac) = fpack (&a, &AC(p1), FALSE); /* pack result */ -return; -} - -/* Unpack floating point operand */ - -void funpack (d10 h, d10 l, UFP *r, t_bool sgn) -{ -d10 fphi, fplo; - -r->sign = GET_FPSIGN (h); -r->exp = GET_FPEXP (h); -fphi = GET_FPHI (h); -fplo = GET_FPLO (l); -r->fhi = (fphi << FP_V_UFHI) | (fplo << FP_V_UFLO); -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; } } } -return; -} - -/* Normalize and optionally round floating point operand */ - -void fnorm (UFP *a, t_int64 rnd) -{ -int32 i; -static t_uint64 normmask[6] = { - 0x6000000000000000, 0x7800000000000000, 0x7F80000000000000, - 0x7FFF800000000000, 0x7FFFFFFF80000000, 0x7FFFFFFFFFFFFFFF }; -static int32 normtab[7] = { 1, 2, 4, 8, 16, 32, 63 }; - -if ((a->fhi | a->flo) == 0) { /* if fraction = 0 */ - a->sign = a->exp = 0; /* result is 0 */ - return; } -while ((a->fhi & FP_UNORM) == 0) { /* normalized? */ - for (i = 0; i < 6; i++) { - 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; } } -return; -} - -/* Pack floating point result */ - -d10 fpack (UFP *r, d10 *lo, t_bool fdvneg) -{ -d10 val[2]; - -if (r->exp < 0) SETF (F_AOV | F_FOV | F_FXU | F_T1); -else if (r->exp > FP_M_EXP) SETF (F_AOV | F_FOV | F_T1); -val[0] = (((((d10) r->exp) & FP_M_EXP) << FP_V_EXP) | - ((r->fhi & FP_UFHI) >> FP_V_UFHI)) & DMASK; -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; } - 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 deleted file mode 100644 index bcb6d9c8..00000000 --- a/PDP10/pdp10_pag.c +++ /dev/null @@ -1,801 +0,0 @@ -/* pdp10_pag.c: PDP-10 paging subsystem simulator - - 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. - - pag KS10 pager - - 02-Dec-01 RMS Fixed bug in ITS LPMR (found by Dave Conroy) - 21-Aug-01 RMS Fixed bug in ITS paging (found by Miriam Lennox) - Removed register from declarations - 19-May-01 RMS Added workaround for TOPS-20 V4.1 boot bug - 03-May-01 RMS Fixed bug in indirect page table pointer processing - 29-Apr-01 RMS Added CLRCSH for ITS, fixed LPMR - - The pager consists of a standard hardware part (the translation - tables) and an operating-system specific page table fill routine. - - There are two translation tables, one for executive mode and one - for user mode. Each table consists of 512 page table entries, - one for each page in the 18b virtual address space. Each pte - contains (in the hardware) a valid bit, a writeable bit, an - address space bit (executive or user), and a cacheable bit, plus - the physical page number corresponding to the virtual page. In - the simulator, the pte is expanded for rapid processing of normal - reads and writes. An expanded pte contains a valid bit, a writeable - bit, and the physical page number shifted left by the page size. - - Expanded pte meaning - 0 invalid - >0 read only - <0 read write - - There is a third, physical table, which is used in place of the - executive and user tables if paging is off. Its entries are always - valid and always writeable. - - To translate a virtual to physical address, the simulator uses - the virtual page number to index into the appropriate page table. - If the page table entry (pte) is not valid, the page fill routine - is called to see if the entry is merely not filled or is truly - inaccessible. If the pte is valid but not writeable, and the - reference is a write reference, the page fill routine is also - called to see if the reference can be resolved. - - The page fill routine is operating system dependent. Three styles - of paging are supported: - - TOPS10 known in the KS10 microcode as KI10 paging, - used by earlier versions of TOPS10 - TOPS20 known in the KS10 microcode as KL10 paging, - used by later versions of TOPS10, and TOPS20 - ITS used only by ITS - - TOPS10 vs TOPS20 is selected by a bit in the EBR; ITS paging is - "hardwired" (it required different microcode). -*/ - -#include "pdp10_defs.h" -#include - -/* Page table (contains expanded pte's) */ - -#define PTBL_ASIZE PAG_N_VPN -#define PTBL_MEMSIZE (1 << PTBL_ASIZE) /* page table size */ -#define PTBL_AMASK (PTBL_MEMSIZE - 1) -#define PTBL_M (1u << 31) /* must be sign bit */ -#define PTBL_V (1u << 30) -#define PTBL_MASK (PAG_PPN | PTBL_M | PTBL_V) - -/* NXM processing */ - -#define REF_V 0 /* ref is virt */ -#define REF_P 1 /* ref is phys */ -#define PF_OK 0 /* pfail ok */ -#define PF_TR 1 /* pfail trap */ - -extern d10 *M; -extern d10 acs[AC_NBLK * AC_NUM]; -extern d10 *ac_cur, *ac_prv, *last_pa; -extern a10 epta, upta; -extern int32 flags; -extern d10 pager_word; -extern int32 apr_flg; -extern d10 ebr, ubr, hsb; -extern d10 spt, cst, cstm, pur; -extern a10 dbr1, dbr2, dbr3, dbr4; -extern d10 pcst, quant; -extern t_bool paging; -extern UNIT cpu_unit; -extern jmp_buf save_env; -extern int32 test_int (void); -extern int32 pi_eval (void); - -int32 eptbl[PTBL_MEMSIZE]; /* exec page table */ -int32 uptbl[PTBL_MEMSIZE]; /* user page table */ -int32 physptbl[PTBL_MEMSIZE]; /* phys page table */ -int32 *ptbl_cur, *ptbl_prv; -int32 save_ea; - -int32 ptbl_fill (a10 ea, int32 *ptbl, int32 mode); -t_stat pag_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw); -t_stat pag_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw); -t_stat pag_reset (DEVICE *dptr); -void pag_nxm (a10 pa, int32 phys, int32 trap); - -/* Pager data structures - - pag_dev pager device descriptor - pag_unit pager units - pager_reg pager register list -*/ - -UNIT pag_unit[] = { - { UDATA (NULL, UNIT_FIX, PTBL_MEMSIZE) }, - { UDATA (NULL, UNIT_FIX, PTBL_MEMSIZE) } }; - -REG pag_reg[] = { - { ORDATA (PANIC_EA, save_ea, PASIZE), REG_HRO }, - { NULL } }; - -DEVICE pag_dev = { - "PAG", pag_unit, pag_reg, NULL, - 2, 8, PTBL_ASIZE, 1, 8, 32, - &pag_ex, &pag_dep, &pag_reset, - NULL, NULL, NULL, - NULL, 0 }; - -/* Memory read and write routines - - Read - read current or previous, read checking - ReadM - read current or previous, write checking - ReadE - read exec - ReadP - read physical - Write - write current or previous - WriteE - write exec - WriteP - write physical - AccChk - test accessibility of virtual address -*/ - -d10 Read (a10 ea, int32 prv) -{ -int32 pa, vpn, xpte; - -if (ea < AC_NUM) return (prv? ac_prv[ea]: ac_cur[ea]); /* AC request */ -vpn = PAG_GETVPN (ea); /* get page num */ -xpte = prv? ptbl_prv[vpn]: ptbl_cur[vpn]; /* get exp pte */ -if (xpte == 0) xpte = ptbl_fill (ea, prv? ptbl_prv: ptbl_cur, PTF_RD); -pa = PAG_XPTEPA (xpte, ea); /* calc phys addr */ -if (MEM_ADDR_NXM (pa)) pag_nxm (pa, REF_V, PF_TR); /* process nxm */ -return M[pa]; /* return data */ -} - -d10 ReadM (a10 ea, int32 prv) -{ -int32 pa, vpn, xpte; - -if (ea < AC_NUM) return (prv? ac_prv[ea]: ac_cur[ea]); /* AC request */ -vpn = PAG_GETVPN (ea); /* get page num */ -xpte = prv? ptbl_prv[vpn]: ptbl_cur[vpn]; /* get exp pte */ -if (xpte >= 0) xpte = ptbl_fill (ea, prv? ptbl_prv: ptbl_cur, PTF_WR); -pa = PAG_XPTEPA (xpte, ea); /* calc phys addr */ -if (MEM_ADDR_NXM (pa)) pag_nxm (pa, REF_V, PF_TR); /* process nxm */ -return M[pa]; /* return data */ -} - -d10 ReadE (a10 ea) -{ -int32 pa, vpn, xpte; - -if (ea < AC_NUM) return AC(ea); /* AC? use current */ -if (!PAGING) return M[ea]; /* phys? no mapping */ -vpn = PAG_GETVPN (ea); /* get page num */ -xpte = eptbl[vpn]; /* get exp pte, exec tbl */ -if (xpte == 0) xpte = ptbl_fill (ea, eptbl, PTF_RD); -pa = PAG_XPTEPA (xpte, ea); /* calc phys addr */ -if (MEM_ADDR_NXM (pa)) pag_nxm (pa, REF_V, PF_TR); /* process nxm */ -return M[pa]; /* return data */ -} - -d10 ReadP (a10 ea) -{ -if (ea < AC_NUM) return AC(ea); /* AC request */ -if (MEM_ADDR_NXM (ea)) pag_nxm (ea, REF_P, PF_TR); /* process nxm */ -return M[ea]; /* return data */ -} - -void Write (a10 ea, d10 val, int32 prv) -{ -int32 pa, vpn, xpte; - -if (ea < AC_NUM) { /* AC request */ - if (prv) ac_prv[ea] = val; /* write AC */ - else ac_cur[ea] = val; } -else { vpn = PAG_GETVPN (ea); /* get page num */ - xpte = prv? ptbl_prv[vpn]: ptbl_cur[vpn]; /* get exp pte */ - if (xpte >= 0) xpte = ptbl_fill (ea, prv? ptbl_prv: ptbl_cur, PTF_WR); - pa = PAG_XPTEPA (xpte, ea); /* calc phys addr */ - if (MEM_ADDR_NXM (pa)) pag_nxm (pa, REF_V, PF_TR); /* process nxm */ - else M[pa] = val; } /* write data */ -return; -} - -void WriteE (a10 ea, d10 val) -{ -int32 pa, vpn, xpte; - -if (ea < AC_NUM) AC(ea) = val; /* AC? use current */ -else if (!PAGING) M[ea] = val; /* phys? no mapping */ -else { vpn = PAG_GETVPN (ea); /* get page num */ - xpte = eptbl[vpn]; /* get exp pte, exec tbl */ - if (xpte >= 0) xpte = ptbl_fill (ea, eptbl, PTF_WR); - pa = PAG_XPTEPA (xpte, ea); /* calc phys addr */ - if (MEM_ADDR_NXM (pa)) pag_nxm (pa, REF_V, PF_TR); /* process nxm */ - else M[pa] = val; } /* write data */ -return; -} - -void WriteP (a10 ea, d10 val) -{ -if (ea < AC_NUM) AC(ea) = val; /* AC request */ -else { if (MEM_ADDR_NXM (ea)) pag_nxm (ea, REF_P, PF_TR); /* process nxm */ - M[ea] = val; } /* memory */ -return; -} - -t_bool AccViol (a10 ea, int32 prv, int32 mode) -{ -int32 vpn, xpte; - -if (ea < AC_NUM) return FALSE; /* AC request */ -vpn = PAG_GETVPN (ea); /* get page num */ -xpte = prv? ptbl_prv[vpn]: ptbl_cur[vpn]; /* get exp pte */ -if ((xpte == 0) || ((mode & PTF_WR) && (xpte > 0))) /* not accessible? */ - xpte = ptbl_fill (ea, prv? ptbl_prv: ptbl_cur, mode | PTF_MAP); -if (xpte) return FALSE; /* accessible */ -return TRUE; /* not accessible */ -} - -void pag_nxm (a10 pa, int32 phys, int32 trap) -{ -apr_flg = apr_flg | APRF_NXM; /* set APR flag */ -pi_eval (); /* eval intr */ -pager_word = PF_NXM | (phys? PF_NXMP: 0) | - (TSTF (F_USR)? PF_USER: 0) | ((d10) pa); -if (PAGING && trap) ABORT (PAGE_FAIL); /* trap? */ -return; -} - -/* Page table fill - - This routine is called if the page table is invalid, or on a write - reference if the page table is read only. If the access is allowed - it stores the pte in the page table entry and returns an expanded - pte for use by the caller. Otherwise, it generates a page fail. - - Notes: - - If called from the console, invalid references return a pte - of 0, and the page table entry is not filled. - - If called from MAP, invalid references return a pte of 0. The - page fail word is properly set up. -*/ - -#define PAGE_FAIL_TRAP if (mode & (PTF_CON | PTF_MAP)) return 0; \ - ABORT (PAGE_FAIL) -#define READPT(x,y) if (MEM_ADDR_NXM (y)) { \ - pag_nxm (y, REF_P, PF_OK); \ - PAGE_FAIL_TRAP; } \ - x = ReadP (y) - -int32 ptbl_fill (a10 ea, int32 *tbl, int32 mode) -{ - -/* ITS paging is based on conventional page tables. ITS divides each address - space into a 128K high and low section, and uses different descriptor base - pointers (dbr) for each. ITS pages are twice the size of DEC standard; - therefore, the fill routine fills two page table entries and returns the pte - that maps the correct ITS half page. This allows the DEC paging macros to - be used in the normal path read-write routines. - - ITS has no MAP instruction, therefore, physical NXM traps are ok. -*/ - -if (ITS) { /* ITS paging */ - int32 acc, decvpn, pte, vpn, ptead, xpte; - d10 ptewd; - - vpn = ITS_GETVPN (ea); /* get ITS pagno */ - if (tbl == uptbl) - 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); - 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)); } - PAGE_FAIL_TRAP; - } /* end ITS paging */ - -/* TOPS-10 paging - checked against KS10 microcode - - TOPS-10 paging is also based on conventional page tables. The user page - tables are arranged contiguously at the beginning of the user process table; - however, the executive page tables are scattered through the executive and - user process tables. -*/ - -else if (!T20) { /* TOPS-10 paging */ - int32 pte, vpn, ptead, xpte; - d10 ptewd; - - vpn = PAG_GETVPN (ea); /* get virt page num */ - if (tbl == uptbl) ptead = upta + UPT_T10_UMAP + (vpn >> 1); - else if (vpn < 0340) ptead = epta + EPT_T10_X000 + (vpn >> 1); - else if (vpn < 0400) ptead = upta + UPT_T10_X340 + ((vpn - 0340) >> 1); - else ptead = epta + EPT_T10_X400 + ((vpn - 0400) >> 1); - READPT (ptewd, ptead); /* get PTE pair */ - pte = (int32) ((ptewd >> ((vpn & 1)? 0: 18)) & RMASK); - 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); - 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); - if (!(mode & PTF_CON)) tbl[vpn] = xpte; /* set tbl if ~cons */ - return xpte; } - PAGE_FAIL_TRAP; - } /* end TOPS10 paging */ - -/* TOPS-20 paging - checked against KS10 ucode. - - TOPS-20 paging has three phases: - - 1. Starting at EPT/UPT + 540 + section number, chase section pointers to - get the pointer to the section page table. In the KS10, because there - is only one section, the microcode caches the result of this evaluation. - Also, the evaluation of indirect pointers is simplified, as the section - table index is ignored. - - 2. Starting with the page map pointer, chase page pointers to get the - pointer to the page. The KS10 allows the operating system to inhibit - updating of the CST (base address = 0). - - 3. Use the page pointer to get the CST entry. If a write reference to - a writeable page, set CST_M. If CST_M is set, set M in page table. -*/ - -else { /* TOPS-20 paging */ - int32 pmi, vpn, xpte; - int32 flg, t; - t_bool stop; - a10 pa, csta; - d10 ptr, cste; - 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 */ - -/* 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 - process. In particular, the indirect pointer calculation assumes that - the section table index will be 0. It adds the full pointer (not just - the right half) to the SPT base. If the section index is > 0, the - result is a physical memory address > 256KW. Depending on the size of - memory, the SPT fetch may or may not generate a NXM page fail. The - KS10 then ignores the section table index in fetching the next pointer. - - The KS10 KL10 memory management diagnostic (dskec.sav) tests for this - behavior with a section index of 3. However, this would be a legal - physical address in a system with 1MW. Accordingly, the simulator - special cases non-zero section indices (which can't work in any case) - to generate the right behavior for the diagnostic. -*/ - - vpn = PAG_GETVPN (ea); /* get virt page num */ - 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 */ - -/* 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 */ - -/* 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 */ - 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 (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); - if (!(mode & PTF_CON)) tbl[vpn] = xpte; /* set tbl if ~cons */ - return xpte; - } /* end TOPS20 paging */ -} - -/* Set up pointers for AC, memory, and process table access */ - -void set_dyn_ptrs (void) -{ -int32 t; - -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 { ac_cur = ac_prv = &acs[0]; - ptbl_cur = ptbl_prv = &physptbl[0]; } -t = EBR_GETEBR (ebr); -epta = t << PAG_V_PN; -if (ITS) upta = (int32) ubr & PAMASK; -else { t = UBR_GETUBR (ubr); - upta = t << PAG_V_PN; } -return; -} - -/* MAP instruction, TOPS-10 and TOPS-20 only - - According to the KS-10 ucode, map with paging disabled sets - "accessible, writeable, software", regardless of whether - TOPS-10 or TOPS-20 paging is implemented -*/ - -d10 map (a10 ea, int32 prv) -{ -int32 xpte; -d10 val = (TSTF (F_USR)? PF_USER: 0); - -if (!PAGING) return (val | PF_T10_A | PF_T10_W | PF_T10_S | ea); -xpte = ptbl_fill (ea, prv? ptbl_prv: ptbl_cur, PTF_MAP); /* get exp pte */ -if (xpte) val = (pager_word & ~PAMASK) | PAG_XPTEPA (xpte, ea); -else { if (pager_word & PF_HARD) val = pager_word; /* hard error */ - else val = val | PF_VIRT | ea; } /* inaccessible */ -return val; -} - -/* Mapping routine for console */ - -a10 conmap (a10 ea, int32 mode, int32 sw) -{ -int32 xpte, *tbl; - -if (!PAGING) return ea; -set_dyn_ptrs (); /* in case changed */ -if (sw & SWMASK ('E')) tbl = eptbl; -else if (sw & SWMASK ('U')) tbl = uptbl; -else tbl = ptbl_cur; -xpte = ptbl_fill (ea, tbl, mode); -if (xpte) return PAG_XPTEPA (xpte, ea); -else return MAXMEMSIZE; -} - -/* Common pager instructions */ - -t_bool clrpt (a10 ea, int32 prv) -{ -int32 vpn = PAG_GETVPN (ea); /* get page num */ - -if (ITS) { /* ITS? */ - uptbl[vpn & ~1] = 0; /* clear double size */ - uptbl[vpn | 1] = 0; /* entries in */ - eptbl[vpn & ~1] = 0; /* both page tables */ - eptbl[vpn | 1] = 0; } -else { uptbl[vpn] = 0; /* clear entries in */ - eptbl[vpn] = 0; } /* both page tables */ -return FALSE; -} - -t_bool wrebr (a10 ea, int32 prv) -{ -ebr = ea & EBR_MASK; /* store EBR */ -pag_reset (&pag_dev); /* clear page tables */ -set_dyn_ptrs (); /* set dynamic ptrs */ -return FALSE; -} - -t_bool rdebr (a10 ea, int32 prv) -{ -Write (ea, (ebr & EBR_MASK), prv); -return FALSE; -} - -t_bool wrubr (a10 ea, int32 prv) -{ -d10 val = Read (ea, prv); -d10 ubr_mask = (ITS)? PAMASK: UBR_UBRMASK; /* ITS: ubr is wd addr */ - -if (val & UBR_SETACB) ubr = ubr & ~UBR_ACBMASK; /* set AC's? */ -else val = val & ~UBR_ACBMASK; /* no, keep old val */ -if (val & UBR_SETUBR) { /* set UBR? */ - ubr = ubr & ~ubr_mask; - pag_reset (&pag_dev); } /* yes, clr pg tbls */ -else val = val & ~ubr_mask; /* no, keep old val */ -ubr = (ubr | val) & (UBR_ACBMASK | ubr_mask); -set_dyn_ptrs (); -return FALSE; -} - -t_bool rdubr (a10 ea, int32 prv) -{ -ubr = ubr & (UBR_ACBMASK | (ITS? PAMASK: UBR_UBRMASK)); -Write (ea, UBRWORD, prv); -return FALSE; -} - -t_bool wrhsb (a10 ea, int32 prv) -{ -hsb = Read (ea, prv) & PAMASK; -return FALSE; -} - -t_bool rdhsb (a10 ea, int32 prv) -{ -Write (ea, hsb, prv); -return FALSE; -} - -/* TOPS20 pager instructions */ - -t_bool wrspb (a10 ea, int32 prv) -{ -spt = Read (ea, prv); -return FALSE; -} - -t_bool rdspb (a10 ea, int32 prv) -{ -Write (ea, spt, prv); -return FALSE; -} - -t_bool wrcsb (a10 ea, int32 prv) -{ -cst = Read (ea, prv); -return FALSE; -} - -t_bool rdcsb (a10 ea, int32 prv) -{ -Write (ea, cst, prv); -return FALSE; -} - -t_bool wrpur (a10 ea, int32 prv) -{ -pur = Read (ea, prv); -return FALSE; -} - -t_bool rdpur (a10 ea, int32 prv) -{ -Write (ea, pur, prv); -return FALSE; -} - -t_bool wrcstm (a10 ea, int32 prv) -{ -cstm = Read (ea, prv); -if ((cpu_unit.flags & UNIT_T20V41) && (ea == 040127)) - cstm = 0770000000000; -return FALSE; -} - -t_bool rdcstm (a10 ea, int32 prv) -{ -Write (ea, cstm, prv); -return FALSE; -} - -/* ITS pager instructions - The KS10 does not implement the JPC option. -*/ - -t_bool clrcsh (a10 ea, int32 prv) -{ -return FALSE; -} - -t_bool ldbr1 (a10 ea, int32 prv) -{ -dbr1 = ea; -pag_reset (&pag_dev); -return FALSE; -} - -t_bool sdbr1 (a10 ea, int32 prv) -{ -Write (ea, dbr1, prv); -return FALSE; -} - -t_bool ldbr2 (a10 ea, int32 prv) -{ -dbr2 = ea; -pag_reset (&pag_dev); -return FALSE; -} - -t_bool sdbr2 (a10 ea, int32 prv) -{ -Write (ea, dbr2, prv); -return FALSE; -} - -t_bool ldbr3 (a10 ea, int32 prv) -{ -dbr3 = ea; -pag_reset (&pag_dev); -return FALSE; -} - -t_bool sdbr3 (a10 ea, int32 prv) -{ -Write (ea, dbr3, prv); -return FALSE; -} - -t_bool ldbr4 (a10 ea, int32 prv) -{ -dbr4 = ea; -pag_reset (&pag_dev); -return FALSE; -} - -t_bool sdbr4 (a10 ea, int32 prv) -{ -Write (ea, dbr4, prv); -return FALSE; -} - -t_bool wrpcst (a10 ea, int32 prv) -{ -pcst = Read (ea, prv); -return FALSE; -} - -t_bool rdpcst (a10 ea, int32 prv) -{ -Write (ea, pcst, prv); -return FALSE; -} - -t_bool lpmr (a10 ea, int32 prv) -{ -d10 val; - -val = Read (ADDA (ea, 2), prv); -dbr1 = (a10) (Read (ea, prv) & AMASK); -dbr2 = (a10) (Read (ADDA (ea, 1), prv) & AMASK); -quant = val; -pag_reset (&pag_dev); -return FALSE; -} - -t_bool spm (a10 ea, int32 prv) -{ - -ReadM (ADDA (ea, 2), prv); -Write (ea, dbr1, prv); -Write (ADDA (ea, 1), dbr2, prv); -Write (ADDA (ea, 2), quant, prv); -return FALSE; -} - -t_stat pag_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) -{ -int32 tbln = uptr - pag_unit; - -if (addr >= PTBL_MEMSIZE) return SCPE_NXM; -*vptr = tbln? uptbl[addr]: eptbl[addr];; -return SCPE_OK; -} - -t_stat pag_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw) -{ -int32 tbln = uptr - pag_unit; - -if (addr >= PTBL_MEMSIZE) return SCPE_NXM; -if (tbln) uptbl[addr] = (int32) val & PTBL_MASK; -else eptbl[addr] = (int32) val & PTBL_MASK; -return SCPE_OK; -} - -t_stat pag_reset (DEVICE *dptr) -{ -int32 i; - -for (i = 0; i < PTBL_MEMSIZE; i++) { - eptbl[i] = uptbl[i] = 0; - physptbl[i] = (i << PAG_V_PN) + PTBL_M + PTBL_V; } -return SCPE_OK; -} diff --git a/PDP10/pdp10_rp.c b/PDP10/pdp10_rp.c deleted file mode 100644 index 712a6bbc..00000000 --- a/PDP10/pdp10_rp.c +++ /dev/null @@ -1,1138 +0,0 @@ -/* pdp10_rp.c - RH11/RP04/05/06/07 RM02/03/05/80 "Massbus" disk controller - - 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. - - rp RH/RP/RM moving head disks - - 23-Jul-03 RMS Fixed bug in read header stub - 25-Apr-03 RMS Revised for extended file support - 21-Nov-02 RMS Fixed bug in bootstrap (reported by Michael Thompson) - 29-Sep-02 RMS Added variable vector support - New data structures - 30-Nov-01 RMS Added read only unit, extended SET/SHOW support support - 24-Nov-01 RMS Changed RPER, RPDS, FNC, FLG to arrays - 23-Oct-01 RMS Fixed bug in error interrupts - New IO page address constants - 05-Oct-01 RMS Rewrote interrupt handling from schematics - 02-Oct-01 RMS Revised CS1 write code - 30-Sep-01 RMS Moved CS1<5:0> into drives - 28-Sep-01 RMS Fixed interrupt handling for SC/ATA - 23-Aug-01 RMS Added read/write header stubs for ITS - (found by Mirian Crzig Lennox) - 13-Jul-01 RMS Changed fread call to fxread (found by Peter Schorn) - 14-May-01 RMS Added check for unattached drive - - The "Massbus style" disks consisted of several different large - capacity drives interfaced through a reasonably common (but not - 100% compatible) family of interfaces into the KS10 Unibus via - the RH11 disk controller. - - WARNING: The interupt logic of the RH11/RH70 is unusual and must be - simulated with great precision. The RH11 has an internal interrupt - request flop, CSTB INTR, which is controlled as follows: - - Writing IE and DONE simultaneously sets CSTB INTR - - Controller clear, INIT, and interrupt acknowledge clear CSTB INTR - (and also clear IE) - - A transition of DONE from 0 to 1 sets CSTB from INTR - The output of INTR is OR'd with the AND of RPCS1 to - create the interrupt request signal. Thus, - - The DONE interrupt is edge sensitive, but the SC interrupt is - level sensitive. - - The DONE interrupt, once set, is not disabled if IE is cleared, - but the SC interrupt is. -*/ - -#include "pdp10_defs.h" -#include - -#define RP_NUMDR 8 /* #drives */ -#define RP_NUMWD 128 /* 36b words/sector */ -#define RP_MAXFR 32768 /* max transfer */ -#define GET_SECTOR(x,d) ((int) fmod (sim_gtime() / ((double) (x)), \ - ((double) drv_tab[d].sect))) - -/* Flags in the unit flags word */ - -#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */ -#define UNIT_V_DTYPE (UNIT_V_UF + 1) /* disk type */ -#define UNIT_M_DTYPE 7 -#define UNIT_V_AUTO (UNIT_V_UF + 4) /* autosize */ -#define UNIT_V_DUMMY (UNIT_V_UF + 5) /* dummy flag */ -#define UNIT_WLK (1 << UNIT_V_WLK) -#define UNIT_DTYPE (UNIT_M_DTYPE << UNIT_V_DTYPE) -#define UNIT_AUTO (1 << UNIT_V_AUTO) -#define UNIT_DUMMY (1 << UNIT_V_DUMMY) -#define GET_DTYPE(x) (((x) >> UNIT_V_DTYPE) & UNIT_M_DTYPE) -#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */ - -/* Parameters in the unit descriptor */ - -#define CYL u3 /* current cylinder */ -#define FUNC u4 /* function */ - -/* RPCS1 - 176700 - control/status 1 */ - -#define CS1_GO CSR_GO /* go */ -#define CS1_V_FNC 1 /* function pos */ -#define CS1_M_FNC 037 /* function mask */ -#define CS1_FNC (CS1_M_FNC << CS1_V_FNC) -#define FNC_NOP 000 /* no operation */ -#define FNC_UNLOAD 001 /* unload */ -#define FNC_SEEK 002 /* seek */ -#define FNC_RECAL 003 /* recalibrate */ -#define FNC_DCLR 004 /* drive clear */ -#define FNC_RELEASE 005 /* port release */ -#define FNC_OFFSET 006 /* offset */ -#define FNC_RETURN 007 /* return to center */ -#define FNC_PRESET 010 /* read-in preset */ -#define FNC_PACK 011 /* pack acknowledge */ -#define FNC_SEARCH 014 /* search */ -#define FNC_XFER 024 /* >=? data xfr */ -#define FNC_WCHK 024 /* write check */ -#define FNC_WRITE 030 /* write */ -#define FNC_WRITEH 031 /* write w/ headers */ -#define FNC_READ 034 /* read */ -#define FNC_READH 035 /* read w/ headers */ -#define CS1_IE CSR_IE /* int enable */ -#define CS1_DONE CSR_DONE /* ready */ -#define CS1_V_UAE 8 /* Unibus addr ext */ -#define CS1_M_UAE 03 -#define CS1_UAE (CS1_M_UAE << CS1_V_UAE) -#define CS1_DVA 0004000 /* drive avail NI */ -#define CS1_MCPE 0020000 /* Mbus par err NI */ -#define CS1_TRE 0040000 /* transfer err */ -#define CS1_SC 0100000 /* special cond */ -#define CS1_MBZ 0012000 -#define CS1_DRV (CS1_FNC | CS1_GO) -#define GET_FNC(x) (((x) >> CS1_V_FNC) & CS1_M_FNC) -#define GET_UAE(x) (((x) & CS1_UAE) << (16 - CS1_V_UAE)) - -/* RPWC - 176702 - word count */ - -/* RPBA - 176704 - base address */ - -#define BA_MBZ 0000001 /* must be zero */ - -/* RPDA - 176706 - sector/track */ - -#define DA_V_SC 0 /* sector pos */ -#define DA_M_SC 077 /* sector mask */ -#define DA_V_SF 8 /* track pos */ -#define DA_M_SF 077 /* track mask */ -#define DA_MBZ 0140300 -#define GET_SC(x) (((x) >> DA_V_SC) & DA_M_SC) -#define GET_SF(x) (((x) >> DA_V_SF) & DA_M_SF) - -/* RPCS2 - 176710 - control/status 2 */ - -#define CS2_V_UNIT 0 /* unit pos */ -#define CS2_M_UNIT 07 /* unit mask */ -#define CS2_UNIT (CS2_M_UNIT << CS2_V_UNIT) -#define CS2_UAI 0000010 /* addr inhibit */ -#define CS2_PAT 0000020 /* parity test NI */ -#define CS2_CLR 0000040 /* controller clear */ -#define CS2_IR 0000100 /* input ready */ -#define CS2_OR 0000200 /* output ready */ -#define CS2_MDPE 0000400 /* Mbus par err NI */ -#define CS2_MXF 0001000 /* missed xfer NI */ -#define CS2_PGE 0002000 /* program err */ -#define CS2_NEM 0004000 /* nx mem err */ -#define CS2_NED 0010000 /* nx drive err */ -#define CS2_PE 0020000 /* parity err NI */ -#define CS2_WCE 0040000 /* write check err */ -#define CS2_DLT 0100000 /* data late NI */ -#define CS2_MBZ (CS2_CLR) -#define CS2_RW (CS2_UNIT | CS2_UAI | CS2_PAT | CS2_MXF | CS2_PE) -#define CS2_ERR (CS2_MDPE | CS2_MXF | CS2_PGE | CS2_NEM | \ - CS2_NED | CS2_PE | CS2_WCE | CS2_DLT ) -#define GET_UNIT(x) (((x) >> CS2_V_UNIT) & CS2_M_UNIT) - -/* RPDS - 176712 - drive status */ - -#define DS_OF 0000001 /* offset mode */ -#define DS_VV 0000100 /* volume valid */ -#define DS_RDY 0000200 /* drive ready */ -#define DS_DPR 0000400 /* drive present */ -#define DS_PGM 0001000 /* programable NI */ -#define DS_LST 0002000 /* last sector */ -#define DS_WRL 0004000 /* write locked */ -#define DS_MOL 0010000 /* medium online */ -#define DS_PIP 0020000 /* pos in progress */ -#define DS_ERR 0040000 /* error */ -#define DS_ATA 0100000 /* attention active */ -#define DS_MBZ 0000076 - -/* RPER1 - 176714 - error status 1 */ - -#define ER1_ILF 0000001 /* illegal func */ -#define ER1_ILR 0000002 /* illegal register */ -#define ER1_RMR 0000004 /* reg mod refused */ -#define ER1_PAR 0000010 /* parity err */ -#define ER1_FER 0000020 /* format err NI */ -#define ER1_WCF 0000040 /* write clk fail NI */ -#define ER1_ECH 0000100 /* ECC hard err NI */ -#define ER1_HCE 0000200 /* hdr comp err NI */ -#define ER1_HCR 0000400 /* hdr CRC err NI */ -#define ER1_AOE 0001000 /* addr ovflo err */ -#define ER1_IAE 0002000 /* invalid addr err */ -#define ER1_WLE 0004000 /* write lock err */ -#define ER1_DTE 0010000 /* drive time err NI */ -#define ER1_OPI 0020000 /* op incomplete */ -#define ER1_UNS 0040000 /* drive unsafe */ -#define ER1_DCK 0100000 /* data check NI */ - -/* RPAS - 176716 - attention summary */ - -#define AS_U0 0000001 /* unit 0 flag */ - -/* RPLA - 176720 - look ahead register */ - -#define LA_V_SC 6 /* sector pos */ - -/* RPDB - 176722 - data buffer */ -/* RPMR - 176724 - maintenace register */ -/* RPDT - 176726 - drive type */ -/* RPSN - 176730 - serial number */ - -/* RPOF - 176732 - offset register */ - -#define OF_HCI 0002000 /* hdr cmp inh NI */ -#define OF_ECI 0004000 /* ECC inhibit NI */ -#define OF_F22 0010000 /* format NI */ -#define OF_MBZ 0161400 - -/* RPDC - 176734 - desired cylinder */ - -#define DC_V_CY 0 /* cylinder pos */ -#define DC_M_CY 01777 /* cylinder mask */ -#define DC_MBZ 0176000 -#define GET_CY(x) (((x) >> DC_V_CY) & DC_M_CY) -#define GET_DA(c,fs,d) ((((GET_CY (c) * drv_tab[d].surf) + \ - GET_SF (fs)) * drv_tab[d].sect) + GET_SC (fs)) - -/* RPCC - 176736 - current cylinder */ -/* RPER2 - 176740 - error status 2 - drive unsafe conditions - unimplemented */ -/* RPER3 - 176742 - error status 3 - more unsafe conditions - unimplemented */ -/* RPEC1 - 176744 - ECC status 1 - unimplemented */ -/* RPEC2 - 176746 - ECC status 2 - unimplemented */ - -/* This controller supports many different disk drive types. These drives - are operated in 576 bytes/sector (128 36b words/sector) mode, which gives - them somewhat different geometry from the PDP-11 variants: - - type #sectors/ #surfaces/ #cylinders/ - surface cylinder drive - - RM02/3 30 5 823 =67MB - RP04/5 20 19 411 =88MB - RM80 30 14 559 =124MB - RP06 20 19 815 =176MB - RM05 30 19 823 =256MB - RP07 43 32 630 =516MB - - 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. -*/ - -#define RM03_DTYPE 0 -#define RM03_SECT 30 -#define RM03_SURF 5 -#define RM03_CYL 823 -#define RM03_DEV 020024 -#define RM03_SIZE (RM03_SECT * RM03_SURF * RM03_CYL * RP_NUMWD) - -#define RP04_DTYPE 1 -#define RP04_SECT 20 -#define RP04_SURF 19 -#define RP04_CYL 411 -#define RP04_DEV 020020 -#define RP04_SIZE (RP04_SECT * RP04_SURF * RP04_CYL * RP_NUMWD) - -#define RM80_DTYPE 2 -#define RM80_SECT 30 -#define RM80_SURF 14 -#define RM80_CYL 559 -#define RM80_DEV 020026 -#define RM80_SIZE (RM80_SECT * RM80_SURF * RM80_CYL * RP_NUMWD) - -#define RP06_DTYPE 3 -#define RP06_SECT 20 -#define RP06_SURF 19 -#define RP06_CYL 815 -#define RP06_DEV 020022 -#define RP06_SIZE (RP06_SECT * RP06_SURF * RP06_CYL * RP_NUMWD) - -#define RM05_DTYPE 4 -#define RM05_SECT 30 -#define RM05_SURF 19 -#define RM05_CYL 823 -#define RM05_DEV 020027 -#define RM05_SIZE (RM05_SECT * RM05_SURF * RM05_CYL * RP_NUMWD) - -#define RP07_DTYPE 5 -#define RP07_SECT 43 -#define RP07_SURF 32 -#define RP07_CYL 630 -#define RP07_DEV 020042 -#define RP07_SIZE (RP07_SECT * RP07_SURF * RP07_CYL * RP_NUMWD) - -struct drvtyp { - int sect; /* sectors */ - int surf; /* surfaces */ - int cyl; /* cylinders */ - int size; /* #blocks */ - int devtype; /* device type */ -}; - -struct drvtyp drv_tab[] = { - { RM03_SECT, RM03_SURF, RM03_CYL, RM03_SIZE, RM03_DEV }, - { RP04_SECT, RP04_SURF, RP04_CYL, RP04_SIZE, RP04_DEV }, - { RM80_SECT, RM80_SURF, RM80_CYL, RM80_SIZE, RM80_DEV }, - { RP06_SECT, RP06_SURF, RP06_CYL, RP06_SIZE, RP06_DEV }, - { RM05_SECT, RM05_SURF, RM05_CYL, RM05_SIZE, RM05_DEV }, - { RP07_SECT, RP07_SURF, RP07_CYL, RP07_SIZE, RP07_DEV }, - { 0 } }; - -extern d10 *M; /* memory */ -extern int32 int_req; -extern int32 int_vec[32]; -extern int32 ubmap[UBANUM][UMAP_MEMSIZE]; /* Unibus maps */ -extern int32 ubcs[UBANUM]; -extern UNIT cpu_unit; - -int32 rpcs1 = 0; /* control/status 1 */ -int32 rpwc = 0; /* word count */ -int32 rpba = 0; /* bus address */ -int32 rpda = 0; /* track/sector */ -int32 rpcs2 = 0; /* control/status 2 */ -int32 rpds[RP_NUMDR] = { 0 }; /* drive status */ -int32 rper1[RP_NUMDR] = { 0 }; /* error status 1 */ -int32 rpdb = 0; /* data buffer */ -int32 rpmr = 0; /* maint register */ -int32 rpof = 0; /* offset */ -int32 rpdc = 0; /* cylinder */ -int32 rper2 = 0; /* error status 2 */ -int32 rper3 = 0; /* error status 3 */ -int32 rpec1 = 0; /* ECC correction 1 */ -int32 rpec2 = 0; /* ECC correction 2 */ -int32 rpiff = 0; /* INTR flip/flop */ -int32 rp_stopioe = 1; /* stop on error */ -int32 rp_swait = 10; /* seek time */ -int32 rp_rwait = 10; /* rotate time */ -static int32 reg_in_drive[32] = { - 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - -t_stat rp_rd (int32 *data, int32 PA, int32 access); -t_stat rp_wr (int32 data, int32 PA, int32 access); -int32 rp_inta (void); -t_stat rp_svc (UNIT *uptr); -t_stat rp_reset (DEVICE *dptr); -t_stat rp_boot (int32 unitno, DEVICE *dptr); -t_stat rp_attach (UNIT *uptr, char *cptr); -t_stat rp_detach (UNIT *uptr); -void update_rpcs (int32 flags, int32 drv); -void rp_go (int32 drv, int32 fnc); -t_stat rp_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); - -/* RP data structures - - rp_dev RP device descriptor - rp_unit RP unit list - rp_reg RP register list - rp_mod RP modifier list -*/ - -DIB rp_dib = { IOBA_RP, IOLN_RP, &rp_rd, &rp_wr, - 1, IVCL (RP), VEC_RP, { &rp_inta } }; - -UNIT rp_unit[] = { - { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+(RP06_DTYPE << UNIT_V_DTYPE), RP06_SIZE) }, - { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+(RP06_DTYPE << UNIT_V_DTYPE), RP06_SIZE) }, - { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+(RP06_DTYPE << UNIT_V_DTYPE), RP06_SIZE) }, - { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+(RP06_DTYPE << UNIT_V_DTYPE), RP06_SIZE) }, - { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+(RP06_DTYPE << UNIT_V_DTYPE), RP06_SIZE) }, - { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+(RP06_DTYPE << UNIT_V_DTYPE), RP06_SIZE) }, - { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+(RP06_DTYPE << UNIT_V_DTYPE), RP06_SIZE) }, - { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+(RP06_DTYPE << UNIT_V_DTYPE), RP06_SIZE) } }; - -REG rp_reg[] = { - { ORDATA (RPCS1, rpcs1, 16) }, - { ORDATA (RPWC, rpwc, 16) }, - { ORDATA (RPBA, rpba, 16) }, - { ORDATA (RPDA, rpda, 16) }, - { ORDATA (RPCS2, rpcs2, 16) }, - { BRDATA (RPDS, rpds, 8, 16, RP_NUMDR) }, - { BRDATA (RPER1, rper1, 8, 16, RP_NUMDR) }, - { ORDATA (RPOF, rpof, 16) }, - { ORDATA (RPDC, rpdc, 16) }, - { ORDATA (RPER2, rper2, 16) }, - { ORDATA (RPER3, rper3, 16) }, - { ORDATA (RPEC1, rpec1, 16) }, - { ORDATA (RPEC2, rpec2, 16) }, - { ORDATA (RPMR, rpmr, 16) }, - { ORDATA (RPDB, rpdb, 16) }, - { FLDATA (IFF, rpiff, 0) }, - { FLDATA (INT, int_req, INT_V_RP) }, - { FLDATA (SC, rpcs1, CSR_V_ERR) }, - { FLDATA (DONE, rpcs1, CSR_V_DONE) }, - { FLDATA (IE, rpcs1, CSR_V_IE) }, - { DRDATA (STIME, rp_swait, 24), REG_NZ + PV_LEFT }, - { DRDATA (RTIME, rp_rwait, 24), REG_NZ + PV_LEFT }, - { URDATA (FNC, rp_unit[0].FUNC, 8, 5, 0, RP_NUMDR, REG_HRO) }, - { URDATA (CAPAC, rp_unit[0].capac, 10, T_ADDR_W, 0, - RP_NUMDR, PV_LEFT | REG_HRO) }, - { FLDATA (STOP_IOE, rp_stopioe, 0) }, - { NULL } }; - -MTAB rp_mod[] = { - { UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL }, - { UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL }, - { (UNIT_DTYPE+UNIT_ATT), (RM03_DTYPE << UNIT_V_DTYPE) + UNIT_ATT, - "RM03", NULL, NULL }, - { (UNIT_DTYPE+UNIT_ATT), (RP04_DTYPE << UNIT_V_DTYPE) + UNIT_ATT, - "RP04", NULL, NULL }, - { (UNIT_DTYPE+UNIT_ATT), (RM80_DTYPE << UNIT_V_DTYPE) + UNIT_ATT, - "RM80", NULL, NULL }, - { (UNIT_DTYPE+UNIT_ATT), (RP06_DTYPE << UNIT_V_DTYPE) + UNIT_ATT, - "RP06", NULL, NULL }, - { (UNIT_DTYPE+UNIT_ATT), (RM05_DTYPE << UNIT_V_DTYPE) + UNIT_ATT, - "RM05", NULL, NULL }, - { (UNIT_DTYPE+UNIT_ATT), (RP07_DTYPE << UNIT_V_DTYPE) + UNIT_ATT, - "RP07", NULL, NULL }, - { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (RM03_DTYPE << UNIT_V_DTYPE), - "RM03", NULL, NULL }, - { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (RP04_DTYPE << UNIT_V_DTYPE), - "RP04", NULL, NULL }, - { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (RM80_DTYPE << UNIT_V_DTYPE), - "RM80", NULL, NULL }, - { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (RP06_DTYPE << UNIT_V_DTYPE), - "RP06", NULL, NULL }, - { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (RM05_DTYPE << UNIT_V_DTYPE), - "RM05", NULL, NULL }, - { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (RP07_DTYPE << UNIT_V_DTYPE), - "RP07", NULL, NULL }, - { (UNIT_AUTO+UNIT_ATT), UNIT_AUTO, "autosize", NULL, NULL }, - { UNIT_AUTO, UNIT_AUTO, NULL, "AUTOSIZE", NULL }, - { (UNIT_AUTO+UNIT_DTYPE), (RM03_DTYPE << UNIT_V_DTYPE), - NULL, "RM03", &rp_set_size }, - { (UNIT_AUTO+UNIT_DTYPE), (RP04_DTYPE << UNIT_V_DTYPE), - NULL, "RP04", &rp_set_size }, - { (UNIT_AUTO+UNIT_DTYPE), (RM80_DTYPE << UNIT_V_DTYPE), - NULL, "RM80", &rp_set_size }, - { (UNIT_AUTO+UNIT_DTYPE), (RP06_DTYPE << UNIT_V_DTYPE), - NULL, "RP06", &rp_set_size }, - { (UNIT_AUTO+UNIT_DTYPE), (RM05_DTYPE << UNIT_V_DTYPE), - NULL, "RM05", &rp_set_size }, - { (UNIT_AUTO+UNIT_DTYPE), (RP07_DTYPE << UNIT_V_DTYPE), - NULL, "RP07", &rp_set_size }, - { MTAB_XTD|MTAB_VDV, 0, "ADDRESS", NULL, - NULL, &show_addr, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "VECTOR", NULL, - NULL, &show_vec, NULL }, - { 0 } }; - -DEVICE rp_dev = { - "RP", rp_unit, rp_reg, rp_mod, - RP_NUMDR, 8, 30, 1, 8, 36, - NULL, NULL, &rp_reset, - &rp_boot, &rp_attach, &rp_detach, - &rp_dib, DEV_UBUS }; - -/* I/O dispatch routines, I/O addresses 17776700 - 17776776 */ - -t_stat rp_rd (int32 *data, int32 PA, int32 access) -{ -int32 drv, dtype, i, j; - -drv = GET_UNIT (rpcs2); /* get current unit */ -dtype = GET_DTYPE (rp_unit[drv].flags); /* get drive type */ -j = (PA >> 1) & 037; /* get reg offset */ -if (reg_in_drive[j] && (rp_unit[drv].flags & UNIT_DIS)) { /* nx disk */ - rpcs2 = rpcs2 | CS2_NED; /* set error flag */ - update_rpcs (CS1_SC, drv); /* request intr */ - *data = 0; - return SCPE_OK; } - -update_rpcs (0, drv); /* update status */ -switch (j) { /* decode PA<5:1> */ -case 000: /* RPCS1 */ - *data = rpcs1; - break; -case 001: /* RPWC */ - *data = rpwc; - break; -case 002: /* RPBA */ - *data = rpba = rpba & ~BA_MBZ; - break; -case 003: /* RPDA */ - *data = rpda = rpda & ~DA_MBZ; - break; -case 004: /* RPCS2 */ - *data = rpcs2 = (rpcs2 & ~CS2_MBZ) | CS2_IR | CS2_OR; - break; -case 005: /* RPDS */ - *data = rpds[drv]; - break; -case 006: /* RPER1 */ - *data = rper1[drv]; - break; -case 007: /* RPAS */ - *data = 0; - for (i = 0; i < RP_NUMDR; i++) - if (rpds[i] & DS_ATA) *data = *data | (AS_U0 << i); - break; -case 010: /* RPLA */ - *data = GET_SECTOR (rp_rwait, dtype) << LA_V_SC; - break; -case 011: /* RPDB */ - *data = rpdb; - break; -case 012: /* RPMR */ - *data = rpmr; - break; -case 013: /* RPDT */ - *data = drv_tab[dtype].devtype; - break; -case 014: /* RPSN */ - *data = 020 | (drv + 1); - break; -case 015: /* RPOF */ - *data = rpof = rpof & ~OF_MBZ; - break; -case 016: /* RPDC */ - *data = rpdc = rpdc & ~DC_MBZ; - break; -case 017: /* RPCC, RMHR */ - *data = rp_unit[drv].CYL; - break; -case 020: /* RPER2, RMMR2 */ - *data = rper2; - break; -case 021: /* RPER3, RMER2 */ - *data = rper3; - break; -case 022: /* RPEC1 */ - *data = rpec1; - break; -case 023: /* RPEC2 */ - *data = rpec2; - break; -default: /* all others */ - rper1[drv] = rper1[drv] | ER1_ILR; - update_rpcs (0, drv); - break; } -return SCPE_OK; -} - -t_stat rp_wr (int32 data, int32 PA, int32 access) -{ -int32 cs1f, drv, i, j; -UNIT *uptr; - -cs1f = 0; /* no int on cs1 upd */ -drv = GET_UNIT (rpcs2); /* get current unit */ -uptr = rp_dev.units + drv; /* get unit */ -j = (PA >> 1) & 037; /* get reg offset */ -if (reg_in_drive[j] && (rp_unit[drv].flags & UNIT_DIS)) { /* nx disk */ - rpcs2 = rpcs2 | CS2_NED; /* set error flag */ - update_rpcs (CS1_SC, drv); /* request intr */ - return SCPE_OK; } -if (reg_in_drive[j] && sim_is_active (&rp_unit[drv])) { /* unit busy? */ - rper1[drv] = rper1[drv] | ER1_RMR; /* won't write */ - update_rpcs (0, drv); - return SCPE_OK; } - -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> */ - if ((access == WRITE) || (PA & 1)) { /* hi byte write? */ - 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); } } - break; -case 001: /* RPWC */ - if (access == WRITEB) data = (PA & 1)? - (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 = data & ~BA_MBZ; - break; -case 003: /* RPDA */ - if (access == WRITEB) data = (PA & 1)? - (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; } - drv = GET_UNIT (rpcs2); - break; -case 006: /* RPER1 */ - if (access == WRITEB) break; - rper1[drv] = rper1[drv] & data; - break; -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; - break; -case 011: /* RPDB */ - if (access == WRITEB) data = (PA & 1)? - (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 = data; - break; -case 015: /* RPOF */ - if (access == WRITEB) data = (PA & 1)? - (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 = data & ~DC_MBZ; - break; -case 005: /* RPDS */ -case 010: /* RPLA */ -case 013: /* RPDT */ -case 014: /* RPSN */ -case 017: /* RPDC, RMHR */ -case 020: /* RPER2, RMMN2 */ -case 021: /* RPER3, RMER2 */ -case 022: /* RPEC1 */ -case 023: /* RPEC2 */ - break; /* read only */ -default: /* all others */ - rper1[drv] = rper1[drv] | ER1_ILR; - break; } /* end switch */ -update_rpcs (cs1f, drv); /* update status */ -return SCPE_OK; -} - -/* Initiate operation - unit not busy, function set */ - -void rp_go (int32 drv, int32 fnc) -{ -int32 dc, dtype, t; -UNIT *uptr; - -uptr = rp_dev.units + drv; /* get unit */ -if (uptr->flags & UNIT_DIS) { /* nx unit? */ - rpcs2 = rpcs2 | CS2_NED; /* set error flag */ - update_rpcs (CS1_SC, drv); /* request intr */ - return; } -if ((fnc != FNC_DCLR) && (rpds[drv] & DS_ERR)) { /* err & ~clear? */ - rper1[drv] = rper1[drv] | ER1_ILF; /* not allowed */ - rpds[drv] = rpds[drv] | DS_ATA; /* set attention */ - update_rpcs (CS1_SC, drv); /* request intr */ - return; } -dtype = GET_DTYPE (uptr->flags); /* get drive type */ -rpds[drv] = rpds[drv] & ~DS_ATA; /* clear attention */ -dc = rpdc; /* assume seek, sch */ - -switch (fnc) { /* case on function */ -case FNC_DCLR: /* drive clear */ - rpda = 0; /* clear disk addr */ - rper1[drv] = rper2 = rper3 = 0; /* clear errors */ -case FNC_NOP: /* no operation */ -case FNC_RELEASE: /* port release */ - return; - -case FNC_PRESET: /* read-in preset */ - rpdc = 0; /* clear disk addr */ - rpda = 0; - rpof = 0; /* clear offset */ -case FNC_PACK: /* pack acknowledge */ - rpds[drv] = rpds[drv] | DS_VV; /* set volume valid */ - return; - -case FNC_OFFSET: /* offset mode */ -case FNC_RETURN: - if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */ - 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; - -case FNC_UNLOAD: /* unload */ -case FNC_RECAL: /* recalibrate */ - dc = 0; /* seek to 0 */ -case FNC_SEEK: /* seek */ -case FNC_SEARCH: /* search */ - if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */ - 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; } - rpds[drv] = (rpds[drv] & ~DS_RDY) | DS_PIP; /* set positioning */ - t = abs (dc - uptr->CYL); /* cyl diff */ - if (t == 0) t = 1; /* min time */ - sim_activate (uptr, rp_swait * t); /* schedule */ - uptr->CYL = dc; /* save cylinder */ - return; - -case FNC_WRITEH: /* write headers */ -case FNC_WRITE: /* write */ -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; } - 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; } - 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 */ - return; - -default: /* all others */ - rper1[drv] = rper1[drv] | ER1_ILF; /* not supported */ - break; } -rpds[drv] = rpds[drv] | DS_ATA; /* error, set attn */ -update_rpcs (CS1_SC, drv); /* req intr */ -return; -} - -/* Service unit timeout - - Complete movement or data transfer command - Unit must exist - can't remove an active unit - Unit must be attached - detach cancels in progress operations -*/ - -t_stat rp_svc (UNIT *uptr) -{ -int32 i, dtype, drv, err; -int32 ba, da, vpn; -a10 pa10, mpa10; -int32 wc10, twc10, awc10, fc10; -static d10 dbuf[RP_MAXFR]; - -dtype = GET_DTYPE (uptr->flags); /* get drive type */ -drv = uptr - rp_dev.units; /* get drv number */ -rpds[drv] = (rpds[drv] & ~DS_PIP) | DS_RDY; /* change drive status */ - -switch (uptr->FUNC) { /* case on function */ -case FNC_OFFSET: /* offset */ - rpds[drv] = rpds[drv] | DS_OF | DS_ATA; /* set offset, attention */ - update_rpcs (CS1_SC, drv); - break; -case FNC_RETURN: /* return to centerline */ - rpds[drv] = (rpds[drv] & ~DS_OF) | DS_ATA; /* clear offset, set attn */ - update_rpcs (CS1_SC, drv); - break; -case FNC_UNLOAD: /* unload */ - rp_detach (uptr); /* detach unit */ - break; -case FNC_RECAL: /* recalibrate */ -case FNC_SEARCH: /* search */ -case FNC_SEEK: /* seek */ - rpds[drv] = rpds[drv] | DS_ATA; /* set attention */ - update_rpcs (CS1_SC, drv); - break; - -/* Reads and writes must take into account the complicated relationship - between Unibus addresses and PDP-10 memory addresses, and Unibus - byte and word counts, PDP-10 UBA word counts, and simulator PDP-10 - word counts (due to the fact that the simulator must transfer eight - 8b bytes to do a 36b transfer, whereas the UBA did four 9b bytes). -*/ - -#define XWC_MBZ 0000001 /* wc<0> must be 0 */ -#define XBA_MBZ 0000003 /* addr<1:0> must be 0 */ - -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; } -case FNC_WCHK: /* write check */ -case FNC_READ: /* read */ -case FNC_READH: /* read headers */ - ba = GET_UAE (rpcs1) | rpba; /* get byte addr */ - 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; } - - err = fseek (uptr->fileref, da * sizeof (d10), SEEK_SET); - if (uptr->FUNC == FNC_WRITE) { /* write? */ - for (twc10 = 0; twc10 < wc10; twc10++) { - pa10 = ba >> 2; - vpn = PAG_GETVPN (pa10); /* map addr */ - if ((vpn >= UMAP_MEMSIZE) || (ba & XBA_MBZ) || (rpwc & XWC_MBZ) || - ((ubmap[0][vpn] & (UMAP_VLD | UMAP_DSB | UMAP_RRV)) != UMAP_VLD)) { - rpcs2 = rpcs2 | CS2_NEM; /* set error */ - ubcs[0] = ubcs[0] | UBCS_TMO; /* UBA times out */ - break; } - mpa10 = (ubmap[0][vpn] + PAG_GETOFF (pa10)) & PAMASK; - if (MEM_ADDR_NXM (mpa10)) { /* nx memory? */ - rpcs2 = rpcs2 | CS2_NEM; /* set error */ - ubcs[0] = ubcs[0] | UBCS_TMO; /* UBA times out */ - break; } - dbuf[twc10] = M[mpa10]; /* write to disk */ - if ((rpcs2 & CS2_UAI) == 0) ba = ba + 4; } - if (fc10 = twc10 & (RP_NUMWD - 1)) { /* fill? */ - fc10 = RP_NUMWD - fc10; - for (i = 0; i < fc10; i++) dbuf[twc10 + i] = 0; } - fxwrite (dbuf, sizeof (d10), twc10 + fc10, uptr->fileref); - err = ferror (uptr->fileref); - } /* end if */ - else { /* read, wchk, readh */ - awc10 = fxread (dbuf, sizeof (d10), wc10, uptr->fileref); - err = ferror (uptr->fileref); - for ( ; awc10 < wc10; awc10++) dbuf[awc10] = 0; - for (twc10 = 0; twc10 < wc10; twc10++) { - pa10 = ba >> 2; - vpn = PAG_GETVPN (pa10); /* map addr */ - if ((vpn >= UMAP_MEMSIZE) || (ba & XBA_MBZ) || (rpwc & XWC_MBZ) || - ((ubmap[0][vpn] & (UMAP_VLD | UMAP_DSB | UMAP_RRV)) != UMAP_VLD)) { - rpcs2 = rpcs2 | CS2_NEM; /* set error */ - ubcs[0] = ubcs[0] | UBCS_TMO; /* UBA times out */ - break; } - mpa10 = (ubmap[0][vpn] + PAG_GETOFF (pa10)) & PAMASK; - if (MEM_ADDR_NXM (mpa10)) { /* nx memory? */ - rpcs2 = rpcs2 | CS2_NEM; /* set error */ - ubcs[0] = ubcs[0] | UBCS_TMO; /* UBA times out */ - break; } - if ((uptr->FUNC == FNC_READ) || /* read or */ - (uptr->FUNC == FNC_READH)) /* read header */ - M[mpa10] = dbuf[twc10]; - else if (M[mpa10] != dbuf[twc10]) { /* wchk, mismatch? */ - rpcs2 = rpcs2 | CS2_WCE; /* set error */ - break; } - if ((rpcs2 & CS2_UAI) == 0) ba = ba + 4; } - } /* end else */ - - rpwc = (rpwc + (twc10 << 1)) & 0177777; /* final word count */ - rpba = (ba & 0177777) & ~BA_MBZ; /* lower 16b */ - rpcs1 = (rpcs1 & ~ CS1_UAE) | ((ba >> (16 - CS1_V_UAE)) & CS1_UAE); - da = da + twc10 + (RP_NUMWD - 1); - if (da >= drv_tab[dtype].size) rpds[drv] = rpds[drv] | DS_LST; - da = da / RP_NUMWD; - rpda = da % drv_tab[dtype].sect; - da = da / drv_tab[dtype].sect; - rpda = rpda | ((da % drv_tab[dtype].surf) << DA_V_SF); - 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; } -case FNC_WRITEH: /* write headers stub */ - update_rpcs (CS1_DONE, drv); /* set done */ - break; } /* end case func */ -return SCPE_OK; -} - -/* Controller status update - - Check for done transition - Update drive status - Update RPCS1 - Update interrupt request -*/ - -void update_rpcs (int32 flag, int32 drv) -{ -int32 i; -UNIT *uptr; - -if ((flag & ~rpcs1) & CS1_DONE) /* DONE 0 to 1? */ - rpiff = (rpcs1 & CS1_IE)? 1: 0; /* CSTB INTR <- IE */ -uptr = rp_dev.units + drv; /* get unit */ -if (rp_unit[drv].flags & UNIT_DIS) rpds[drv] = rper1[drv] = 0; -else rpds[drv] = (rpds[drv] | DS_DPR) & ~DS_PGM; -if (rp_unit[drv].flags & UNIT_ATT) rpds[drv] = rpds[drv] | DS_MOL; -else rpds[drv] = rpds[drv] & ~(DS_MOL | DS_VV | DS_RDY); -if (rper1[drv] | rper2 | rper3) rpds[drv] = rpds[drv] | DS_ERR | DS_ATA; -else rpds[drv] = rpds[drv] & ~DS_ERR; - -rpcs1 = (rpcs1 & ~(CS1_SC | CS1_MCPE | CS1_MBZ | CS1_DRV)) | CS1_DVA | flag; -rpcs1 = rpcs1 | (uptr->FUNC << CS1_V_FNC); -if (sim_is_active (uptr)) rpcs1 = rpcs1 | CS1_GO; -if (rpcs2 & CS2_ERR) rpcs1 = rpcs1 | CS1_TRE | CS1_SC; -else if (rpcs1 & CS1_TRE) rpcs1 = rpcs1 | CS1_SC; -for (i = 0; i < RP_NUMDR; i++) - if (rpds[i] & DS_ATA) rpcs1 = rpcs1 | CS1_SC; -if (rpiff || ((rpcs1 & CS1_SC) && (rpcs1 & CS1_DONE) && (rpcs1 & CS1_IE))) - int_req = int_req | INT_RP; -else int_req = int_req & ~INT_RP; -return; -} - -/* Interrupt acknowledge */ - -int32 rp_inta (void) -{ -rpcs1 = rpcs1 & ~CS1_IE; /* clear int enable */ -rpiff = 0; /* clear CSTB INTR */ -return VEC_RP; /* acknowledge */ -} - -/* Device reset */ - -t_stat rp_reset (DEVICE *dptr) -{ -int32 i; -UNIT *uptr; - -rpcs1 = CS1_DVA | CS1_DONE; -rpcs2 = CS2_IR | CS2_OR; -rpba = rpda = 0; -rpof = rpdc = 0; -rper2 = rper3 = 0; -rpec1 = rpec2 = 0; -rpiff = 0; /* clear CSTB INTR */ -int_req = int_req & ~INT_RP; /* clear intr req */ -for (i = 0; i < RP_NUMDR; i++) { - uptr = rp_dev.units + 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); - else if (uptr->flags & UNIT_DIS) rpds[i] = 0; - else rpds[i] = DS_DPR; - rper1[i] = 0; } -return SCPE_OK; -} - -/* Device attach */ - -t_stat rp_attach (UNIT *uptr, char *cptr) -{ -int32 drv, i, p; -t_stat r; - -uptr->capac = drv_tab[GET_DTYPE (uptr->flags)].size; -r = attach_unit (uptr, cptr); -if (r != SCPE_OK) return r; -drv = uptr - rp_dev.units; /* get drv number */ -rpds[drv] = DS_ATA | DS_MOL | DS_RDY | DS_DPR | - ((uptr->flags & UNIT_WPRT)? DS_WRL: 0); -rper1[drv] = 0; -update_rpcs (CS1_SC, drv); - -if ((uptr->flags & UNIT_AUTO) == 0) return SCPE_OK; /* autosize? */ -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 (d10))) { - uptr->flags = (uptr->flags & ~UNIT_DTYPE) | (i << UNIT_V_DTYPE); - uptr->capac = drv_tab[i].size; - return SCPE_OK; } } -return SCPE_OK; -} - -/* Device detach */ - -t_stat rp_detach (UNIT *uptr) -{ -int32 drv; - -drv = uptr - rp_dev.units; /* get drv number */ -rpds[drv] = (rpds[drv] & ~(DS_MOL | DS_RDY | DS_WRL | DS_VV | DS_OF)) | - DS_ATA; -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 */ -update_rpcs (CS1_SC, drv); /* request intr */ -return detach_unit (uptr); -} - -/* Set size command validation routine */ - -t_stat rp_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; -} - -/* Device bootstrap */ - -#define BOOT_START 0377000 /* start */ -#define BOOT_LEN (sizeof (boot_rom_dec) / sizeof (d10)) - -static const d10 boot_rom_dec[] = { - 0515040000001, /* boot:hrlzi 1,1 ; uba # */ - 0201000140001, /* movei 0,140001 ; vld,fst,pg 1 */ - 0713001000000+(IOBA_UBMAP+1 & RMASK), /* wrio 0,763001(1); set ubmap */ - 0435040000000+(IOBA_RP & RMASK), /* iori 1,776700 ; rh addr */ - 0202040000000+FE_RHBASE, /* movem 1,FE_RHBASE */ - 0201000000040, /* movei 0,40 ; ctrl reset */ - 0713001000010, /* wrio 0,10(1) ; ->RPCS2 */ - 0201000000021, /* movei 0,21 ; preset */ - 0713001000000, /* wrio 0,0(1) ; ->RPCS1 */ - 0201100000001, /* movei 2,1 ; blk #1 */ - 0265740377032, /* jsp 17,rdbl ; read */ - 0204140001000, /* movs 3,1000 ; id word */ - 0306140505755, /* cain 3,sixbit /HOM/ */ - 0254000377023, /* jrst .+6 ; match */ - 0201100000010, /* movei 2,10 ; blk #10 */ - 0265740377032, /* jsp 17,rdbl ; read */ - 0204140001000, /* movs 3,1000 ; id word */ - 0302140505755, /* caie 3,sixbit /HOM/ */ - 0254200377022, /* halt . ; inv home */ - 0336100001103, /* skipn 2,1103 ; pg of ptrs */ - 0254200377024, /* halt . ; inv ptr */ - 0265740377032, /* jsp 17,rdbl ; read */ - 0336100001004, /* skipn 2,1004 ; mon boot */ - 0254200377027, /* halt . ; inv ptr */ - 0265740377032, /* jsp 17,rdbl ; read */ - 0254000001000, /* jrst 1000 ; start */ - 0201140176000, /* rdbl:movei 3,176000 ; wd cnt */ - 0201200004000, /* movei 4,4000 ; addr */ - 0200240000000+FE_UNIT, /* move 5,FE_UNIT ; unit */ - 0200300000002, /* move 6,2 */ - 0242300777750, /* lsh 6,-24. ; cyl */ - 0713141000002, /* wrio 3,2(1) ; ->RPWC */ - 0713201000004, /* wrio 4,4(1) ; ->RPBA */ - 0713101000006, /* wrio 2,6(1) ; ->RPDA */ - 0713241000010, /* wrio 5,10(1) ; ->RPCS2 */ - 0713301000034, /* wrio 6,34(1) ; ->RPDC */ - 0201000000071, /* movei 0,71 ; read+go */ - 0713001000000, /* wrio 0,0(1) ; ->RPCS1 */ - 0712341000000, /* rdio 7,0(1) ; read csr */ - 0606340000200, /* trnn 7,200 ; test rdy */ - 0254000377046, /* jrst .-2 ; loop */ - 0602340100000, /* trne 7,100000 ; test err */ - 0254200377052, /* halt */ - 0254017000000, /* jrst 0(17) ; return */ -}; - -static const d10 boot_rom_its[] = { - 0515040000001, /* boot:hrlzi 1,1 ; uba # */ - 0201000140001, /* movei 0,140001 ; vld,fst,pg 1 */ - 0715000000000+(IOBA_UBMAP+1 & RMASK), /* iowrq 0,763001 ; set ubmap */ - 0435040000000+(IOBA_RP & RMASK), /* iori 1,776700 ; rh addr */ - 0202040000000+FE_RHBASE, /* movem 1,FE_RHBASE */ - 0201000000040, /* movei 0,40 ; ctrl reset */ - 0715001000010, /* iowrq 0,10(1) ; ->RPCS2 */ - 0201000000021, /* movei 0,21 ; preset */ - 0715001000000, /* iowrq 0,0(1) ; ->RPCS1 */ - 0201100000001, /* movei 2,1 ; blk #1 */ - 0265740377032, /* jsp 17,rdbl ; read */ - 0204140001000, /* movs 3,1000 ; id word */ - 0306140505755, /* cain 3,sixbit /HOM/ */ - 0254000377023, /* jrst .+6 ; match */ - 0201100000010, /* movei 2,10 ; blk #10 */ - 0265740377032, /* jsp 17,rdbl ; read */ - 0204140001000, /* movs 3,1000 ; id word */ - 0302140505755, /* caie 3,sixbit /HOM/ */ - 0254200377022, /* halt . ; inv home */ - 0336100001103, /* skipn 2,1103 ; pg of ptrs */ - 0254200377024, /* halt . ; inv ptr */ - 0265740377032, /* jsp 17,rdbl ; read */ - 0336100001004, /* skipn 2,1004 ; mon boot */ - 0254200377027, /* halt . ; inv ptr */ - 0265740377032, /* jsp 17,rdbl ; read */ - 0254000001000, /* jrst 1000 ; start */ - 0201140176000, /* rdbl:movei 3,176000 ; wd cnt */ - 0201200004000, /* movei 4,4000 ; addr */ - 0200240000000+FE_UNIT, /* move 5,FE_UNIT ; unit */ - 0200300000002, /* move 6,2 */ - 0242300777750, /* lsh 6,-24. ; cyl */ - 0715141000002, /* iowrq 3,2(1) ; ->RPWC */ - 0715201000004, /* iowrq 4,4(1) ; ->RPBA */ - 0715101000006, /* iowrq 2,6(1) ; ->RPDA */ - 0715241000010, /* iowrq 5,10(1) ; ->RPCS2 */ - 0715301000034, /* iowrq 6,34(1) ; ->RPDC */ - 0201000000071, /* movei 0,71 ; read+go */ - 0715001000000, /* iowrq 0,0(1) ; ->RPCS1 */ - 0711341000000, /* iordq 7,0(1) ; read csr */ - 0606340000200, /* trnn 7,200 ; test rdy */ - 0254000377046, /* jrst .-2 ; loop */ - 0602340100000, /* trne 7,100000 ; test err */ - 0254200377052, /* halt */ - 0254017000000, /* jrst 0(17) ; return */ -}; - -t_stat rp_boot (int32 unitno, DEVICE *dptr) -{ -int32 i; -extern a10 saved_PC; - -M[FE_UNIT] = unitno & CS2_M_UNIT; -for (i = 0; i < BOOT_LEN; i++) - M[BOOT_START + i] = ITS? boot_rom_its[i]: boot_rom_dec[i]; -saved_PC = BOOT_START; -return SCPE_OK; -} diff --git a/PDP10/pdp10_sys.c b/PDP10/pdp10_sys.c deleted file mode 100644 index 477b5c47..00000000 --- a/PDP10/pdp10_sys.c +++ /dev/null @@ -1,798 +0,0 @@ -/* pdp10_sys.c: PDP-10 simulator interface - - 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. - - 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 - 25-Aug-01 RMS Enabled DZ11 - 27-May-01 RMS Added multiconsole support - 29-Apr-01 RMS Fixed format for RDPCST, WRPCST - Added CLRCSH for ITS - 03-Apr-01 RMS Added support for loading EXE files - 19-Mar-01 RMS Added support for loading SAV files - 30-Oct-00 RMS Added support for examine to file -*/ - -#include "pdp10_defs.h" -#include - -extern DEVICE cpu_dev, pag_dev; -extern DEVICE tim_dev, fe_dev, uba_dev; -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; -extern a10 saved_PC; - -/* 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-10"; - -REG *sim_PC = &cpu_reg[0]; - -int32 sim_emax = 1; - -DEVICE *sim_devices[] = { - &cpu_dev, - &pag_dev, - &tim_dev, - &fe_dev, - &uba_dev, - &ptr_dev, - &ptp_dev, - &ry_dev, - &lp20_dev, - &rp_dev, - &tu_dev, - &dz_dev, - &xu_dev, - NULL }; - -const char *sim_stop_messages[] = { - "Unknown error", - "HALT instruction", - "Breakpoint", - "Illegal instruction", - "Illegal interrupt instruction", - "Paging error in interrupt", - "Zero vector table", - "NXM on UPT/EPT reference", - "Nested indirect address limit exceeded", - "Nested XCT limit exceeded", - "Invalid I/O controller", - "Address stop", - "Panic stop" }; - -/* Binary loader, supports RIM10, SAV, EXE */ - -#define FMT_R 1 /* RIM10 */ -#define FMT_S 2 /* SAV */ -#define FMT_E 3 /* EXE */ - -#define EXE_DIR 01776 /* EXE directory */ -#define EXE_VEC 01775 /* EXE entry vec */ -#define EXE_PDV 01774 /* EXE ignored */ -#define EXE_END 01777 /* EXE end - -/* RIM10 loader - - RIM10 format is a binary paper tape format (all data frames - are 200 or greater). It consists of blocks containing - - -count,,origin-1 - word - : - word - checksum (includes IOWD) - : - JRST start -*/ - -d10 getrimw (FILE *fileref) -{ -int32 i, tmp; -d10 word; - -word = 0; -for (i = 0; i < 6;) { - if ((tmp = getc (fileref)) == EOF) return -1; - if (tmp & 0200) { - word = (word << 6) | ((d10) tmp & 077); - i++; } } -return word; -} - -t_stat load_rim (FILE *fileref) -{ -d10 count, cksm, data; -a10 pa; -int32 op; - -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 */ - } /* end for */ -return SCPE_FMT; -} - -/* SAV file loader - - SAV format is a disk file format (36b words). It consists of - blocks containing: - - -count,,origin-1 - word - : - word - : - JRST start -*/ - -t_stat load_sav (FILE *fileref) -{ -d10 count, data; -a10 pa; -int32 wc, op; - -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 */ - } /* end for */ -return SCPE_FMT; -} - -/* EXE file loader - - EXE format is a disk file format (36b words). It consists of - blocks containing: - - block type,,total words = n - n - 1 data words - - Block types are - - EXE_DIR (1776) directory - EXE_VEC (1775) entry vector - EXE_PDV (1774) optional blocks - EXE_END (1777) end block - - The directory blocks are the most important and contain doubleword - page loading information: - - word0<0:8> = flags - <9:35> = page in file (0 if 0 page) - word1<0:8> = repeat count - 1 - <9:35> = page in memory -*/ - -#define DIRSIZ (2 * PAG_SIZE) - -t_stat load_exe (FILE *fileref) -{ -d10 data, dirbuf[DIRSIZ], pagbuf[PAG_SIZE], entbuf[2]; -int32 ndir, entvec, i, j, k, cont, bsz, bty, rpt, wc; -int32 fpage, mpage; -a10 ma; - -ndir = entvec = 0; /* no dir, entvec */ -cont = 1; -do { wc = fxread (&data, sizeof (d10), 1, fileref); /* read blk hdr */ - if (wc == 0) return SCPE_FMT; /* error? */ - bsz = (int32) ((data & RMASK) - 1); /* get count */ - if (bsz <= 0) return SCPE_FMT; /* zero? */ - 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; - case EXE_PDV: /* ??? */ - 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; - case EXE_END: /* end */ - if (bsz != 0) return SCPE_FMT; /* must be hdr */ - cont = 0; /* stop */ - break; - default: - return SCPE_FMT; } /* end switch */ - } /* end do */ -while (cont); - -for (i = 0; i < ndir; i = i + 2) { /* loop thru dir */ - fpage = (int32) (dirbuf[i] & RMASK); /* file page */ - 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 */ - } /* end directory */ -if (entvec && entbuf[1]) - saved_PC = (int32) entbuf[1] & RMASK; /* start addr */ -return SCPE_OK; -} - -/* Master loader */ - -t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag) -{ -d10 data; -int32 wc, fmt; -extern int32 sim_switches; - -fmt = 0; /* no fmt */ -if (sim_switches & SWMASK ('R')) fmt = FMT_R; /* -r? */ -else if (sim_switches & SWMASK ('S')) fmt = FMT_S; /* -s? */ -else if (sim_switches & SWMASK ('E')) fmt = FMT_E; /* -e? */ -else if (match_ext (fnam, "RIM")) fmt = FMT_R; /* .RIM? */ -else if (match_ext (fnam, "SAV")) fmt = FMT_S; /* .SAV? */ -else if (match_ext (fnam, "EXE")) fmt = FMT_E; /* .EXE? */ -else { wc = fxread (&data, sizeof (d10), 1, fileref); /* read hdr */ - if (wc == 0) return SCPE_FMT; /* error? */ - if (LRZ (data) == EXE_DIR) fmt = FMT_E; /* EXE magic? */ - else if (TSTS (data)) fmt = FMT_S; /* SAV magic? */ - fseek (fileref, 0, SEEK_SET); } /* rewind */ -switch (fmt) { /* case fmt */ -case FMT_R: /* RIM */ - return load_rim (fileref); -case FMT_S: /* SAV */ - return load_sav (fileref); -case FMT_E: /* EXE */ - return load_exe (fileref); } -printf ("Can't determine load file format\n"); -return SCPE_FMT; -} - -/* Symbol tables */ - -#define I_V_FL 39 /* inst class */ -#define I_M_FL 03 /* class mask */ -#define I_ITS 004000000000000 /* ITS flag */ -#define I_AC 000000000000000 /* AC, address */ -#define I_OP 010000000000000 /* address only */ -#define I_IO 020000000000000 /* classic I/O */ -#define I_V_AC 00 -#define I_V_OP 01 -#define I_V_IO 02 - -static const d10 masks[] = { - 0777000000000, 0777740000000, - 0700340000000, 0777777777777 }; - -static const char *opcode[] = { -"XCTR", "XCTI", /* ITS only */ -"IORDI", "IORDQ", "IORD", "IOWR", "IOWRI", "IOWRQ", -"IORDBI", "IORDBQ", "IORDB", "IOWRB", "IOWRBI", "IOWRBQ", -"CLRCSH", "RDPCST", "WRPCST", -"SDBR1", "SDBR2", "SDBR3", "SDBR4", "SPM", -"LDBR1", "LDBR2", "LDBR3", "LDBR4", "LPMR", - -"PORTAL", "JRSTF", "HALT", /* AC defines op */ -"XJRSTF", "XJEN", "XPCW", -"JEN", "SFM", "XJRST", "IBP", -"JFOV", "JCRY1", "JCRY0", "JCRY", "JOV", - -"APRID", "WRAPR", "RDAPR", "WRPI", "RDPI", "RDUBR", "CLRPT", "WRUBR", -"WREBR", "RDEBR", -"RDSPB", "RDCSB", "RDPUR", "RDCSTM", "RDTIM", "RDINT", "RDHSB", -"WRSPB", "WRCSB", "WRPUR", "WRCSTM", "WRTIM", "WRINT", "WRHSB", - - "LUUO01", "LUUO02", "LUUO03", "LUUO04", "LUUO05", "LUUO06", "LUUO07", -"LUUO10", "LUUO11", "LUUO12", "LUUO13", "LUUO14", "LUUO15", "LUUO16", "LUUO17", -"LUUO20", "LUUO21", "LUUO22", "LUUO23", "LUUO24", "LUUO25", "LUUO26", "LUUO27", -"LUUO30", "LUUO31", "LUUO32", "LUUO33", "LUUO34", "LUUO35", "LUUO36", "LUUO37", -"MUUO40", "MUUO41", "MUUO42", "MUUO43", "MUUO44", "MUUO45", "MUUO46", "MUUO47", -"MUUO50", "MUUO51", "MUUO52", "MUUO53", "MUUO54", "MUUO55", "MUUO56", "MUUO57", -"MUUO60", "MUUO61", "MUUO62", "MUUO63", "MUUO64", "MUUO65", "MUUO66", "MUUO67", -"MUUO70", "MUUO71", "MUUO72", "MUUO73", "MUUO74", "MUUO75", "MUUO76", "MUUO77", - -"UJEN", "GFAD", "GFSB", "JSYS", "ADJSP", "GFMP", "GFDV ", -"DFAD", "DFSB", "DFMP", "DFDV", "DADD", "DSUB", "DMUL", "DDIV", -"DMOVE", "DMOVN", "FIX", "EXTEND", "DMOVEM", "DMOVNM", "FIXR", "FLTR", -"UFA", "DFN", "FSC", "ADJBP", "ILDB", "LDB", "IDPB", "DPB", -"FAD", "FADL", "FADM", "FADB", "FADR", "FADRL", "FADRM", "FADRB", -"FSB", "FSBL", "FSBM", "FSBB", "FSBR", "FSBRL", "FSBRM", "FSBRB", -"FMP", "FMPL", "FMPM", "FMPB", "FMPR", "FMPRL", "FMPRM", "FMPRB", -"FDV", "FDVL", "FDVM", "FDVB", "FDVR", "FDVRL", "FDVRM", "FDVRB", - -"MOVE", "MOVEI", "MOVEM", "MOVES", "MOVS", "MOVSI", "MOVSM", "MOVSS", -"MOVN", "MOVNI", "MOVNM", "MOVNS", "MOVM", "MOVMI", "MOVMM", "MOVMS", -"IMUL", "IMULI", "IMULM", "IMULB", "MUL", "MULI", "MULM", "MULB", -"IDIV", "IDIVI", "IDIVM", "IDIVB", "DIV", "DIVI", "DIVM", "DIVB", -"ASH", "ROT", "LSH", "JFFO", "ASHC", "ROTC", "LSHC", "CIRC", -"EXCH", "BLT", "AOBJP", "AOBJN", "JRST", "JFCL", "XCT", "MAP", -"PUSHJ", "PUSH", "POP", "POPJ", "JSR", "JSP", "JSA", "JRA", -"ADD", "ADDI", "ADDM", "ADDB", "SUB", "SUBI", "SUBM", "SUBB", - -"CAI", "CAIL", "CAIE", "CAILE", "CAIA", "CAIGE", "CAIN", "CAIG", -"CAM", "CAML", "CAME", "CAMLE", "CAMA", "CAMGE", "CAMN", "CAMG", -"JUMP", "JUMPL", "JUMPE", "JUMPLE", "JUMPA", "JUMPGE", "JUMPN", "JUMPG", -"SKIP", "SKIPL", "SKIPE", "SKIPLE", "SKIPA", "SKIPGE", "SKIPN", "SKIPG", -"AOJ", "AOJL", "AOJE", "AOJLE", "AOJA", "AOJGE", "AOJN", "AOJG", -"AOS", "AOSL", "AOSE", "AOSLE", "AOSA", "AOSGE", "AOSN", "AOSG", -"SOJ", "SOJL", "SOJE", "SOJLE", "SOJA", "SOJGE", "SOJN", "SOJG", -"SOS", "SOSL", "SOSE", "SOSLE", "SOSA", "SOSGE", "SOSN", "SOSG", - -"SETZ", "SETZI", "SETZM", "SETZB", "AND", "ANDI", "ANDM", "ANDB", -"ANDCA", "ANDCAI", "ANDCAM", "ANDCAB", "SETM", "SETMI", "SETMM", "SETMB", -"ANDCM", "ANDCMI", "ANDCMM", "ANDCMB", "SETA", "SETAI", "SETAM", "SETAB", -"XOR", "XORI", "XORM", "XORB", "IOR", "IORI", "IORM", "IORB", -"ANDCB", "ANDCBI", "ANDCBM", "ANDCBB", "EQV", "EQVI", "EQVM", "EQVB", -"SETCA", "SETCAI", "SETCAM", "SETCAB", "ORCA", "ORCAI", "ORCAM", "ORCAB", -"SETCM", "SETCMI", "SETCMM", "SETCMB", "ORCM", "ORCMI", "ORCMM", "ORCMB", -"ORCB", "ORCBI", "ORCBM", "ORCBB", "SETO", "SETOI", "SETOM", "SETOB", - -"HLL", "HLLI", "HLLM", "HLLS", "HRL", "HRLI", "HRLM", "HRLS", -"HLLZ", "HLLZI", "HLLZM", "HLLZS", "HRLZ", "HRLZI", "HRLZM", "HRLZS", -"HLLO", "HLLOI", "HLLOM", "HLLOS", "HRLO", "HRLOI", "HRLOM", "HRLOS", -"HLLE", "HLLEI", "HLLEM", "HLLES", "HRLE", "HRLEI", "HRLEM", "HRLES", -"HRR", "HRRI", "HRRM", "HRRS", "HLR", "HLRI", "HLRM", "HLRS", -"HRRZ", "HRRZI", "HRRZM", "HRRZS", "HLRZ", "HLRZI", "HLRZM", "HLRZS", -"HRRO", "HRROI", "HRROM", "HRROS", "HLRO", "HLROI", "HLROM", "HLROS", -"HRRE", "HRREI", "HRREM", "HRRES", "HLRE", "HLREI", "HLREM", "HLRES", - -"TRN", "TLN", "TRNE", "TLNE", "TRNA", "TLNA", "TRNN", "TLNN", -"TDN", "TSN", "TDNE", "TSNE", "TDNA", "TSNA", "TDNN", "TSNN", -"TRZ", "TLZ", "TRZE", "TLZE", "TRZA", "TLZA", "TRZN", "TLZN", -"TDZ", "TSZ", "TDZE", "TSZE", "TDZA", "TSZA", "TDZN", "TSZN", -"TRC", "TLC", "TRCE", "TLCE", "TRCA", "TLCA", "TRCN", "TLCN", -"TDC", "TSC", "TDCE", "TSCE", "TDCA", "TSCA", "TDCN", "TSCN", -"TRO", "TLO", "TROE", "TLOE", "TROA", "TLOA", "TRON", "TLON", -"TDO", "TSO", "TDOE", "TSOE", "TDOA", "TSOA", "TDON", "TSON", - -"UMOVE", "UMOVEM", /* KS10 I/O */ -"TIOE", "TION", "RDIO", "WRIO", -"BSIO", "BCIO", "BLTBU", "BLTUB", -"TIOEB", "TIONB", "RDIOB", "WRIOB", -"BSIOB", "BCIOB", - -"BLKI", "DATAI", "BLKO", "DATAO", /* classic I/O */ -"CONO", "CONI", "CONSZ", "CONSO", - -"CLEAR", "CLEARI", "CLEARM", "CLEARB", -"OR", "ORI", "ORM", "ORB", "XMOVEI", "XHLLI", /* alternate ops */ - - "CMPSL", "CMPSE", "CMPSLE", /* extended ops */ -"EDIT", "CMPSGE", "CMPSN", "CMPSG", -"CVTDBO", "CVTDBT", "CVTBDO", "CVTBDT", -"MOVSO", "MOVST", "MOVSLJ", "MOVSRJ", -"XBLT", "GSNGL", "GDBLE", "GDFIX", -"GFIX", "GDFIXR", "GFIXR", "DGFLTR", -"GFLTR", "GFSC", - -NULL }; - -static const d10 opc_val[] = { - 0102000000000+I_AC+I_ITS, 0103000000000+I_AC+I_ITS, - 0710000000000+I_AC+I_ITS, 0711000000000+I_AC+I_ITS, 0712000000000+I_AC+I_ITS, - 0713000000000+I_AC+I_ITS, 0714000000000+I_AC+I_ITS, 0715000000000+I_AC+I_ITS, - 0720000000000+I_AC+I_ITS, 0721000000000+I_AC+I_ITS, 0722000000000+I_AC+I_ITS, - 0723000000000+I_AC+I_ITS, 0724000000000+I_AC+I_ITS, 0725000000000+I_AC+I_ITS, - 0701000000000+I_OP+I_ITS, 0701440000000+I_OP+I_ITS, 0701540000000+I_OP+I_ITS, - 0702000000000+I_OP+I_ITS, 0702040000000+I_OP+I_ITS, - 0702100000000+I_OP+I_ITS, 0702140000000+I_OP+I_ITS, 0702340000000+I_OP+I_ITS, - 0702400000000+I_OP+I_ITS, 0702440000000+I_OP+I_ITS, - 0702500000000+I_OP+I_ITS, 0702540000000+I_OP+I_ITS, 0702740000000+I_OP+I_ITS, - - 0254040000000+I_OP, 0254100000000+I_OP, - 0254200000000+I_OP, 0254240000000+I_OP, 0254300000000+I_OP, 0254340000000+I_OP, - 0254500000000+I_OP, 0254600000000+I_OP, 0254640000000+I_OP, 0133000000000+I_OP, - 0255040000000+I_OP, 0255100000000+I_OP, 0255200000000+I_OP, 0255300000000+I_OP, - 0255400000000+I_OP, - - 0700000000000+I_OP, 0700200000000+I_OP, 0700240000000+I_OP, 0700600000000+I_OP, - 0700640000000+I_OP, 0701040000000+I_OP, 0701100000000+I_OP, 0701140000000+I_OP, - 0701200000000+I_OP, 0701240000000+I_OP, - 0702000000000+I_OP, 0702040000000+I_OP, 0702100000000+I_OP, 0702140000000+I_OP, - 0702200000000+I_OP, 0702240000000+I_OP, 0702300000000+I_OP, - 0702400000000+I_OP, 0702440000000+I_OP, 0702500000000+I_OP, 0702540000000+I_OP, - 0702600000000+I_OP, 0702640000000+I_OP, 0702700000000+I_OP, - - 0001000000000+I_AC, 0002000000000+I_AC, 0003000000000+I_AC, - 0004000000000+I_AC, 0005000000000+I_AC, 0006000000000+I_AC, 0007000000000+I_AC, - 0010000000000+I_AC, 0011000000000+I_AC, 0012000000000+I_AC, 0013000000000+I_AC, - 0014000000000+I_AC, 0015000000000+I_AC, 0016000000000+I_AC, 0017000000000+I_AC, - 0020000000000+I_AC, 0021000000000+I_AC, 0022000000000+I_AC, 0023000000000+I_AC, - 0024000000000+I_AC, 0025000000000+I_AC, 0026000000000+I_AC, 0027000000000+I_AC, - 0030000000000+I_AC, 0031000000000+I_AC, 0032000000000+I_AC, 0033000000000+I_AC, - 0034000000000+I_AC, 0035000000000+I_AC, 0036000000000+I_AC, 0037000000000+I_AC, - 0040000000000+I_AC, 0041000000000+I_AC, 0042000000000+I_AC, 0043000000000+I_AC, - 0044000000000+I_AC, 0045000000000+I_AC, 0046000000000+I_AC, 0047000000000+I_AC, - 0050000000000+I_AC, 0051000000000+I_AC, 0052000000000+I_AC, 0053000000000+I_AC, - 0054000000000+I_AC, 0055000000000+I_AC, 0056000000000+I_AC, 0057000000000+I_AC, - 0060000000000+I_AC, 0061000000000+I_AC, 0062000000000+I_AC, 0063000000000+I_AC, - 0064000000000+I_AC, 0065000000000+I_AC, 0066000000000+I_AC, 0067000000000+I_AC, - 0070000000000+I_AC, 0071000000000+I_AC, 0072000000000+I_AC, 0073000000000+I_AC, - 0074000000000+I_AC, 0075000000000+I_AC, 0076000000000+I_AC, 0077000000000+I_AC, - - 0100000000000+I_AC, 0102000000000+I_AC, 0103000000000+I_AC, - 0104000000000+I_AC, 0105000000000+I_AC, 0106000000000+I_AC, 0107000000000+I_AC, - 0110000000000+I_AC, 0111000000000+I_AC, 0112000000000+I_AC, 0113000000000+I_AC, - 0114000000000+I_AC, 0115000000000+I_AC, 0116000000000+I_AC, 0117000000000+I_AC, - 0120000000000+I_AC, 0121000000000+I_AC, 0122000000000+I_AC, 0123000000000+I_AC, - 0124000000000+I_AC, 0125000000000+I_AC, 0126000000000+I_AC, 0127000000000+I_AC, - 0130000000000+I_AC, 0131000000000+I_AC, 0132000000000+I_AC, 0133000000000+I_AC, - 0134000000000+I_AC, 0135000000000+I_AC, 0136000000000+I_AC, 0137000000000+I_AC, - 0140000000000+I_AC, 0141000000000+I_AC, 0142000000000+I_AC, 0143000000000+I_AC, - 0144000000000+I_AC, 0145000000000+I_AC, 0146000000000+I_AC, 0147000000000+I_AC, - 0150000000000+I_AC, 0151000000000+I_AC, 0152000000000+I_AC, 0153000000000+I_AC, - 0154000000000+I_AC, 0155000000000+I_AC, 0156000000000+I_AC, 0157000000000+I_AC, - 0160000000000+I_AC, 0161000000000+I_AC, 0162000000000+I_AC, 0163000000000+I_AC, - 0164000000000+I_AC, 0165000000000+I_AC, 0166000000000+I_AC, 0167000000000+I_AC, - 0170000000000+I_AC, 0171000000000+I_AC, 0172000000000+I_AC, 0173000000000+I_AC, - 0174000000000+I_AC, 0175000000000+I_AC, 0176000000000+I_AC, 0177000000000+I_AC, - - 0200000000000+I_AC, 0201000000000+I_AC, 0202000000000+I_AC, 0203000000000+I_AC, - 0204000000000+I_AC, 0205000000000+I_AC, 0206000000000+I_AC, 0207000000000+I_AC, - 0210000000000+I_AC, 0211000000000+I_AC, 0212000000000+I_AC, 0213000000000+I_AC, - 0214000000000+I_AC, 0215000000000+I_AC, 0216000000000+I_AC, 0217000000000+I_AC, - 0220000000000+I_AC, 0221000000000+I_AC, 0222000000000+I_AC, 0223000000000+I_AC, - 0224000000000+I_AC, 0225000000000+I_AC, 0226000000000+I_AC, 0227000000000+I_AC, - 0230000000000+I_AC, 0231000000000+I_AC, 0232000000000+I_AC, 0233000000000+I_AC, - 0234000000000+I_AC, 0235000000000+I_AC, 0236000000000+I_AC, 0237000000000+I_AC, - 0240000000000+I_AC, 0241000000000+I_AC, 0242000000000+I_AC, 0243000000000+I_AC, - 0244000000000+I_AC, 0245000000000+I_AC, 0246000000000+I_AC, 0247000000000+I_AC+I_ITS, - 0250000000000+I_AC, 0251000000000+I_AC, 0252000000000+I_AC, 0253000000000+I_AC, - 0254000000000+I_AC, 0255000000000+I_AC, 0256000000000+I_AC, 0257000000000+I_AC, - 0260000000000+I_AC, 0261000000000+I_AC, 0262000000000+I_AC, 0263000000000+I_AC, - 0264000000000+I_AC, 0265000000000+I_AC, 0266000000000+I_AC, 0267000000000+I_AC, - 0270000000000+I_AC, 0271000000000+I_AC, 0272000000000+I_AC, 0273000000000+I_AC, - 0274000000000+I_AC, 0275000000000+I_AC, 0276000000000+I_AC, 0277000000000+I_AC, - - 0300000000000+I_AC, 0301000000000+I_AC, 0302000000000+I_AC, 0303000000000+I_AC, - 0304000000000+I_AC, 0305000000000+I_AC, 0306000000000+I_AC, 0307000000000+I_AC, - 0310000000000+I_AC, 0311000000000+I_AC, 0312000000000+I_AC, 0313000000000+I_AC, - 0314000000000+I_AC, 0315000000000+I_AC, 0316000000000+I_AC, 0317000000000+I_AC, - 0320000000000+I_AC, 0321000000000+I_AC, 0322000000000+I_AC, 0323000000000+I_AC, - 0324000000000+I_AC, 0325000000000+I_AC, 0326000000000+I_AC, 0327000000000+I_AC, - 0330000000000+I_AC, 0331000000000+I_AC, 0332000000000+I_AC, 0333000000000+I_AC, - 0334000000000+I_AC, 0335000000000+I_AC, 0336000000000+I_AC, 0337000000000+I_AC, - 0340000000000+I_AC, 0341000000000+I_AC, 0342000000000+I_AC, 0343000000000+I_AC, - 0344000000000+I_AC, 0345000000000+I_AC, 0346000000000+I_AC, 0347000000000+I_AC, - 0350000000000+I_AC, 0351000000000+I_AC, 0352000000000+I_AC, 0353000000000+I_AC, - 0354000000000+I_AC, 0355000000000+I_AC, 0356000000000+I_AC, 0357000000000+I_AC, - 0360000000000+I_AC, 0361000000000+I_AC, 0362000000000+I_AC, 0363000000000+I_AC, - 0364000000000+I_AC, 0365000000000+I_AC, 0366000000000+I_AC, 0367000000000+I_AC, - 0370000000000+I_AC, 0371000000000+I_AC, 0372000000000+I_AC, 0373000000000+I_AC, - 0374000000000+I_AC, 0375000000000+I_AC, 0376000000000+I_AC, 0377000000000+I_AC, - - 0400000000000+I_AC, 0401000000000+I_AC, 0402000000000+I_AC, 0403000000000+I_AC, - 0404000000000+I_AC, 0405000000000+I_AC, 0406000000000+I_AC, 0407000000000+I_AC, - 0410000000000+I_AC, 0411000000000+I_AC, 0412000000000+I_AC, 0413000000000+I_AC, - 0414000000000+I_AC, 0415000000000+I_AC, 0416000000000+I_AC, 0417000000000+I_AC, - 0420000000000+I_AC, 0421000000000+I_AC, 0422000000000+I_AC, 0423000000000+I_AC, - 0424000000000+I_AC, 0425000000000+I_AC, 0426000000000+I_AC, 0427000000000+I_AC, - 0430000000000+I_AC, 0431000000000+I_AC, 0432000000000+I_AC, 0433000000000+I_AC, - 0434000000000+I_AC, 0435000000000+I_AC, 0436000000000+I_AC, 0437000000000+I_AC, - 0440000000000+I_AC, 0441000000000+I_AC, 0442000000000+I_AC, 0443000000000+I_AC, - 0444000000000+I_AC, 0445000000000+I_AC, 0446000000000+I_AC, 0447000000000+I_AC, - 0450000000000+I_AC, 0451000000000+I_AC, 0452000000000+I_AC, 0453000000000+I_AC, - 0454000000000+I_AC, 0455000000000+I_AC, 0456000000000+I_AC, 0457000000000+I_AC, - 0460000000000+I_AC, 0461000000000+I_AC, 0462000000000+I_AC, 0463000000000+I_AC, - 0464000000000+I_AC, 0465000000000+I_AC, 0466000000000+I_AC, 0467000000000+I_AC, - 0470000000000+I_AC, 0471000000000+I_AC, 0472000000000+I_AC, 0473000000000+I_AC, - 0474000000000+I_AC, 0475000000000+I_AC, 0476000000000+I_AC, 0477000000000+I_AC, - - 0500000000000+I_AC, 0501000000000+I_AC, 0502000000000+I_AC, 0503000000000+I_AC, - 0504000000000+I_AC, 0505000000000+I_AC, 0506000000000+I_AC, 0507000000000+I_AC, - 0510000000000+I_AC, 0511000000000+I_AC, 0512000000000+I_AC, 0513000000000+I_AC, - 0514000000000+I_AC, 0515000000000+I_AC, 0516000000000+I_AC, 0517000000000+I_AC, - 0520000000000+I_AC, 0521000000000+I_AC, 0522000000000+I_AC, 0523000000000+I_AC, - 0524000000000+I_AC, 0525000000000+I_AC, 0526000000000+I_AC, 0527000000000+I_AC, - 0530000000000+I_AC, 0531000000000+I_AC, 0532000000000+I_AC, 0533000000000+I_AC, - 0534000000000+I_AC, 0535000000000+I_AC, 0536000000000+I_AC, 0537000000000+I_AC, - 0540000000000+I_AC, 0541000000000+I_AC, 0542000000000+I_AC, 0543000000000+I_AC, - 0544000000000+I_AC, 0545000000000+I_AC, 0546000000000+I_AC, 0547000000000+I_AC, - 0550000000000+I_AC, 0551000000000+I_AC, 0552000000000+I_AC, 0553000000000+I_AC, - 0554000000000+I_AC, 0555000000000+I_AC, 0556000000000+I_AC, 0557000000000+I_AC, - 0560000000000+I_AC, 0561000000000+I_AC, 0562000000000+I_AC, 0563000000000+I_AC, - 0564000000000+I_AC, 0565000000000+I_AC, 0566000000000+I_AC, 0567000000000+I_AC, - 0570000000000+I_AC, 0571000000000+I_AC, 0572000000000+I_AC, 0573000000000+I_AC, - 0574000000000+I_AC, 0575000000000+I_AC, 0576000000000+I_AC, 0577000000000+I_AC, - - 0600000000000+I_AC, 0601000000000+I_AC, 0602000000000+I_AC, 0603000000000+I_AC, - 0604000000000+I_AC, 0605000000000+I_AC, 0606000000000+I_AC, 0607000000000+I_AC, - 0610000000000+I_AC, 0611000000000+I_AC, 0612000000000+I_AC, 0613000000000+I_AC, - 0614000000000+I_AC, 0615000000000+I_AC, 0616000000000+I_AC, 0617000000000+I_AC, - 0620000000000+I_AC, 0621000000000+I_AC, 0622000000000+I_AC, 0623000000000+I_AC, - 0624000000000+I_AC, 0625000000000+I_AC, 0626000000000+I_AC, 0627000000000+I_AC, - 0630000000000+I_AC, 0631000000000+I_AC, 0632000000000+I_AC, 0633000000000+I_AC, - 0634000000000+I_AC, 0635000000000+I_AC, 0636000000000+I_AC, 0637000000000+I_AC, - 0640000000000+I_AC, 0641000000000+I_AC, 0642000000000+I_AC, 0643000000000+I_AC, - 0644000000000+I_AC, 0645000000000+I_AC, 0646000000000+I_AC, 0647000000000+I_AC, - 0650000000000+I_AC, 0651000000000+I_AC, 0652000000000+I_AC, 0653000000000+I_AC, - 0654000000000+I_AC, 0655000000000+I_AC, 0656000000000+I_AC, 0657000000000+I_AC, - 0660000000000+I_AC, 0661000000000+I_AC, 0662000000000+I_AC, 0663000000000+I_AC, - 0664000000000+I_AC, 0665000000000+I_AC, 0666000000000+I_AC, 0667000000000+I_AC, - 0670000000000+I_AC, 0671000000000+I_AC, 0672000000000+I_AC, 0673000000000+I_AC, - 0674000000000+I_AC, 0675000000000+I_AC, 0676000000000+I_AC, 0677000000000+I_AC, - - 0704000000000+I_AC, 0705000000000+I_AC, - 0710000000000+I_AC, 0711000000000+I_AC, 0712000000000+I_AC, 0713000000000+I_AC, - 0714000000000+I_AC, 0715000000000+I_AC, 0716000000000+I_AC, 0717000000000+I_AC, - 0720000000000+I_AC, 0721000000000+I_AC, 0722000000000+I_AC, 0723000000000+I_AC, - 0724000000000+I_AC, 0725000000000+I_AC, - - 0700000000000+I_IO, 0700040000000+I_IO, 0700100000000+I_IO, 0700140000000+I_IO, - 0700200000000+I_IO, 0700240000000+I_IO, 0700300000000+I_IO, 0700340000000+I_IO, - - 0400000000000+I_AC, 0401000000000+I_AC, 0402000000000+I_AC, 0403000000000+I_AC, - 0434000000000+I_AC, 0435000000000+I_AC, 0436000000000+I_AC, 0437000000000+I_AC, - 0415000000000+I_AC, 0501000000000+I_AC, - - 0001000000000+I_AC, 0002000000000+I_AC, 0003000000000+I_AC, - 0004000000000+I_AC, 0005000000000+I_AC, 0006000000000+I_AC, 0007000000000+I_AC, - 0010000000000+I_AC, 0011000000000+I_AC, 0012000000000+I_AC, 0013000000000+I_AC, - 0014000000000+I_AC, 0015000000000+I_AC, 0016000000000+I_AC, 0017000000000+I_AC, - 0020000000000+I_AC, 0021000000000+I_AC, 0022000000000+I_AC, 0023000000000+I_AC, - 0024000000000+I_AC, 0025000000000+I_AC, 0026000000000+I_AC, 0027000000000+I_AC, - 0030000000000+I_AC, 0031000000000+I_AC, --1 }; - -#define NUMDEV 6 - -static const char *devnam[NUMDEV] = { - "APR", "PI", "PAG", "CCA", "TIM", "MTR"}; - - -/* 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) ((x) + 040) - -t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, - UNIT *uptr, int32 sw) -{ -int32 i, j, c, cflag, ac, xr, y, dev; -d10 inst; - -inst = val[0]; -cflag = (uptr == NULL) || (uptr == &cpu_unit); -if (sw & SWMASK ('A')) { /* ASCII? */ - if (inst > 0377) return SCPE_ARG; - fprintf (of, FMTASC ((int32) (inst & 0177))); - 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)); } - 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)); } - return SCPE_OK; } -if (!(sw & SWMASK ('M'))) return SCPE_ARG; - -/* Instruction decode */ - -ac = GET_AC (inst); -xr = GET_XR (inst); -y = GET_ADDR (inst); -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)) { - 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 */ - 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; - 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 */ - return SCPE_OK; } /* end if */ - } /* end for */ -return SCPE_ARG; -} - -/* Get operand, including indirect and index - - Inputs: - *cptr = pointer to input string - *status = pointer to error status - Outputs: - val = output value -*/ - -t_value get_opnd (char *cptr, t_stat *status) -{ -int32 sign = 0; -t_value val, xr = 0, ind = 0; -char *tptr; - -*status = SCPE_ARG; /* assume fail */ -if (*cptr == '@') { - ind = INST_IND; - cptr++; } -if (*cptr == '+') cptr++; -else if (*cptr == '-') { - sign = 1; - cptr++; } -val = strtotv (cptr, &tptr, 8); -if (val > 0777777) return 0; -if (sign) val = (~val + 1) & 0777777; -cptr = tptr; -if (*cptr == '(') { - cptr++; - xr = strtotv (cptr, &tptr, 8); - if ((cptr == tptr) || (*tptr != ')') || - (xr > AC_NUM) || (xr == 0)) return 0; - cptr = ++tptr; } -if (*cptr == 0) *status = SCPE_OK; -return (ind | (xr << 18) | val); -} - -/* 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, i, j; -t_value ac, dev; -t_stat r; -char gbuf[CBUFSIZE]; - -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; } } -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 */ - for (i = 0; i < 6; i++) { - 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 */ - for (i = 0; i < 5; i++) val[0] = (val[0] << 7) | ((t_value) cptr[i]); - val[0] = val[0] << 1; - 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 = (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); } } -case I_V_OP: /* operand */ - cptr = get_glyph (cptr, gbuf, 0); - val[0] = val[0] | get_opnd (gbuf, &r); - if (r != SCPE_OK) return SCPE_ARG; - break; -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; } - val[0] = val[0] | (dev << INST_V_DEV); - cptr = get_glyph (cptr, gbuf, 0); - val[0] = val[0] | get_opnd (gbuf, &r); - if (r != SCPE_OK) return SCPE_ARG; - break; } /* end case */ -if (*cptr != 0) return SCPE_ARG; /* junk at end? */ -return SCPE_OK; -} diff --git a/PDP10/pdp10_tim.c b/PDP10/pdp10_tim.c deleted file mode 100644 index e2a0036b..00000000 --- a/PDP10/pdp10_tim.c +++ /dev/null @@ -1,201 +0,0 @@ -/* pdp10_tim.c: PDP-10 tim subsystem simulator - - 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. - - tim timer subsystem - - 29-Jan-02 RMS New data structures - 06-Jan-02 RMS Added enable/disable support - 02-Dec-01 RMS Fixed bug in ITS PC sampling (found by Dave Conroy) - 31-Aug-01 RMS Changed int64 to t_int64 for Windoze - 17-Jul-01 RMS Moved function prototype - 04-Jul-01 RMS Added DZ11 support -*/ - -#include "pdp10_defs.h" -#include - -#define TIM_N_HWRE 12 /* hwre bits */ -#define TIM_HWRE 0000000010000 /* hwre incr */ -#define TIM_DELAY 500 -#define TIM_TPS 1001 /* ticks per sec */ -#define DZ_MULT (TIM_TPS / 60) /* DZ poll multiplier */ -#define TB_MASK 037777777777777777777; /* 71 - 12 bits */ -#define UNIT_V_Y2K (UNIT_V_UF) /* Y2K compliant OS */ -#define UNIT_Y2K (1u << UNIT_V_Y2K) - -extern int32 apr_flg, pi_act; -extern UNIT cpu_unit; -extern d10 pcst; -extern a10 pager_PC; -t_int64 timebase = 0; /* 71b timebase */ -d10 ttg = 0; /* time to go */ -d10 period = 0; /* period */ -d10 quant = 0; /* ITS quantum */ -int32 diagflg = 0; /* diagnostics? */ -int32 tmxr_poll = TIM_DELAY * DZ_MULT; /* term mux poll */ - -DEVICE tim_dev; -t_stat tcu_rd (int32 *data, int32 PA, int32 access); -extern t_stat wr_nop (int32 data, int32 PA, int32 access); -t_stat tim_svc (UNIT *uptr); -t_stat tim_reset (DEVICE *dptr); -extern d10 Read (a10 ea, int32 prv); -extern d10 ReadM (a10 ea, int32 prv); -extern void Write (a10 ea, d10 val, int32 prv); -extern void WriteP (a10 ea, d10 val); -extern int32 pi_eval (void); - -/* TIM data structures - - tim_dev TIM device descriptor - tim_unit TIM unit descriptor - tim_reg TIM register list -*/ - -DIB tcu_dib = { IOBA_TCU, IOLN_TCU, &tcu_rd, &wr_nop, 0 }; - -UNIT tim_unit = { UDATA (&tim_svc, 0, 0), TIM_DELAY }; - -REG tim_reg[] = { - { ORDATA (TIMEBASE, timebase, 71 - TIM_N_HWRE) }, - { ORDATA (TTG, ttg, 36) }, - { ORDATA (PERIOD, period, 36) }, - { ORDATA (QUANT, quant, 36) }, - { DRDATA (TIME, tim_unit.wait, 24), REG_NZ + PV_LEFT }, - { FLDATA (DIAG, diagflg, 0) }, - { FLDATA (Y2K, tim_unit.flags, UNIT_V_Y2K), REG_HRO }, - { NULL } }; - -MTAB tim_mod[] = { - { UNIT_Y2K, 0, "non Y2K OS", "NOY2K", NULL }, - { UNIT_Y2K, UNIT_Y2K, "Y2K OS", "Y2K", NULL }, - { MTAB_XTD|MTAB_VDV, 000, "ADDRESS", NULL, - NULL, &show_addr, NULL }, - { 0 } }; - -DEVICE tim_dev = { - "TIM", &tim_unit, tim_reg, tim_mod, - 1, 0, 0, 0, 0, 0, - NULL, NULL, &tim_reset, - NULL, NULL, NULL, - &tcu_dib, DEV_DISABLE | DEV_UBUS }; - -/* Timer instructions */ - -t_bool rdtim (a10 ea, int32 prv) -{ -ReadM (INCA (ea), prv); -Write (ea, (timebase >> (35 - TIM_N_HWRE)) & DMASK, prv); -Write (INCA(ea), (timebase << TIM_N_HWRE) & MMASK, prv); -return FALSE; -} - -t_bool wrtim (a10 ea, int32 prv) -{ -timebase = (Read (ea, prv) << (35 - TIM_N_HWRE)) | - (CLRS (Read (INCA (ea), prv)) >> TIM_N_HWRE); -return FALSE; -} - -t_bool rdint (a10 ea, int32 prv) -{ -Write (ea, period, prv); -return FALSE; -} - -t_bool wrint (a10 ea, int32 prv) -{ -period = Read (ea, prv); -ttg = period; -return FALSE; -} - -/* Timer routines - - tim_svc process event (timer tick) - tim_reset process reset -*/ - -t_stat tim_svc (UNIT *uptr) -{ -int32 t; - -t = diagflg? tim_unit.wait: sim_rtc_calb (TIM_TPS); /* calibrate clock */ -sim_activate (&tim_unit, t); /* reactivate unit */ -tmxr_poll = t * DZ_MULT; /* set mux poll */ -timebase = (timebase + 1) & TB_MASK; /* increment timebase */ -ttg = ttg - TIM_HWRE; /* decrement timer */ -if (ttg <= 0) { /* timeout? */ - ttg = period; /* reload */ - apr_flg = apr_flg | APRF_TIM; } /* request interrupt */ -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 */ - } /* end ITS */ -return SCPE_OK; -} - -t_stat tim_reset (DEVICE *dptr) -{ -period = ttg = 0; /* clear timer */ -apr_flg = apr_flg & ~APRF_TIM; /* clear interrupt */ -sim_activate (&tim_unit, tim_unit.wait); /* activate unit */ -tmxr_poll = tim_unit.wait * DZ_MULT; /* set mux poll */ -return SCPE_OK; -} - -/* Time of year clock */ - -t_stat tcu_rd (int32 *data, int32 PA, int32 access) -{ -time_t curtim; -struct tm *tptr; - -curtim = time (NULL); /* get time */ -tptr = localtime (&curtim); /* decompose */ -if (tptr == NULL) return SCPE_NXM; /* Y2K prob? */ -if ((tptr->tm_year > 99) && !(tim_unit.flags & UNIT_Y2K)) - tptr->tm_year = 99; - -switch ((PA >> 1) & 03) { /* decode PA<3:1> */ -case 0: /* year/month/day */ - *data = (((tptr->tm_year) & 0177) << 9) | - (((tptr->tm_mon + 1) & 017) << 5) | - ((tptr->tm_mday) & 037); - return SCPE_OK; -case 1: /* hour/minute */ - *data = (((tptr->tm_hour) & 037) << 8) | - ((tptr->tm_min) & 077); - return SCPE_OK; -case 2: /* second */ - *data = (tptr->tm_sec) & 077; - return SCPE_OK; -case 3: /* status */ - *data = CSR_DONE; - return SCPE_OK; } -return SCPE_NXM; /* can't get here */ -} diff --git a/PDP10/pdp10_tu.c b/PDP10/pdp10_tu.c deleted file mode 100644 index f457131a..00000000 --- a/PDP10/pdp10_tu.c +++ /dev/null @@ -1,1058 +0,0 @@ -/* pdp10_tu.c - PDP-10 RH11/TM03/TU45 magnetic tape simulator - - 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. - - tu RH11/TM03/TU45 magtape - - 25-Apr-03 RMS Revised for extended file support - 28-Mar-03 RMS Added multiformat support - 28-Feb-03 RMS Revised for magtape library - 27-Jan-03 RMS Changed to dynamically allocate buffer - 21-Nov-02 RMS Fixed bug in bootstrap (reported by Michael Thompson) - Fixed bug in read (reported by Harris Newman) - 29-Sep-02 RMS Added variable vector support - New data structures - 28-Aug-02 RMS Added end of medium support - 30-May-02 RMS Widened POS to 32b - 22-Apr-02 RMS Changed record length error code - 06-Jan-02 RMS Revised enable/disable support - 30-Nov-01 RMS Added read only unit, extended SET/SHOW support - 24-Nov-01 RMS Changed POS, FLG, UST to arrays - 23-Oct-01 RMS Fixed bug in error interrupts - New IO page address constants - 05-Oct-01 RMS Rewrote interrupt handling from schematics - 30-Sep-01 RMS Fixed handling of non-existent formatters - 28-Sep-01 RMS Fixed interrupt handling for SC/ATA - 4-May-01 RMS Fixed bug in odd address test - 3-May-01 RMS Fixed drive reset to clear SSC - - Magnetic tapes are represented as a series of variable 8b records - of the form: - - 32b record length in bytes - exact number, sign = error - byte 0 - byte 1 - : - byte n-2 - byte n-1 - 32b record length in bytes - exact number, sign = error - - 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. - - WARNING: The interupt logic of the RH11/RH70 is unusual and must be - simulated with great precision. The RH11 has an internal interrupt - request flop, CSTB INTR, which is controlled as follows: - - Writing IE and DONE simultaneously sets CSTB INTR - - Controller clear, INIT, and interrupt acknowledge clear CSTB INTR - (and also clear IE) - - A transition of DONE from 0 to 1 sets CSTB from INTR - The output of INTR is OR'd with the AND of RPCS1 to - create the interrupt request signal. Thus, - - The DONE interrupt is edge sensitive, but the SC interrupt is - level sensitive. - - The DONE interrupt, once set, is not disabled if IE is cleared, - but the SC interrupt is. -*/ - -#include "pdp10_defs.h" -#include "sim_tape.h" - -#define TU_NUMFM 1 /* #formatters */ -#define TU_NUMDR 8 /* #drives */ -#define USTAT u3 /* unit status */ -#define UDENS u4 /* unit density */ -#define UD_UNK 0 /* unknown */ -#define MT_MAXFR (1 << 16) /* max data buf */ - -/* MTCS1 - 172440 - control/status 1 */ - -#define CS1_GO CSR_GO /* go */ -#define CS1_V_FNC 1 /* function pos */ -#define CS1_M_FNC 037 /* function mask */ -#define CS1_FNC (CS1_M_FNC << CS1_V_FNC) -#define FNC_NOP 000 /* no operation */ -#define FNC_UNLOAD 001 /* unload */ -#define FNC_REWIND 003 /* rewind */ -#define FNC_FCLR 004 /* formatter clear */ -#define FNC_RIP 010 /* read in preset */ -#define FNC_ERASE 012 /* erase tape */ -#define FNC_WREOF 013 /* write tape mark */ -#define FNC_SPACEF 014 /* space forward */ -#define FNC_SPACER 015 /* space reverse */ -#define FNC_XFER 024 /* >=? data xfr */ -#define FNC_WCHKF 024 /* write check */ -#define FNC_WCHKR 027 /* write check rev */ -#define FNC_WRITE 030 /* write */ -#define FNC_READF 034 /* read forward */ -#define FNC_READR 037 /* read reverse */ -#define CS1_IE CSR_IE /* int enable */ -#define CS1_DONE CSR_DONE /* ready */ -#define CS1_V_UAE 8 /* Unibus addr ext */ -#define CS1_M_UAE 03 -#define CS1_UAE (CS1_M_UAE << CS1_V_UAE) -#define CS1_DVA 0004000 /* drive avail NI */ -#define CS1_MCPE 0020000 /* Mbus par err NI */ -#define CS1_TRE 0040000 /* transfer err */ -#define CS1_SC 0100000 /* special cond */ -#define CS1_MBZ 0012000 -#define CS1_DRV (CS1_FNC | CS1_GO) -#define GET_FNC(x) (((x) >> CS1_V_FNC) & CS1_M_FNC) -#define GET_UAE(x) (((x) & CS1_UAE) << (16 - CS1_V_UAE)) - -/* MTWC - 172442 - word count */ - -/* MTBA - 172444 - base address */ - -#define BA_MBZ 0000001 /* must be zero */ - -/* MTFC - 172446 - frame count */ - -/* MTCS2 - 172450 - control/status 2 */ - -#define CS2_V_FMTR 0 /* formatter select */ -#define CS2_M_FMTR 07 -#define CS2_FMTR (CS2_M_FMTR << CS2_V_FMTR) -#define CS2_UAI 0000010 /* addr inhibit NI */ -#define CS2_PAT 0000020 /* parity test NI */ -#define CS2_CLR 0000040 /* controller clear */ -#define CS2_IR 0000100 /* input ready */ -#define CS2_OR 0000200 /* output ready */ -#define CS2_MDPE 0000400 /* Mbus par err NI */ -#define CS2_MXF 0001000 /* missed xfer NI */ -#define CS2_PGE 0002000 /* program err */ -#define CS2_NEM 0004000 /* nx mem err */ -#define CS2_NEF 0010000 /* nx fmter err */ -#define CS2_PE 0020000 /* parity err NI */ -#define CS2_WCE 0040000 /* write chk err NI */ -#define CS2_DLT 0100000 /* data late NI */ -#define CS2_MBZ (CS2_CLR | CS2_WCE) -#define CS2_RW (CS2_FMTR | CS2_UAI | CS2_PAT | CS2_MXF | CS2_PE) -#define CS2_ERR (CS2_MDPE | CS2_MXF | CS2_PGE | CS2_NEM | \ - CS2_NEF | CS2_PE | CS2_DLT ) -#define GET_FMTR(x) (((x) >> CS2_V_FMTR) & CS2_M_FMTR) - -/* MTFS - 172452 - formatter status - + indicates kept in drive status - ^ indicates calculated on the fly -*/ - -#define FS_SAT 0000001 /* slave attention */ -#define FS_BOT 0000002 /* ^beginning of tape */ -#define FS_TMK 0000004 /* end of file */ -#define FS_ID 0000010 /* ID burst detected */ -#define FS_SLOW 0000020 /* slowing down NI */ -#define FS_PE 0000040 /* ^PE status */ -#define FS_SSC 0000100 /* slave stat change */ -#define FS_RDY 0000200 /* ^formatter ready */ -#define FS_FPR 0000400 /* formatter present */ -#define FS_EOT 0002000 /* +end of tape */ -#define FS_WRL 0004000 /* ^write locked */ -#define FS_MOL 0010000 /* ^medium online */ -#define FS_PIP 0020000 /* +pos in progress */ -#define FS_ERR 0040000 /* ^error */ -#define FS_ATA 0100000 /* attention active */ -#define FS_REW 0200000 /* +rewinding */ - -#define FS_DYN (FS_ERR | FS_PIP | FS_MOL | FS_WRL | FS_EOT | \ - FS_RDY | FS_PE | FS_BOT) - -/* MTER - 172454 - error register */ - -#define ER_ILF 0000001 /* illegal func */ -#define ER_ILR 0000002 /* illegal register */ -#define ER_RMR 0000004 /* reg mod refused */ -#define ER_MCP 0000010 /* Mbus cpar err NI */ -#define ER_FER 0000020 /* format sel err */ -#define ER_MDP 0000040 /* Mbus dpar err NI */ -#define ER_VPE 0000100 /* vert parity err */ -#define ER_CRC 0000200 /* CRC err NI */ -#define ER_NSG 0000400 /* non std gap err NI */ -#define ER_FCE 0001000 /* frame count err */ -#define ER_ITM 0002000 /* inv tape mark NI */ -#define ER_NXF 0004000 /* wlock or fnc err */ -#define ER_DTE 0010000 /* time err NI */ -#define ER_OPI 0020000 /* op incomplete */ -#define ER_UNS 0040000 /* drive unsafe */ -#define ER_DCK 0100000 /* data check NI */ - -/* MTAS - 172456 - attention summary */ - -#define AS_U0 0000001 /* unit 0 flag */ - -/* MTCC - 172460 - check character, read only */ - -#define CC_MBZ 0177000 /* must be zero */ - -/* MTDB - 172462 - data buffer */ - -/* MTMR - 172464 - maintenance register */ - -#define MR_RW 0177637 /* read/write */ - -/* MTDT - 172466 - drive type */ - -#define DT_TAPE 0040000 /* tape */ -#define DT_PRES 0002000 /* slave present */ -#define DT_TM03 0000040 /* TM03 formatter */ -#define DT_OFF 0000010 /* drive off */ -#define DT_TE16 0000011 /* TE16 */ -#define DT_TU45 0000012 /* TU45 */ -#define DT_TU77 0000014 /* TU77 */ - -/* MTSN - 172470 - serial number */ - -/* MTTC - 172472 - tape control register */ - -#define TC_V_UNIT 0 /* unit select */ -#define TC_M_UNIT 07 -#define TC_V_EVN 0000010 /* even parity */ -#define TC_V_FMT 4 /* format select */ -#define TC_M_FMT 017 -#define TC_10C 00 /* PDP-10 core dump */ -#define TC_IND 03 /* industry standard */ -#define TC_V_DEN 8 /* density select */ -#define TC_M_DEN 07 -#define TC_800 3 /* 800 bpi */ -#define TC_1600 4 /* 1600 bpi */ -#define TC_AER 0010000 /* abort on error */ -#define TC_SAC 0020000 /* slave addr change */ -#define TC_FCS 0040000 /* frame count status */ -#define TC_ACC 0100000 /* accelerating NI */ -#define TC_RW 0013777 -#define TC_MBZ 0004000 -#define GET_DEN(x) (((x) >> TC_V_DEN) & TC_M_DEN) -#define GET_FMT(x) (((x) >> TC_V_FMT) & TC_M_FMT) -#define GET_DRV(x) (((x) >> TC_V_UNIT) & TC_M_UNIT) - -/* Mapping macros */ - -#define XWC_MBZ 0000001 /* wc<0> mbz */ -#define XBA_MBZ 0000001 /* addr<0> mbz */ -#define XBA_ODD 0000002 /* odd address */ -#define TXFR(b,w,od) if (((b) & XBA_MBZ) || ((w) & XWC_MBZ) || \ - (((b) & XBA_ODD) != ((od) << 1))) { \ - tucs2 = tucs2 | CS2_NEM; \ - ubcs[1] = ubcs[1] | UBCS_TMO; \ - tucs1 = tucs1 & ~CS1_GO; \ - update_tucs (CS1_DONE, drv); \ - return SCPE_OK; } -#define NEWPAGE(v,m) (((v) & PAG_M_OFF) == (m)) -#define MAPM(v,p,f) vpn = PAG_GETVPN (v); \ - if ((vpn >= UMAP_MEMSIZE) || ((ubmap[1][vpn] & \ - (UMAP_VLD | UMAP_DSB | UMAP_RRV)) != \ - (UMAP_VLD | f))) { \ - tucs2 = tucs2 | CS2_NEM; \ - ubcs[1] = ubcs[1] | UBCS_TMO; \ - break; } \ - p = (ubmap[1][vpn] + PAG_GETOFF (v)) & PAMASK; \ - if (MEM_ADDR_NXM (p)) { \ - tucs2 = tucs2 | CS2_NEM; \ - ubcs[1] = ubcs[1] | UBCS_TMO; \ - break; } \ - - -extern d10 *M; /* memory */ -extern int32 int_req; -extern int32 int_vec[32]; -extern int32 ubmap[UBANUM][UMAP_MEMSIZE]; /* Unibus map */ -extern int32 ubcs[UBANUM]; -extern UNIT cpu_unit; - -int32 tucs1 = 0; /* control/status 1 */ -int32 tuwc = 0; /* word count */ -int32 tuba = 0; /* bus address */ -int32 tufc = 0; /* frame count */ -int32 tucs2 = 0; /* control/status 2 */ -int32 tufs = 0; /* formatter status */ -int32 tuer = 0; /* error status */ -int32 tucc = 0; /* check character */ -int32 tudb = 0; /* data buffer */ -int32 tumr = 0; /* maint register */ -int32 tutc = 0; /* tape control */ -int32 tuiff = 0; /* INTR flip/flop */ -int32 tu_time = 10; /* record latency */ -int32 tu_stopioe = 1; /* stop on error */ -int32 tu_log = 0; /* debug */ -int32 reg_in_fmtr[32] = { /* reg in formatter */ - 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; -int32 reg_in_fmtr1[32] = { /* rmr if write + go */ - 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; -int32 fmt_test[16] = { /* fmt bytes/10 wd */ - 5, 0, 5, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; -int32 den_test[8] = { /* valid densities */ - 0, 0, 0, 1, 1, 0, 0, 0 }; -static uint8 *xbuf = NULL; /* xfer buffer */ - -t_stat tu_rd (int32 *data, int32 PA, int32 access); -t_stat tu_wr (int32 data, int32 PA, int32 access); -int32 tu_inta (void); -t_stat tu_svc (UNIT *uptr); -t_stat tu_reset (DEVICE *dptr); -t_stat tu_attach (UNIT *uptr, char *cptr); -t_stat tu_detach (UNIT *uptr); -t_stat tu_boot (int32 unitno, DEVICE *dptr); -void tu_go (int32 drv); -void update_tucs (int32 flag, int32 drv); -t_stat tu_map_err (UNIT *uptr, t_stat st); - -/* TU data structures - - tu_dev TU device descriptor - tu_unit TU unit list - tu_reg TU register list - tu_mod TU modifier list -*/ - -DIB tu_dib = { IOBA_TU, IOLN_TU, &tu_rd, &tu_wr, - 1, IVCL (TU), VEC_TU, { &tu_inta } }; - -UNIT tu_unit[] = { - { UDATA (&tu_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) }, - { UDATA (&tu_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) }, - { UDATA (&tu_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) }, - { UDATA (&tu_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) }, - { UDATA (&tu_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) }, - { UDATA (&tu_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) }, - { UDATA (&tu_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) }, - { UDATA (&tu_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) } }; - -REG tu_reg[] = { - { ORDATA (MTCS1, tucs1, 16) }, - { ORDATA (MTWC, tuwc, 16) }, - { ORDATA (MTBA, tuba, 16) }, - { ORDATA (MTFC, tufc, 16) }, - { ORDATA (MTCS2, tucs2, 16) }, - { ORDATA (MTFS, tufs, 16) }, - { ORDATA (MTER, tuer, 16) }, - { ORDATA (MTCC, tucc, 16) }, - { ORDATA (MTDB, tudb, 16) }, - { ORDATA (MTMR, tumr, 16) }, - { ORDATA (MTTC, tutc, 16) }, - { FLDATA (IFF, tuiff, 0) }, - { FLDATA (INT, int_req, INT_V_TU) }, - { FLDATA (DONE, tucs1, CSR_V_DONE) }, - { FLDATA (IE, tucs1, CSR_V_IE) }, - { FLDATA (STOP_IOE, tu_stopioe, 0) }, - { DRDATA (TIME, tu_time, 24), PV_LEFT }, - { URDATA (UST, tu_unit[0].USTAT, 8, 17, 0, TU_NUMDR, 0) }, - { URDATA (POS, tu_unit[0].pos, 10, T_ADDR_W, 0, - TU_NUMDR, PV_LEFT | REG_RO) }, - { ORDATA (LOG, tu_log, 8), REG_HIDDEN }, - { NULL } }; - -MTAB tu_mod[] = { - { MTUF_WLK, 0, "write enabled", "WRITEENABLED", NULL }, - { MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL }, - { MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT", - &sim_tape_set_fmt, &sim_tape_show_fmt, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "ADDRESS", NULL, - NULL, &show_addr, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "VECTOR", NULL, - NULL, &show_vec, NULL }, - { 0 } }; - -DEVICE tu_dev = { - "TU", tu_unit, tu_reg, tu_mod, - TU_NUMDR, 10, 31, 1, 8, 8, - NULL, NULL, &tu_reset, - &tu_boot, &tu_attach, &tu_detach, - &tu_dib, DEV_UBUS }; - -/* I/O dispatch routine, I/O addresses 17772440 - 17772472 */ - -t_stat tu_rd (int32 *data, int32 PA, int32 access) -{ -int32 fmtr, drv, j; - -fmtr = GET_FMTR (tucs2); /* get current fmtr */ -drv = GET_DRV (tutc); /* get current drive */ -j = (PA >> 1) & 017; /* get reg offset */ -if (reg_in_fmtr[j] && (fmtr != 0)) { /* nx formatter */ - tucs2 = tucs2 | CS2_NEF; /* set error flag */ - update_tucs (CS1_SC, drv); /* request intr */ - *data = 0; - return SCPE_OK; } - -update_tucs (0, drv); /* update status */ -switch (j) { /* decode PA<4:1> */ -case 000: /* MTCS1 */ - if (fmtr != 0) *data = tucs1 & ~CS1_DRV; - else *data = tucs1; - break; -case 001: /* MTWC */ - *data = tuwc; - break; -case 002: /* MTBA */ - *data = tuba = tuba & ~BA_MBZ; - break; -case 003: /* MTFC */ - *data = tufc; - break; -case 004: /* MTCS2 */ - *data = tucs2 = (tucs2 & ~CS2_MBZ) | CS2_IR | CS2_OR; - break; -case 005: /* MTFS */ - *data = tufs & 0177777; /* mask off rewind */ - break; -case 006: /* MTER */ - *data = tuer; - break; -case 007: /* MTAS */ - *data = (tufs & FS_ATA)? AS_U0: 0; - break; -case 010: /* MTCC */ - *data = tucc = tucc & ~CC_MBZ; - break; -case 011: /* MTDB */ - *data = tudb; - break; -case 012: /* MTMR */ - *data = tumr; - break; -case 013: /* MTDT */ - *data = DT_TAPE | DT_TM03 | ((tu_unit[drv].flags & UNIT_DIS)? - DT_OFF: (DT_PRES | DT_TU45)); - break; -case 014: /* MTSN */ - *data = (tu_unit[drv].flags & UNIT_DIS)? 0: 040 | (drv + 1); - break; -case 015: /* MTTC */ - *data = tutc = tutc & ~TC_MBZ; - break; -default: /* all others */ - tuer = tuer | ER_ILR; - update_tucs (0, drv); - break; } -return SCPE_OK; -} - -t_stat tu_wr (int32 data, int32 PA, int32 access) -{ -int32 cs1f, fmtr, drv, j; - -cs1f = 0; /* no int on cs1 upd */ -fmtr = GET_FMTR (tucs2); /* get formatter */ -drv = GET_DRV (tutc); /* get current unit */ -j = (PA >> 1) & 017; /* get reg offset */ -if (reg_in_fmtr[j] && (fmtr != 0)) { /* nx formatter */ - tucs2 = tucs2 | CS2_NEF; /* set error flag */ - update_tucs (CS1_SC, drv); /* request intr */ - return SCPE_OK; } -if (reg_in_fmtr1[j] && ((tucs1 & CS1_DONE) == 0)) { /* formatter busy? */ - tuer = tuer | ER_RMR; /* won't write */ - update_tucs (0, drv); - return SCPE_OK; } - -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> */ - if ((access == WRITE) || (PA & 1)) { /* hi byte write? */ - 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); } } - break; -case 001: /* MTWC */ - if (access == WRITEB) data = (PA & 1)? - (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 = data & ~BA_MBZ; - break; -case 003: /* MTFC */ - if (access == WRITEB) data = (PA & 1)? - (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; } - break; -case 007: /* MTAS */ - if ((access == WRITEB) && (PA & 1)) break; - if (data & AS_U0) tufs = tufs & ~FS_ATA; - break; -case 011: /* MTDB */ - if (access == WRITEB) data = (PA & 1)? - (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 = (tumr & ~MR_RW) | (data & MR_RW); - break; -case 015: /* MTTC */ - if (access == WRITEB) data = (PA & 1)? - (tutc & 0377) | (data << 8): (tutc & ~0377) | data; - tutc = (tutc & ~TC_RW) | (data & TC_RW) | TC_SAC; - drv = GET_DRV (tutc); - break; -case 005: /* MTFS */ -case 006: /* MTER */ -case 010: /* MTCC */ -case 013: /* MTDT */ -case 014: /* MTSN */ - break; /* read only */ -default: /* all others */ - tuer = tuer | ER_ILR; - break; } /* end switch */ -update_tucs (cs1f, drv); /* update status */ -return SCPE_OK; -} - -/* New magtape command */ - -void tu_go (int32 drv) -{ -int32 fnc, den, space_test = FS_BOT; -UNIT *uptr; - -fnc = GET_FNC (tucs1); /* get function */ -den = GET_DEN (tutc); /* get density */ -uptr = tu_dev.units + drv; /* get unit */ -if ((fnc != FNC_FCLR) && /* not clear & err */ - ((tufs & FS_ERR) || sim_is_active (uptr))) { /* or in motion? */ - tuer = tuer | ER_ILF; /* set error flag */ - tufs = tufs | FS_ATA; /* exception */ - tucs1 = tucs1 & ~CS1_GO; /* clear go */ - update_tucs (CS1_SC, drv); /* request intr */ - return; } -tufs = tufs & ~FS_ATA; /* clear attention */ -tutc = tutc & ~TC_SAC; /* clear addr change */ - -switch (fnc) { /* case on function */ -case FNC_FCLR: /* drive clear */ - tuer = 0; /* clear errors */ - tutc = tutc & ~TC_FCS; /* clear fc status */ - tufs = tufs & ~(FS_SAT | FS_SSC | FS_ID | FS_TMK | FS_ERR); - sim_cancel (uptr); /* reset drive */ - uptr->USTAT = 0; -case FNC_NOP: - tucs1 = tucs1 & ~CS1_GO; /* no operation */ - return; -case FNC_RIP: /* read-in preset */ - tutc = TC_800; /* density = 800 */ - sim_tape_rewind (&tu_unit[0]); /* rewind unit 0 */ - tu_unit[0].USTAT = 0; - tucs1 = tucs1 & ~CS1_GO; - return; - -case FNC_UNLOAD: /* unload */ - if ((uptr->flags & UNIT_ATT) == 0) { /* unattached? */ - tuer = tuer | ER_UNS; - break; } - detach_unit (uptr); - uptr->USTAT = FS_REW; - sim_activate (uptr, tu_time); - tucs1 = tucs1 & ~CS1_GO; - return; -case FNC_REWIND: - if ((uptr->flags & UNIT_ATT) == 0) { /* unattached? */ - tuer = tuer | ER_UNS; - break; } - uptr->USTAT = FS_PIP | FS_REW; - sim_activate (uptr, tu_time); - tucs1 = tucs1 & ~CS1_GO; - return; - -case FNC_SPACEF: - space_test = FS_EOT; -case FNC_SPACER: - if ((uptr->flags & UNIT_ATT) == 0) { /* unattached? */ - tuer = tuer | ER_UNS; - break; } - if ((tufs & space_test) || ((tutc & TC_FCS) == 0)) { - 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; } - 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; } -case FNC_WREOF: /* write tape mark */ -case FNC_ERASE: /* erase */ - if (sim_tape_wrp (uptr)) { /* write locked? */ - 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; } - if (fmt_test[GET_FMT (tutc)] == 0) { /* invalid format? */ - tuer = tuer | ER_FER; - break; } - if (den_test[den] == 0) { /* invalid density? */ - 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; } */ - uptr->USTAT = 0; - tucs1 = tucs1 & ~CS1_DONE; /* clear done */ -GO_XFER: - tucs2 = tucs2 & ~CS2_ERR; /* clear errors */ - tucs1 = tucs1 & ~(CS1_TRE | CS1_MCPE); - tufs = tufs & ~(FS_TMK | FS_ID); /* clear eof, id */ - sim_activate (uptr, tu_time); - return; - -default: /* all others */ - tuer = tuer | ER_ILF; /* not supported */ - break; } /* end case function */ -tucs1 = tucs1 & ~CS1_GO; /* clear go */ -tufs = tufs | FS_ATA; /* set attn */ -update_tucs (CS1_SC, drv); /* set intr */ -return; -} - -/* Unit service - - Complete movement or data transfer command - Unit must exist - can't remove an active unit - Unit must be attached - detach cancels in progress operations -*/ - -t_stat tu_svc (UNIT *uptr) -{ -int32 f, fmt, i, j, k, wc10, ba10; -int32 ba, fc, wc, drv, mpa10, vpn; -d10 val, v[4]; -t_mtrlnt tbc; -t_stat st, r = SCPE_OK; - -drv = uptr - tu_dev.units; /* get drive # */ -if (uptr->USTAT & FS_REW) { /* rewind or unload? */ - sim_tape_rewind (uptr); /* rewind tape */ - uptr->USTAT = 0; /* clear status */ - tufs = tufs | FS_ATA | FS_SSC; - update_tucs (CS1_SC, drv); /* update status */ - return SCPE_OK; } - -f = GET_FNC (tucs1); /* get command */ -fmt = GET_FMT (tutc); /* get format */ -ba = GET_UAE (tucs1) | tuba; /* get bus address */ -wc = 0200000 - tuwc; /* get word count */ -fc = 0200000 - tufc; /* get frame count */ -wc10 = wc >> 1; /* 10 word count */ -ba10 = ba >> 2; /* 10 word addr */ -uptr->USTAT = 0; /* clear status */ - -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 (st = sim_tape_sprecf (uptr, &tbc)) { /* space rec fwd, err? */ - r = tu_map_err (uptr, st); /* map error */ - break; } - } - while (tufc != 0); - if (tufc) tuer = tuer | ER_FCE; - else tutc = tutc & ~TC_FCS; - tufs = tufs | FS_ATA; - break; - -case FNC_SPACER: /* space reverse */ - do { - tufc = (tufc + 1) & 0177777; /* incr wc */ - if (st = sim_tape_sprecr (uptr, &tbc)) { /* space rec rev, err? */ - r = tu_map_err (uptr, st); /* map error */ - break; } - } - while (tufc != 0); - if (tufc) tuer = tuer | ER_FCE; - else tutc = tutc & ~TC_FCS; - tufs = tufs | FS_ATA; - break; - -case FNC_WREOF: /* write end of file */ - if (st = sim_tape_wrtmk (uptr)) /* write tmk, err? */ - r = tu_map_err (uptr, st); /* map error */ - tufs = tufs | FS_ATA; - break; - -case FNC_ERASE: - if (sim_tape_wrp (uptr)) /* write protected? */ - r = tu_map_err (uptr, MTSE_WRP); /* map error */ - tufs = tufs | FS_ATA; - break; - -/* Unit service - data transfer commands - - These commands must take into account the action of the "bit fiddler", which - converts between PDP-10 format and tape format. Only two tape formats are - supported: - - PDP-10 core dump: write 36b as byte 0/byte 1/byte 2/byte 3/0000'last nibble - industry mode: write hi 32b as byte 0/byte 1/byte 2/byte 3 - - These commands must also take into account the action of the Unibus adapter, - which munges PDP-10 addresses through the Unibus map. -*/ - -case FNC_READF: /* read */ -case FNC_WCHKF: /* wcheck = read */ - tufc = 0; /* clear frame count */ - if ((uptr->UDENS == TC_1600) && sim_tape_bot (uptr)) - tufs = tufs | FS_ID; /* PE BOT? ID burst */ - TXFR (ba, wc, 0); /* validate transfer */ - if (st = sim_tape_rdrecf (uptr, xbuf, &tbc, MT_MAXFR)) { /* read fwd */ - r = tu_map_err (uptr, st); /* map error */ - break; } /* done */ - 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 */ - tufc = tbc & 0177777; - tuwc = (tuwc + (i << 1)) & 0177777; - ba = ba + (i << 2); - break; - -case FNC_WRITE: /* write */ - TXFR (ba, wc, 0); /* validate transfer */ - 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 (j < fc) fc = j; /* short record? */ - if (st = sim_tape_wrrecf (uptr, xbuf, fc)) /* write rec, err? */ - r = tu_map_err (uptr, st); /* map error */ - else { - 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 */ -case FNC_WCHKR: /* wcheck = read */ - tufc = 0; /* clear frame count */ - TXFR (ba, wc, 1); /* validate xfer rev */ - if (st = sim_tape_rdrecr (uptr, xbuf + 4, &tbc, MT_MAXFR)) { /* read rev */ - r = tu_map_err (uptr, st); /* map error */ - break; } /* done */ - for (i = 0; i < 4; i++) xbuf[i] = 0; - 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 */ - tufc = tbc & 0177777; - tuwc = (tuwc + (i << 1)) & 0177777; - ba = ba - (i << 2); - break; } /* end case */ - -tucs1 = (tucs1 & ~CS1_UAE) | ((ba >> (16 - CS1_V_UAE)) & CS1_UAE); -tuba = ba & 0177777; /* update mem addr */ -tucs1 = tucs1 & ~CS1_GO; /* clear go */ -update_tucs (CS1_DONE, drv); -return SCPE_OK; -} - -/* Controller status update - - Check for done transition - Update drive status - Update MTCS1 - Update interrupt request -*/ - -void update_tucs (int32 flag, int32 drv) -{ -int32 act = sim_is_active (&tu_unit[drv]); - -if ((flag & ~tucs1) & CS1_DONE) /* DONE 0 to 1? */ - tuiff = (tucs1 & CS1_IE)? 1: 0; /* CSTB INTR <- IE */ -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 (sim_tape_wrp (&tu_unit[drv])) tufs = tufs | FS_WRL; - if (sim_tape_bot (&tu_unit[drv]) && !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; -if (tucs2 & CS2_ERR) tucs1 = tucs1 | CS1_TRE | CS1_SC; -else if (tucs1 & CS1_TRE) tucs1 = tucs1 | CS1_SC; -if (tufs & FS_ATA) tucs1 = tucs1 | CS1_SC; -if (tuiff || ((tucs1 & CS1_SC) && (tucs1 & CS1_DONE) && (tucs1 & CS1_IE))) - int_req = int_req | INT_TU; -else int_req = int_req & ~INT_TU; -if ((tucs1 & CS1_DONE) && tufs && !act) tufs = tufs | FS_RDY; -return; -} - -/* Interrupt acknowledge */ - -int32 tu_inta (void) -{ -tucs1 = tucs1 & ~CS1_IE; /* clear int enable */ -tuiff = 0; /* clear CSTB INTR */ -return VEC_TU; /* acknowledge */ -} - -/* Map tape error status */ - -t_stat tu_map_err (UNIT *uptr, t_stat st) -{ -switch (st) { -case MTSE_FMT: /* illegal fmt */ -case MTSE_UNATT: /* not attached */ - tuer = tuer | ER_NXF; /* can't execute */ -case MTSE_OK: /* no error */ - return SCPE_IERR; -case MTSE_TMK: /* end of file */ - tufs = tufs | FS_TMK; - break; -case MTSE_IOERR: /* IO error */ - tuer = tuer | ER_VPE; /* flag error */ - if (tu_stopioe) return SCPE_IOERR; - break; -case MTSE_INVRL: /* invalid rec lnt */ - tuer = tuer | ER_VPE; /* flag error */ - return SCPE_MTRLNT; -case MTSE_RECE: /* record in error */ - tuer = tuer | ER_CRC; /* set crc err */ - break; -case MTSE_EOM: /* end of medium */ - tuer = tuer | ER_OPI; /* incomplete */ - break; -case MTSE_BOT: /* reverse into BOT */ - break; -case MTSE_WRP: /* write protect */ - tuer = tuer | ER_NXF; /* can't execute */ - break; } -return SCPE_OK; -} - -/* Reset routine */ - -t_stat tu_reset (DEVICE *dptr) -{ -int32 u; -UNIT *uptr; - -tucs1 = CS1_DVA | CS1_DONE; -tucs2 = CS2_IR | CS2_OR; -tuba = tufc = 0; -tutc = tuer = 0; -tufs = FS_FPR | FS_RDY; -tuiff = 0; /* clear CSTB INTR */ -int_req = int_req & ~INT_TU; /* clear interrupt */ -for (u = 0; u < TU_NUMDR; u++) { /* loop thru units */ - uptr = tu_dev.units + u; - sim_tape_reset (uptr); /* clear pos flag */ - sim_cancel (uptr); /* cancel activity */ - uptr->USTAT = 0; } -if (xbuf == NULL) xbuf = calloc (MT_MAXFR + 4, sizeof (uint8)); -if (xbuf == NULL) return SCPE_MEM; -return SCPE_OK; -} - -/* Attach routine */ - -t_stat tu_attach (UNIT *uptr, char *cptr) -{ -int32 drv = uptr - tu_dev.units; -t_stat r; - -r = sim_tape_attach (uptr, cptr); -if (r != SCPE_OK) return r; -uptr->USTAT = 0; /* clear unit status */ -uptr->UDENS = UD_UNK; /* unknown density */ -tufs = tufs | FS_ATA | FS_SSC; /* set attention */ -if ((GET_FMTR (tucs2) == 0) && (GET_DRV (tutc) == drv)) /* selected drive? */ - tufs = tufs | FS_SAT; /* set slave attn */ -update_tucs (CS1_SC, drv); /* update status */ -return r; -} - -/* Detach routine */ - -t_stat tu_detach (UNIT* uptr) -{ -int32 drv = uptr - tu_dev.units; - -if (sim_is_active (uptr)) { /* unit active? */ - sim_cancel (uptr); /* cancel operation */ - tuer = tuer | ER_UNS; /* set formatter error */ - if ((uptr->USTAT & FS_REW) == 0) /* data transfer? */ - tucs1 = tucs1 | CS1_DONE | CS1_TRE; } /* set done, err */ -uptr->USTAT = 0; /* clear status flags */ -tufs = tufs | FS_ATA | FS_SSC; /* set attention */ -update_tucs (CS1_SC, drv); /* update status */ -return sim_tape_detach (uptr); -} - -/* Device bootstrap */ - -#define BOOT_START 0377000 /* start */ -#define BOOT_LEN (sizeof (boot_rom_dec) / sizeof (d10)) - -static const d10 boot_rom_dec[] = { - 0515040000003, /* boot:hrlzi 1,3 ; uba # */ - 0201000040001, /* movei 0,40001 ; vld,pg 1 */ - 0713001000000+(IOBA_UBMAP+1 & RMASK), /* wrio 0,763001(1); set ubmap */ - 0435040000000+(IOBA_TU & RMASK), /* iori 1,772440 ; rh addr */ - 0202040000000+FE_RHBASE, /* movem 1,FE_RHBASE */ - 0201000000040, /* movei 0,40 ; ctrl reset */ - 0713001000010, /* wrio 0,10(1) ; ->MTFS */ - 0201100000031, /* movei 2,31 ; space f */ - 0265740377014, /* jsp 17,tpop ; skip ucode */ - 0201100000071, /* movei 2,71 ; read f */ - 0265740377014, /* jsp 17,tpop ; read boot */ - 0254000001000, /* jrst 1000 ; start */ - 0200000000000+FE_MTFMT, /* tpop:move 0,FE_MTFMT ; den,fmt,slv */ - 0713001000032, /* wrio 0,32(1) ; ->MTTC */ - 0201000000011, /* movei 0,11 ; clr+go */ - 0713001000000, /* wrio 0,0(1) ; ->MTCS1 */ - 0201140176000, /* movei 3,176000 ; wd cnt */ - 0201200004000, /* movei 4,4000 ; addr */ - 0200240000000+FE_MTFMT, /* move 5,FE_MTFMT ; unit */ - 0201300000000, /* movei 6,0 ; fmtr */ - 0713141000002, /* wrio 3,2(1) ; ->MTWC */ - 0713201000004, /* wrio 4,4(1) ; ->MTBA */ - 0713301000006, /* wrio 6,6(1) ; ->MTFC */ - 0713301000010, /* wrio 6,10(1) ; ->MTFS */ - 0713241000032, /* wrio 5,32(1) ; ->MTTC */ - 0713101000000, /* wrio 2,0(1) ; ->MTCS1 */ - 0712341000012, /* rdio 7,12(1) ; read FS */ - 0606340000200, /* trnn 7,200 ; test rdy */ - 0254000377032, /* jrst .-2 ; loop */ - 0606340040000, /* trnn 7,40000 ; test err */ - 0254017000000, /* jrst 0(17) ; return */ - 0712341000014, /* rdio 7,14(1) ; read err */ - 0302340001000, /* caie 7,1000 ; fce? */ - 0254200377052, /* halt */ - 0254017000000, /* jrst 0(17) ; return */ -}; - -static const d10 boot_rom_its[] = { - 0515040000003, /* boot:hrlzi 1,3 ; uba # - not used */ - 0201000040001, /* movei 0,40001 ; vld,pg 1 */ - 0714000000000+(IOBA_UBMAP+1 & RMASK), /* iowri 0,763001 ; set ubmap */ - 0435040000000+(IOBA_TU & RMASK), /* iori 1,772440 ; rh addr */ - 0202040000000+FE_RHBASE, /* movem 1,FE_RHBASE */ - 0201000000040, /* movei 0,40 ; ctrl reset */ - 0714001000010, /* iowri 0,10(1) ; ->MTFS */ - 0201100000031, /* movei 2,31 ; space f */ - 0265740377014, /* jsp 17,tpop ; skip ucode */ - 0201100000071, /* movei 2,71 ; read f */ - 0265740377014, /* jsp 17,tpop ; read boot */ - 0254000001000, /* jrst 1000 ; start */ - 0200000000000+FE_MTFMT, /* tpop:move 0,FE_MTFMT ; den,fmt,slv */ - 0714001000032, /* iowri 0,32(1) ; ->MTTC */ - 0201000000011, /* movei 0,11 ; clr+go */ - 0714001000000, /* iowri 0,0(1) ; ->MTCS1 */ - 0201140176000, /* movei 3,176000 ; wd cnt */ - 0201200004000, /* movei 4,4000 ; addr */ - 0200240000000+FE_MTFMT, /* move 5,FE_MTFMT ; unit */ - 0201300000000, /* movei 6,0 ; fmtr */ - 0714141000002, /* iowri 3,2(1) ; ->MTWC */ - 0714201000004, /* iowri 4,4(1) ; ->MTBA */ - 0714301000006, /* iowri 6,6(1) ; ->MTFC */ - 0714301000010, /* iowri 6,10(1) ; ->MTFS */ - 0714241000032, /* iowri 5,32(1) ; ->MTTC */ - 0714101000000, /* iowri 2,0(1) ; ->MTCS1 */ - 0710341000012, /* iordi 7,12(1) ; read FS */ - 0606340000200, /* trnn 7,200 ; test rdy */ - 0254000377032, /* jrst .-2 ; loop */ - 0606340040000, /* trnn 7,40000 ; test err */ - 0254017000000, /* jrst 0(17) ; return */ - 0710341000014, /* iordi 7,14(1) ; read err */ - 0302340001000, /* caie 7,1000 ; fce? */ - 0254200377052, /* halt */ - 0254017000000, /* jrst 0(17) ; return */ -}; -t_stat tu_boot (int32 unitno, DEVICE *dptr) -{ -int32 i; -extern a10 saved_PC; - -M[FE_UNIT] = 0; -M[FE_MTFMT] = (unitno & TC_M_UNIT) | (TC_1600 << TC_V_DEN) | (TC_10C << TC_V_FMT); -tu_unit[unitno].pos = 0; -for (i = 0; i < BOOT_LEN; i++) - M[BOOT_START + i] = ITS? boot_rom_its[i]: boot_rom_dec[i]; -saved_PC = BOOT_START; -return SCPE_OK; -} diff --git a/PDP10/pdp10_xtnd.c b/PDP10/pdp10_xtnd.c deleted file mode 100644 index 3c17e676..00000000 --- a/PDP10/pdp10_xtnd.c +++ /dev/null @@ -1,642 +0,0 @@ -/* pdp10_xtnd.c: PDP-10 extended instruction simulator - - 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. - - 12-May-01 RMS Fixed compiler warning in xlate - - Instructions handled in this module: - MOVSLJ move string left justified - MOVSO move string offset - MOVST move string translated - MOVSRJ move string right justified - CMPSL compare string, skip on less - CMPSE compare string, skip on equal - CMPSLE compare string, skip on less or equal - CMPSGE compare string, skip on greater or equal - CMPSN compare string, skip on unequal - CMPSG compare string, skip on greater - CVTDBO convert decimal to binary offset - CVTDBT convert decimal to binary translated - CVTBDO convert binary to decimal offset - CVTBDT convert binary to decimal translated - EDIT edit - - The PDP-10 extended instructions deal with non-binary data types, - particularly byte strings and decimal strings. (In the KL10, the - extended instructions include G floating support as well.) They - are very complicated microcoded subroutines that can potentially - run for a very long time. Accordingly, the instructions must test - for interrupts as well as page faults, and be prepared to restart - from either. - - In general, the simulator attempts to keep the AC block up to date, - so that page fails and interrupts can be taken directly at any point. - If the AC block is not up to date, memory accessibility must be tested - before the actual read or write is done. - - The extended instruction routine returns a status code as follows: - XT_NOSK no skip completion - XT_SKIP skip completion - XT_MUUO invalid extended instruction -*/ - -#include "pdp10_defs.h" -#include - -#define MM_XSRC (pflgs & XSRC_PXCT) -#define MM_XDST (pflgs & XDST_PXCT) -#define MM_EA_XSRC ((pflgs & EA_PXCT) && MM_XSRC) -#define MM_EA_XDST ((pflgs & EA_PXCT) && MM_XDST) - -#define XT_CMPSL 001 /* opcodes */ -#define XT_CMPSE 002 -#define XT_CMPSLE 003 -#define XT_EDIT 004 -#define XT_CMPSGE 005 -#define XT_CMPSN 006 -#define XT_CMPSG 007 -#define XT_CVTDBO 010 -#define XT_CVTDBT 011 -#define XT_CVTBDO 012 -#define XT_CVTBDT 013 -#define XT_MOVSO 014 -#define XT_MOVST 015 -#define XT_MOVSLJ 016 -#define XT_MOVSRJ 017 - -/* Translation control */ - -#define XT_LFLG 0400000000000 /* L flag */ -#define XT_SFLG 0400000000000 /* S flag */ -#define XT_NFLG 0200000000000 /* N flag */ -#define XT_MFLG 0100000000000 /* M flag */ - -/* Translation table */ - -#define XT_V_CODE 15 /* translation op */ -#define XT_M_CODE 07 -#define XT_BYMASK 07777 /* byte mask */ -#define XT_DGMASK 017 /* digit mask */ -#define XT_GETCODE(x) ((int32) (((x) >> XT_V_CODE) & XT_M_CODE)) - -/* AC masks */ - -#define XLNTMASK 0000777777777 /* length */ -#define XFLGMASK 0700000000000 /* flags */ -#define XT_MBZ 0777000000000 /* must be zero */ -#define XT_MBZE 0047777000000 /* must be zero, edit */ - -/* Register change log */ - -#define XT_N_RLOG 5 /* entry width */ -#define XT_M_RLOG ((1 << XT_N_RLOG) - 1) /* entry mask */ -#define XT_O_RLOG 1 /* entry offset */ -#define XT_INSRLOG(x,v) v = ((v << XT_N_RLOG) | (((x) + XT_O_RLOG) & XT_M_RLOG)) -#define XT_REMRLOG(x,v) x = (v & XT_M_RLOG) - XT_O_RLOG; \ - v = v >> XT_N_RLOG - -/* Edit */ - -#define ED_V_PBYN 30 /* pattern byte # */ -#define ED_M_PBYN 03 -#define ED_PBYNO 0040000000000 /* overflow bit */ -#define ED_GETPBYN(x) ((int32) (((x) >> ED_V_PBYN) & ED_M_PBYN)) -#define ED_V_POPC 6 /* pattern byte opcode */ -#define ED_M_PAT 0777 /* pattern byte mask */ -#define ED_M_NUM 0077 /* number for msg, etc */ -#define ED_PBYTE(x,y) ((int32) (((x) >> (27 - (ED_GETPBYN (y) * 9))) & ED_M_PAT)) -#define ED_STOP 0000 /* stop */ -#define ED_SELECT 0001 /* select source */ -#define ED_SIGST 0002 /* start significance */ -#define ED_FLDSEP 0003 /* field separator */ -#define ED_EXCHMD 0004 /* exchange mark, dst */ -#define ED_MESSAG 0100 /* message */ -#define ED_SKPM 0500 /* skip if M */ -#define ED_SKPN 0600 /* skip if N */ -#define ED_SKPA 0700 /* skip always */ - -extern d10 *ac_cur; /* current AC block */ -extern d10 bytemask[64]; -extern int32 flags; -extern int32 rlog; -extern jmp_buf save_env; - -extern d10 Read (int32 ea, int32 prv); -extern void Write (int32 ea, d10 val, int32 prv); -extern a10 calc_ea (d10 inst, int32 prv); -extern int32 test_int (void); -d10 incbp (d10 bp); -d10 incloadbp (int32 ac, int32 pflgs); -void incstorebp (d10 val, int32 ac, int32 pflgs); -d10 xlate (d10 by, a10 tblad, d10 *xflgs, int32 pflgs); -void filldst (d10 fill, int32 ac, d10 cnt, int32 pflgs); - -static const d10 pwrs10[23][2] = { - 0, 0, - 0, 1, - 0, 10, - 0, 100, - 0, 1000, - 0, 10000, - 0, 100000, - 0, 1000000, - 0, 10000000, - 0, 100000000, - 0, 1000000000, - 0, 10000000000, - 2, 31280523264, - 29, 3567587328, - 291, 1316134912, - 2910, 13161349120, - 29103, 28534276096, - 291038, 10464854016, - 2910383, 1569325056, - 29103830, 15693250560, - 291038304, 19493552128, - 2910383045, 23136829440, - 29103830456, 25209864192 }; - -int xtend (int32 ac, int32 ea, int32 pflgs) -{ -d10 b1, b2, ppi; -d10 xinst, xoff, digit, f1, f2, rs[2]; -d10 xflgs = 0; -a10 e1, entad; -int32 p1 = ADDAC (ac, 1); -int32 p3 = ADDAC (ac, 3); -int32 p4 = ADDAC (ac, 4); -int32 flg, i, s2, t, pp, pat, xop, xac, ret; - -xinst = Read (ea, MM_OPND); /* get extended instr */ -xop = GET_OP (xinst); /* get opcode */ -xac = GET_AC (xinst); /* get AC */ -if (xac || (xop == 0) || (xop > XT_MOVSRJ)) return XT_MUUO; -rlog = 0; /* clear log */ -switch (xop) { /* case on opcode */ - -/* String compares - checked against KS10 ucode - If both strings are zero length, they are considered equal. - Both source and destination lengths are MBZ checked. - - AC = source1 length - AC + 1 = source1 byte pointer - AC + 3 = source2 length - AC + 4 = source2 byte pointer -*/ - -case XT_CMPSL: /* CMPSL */ -case XT_CMPSE: /* CMPSE */ -case XT_CMPSLE: /* CMPSLE */ -case XT_CMPSGE: /* CMPSGE */ -case XT_CMPSN: /* CMPSN */ -case XT_CMPSG: /* CMPSG */ - if ((AC(ac) | AC(p3)) & XT_MBZ) return XT_MUUO; /* check length MBZ */ - f1 = Read (ADDA (ea, 1), MM_OPND) & bytemask[GET_S (AC(p1))]; - 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; } - switch (xop) { - case XT_CMPSL: return (b1 < b2)? XT_SKIP: XT_NOSK; - case XT_CMPSE: return (b1 == b2)? XT_SKIP: XT_NOSK; - case XT_CMPSLE: return (b1 <= b2)? XT_SKIP: XT_NOSK; - case XT_CMPSGE: return (b1 >= b2)? XT_SKIP: XT_NOSK; - case XT_CMPSN: return (b1 != b2)? XT_SKIP: XT_NOSK; - case XT_CMPSG: return (b1 > b2)? XT_SKIP: XT_NOSK; } - return XT_MUUO; - -/* Convert binary to decimal instructions - checked against KS10 ucode - There are no MBZ tests. - - AC'AC + 1 = double precision integer source - AC + 3 = flags and destination length - AC + 4 = destination byte pointer -*/ - -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 */ - 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 */ - -/* 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); } - CLRF (F_FPD); /* clear FPD */ - return XT_SKIP; - -/* Convert decimal to binary instructions - checked against KS10 ucode - There are no MBZ tests. - - AC = flags and source length - AC + 1 = source byte pointer - AC + 3'AC + 4 = double precision integer result -*/ - -case XT_CVTDBT: /* CVTDBT */ -case XT_CVTDBO: /* CVTDBO */ - e1 = calc_ea (xinst, MM_EA); /* get ext inst addr */ - 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 */ - 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 (AC(ac) & XT_MFLG) { - 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; - -/* String move instructions - checked against KS10 ucode - Only the destination length is MBZ checked. - - AC = flags (MOVST only) and source length - AC + 1 = source byte pointer - AC + 3 = destination length - AC + 4 = destination byte pointer -*/ - -case XT_MOVSO: /* MOVSO */ -case XT_MOVST: /* MOVST */ -case XT_MOVSRJ: /* MOVSRJ */ -case XT_MOVSLJ: /* MOVSLJ */ - if (AC(p3) & XT_MBZ) return XT_MUUO; /* test dst lnt MBZ */ - 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; - case XT_MOVST: /* MOVST */ - 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); - break; - case XT_MOVSLJ: /* MOVSLJ */ - AC(ac) = AC(ac) & XLNTMASK; /* trim src length */ - break; } - - 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); } - return (AC(ac) & XLNTMASK)? XT_NOSK: XT_SKIP; - -/* Edit - checked against KS10 ucode - Only the flags/pattern pointer word is MBZ checked. - - AC = flags, pattern pointer - AC + 1 = source byte pointer - AC + 3 = mark address - AC + 4 = destination byte pointer -*/ - -case XT_EDIT: /* EDIT */ - if (AC(ac) & XT_MBZE) return XT_MUUO; /* check pattern MBZ */ - 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; - 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; - case ED_FLDSEP: /* separate fields */ - 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; - 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; - case (0100 + (ED_SKPM >> ED_V_POPC)): /* skip on M */ - 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; - case (0100 + (ED_SKPA >> ED_V_POPC)): /* skip always */ - ppi = (pat & ED_M_NUM) + 2; - break; - default: /* NOP or undefined */ - 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)); } - return ret; } /* end case xop */ -return XT_MUUO; -} - -/* Supporting subroutines */ - -/* Increment byte pointer, register version */ - -d10 incbp (d10 bp) -{ -int32 p, s; - -p = GET_P (bp); /* get P and S */ -s = GET_S (bp); -p = p - s; /* adv P */ -if (p < 0) { /* end of word? */ - bp = (bp & LMASK) | (INCR (bp)); /* increment addr */ - p = (36 - s) & 077; } /* reset P */ -bp = PUT_P (bp, p); /* store new P */ -return bp; -} - -/* Increment and load byte, extended version - uses register log */ - -d10 incloadbp (int32 ac, int32 pflgs) -{ -a10 ba; -d10 bp, wd; -int32 p, s; - -bp = AC(ac) = incbp (AC(ac)); /* increment bp */ -XT_INSRLOG (ac, rlog); /* log change */ -p = GET_P (bp); /* get P and S */ -s = GET_S (bp); -ba = calc_ea (bp, MM_EA_XSRC); /* calc bp eff addr */ -wd = Read (ba, MM_XSRC); /* read word */ -wd = (wd >> p) & bytemask[s]; /* get byte */ -return wd; -} - -/* Increment and deposit byte, extended version - uses register log */ - -void incstorebp (d10 val, int32 ac, int32 pflgs) -{ -a10 ba; -d10 bp, wd, mask; -int32 p, s; - -bp = AC(ac) = incbp (AC(ac)); /* increment bp */ -XT_INSRLOG (ac, rlog); /* log change */ -p = GET_P (bp); /* get P and S */ -s = GET_S (bp); -ba = calc_ea (bp, MM_EA_XDST); /* calc bp eff addr */ -wd = Read (ba, MM_XDST); /* read, write test */ -mask = bytemask[s] << p; /* shift mask, val */ -val = val << p; -wd = (wd & ~mask) | (val & mask); /* insert byte */ -Write (ba, wd & DMASK, MM_XDST); -return; -} - -/* Translate byte - - Arguments - by = byte to translate - tblad = virtual address of translation table - *xflgs = pointer to word containing translation flags - prv = previous mode flag for table lookup - Returns - xby = >= 0, translated byte - < 0, terminate translation -*/ - -d10 xlate (d10 by, a10 tblad, d10 *xflgs, int32 prv) -{ -a10 ea; -int32 tcode; -d10 tblent; - -ea = (tblad + ((int32) by >> 1)) & AMASK; -tblent = ((Read (ea, prv) >> ((by & 1)? 0: 18)) & RMASK); -tcode = XT_GETCODE (tblent); /* get xlate code */ -switch (tcode) { -case 00: - return (*xflgs & XT_SFLG)? tblent: by; -case 01: - break; -case 02: - *xflgs = *xflgs & ~XT_MFLG; - return (*xflgs & XT_SFLG)? tblent: by; -case 03: - *xflgs = *xflgs | XT_MFLG; - return (*xflgs & XT_SFLG)? tblent: by; -case 04: - *xflgs = *xflgs | XT_SFLG | XT_NFLG; - return tblent; -case 05: - *xflgs = *xflgs | XT_NFLG; - break; -case 06: - *xflgs = (*xflgs | XT_SFLG | XT_NFLG) & ~XT_MFLG; - return tblent; -case 07: - *xflgs = *xflgs | XT_SFLG | XT_NFLG | XT_MFLG; - return tblent; } /* end case xlate code */ -return -1; -} - -/* Fill out the destination string - - Arguments: - fill = fill - ac = 2 word AC block (length, byte pointer) - cnt = fill count - pflgs = PXCT flags -*/ - -void filldst (d10 fill, int32 ac, d10 cnt, int32 pflgs) -{ -int32 i, t; -int32 p1 = ADDA (ac, 1); - -for (i = 0; i < cnt; i++) { - if (i && (t = test_int ())) ABORT (t); - rlog = 0; /* clear log */ - incstorebp (fill, p1, pflgs); - AC(ac) = (AC(ac) & XFLGMASK) | ((AC(ac) - 1) & XLNTMASK); } - rlog = 0; -return; -} - -/* Clean up after page fault - - Arguments: - logv = register change log - - For each register in logv, decrement the register's contents as - though it were a byte pointer. Note that the KS10 does - do a full decrement calculation but merely adds S to P. -*/ - -void xtcln (int32 logv) -{ -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 */ - } -return; -} diff --git a/PDP11/pdp11_cis.c b/PDP11/pdp11_cis.c deleted file mode 100644 index 4190b7be..00000000 --- a/PDP11/pdp11_cis.c +++ /dev/null @@ -1,1265 +0,0 @@ -/* pdp11_cis.c: PDP-11 CIS optional instruction set simulator - - 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 module simulates the PDP-11 commercial instruction set (CIS). - - 17-Oct-02 RMS Fixed compiler warning (found by Hans Pufal) - 08-Oct-02 RMS Fixed macro definitions - - The commercial instruction set consists of three instruction formats: - - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ register operands - | 0 1 1 1 1 1| 0 0 0 0| opcode | 076030:076057 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 076070:076077 - - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ inline operands - | 0 1 1 1 1 1| 0 0 0 1| opcode | 076130:076157 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 076170:076177 - - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ load descriptors - | 0 1 1 1 1 1| 0 0 0 0|op| 1 0| reg | 076020:076027 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 076060:076067 - - The CIS instructions operate on character strings, packed (decimal) - strings, and numeric (decimal) strings. Strings are described by - a two word descriptor: - - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | length in bytes | char string - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ descriptor - | starting byte address | - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | |str type| | length | decimal string - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ descriptor - | starting byte address | - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - Decimal string types are: - - <14:12> data type bytes occupied by n digits - 0 signed zoned n - 1 unsigned zone n - 2 trailing overpunch n - 3 leading overpunch n - 4 trailing separate n+1 - 5 leading separate n+1 - 6 signed packed n/2 +1 - 7 unsigned packed n/2 +1 - - Zero length character strings occupy no memory; zero length decimal strings - require either zero bytes (zoned, overpunch) or one byte (separate, packed). - - CIS instructions can run for a very long time, so they are interruptible - and restartable. In the simulator, all instructions run to completion. - The code is unoptimized. -*/ - -#include "pdp11_defs.h" - -/* Opcode bits */ - -#define INLINE 0100 /* inline */ -#define PACKED 0020 /* packed */ -#define NUMERIC 0000 /* numeric */ - -/* Operand type definitions */ - -#define R0_DESC 1 /* descr in R0:R1 */ -#define R2_DESC 2 /* descr in R2:R3 */ -#define R4_DESC 3 /* descr in R4:R5 */ -#define R4_ARG 4 /* argument in R4 */ -#define IN_DESC 5 /* inline descriptor */ -#define IN_ARG 6 /* inline argument */ -#define IN_DESC_R0 7 /* inline descr to R0:R1 */ -#define MAXOPN 4 /* max # operands */ - -/* Decimal data type definitions */ - -#define XZ 0 /* signed zoned */ -#define UZ 1 /* unsigned zoned */ -#define TO 2 /* trailing overpunch */ -#define LO 3 /* leading overpunch */ -#define TS 4 /* trailing separate */ -#define LS 5 /* leading separate */ -#define XP 6 /* signed packed */ -#define UP 7 /* unsigned packed */ - -/* Decimal descriptor definitions */ - -#define DTYP_M 07 /* type mask */ -#define DTYP_V 12 /* type position */ -#define DLNT_M 037 /* length mask */ -#define DLNT_V 0 /* length position */ -#define GET_DTYP(x) (((x) >> DTYP_V) & DTYP_M) -#define GET_DLNT(x) (((x) >> DLNT_V) & DLNT_M) - -/* Shift operand definitions */ - -#define ASHRND_M 017 /* round digit mask */ -#define ASHRND_V 8 /* round digit pos */ -#define ASHLNT_M 0377 /* shift count mask */ -#define ASHLNT_V 0 /* shift length pos */ -#define ASHSGN 0200 /* shift sign */ -#define GET_ASHRND(x) (((x) >> ASHRND_V) & ASHRND_M) -#define GET_ASHLNT(x) (((x) >> ASHLNT_V) & ASHLNT_M) - -/* Operand array aliases */ - -#define A1LNT arg[0] -#define A1ADR arg[1] -#define A2LNT arg[2] -#define A2ADR arg[3] -#define A3LNT arg[4] -#define A3ADR arg[5] -#define A1 &arg[0] -#define A2 &arg[2] -#define A3 &arg[4] - -/* Condition code macros */ - -#define GET_BIT(ir,n) (((ir) >> (n)) & 1) -#define GET_SIGN_L(ir) GET_BIT((ir), 31) -#define GET_SIGN_W(ir) GET_BIT((ir), 15) -#define GET_SIGN_B(ir) GET_BIT((ir), 7) -#define GET_Z(ir) ((ir) == 0) - -/* Decimal string structure */ - -#define DSTRLNT 4 -#define DSTRMAX (DSTRLNT - 1) -#define MAXDVAL 429496730 /* 2^32 / 10 */ - -struct dstr { - unsigned int32 sign; - unsigned int32 val[DSTRLNT]; }; - -typedef struct dstr DSTR; - -static DSTR Dstr0 = { 0, 0, 0, 0, 0 }; - -extern int32 isenable, dsenable; -extern int32 N, Z, V, C; -extern int32 R[8], trap_req; -extern int32 ReadW (int32 addr); -extern void WriteW (int32 data, int32 addr); -extern int32 ReadB (int32 addr); -extern void WriteB (int32 data, int32 addr); -int32 ReadDstr (int32 *dscr, DSTR *dec, int32 flag); -void WriteDstr (int32 *dscr, DSTR *dec, int32 flag); -int32 AddDstr (DSTR *src1, DSTR *src2, DSTR *dst, int32 cin); -void SubDstr (DSTR *src1, DSTR *src2, DSTR *dst); -int32 CmpDstr (DSTR *src1, DSTR *src2); -int32 TestDstr (DSTR *dsrc); -int32 LntDstr (DSTR *dsrc, int32 nz); -unsigned int32 NibbleLshift (DSTR *dsrc, int32 sc, unsigned int32 cin); -unsigned int32 NibbleRshift (DSTR *dsrc, int32 sc, unsigned int32 cin); -int32 WordLshift (DSTR *dsrc, int32 sc); -void WordRshift (DSTR *dsrc, int32 sc); -void CreateTable (DSTR *dsrc, DSTR mtable[10]); - -/* Table of instruction operands */ - -static int32 opntab[128][MAXOPN] = { - 0, 0, 0, 0, 0, 0, 0, 0, /* 000 - 007 */ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, /* 010 - 017 */ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, /* LD2R */ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - R0_DESC, R2_DESC, R4_ARG, 0, /* MOVC */ - R0_DESC, R2_DESC, R4_ARG, 0, /* MOVRC */ - R0_DESC, R2_DESC, R4_DESC, 0, /* MOVTC */ - 0, 0, 0, 0, /* 033 */ - 0, 0, 0, 0, 0, 0, 0, 0, /* 034 - 037 */ - 0, 0, 0, 0, 0, 0, 0, 0, - R4_ARG, 0, 0, 0, /* LOCC */ - R4_ARG, 0, 0, 0, /* SKPC */ - R4_DESC, 0, 0, 0, /* SCANC */ - R4_DESC, 0, 0, 0, /* SPANC */ - R0_DESC, R2_DESC, R4_ARG, 0, /* CMPC */ - R2_DESC, 0, 0, 0, /* MATC */ - 0, 0, 0, 0, 0, 0, 0, 0, /* 046 - 047 */ - R0_DESC, R2_DESC, R4_DESC, 0, /* ADDN */ - R0_DESC, R2_DESC, R4_DESC, 0, /* SUBN */ - R0_DESC, R2_DESC, 0, 0, /* CMPN */ - R0_DESC, 0, 0, 0, /* CVTNL */ - R0_DESC, R2_DESC, 0, 0, /* CVTPN */ - R0_DESC, R2_DESC, 0, 0, /* CVTNP */ - R0_DESC, R2_DESC, R4_ARG, 0, /* ASHN */ - R0_DESC, 0, 0, 0, /* CVTLN */ - 0, 0, 0, 0, 0, 0, 0, 0, /* LD3R */ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - R0_DESC, R2_DESC, R4_DESC, 0, /* ADDP */ - R0_DESC, R2_DESC, R4_DESC, 0, /* SUBP */ - R0_DESC, R2_DESC, 0, 0, /* CMPP */ - R0_DESC, 0, 0, 0, /* CVTPL */ - R0_DESC, R2_DESC, R4_DESC, 0, /* MULP */ - R0_DESC, R2_DESC, R4_DESC, 0, /* DIVP */ - R0_DESC, R2_DESC, R4_ARG, 0, /* ASHP */ - R0_DESC, 0, 0, 0, /* CVTLP */ - 0, 0, 0, 0, 0, 0, 0, 0, /* 100 - 107 */ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, /* 110 - 117 */ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, /* 120 - 127 */ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - IN_DESC, IN_DESC, IN_ARG, 0, /* MOVCI */ - IN_DESC, IN_DESC, IN_ARG, 0, /* MOVRCI */ - IN_DESC, IN_DESC, IN_ARG, IN_ARG, /* MOVTCI */ - 0, 0, 0, 0, /* 133 */ - 0, 0, 0, 0, 0, 0, 0, 0, /* 134 - 137 */ - 0, 0, 0, 0, 0, 0, 0, 0, - IN_DESC_R0, IN_ARG, 0, 0, /* LOCCI */ - IN_DESC_R0, IN_ARG, 0, 0, /* SKPCI */ - IN_DESC_R0, IN_DESC, 0, 0, /* SCANCI */ - IN_DESC_R0, IN_DESC, 0, 0, /* SPANCI */ - IN_DESC, IN_DESC, IN_ARG, 0, /* CMPCI */ - IN_DESC_R0, IN_DESC, 0, 0, /* MATCI */ - 0, 0, 0, 0, 0, 0, 0, 0, /* 146 - 147 */ - IN_DESC, IN_DESC, IN_DESC, 0, /* ADDNI */ - IN_DESC, IN_DESC, IN_DESC, 0, /* SUBNI */ - IN_DESC, IN_DESC, 0, 0, /* CMPNI */ - IN_DESC, IN_ARG, 0, 0, /* CVTNLI */ - IN_DESC, IN_DESC, 0, 0, /* CVTPNI */ - IN_DESC, IN_DESC, 0, 0, /* CVTNPI */ - IN_DESC, IN_DESC, IN_ARG, 0, /* ASHNI */ - IN_DESC, IN_DESC, 0, 0, /* CVTLNI */ - 0, 0, 0, 0, 0, 0, 0, 0, /* 160 - 167 */ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - IN_DESC, IN_DESC, IN_DESC, 0, /* ADDPI */ - IN_DESC, IN_DESC, IN_DESC, 0, /* SUBPI */ - IN_DESC, IN_DESC, 0, 0, /* CMPPI */ - IN_DESC, 0, 0, 0, /* CVTPLI */ - IN_DESC, IN_DESC, IN_DESC, 0, /* MULPI */ - IN_DESC, IN_DESC, IN_DESC, 0, /* DIVPI */ - IN_DESC, IN_DESC, IN_ARG, 0, /* ASHPI */ - IN_DESC, IN_DESC, 0, 0 /* CVTLPI */ -}; - -/* ASCII to overpunch table: sign is <7>, digit is <4:0> */ - -static int32 overbin[128] = { - 0, 0, 0, 0, 0, 0, 0, 0, /* 000 - 037 */ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0x80, 0, 0, 0, 0, 0, 0, /* 040 - 077 */ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1, 2, 3, 4, 5, 6, 7, - 8, 9, 0x80, 0, 0, 0, 0, 0, - 0, 1, 2, 3, 4, 5, 6, 7, /* 100 - 137 */ - 8, 9, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, - 0x87, 0x88, 0x89, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0x80, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, /* 140 - 177 */ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0x80, 0, 0 -}; - -/* Overpunch to ASCII table: indexed by sign and digit */ - -static int32 binover[2][16] = { - '{', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', - '0', '0', '0', '0', '0', '0', - '}', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', - '0', '0', '0', '0', '0', '0' -}; - -static unsigned char movbuf[65536]; - -/* CIS emulator */ - -void cis11 (int32 IR) -{ -int32 c, i, j, k, t, op, rn, addr; -int32 fill, mask, match, limit, mvlnt, shift; -int32 spc, ldivd, ldivr; -int32 arg[6]; /* operands */ -uint32 nc, digit, result; -static DSTR accum, src1, src2, dst; -static DSTR mptable[10]; -static DSTR Dstr1 = { 0, 0x10, 0, 0, 0 }; - -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; - case R2_DESC: - arg[j++] = R[2]; - arg[j++] = R[3]; - break; - case R4_DESC: - arg[j++] = R[4]; - arg[j++] = R[5]; - break; - case R4_ARG: - 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; - 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; - case IN_ARG: - arg[j++] = ReadW (PC | isenable); - PC = (PC + 2) & 0177777; - break; } /* end case */ - } /* end for */ -switch (op) { /* case on opcode */ - -/* MOVC, MOVTC, MOVCI, MOVTCI - - Operands: - A1LNT, A1ADR = source string descriptor - A2LNT, A2ADR = dest string descriptor - A3LNT<7:0> = fill character - A3ADR = translation table address (MOVTC, MOVTCI only) - - Condition codes: - NZVC = set from src.lnt - dst.lnt - - Registers (MOVC, MOVTC only) - R0 = max (0, src.len - dst.len) - R1:R3 = 0 - R4:R5 = unchanged - - Notes: - - To avoid overlap problems, the entire source string is - buffered in movbuf. On a modern microprocessor, for most - string sizes, this will be handled in the on chip cache. - - If either the source or destination lengths are zero, - the move loops exit immediately. - - If the source length does not exceed the destination - length, the fill loop exits immediately. -*/ - -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); } - for (i = 0; i < mvlnt; i++) { - 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); } - 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; } - return; - -/* MOVRC, MOVRCI - - Operands: - A1LNT, A1ADR = source string descriptor - A2LNT, A2ADR = dest string descriptor - A3LNT<7:0> = fill character - - Condition codes: - NZVC = set from src.lnt - dst.lnt - - Registers (MOVRC only) - R0 = max (0, src.len - dst.len) - R1:R3 = 0 - R4:R5 = unchanged - - Notes: see MOVC, MOVCI -*/ - -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); } - addr = A2ADR + A2LNT - mvlnt; - for (i = 0; i < mvlnt; i++) { - 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); } - 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; } - return; - -/* Load descriptors - no operands */ - -case 020: case 021: case 022: case 023: -case 024: case 025: case 026: case 027: -case 060: case 061: case 062: case 063: -case 064: case 065: case 066: case 067: - limit = (op & 040)? 6: 4; - rn = IR & 07; /* get register */ - 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); } - if (rn >= limit) R[rn] = (R[rn] + limit) & 0177777; - return; - -/* LOCC, SKPC, LOCCI, SKPCI - - Operands: - R0, R1 = source string descriptor - A1LNT<7:0> = match character - - Condition codes: - NZ = set from R0 - VC = 0 - - Registers: - R0:R1 = substring descriptor where operation terminated -*/ - -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; } - N = GET_SIGN_W (R[0]); - Z = GET_Z (R[0]); - V = C = 0; - if ((op & INLINE) == 0) R[4] = R[4] & 0377; /* if reg, set reg */ - return; - -/* SCANC, SPANC, SCANCI, SPANCI - - Operands: - R0, R1 = source string descriptor - A1LNT<7:0> = mask - A1ADR = table address - - Condition codes: - NZ = set from R0 - VC = 0 - - Registers: - R0:R1 = substring descriptor where operation terminated -*/ - -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; } - N = GET_SIGN_W (R[0]); - Z = GET_Z (R[0]); - V = C = 0; - if ((op & INLINE) == 0) R[4] = R[4] & 0377; /* if reg, set reg */ - return; - -/* CMPC, CMPCI - - Operands: - A1LNT, A1ADR = source1 string descriptor - A2LNT, A2ADR = source2 string descriptor - A3LNT<7:0> = fill character - - Condition codes: - NZVC = set from src1 - src2 at mismatch, or - = 0100 if equal - - Registers (CMPC only): - R0:R1 = unmatched source1 substring descriptor - R2:R3 = unmatched source2 substring descriptor -*/ - -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; } - 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; } - return; - -/* MATC, MATCI - - Operands: - R0, R1 = source string descriptor - A1LNT, A1ADR = substring descriptor - - Condition codes: - NZ = set from R0 - VC = 0 - - Registers: - R0:R1 = source substring descriptor for match - - Notes: - - If the string is zero length, and the substring is not, - the outer loop exits immediately, and the result is - "no match" - - If the substring is zero length, the inner loop always - exits immediately, and the result is a "match" - - If the string is zero length, and the substring is as - well, the outer loop executes, the inner loop exits - immediately, and the result is a match, but the result - is the length of the string (zero), or "no match" -*/ - -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 */ - if (!match) { /* if no match */ - R[1] = (R[1] + R[0]) & 0177777; - R[0] = 0; } - N = GET_SIGN_W (R[0]); - Z = GET_Z (R[0]); - V = C = 0; - return; - -/* ADDN, SUBN, ADDP, SUBP, ADDNI, SUBNI, ADDPI, SUBPI - - Operands: - A1LNT, A1ADR = source1 string descriptor - A2LNT, A2ADR = source2 string descriptor - A3LNT, A3ADR = destination string descriptor - - Condition codes: - NZV = set from result - C = 0 - - Registers (ADDN, ADDP, SUBN, SUBP only): - R0:R3 = 0 -*/ - -case 050: case 051: case 070: case 071: -case 0150: case 0151: case 0170: case 0171: - ReadDstr (A1, &src1, op); /* get source1 */ - 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 */ - else { /* addition */ - 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; - return; - -/* MULP, MULPI - - Operands: - A1LNT, A1ADR = source1 string descriptor - A2LNT, A2ADR = source2 string descriptor - A3LNT, A3ADR = destination string descriptor - - Condition codes: - NZV = set from result - C = 0 - - Registers (MULP only): - R0:R3 = 0 -*/ - -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 */ - else V = 0; /* result = 0 */ - C = 0; /* 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; - return; - -/* DIVP, DIVPI - - Operands: - A1LNT, A1ADR = divisor string descriptor - A2LNT, A2ADR = dividend string descriptor - A3LNT, A3ADR = destination string descriptor - - Condition codes: - NZV = set from result - C = set if divide by zero - - Registers (DIVP only): - R0:R3 = 0 -*/ - -case 075: case 0175: - ldivr = ReadDstr (A1, &src1, op); /* get divisor */ - if (ldivr == 0) { /* divisor = 0? */ - 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 */ - dst = Dstr0; /* clear dest */ - 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 */ - 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; - return; - -/* CMPN, CMPP, CMPNI, CMPPI - - Operands: - A1LNT, A1ADR = source1 string descriptor - A2LNT, A2ADR = source2 string descriptor - - Condition codes: - NZ = set from comparison - VC = 0 - - Registers (CMPN, CMPP only): - R0:R3 = 0 -*/ - -case 052: case 072: case 0152: case 0172: - ReadDstr (A1, &src1, op); /* get source1 */ - 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; } - if ((op & INLINE) == 0) /* if reg, clr reg */ - R[0] = R[1] = R[2] = R[3] = 0; - return; - -/* ASHN, ASHP, ASHNI, ASHPI - - Operands: - A1LNT, A1ADR = source string descriptor - A2LNT, A2ADR = destination string descriptor - A3LNT<11:8> = rounding digit - A3LNT<7:0> = shift count - - Condition codes: - NZV = set from result - C = 0 - - Registers (ASHN, ASHP only): - R0:R1, R4 = 0 -*/ - -case 056: case 076: case 0156: case 0176: - ReadDstr (A1, &src1, op); /* get source */ - 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 */ - } /* 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; - } /* end left shift */ - WriteDstr (A2, &src1, op); /* store result */ - if ((op & INLINE) == 0) /* if reg, clr reg */ - R[0] = R[1] = R[4] = 0; - return; - -/* CVTPN, CVTPNI - - Operands: - A1LNT, A1ADR = source string descriptor - A2LNT, A2ADR = destination string descriptor - - Condition codes: - NZV = set from result - C = 0 - - Registers (CVTPN only): - R0:R1 = 0 -*/ - -case 054: case 0154: - ReadDstr (A1, &src1, PACKED); /* get source */ - V = C = 0; /* init cc's */ - WriteDstr (A2, &src1, NUMERIC); /* write dest */ - if ((op & INLINE) == 0) R[0] = R[1] = 0; /* if reg, clr reg */ - return; - -/* CVTNP, CVTNPI - - Operands: - A1LNT, A1ADR = source string descriptor - A2LNT, A2ADR = destination string descriptor - - Condition codes: - NZV = set from result - C = 0 - - Registers (CVTNP only): - R0:R1 = 0 -*/ - -case 055: case 0155: - ReadDstr (A1, &src1, NUMERIC); /* get source */ - V = C = 0; /* init cc's */ - WriteDstr (A2, &src1, PACKED); /* write dest */ - if ((op & INLINE) == 0) R[0] = R[1] = 0; /* if reg, clr reg */ - return; - -/* CVTNL, CVTPL, CVTNLI, CVTPLI - - Operands: - A1LNT, A1ADR = source string descriptor - A2LNT = destination address (inline only) - - Condition codes: - NZV = set from result - C = source < 0 and result != 0 - - Registers (CVTNL, CVTPL only): - R0:R1 = 0 - R2:R3 = result -*/ - -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 */ - 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; } - return; - -/* CVTLN, CVTLP, CVTLNI, CVTLPI - - Operands: - A1LNT, A1ADR = destination string descriptor - A2LNT, A2ADR = source long (CVTLNI, CVTLPI) - VAX format - R2:R3 = source long (CVTLN, CVTLP) - EIS format - - Condition codes: - NZV = set from result - C = 0 - - Registers (CVTLN, CVTLP only) - R2:R3 = 0 -*/ - -case 057: case 077: - result = (R[2] << 16) | R[3]; /* op in EIS format */ - R[2] = R[3] = 0; /* clear registers */ - goto CVTLx; /* join common code */ -case 0157: case 0177: - result = (A2ADR << 16) | A2LNT; /* op in VAX format */ -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)); } - V = C = 0; - WriteDstr (A1, &dst, op); /* write result */ - return; -default: - setTRAP (TRAP_ILL); - break; } -return; -} /* end cis */ - -/* Get decimal string - - Arguments: - dscr = decimal string descriptor - src = decimal string structure - flag = numeric/packed flag - - The routine returns the length in int32's of the non-zero part of - the string. - - This routine plays fast and loose with operand checking, as did the - original 11/23 microcode (half of which I wrote). In particular, - - - If the flag specifies packed, the type is not checked at all. - The sign of an unsigned string is assumed to be 0xF (an - alternative for +). - - If the flag specifies numeric, packed types will be treated - as unsigned zoned. - - For separate, only the '-' sign is checked, not the '+'. - - However, to simplify the code elsewhere, digits are range checked, - and bad digits are replaced with 0's. -*/ - -int32 ReadDstr (int32 *dscr, DSTR *src, int32 flag) -{ -int32 c, i, end, lnt, type, t; - -*src = Dstr0; /* clear result */ -type = GET_DTYP (dscr[0]); /* get type */ -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 */ - 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) == '-'); - 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 */ - } /* end numeric */ -return TestDstr (src); /* clean -0 */ -} - -/* Store decimal string - - Arguments: - dsrc = decimal string descriptor - src = decimal string structure - flag = numeric/packed flag - PSW.NZ are also set to their proper values - PSW.V will be set on overflow; it must be initialized elsewhere - (to allow for external overflow calculations) - - The rules for the stored sign and the PSW sign are: - - Stored sign is negative if input is negative, string type - is signed, and the result is non-zero or there was overflow - - PSW sign is negative if input is negative, string type is - signed, and the result is non-zero - Thus, the stored sign and the PSW sign will differ in one case: - a negative zero generated by overflow is stored with a negative - sign, but PSW.N is clear -*/ - -void WriteDstr (int32 *dscr, DSTR *dst, int32 flag) -{ -int32 c, i, limit, end, type, lnt; -uint32 mask; -static uint32 masktab[8] = { - 0xFFFFFFF0, 0xFFFFFF00, 0xFFFFF000, 0xFFFF0000, - 0xFFF00000, 0xFF000000, 0xF0000000, 0x00000000 }; -static int32 unsignedtab[8] = { 0, 1, 0, 0, 0, 0, 0, 1 }; - -type = GET_DTYP (dscr[0]); /* get type */ -lnt = GET_DLNT (dscr[0]); /* get string length */ -mask = 0; /* can't ovflo */ -Z = 1; /* assume all 0's */ -limit = lnt / 8; /* limit for test */ -for (i = 0; i < DSTRLNT; i++) { /* loop thru value */ - if (i == limit) mask = masktab[lnt % 8]; /* at limit, get mask */ - else if (i > limit) mask = 0xFFFFFFFF; /* beyond, all ovflo */ - if (dst->val[i] & mask) V = 1; /* test for ovflo */ - if (dst->val[i] = dst->val[i] & ~mask) Z = 0; } /* test nz */ -dst->sign = dst->sign & ~unsignedtab[type] & ~(Z & ~V); -N = dst->sign & ~Z; /* N = sign, if ~zero */ - -if (flag & PACKED) { /* packed? */ - end = lnt / 2; /* end of string */ - 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)); - } /* end for */ - } /* end packed */ -else { - if (type >= TS) WriteB (dst->sign? '-': '+', (((type == TS)? - 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 */ - } /* end numeric */ -return; -} - -/* Add decimal string magnitudes - - Arguments: - s1 = source1 decimal string - s2 = source2 decimal string - ds = destination decimal string - cy = carry in - Output = 1 if carry, 0 if no carry - - This algorithm courtesy Anton Chernoff, circa 1992 or even earlier - - We trace the history of a pair of adjacent digits to see how the - carry is fixed; each parenthesized item is a 4b digit. - - Assume we are adding: - (a)(b) I - + (x)(y) J - - First compute I^J: - (a^x)(b^y) TMP - - Note that the low bit of each digit is the same as the low bit of - the sum of the digits, ignoring the cary, since the low bit of the - sum is the xor of the bits. - - Now compute I+J+66 to get decimal addition with carry forced left - one digit: - (a+x+6+carry mod 16)(b+y+6 mod 16) SUM - - Note that if there was a carry from b+y+6, then the low bit of the - left digit is different from the expected low bit from the xor. - If we xor this SUM into TMP, then the low bit of each digit is 1 - if there was a carry, and 0 if not. We need to subtract 6 from each - digit that did not have a carry, so take ~(SUM ^ TMP) & 0x11, shift - it right 4 to the digits that are affected, and subtract 6*adjustment - (actually, shift it right 3 and subtract 3*adjustment). -*/ - -int32 AddDstr (DSTR *s1, DSTR *s2, DSTR *ds, int32 cy) -{ -int32 i; -unsigned int32 sm1, sm2, tm1, tm2, tm3, tm4; - -for (i = 0; i < DSTRLNT; i++) { /* loop low to high */ - tm1 = s1->val[i] ^ (s2->val[i] + cy); /* xor operands */ - sm1 = s1->val[i] + (s2->val[i] + cy); /* sum operands */ - sm2 = sm1 + 0x66666666; /* force carry out */ - cy = ((sm1 < s1->val[i]) || (sm2 < sm1)); /* check for overflow */ - tm2 = tm1 ^ sm2; /* get carry flags */ - tm3 = (tm2 >> 3) | (cy << 29); /* compute adjustment */ - tm4 = 0x22222222 & ~tm3; /* clear where carry */ - ds->val[i] = sm2 - (3 * tm4); } /* final result */ -return cy; -} - -/* Subtract decimal string magnitudes - - Arguments: - s1 = source1 decimal string - s2 = source2 decimal string - ds = destination decimal string - Outputs: s2 - s1 in ds - - Note: the routine assumes that s1 <= s2 - -*/ - -void SubDstr (DSTR *s1, DSTR *s2, DSTR *ds) -{ -int32 i; -DSTR compl; - -for (i = 0; i < DSTRLNT; i++) compl.val[i] = 0x99999999 - s1->val[i]; -AddDstr (&compl, s2, ds, 1); /* s1 + ~s2 + 1 */ -return; -} - -/* Compare decimal string magnitudes - - Arguments: - s1 = source1 decimal string - s2 = source2 decimal string - Output = 1 if >, 0 if =, -1 if < -*/ - -int32 CmpDstr (DSTR *s1, DSTR *s2) -{ -int32 i; - -for (i = DSTRMAX; i >=0; i--) { - if (s1->val[i] > s2->val[i]) return 1; - if (s1->val[i] < s2->val[i]) return -1; } -return 0; -} - -/* Test decimal string for zero - - Arguments: - dsrc = decimal string structure - Returns the non-zero length of the string, in int32 units - If the string is zero, the sign is cleared -*/ - -int32 TestDstr (DSTR *dsrc) -{ -int32 i; - -for (i = DSTRMAX; i >= 0; i--) if (dsrc->val[i]) return (i + 1); -dsrc->sign = 0; -return 0; -} - -/* Get exact length of decimal string - - Arguments: - dsrc = decimal string structure - nz = result from TestDstr -*/ - -int32 LntDstr (DSTR *dsrc, int32 nz) -{ -int32 i; - -for (i = 7; i > 0; i--) { - if ((dsrc->val[nz - 1] >> (i * 4)) & 0xF) break; } -return ((nz - 1) * 8) + i; -} - -/* Create table of multiples - - Arguments: - dsrc = base decimal string structure - mtable[10] = array of decimal string structures - - Note that dsrc has a high order zero nibble; this - guarantees that the largest multiple won't overflow - Also note that mtable[0] is not filled in -*/ - -void CreateTable (DSTR *dsrc, DSTR mtable[10]) -{ -int32 (i); - -mtable[1] = *dsrc; -for (i = 2; i < 10; i++) AddDstr (&mtable[1], &mtable[i-1], &mtable[i], 0); -return; -} - -/* Word shift right - - Arguments: - dsrc = decimal string structure - sc = shift count -*/ - -void WordRshift (DSTR *dsrc, int32 sc) -{ -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; } } -return; -} - -/* Word shift left - - Arguments: - dsrc = decimal string structure - sc = shift count -*/ - -int32 WordLshift (DSTR *dsrc, int32 sc) -{ -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; } } -return c; -} - -/* Nibble shift decimal string right - - Arguments: - dsrc = decimal string structure - sc = shift count - cin = carry in -*/ - -unsigned int32 NibbleRshift (DSTR *dsrc, int32 sc, unsigned int32 cin) -{ -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; } - return cin; } -return 0; -} - -/* Nibble shift decimal string left - - Arguments: - dsrc = decimal string structure - sc = shift count - cin = carry in -*/ - -unsigned int32 NibbleLshift (DSTR *dsrc, int32 sc, unsigned int32 cin) -{ -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; } - return cin; } -return 0; -} diff --git a/PDP11/pdp11_cpu.c b/PDP11/pdp11_cpu.c deleted file mode 100644 index 5e987a4a..00000000 --- a/PDP11/pdp11_cpu.c +++ /dev/null @@ -1,2506 +0,0 @@ -/* pdp11_cpu.c: PDP-11 CPU simulator - - 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. - - cpu PDP-11 CPU (J-11 microprocessor) - - 05-Jun-03 RMS Fixed bugs in memory size table - 12-Mar-03 RMS Added logical name support - 01-Feb-03 RMS Changed R display to follow PSW, added SP display - 19-Jan-03 RMS Changed mode definitions for Apple Dev Kit conflict - 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 - 09-Sep-02 RMS Added KW11P support - 14-Jul-02 RMS Fixed bug in MMR0 error status load - 03-Jun-02 RMS Fixed relocation add overflow, added PS<15:12> = 1111 - special case logic to MFPI and removed it from MTPI - (found by John Dundas) - 29-Apr-02 RMS More fixes to DIV and ASH/ASHC (found by John Dundas) - 28-Apr-02 RMS Fixed bugs in illegal instruction 000010 and in - write-only memory pages (found by Wolfgang Helbig) - 21-Apr-02 RMS Fixed bugs in DIV by zero, DIV overflow, TSTSET, RTS, - ASHC -32, and red zone trap (found by John Dundas) - 04-Mar-02 RMS Changed double operand evaluation order for M+ - 23-Feb-02 RMS Fixed bug in MAINT, CPUERR, MEMERR read - 28-Jan-02 RMS Revised for multiple timers; fixed calc_MMR1 macros - 06-Jan-02 RMS Revised enable/disable support - 30-Dec-01 RMS Added old PC queue - 25-Dec-01 RMS Cleaned up sim_inst declarations - 11-Dec-01 RMS Moved interrupt debug code - 07-Dec-01 RMS Revised to use new breakpoint package - 08-Nov-01 RMS Moved I/O to external module - 26-Oct-01 RMS Revised to use symbolic definitions for IO page - 15-Oct-01 RMS Added debug logging - 08-Oct-01 RMS Fixed bug in revised interrupt logic - 07-Sep-01 RMS Revised device disable and interrupt mechanisms - 26-Aug-01 RMS Added DZ11 support - 10-Aug-01 RMS Removed register from declarations - 17-Jul-01 RMS Fixed warning from VC++ 6.0 - 01-Jun-01 RMS Added DZ11 interrupts - 23-Apr-01 RMS Added RK611 support - 05-Apr-01 RMS Added TS11/TSV05 support - 05-Mar-01 RMS Added clock calibration support - 11-Feb-01 RMS Added DECtape support - 25-Jan-01 RMS Fixed 4M memory definition (found by Eric Smith) - 14-Apr-99 RMS Changed t_addr to unsigned - 18-Aug-98 RMS Added CIS support - 09-May-98 RMS Fixed bug in DIV overflow test - 19-Jan-97 RMS Added RP/RM support - 06-Apr-96 RMS Added dynamic memory sizing - 29-Feb-96 RMS Added TM11 support - 17-Jul-94 RMS Corrected updating of MMR1 if MMR0 locked - - The register state for the PDP-11 is: - - REGFILE[0:5][0] general register set - REGFILE[0:5][1] alternate general register set - STACKFILE[4] stack pointers for kernel, supervisor, unused, user - PC program counter - PSW processor status word - <15:14> = CM current processor mode - <13:12> = PM previous processor mode - <11> = RS register set select - <7:5> = IPL interrupt priority level - <4> = TBIT trace trap enable - <3:0> = NZVC condition codes - FR[0:5] floating point accumulators - FPS floating point status register - FEC floating exception code - FEA floating exception address - MMR0,1,2,3 memory management control registers - APRFILE[0:63] memory management relocation registers for - kernel, supervisor, unused, user - <31:16> = PAR processor address registers - <15:0> = PDR processor data registers - PIRQ processor interrupt request register - CPUERR CPU error register - MEMERR memory system error register - CCR cache control register - MAINT maintenance register - HITMISS cache status register - SR switch register - DR display register -*/ - -/* The PDP-11 has many instruction formats: - - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ double operand - | opcode | source spec | dest spec | 010000:067777 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 110000:167777 - - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ register + operand - | opcode | src reg| dest spec | 004000:004777 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 070000:077777 - - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ single operand - | opcode | dest spec | 000100:000177 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 000300:000377 - 005000:007777 - 105000:107777 - - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ single register - | opcode |dest reg| 000200:000207 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 000230:000237 - - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ no operand - | opcode | 000000:000007 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ branch - | opcode | branch displacement | 000400:003477 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 100000:103477 - - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ EMT/TRAP - | opcode | trap code | 104000:104777 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ cond code operator - | opcode | immediate | 000240:000277 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - An operand specifier consists of an addressing mode and a register. - The addressing modes are: - - 0 register direct R op = R - 1 register deferred (R) op = M[R] - 2 autoincrement (R)+ op = M[R]; R = R + length - 3 autoincrement deferred @(R)+ op = M[M[R]]; R = R + 2 - 4 autodecrement -(R) R = R - length; op = M[R] - 5 autodecrement deferred @-(R) R = R - 2; op = M[M[R]] - 6 displacement d(R) op = M[R + disp] - 7 displacement deferred @d(R) op = M[M[R + disp]] - - There are eight general registers, R0-R7. R6 is the stack pointer, - R7 the PC. The combination of addressing modes with R7 yields: - - 27 immediate #n op = M[PC]; PC = PC + 2 - 37 absolute @#n op = M[M[PC]]; PC = PC + 2 - 67 relative d(PC) op = M[PC + disp] - 77 relative deferred @d(PC) op = M[M[PC + disp]] -*/ - -/* This routine is the instruction decode routine for the PDP-11. It - is called from the simulator control program to execute instructions - in simulated memory, starting at the simulated PC. It runs until an - enabled exception is encountered. - - General notes: - - 1. Virtual address format. PDP-11 memory management uses the 16b - virtual address, the type of reference (instruction or data), and - the current mode, to construct the 22b physical address. To - package this conveniently, the simulator uses a 19b pseudo virtual - address, consisting of the 16b virtual address prefixed with the - current mode and ispace/dspace indicator. These are precalculated - as isenable and dsenable for ispace and dspace, respectively, and - must be recalculated whenever MMR0, MMR3, or PSW changes. - - 2. Traps and interrupts. Variable trap_req bit-encodes all possible - traps. In addition, an interrupt pending bit is encoded as the - lowest priority trap. Traps are processed by trap_vec and trap_clear, - which provide the vector and subordinate traps to clear, respectively. - - Array int_req[0:7] bit encodes all possible interrupts. It is masked - under the interrupt priority level, ipl. If any interrupt request - is not masked, the interrupt bit is set in trap_req. While most - interrupts are handled centrally, a device can supply an interrupt - acknowledge routine. - - 3. PSW handling. The PSW is kept as components, for easier access. - Because the PSW can be explicitly written as address 17777776, - all instructions must update PSW before executing their last write. - - 4. Adding I/O devices. These modules must be modified: - - pdp11_defs.h add device address and interrupt definitions - pdp11_sys.c add to sim_devices table entry -*/ - -/* Definitions */ - -#include "pdp11_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 calc_is(md) ((md) << VA_V_MODE) -#define calc_ds(md) (calc_is((md)) | ((MMR3 & dsmask[(md)])? VA_DS: 0)) -#define calc_MMR1(val) ((MMR1)? (((val) << 8) | MMR1): (val)) -#define GET_SIGN_W(v) ((v) >> 15) -#define GET_SIGN_B(v) ((v) >> 7) -#define GET_Z(v) ((v) == 0) -#define JMP_PC(x) PCQ_ENTRY; PC = (x) -#define BRANCH_F(x) PCQ_ENTRY; PC = (PC + (((x) + (x)) & 0377)) & 0177777 -#define BRANCH_B(x) PCQ_ENTRY; PC = (PC + (((x) + (x)) | 0177400)) & 0177777 -#define last_pa (cpu_unit.u4) /* auto save/rest */ -#define UNIT_V_18B (UNIT_V_UF) /* force 18b addr */ -#define UNIT_V_UBM (UNIT_V_UF + 1) /* bus map present */ -#define UNIT_V_RH11 (UNIT_V_UF + 2) /* RH11 Massbus */ -#define UNIT_V_CIS (UNIT_V_UF + 3) /* CIS present */ -#define UNIT_V_MSIZE (UNIT_V_UF + 4) /* dummy */ -#define UNIT_18B (1u << UNIT_V_18B) -#define UNIT_UBM (1u << UNIT_V_UBM) -#define UNIT_RH11 (1u << UNIT_V_RH11) -#define UNIT_CIS (1u << UNIT_V_CIS) -#define UNIT_MSIZE (1u << UNIT_V_MSIZE) -#define UNIT_MAP (UNIT_18B | UNIT_UBM | UNIT_RH11) - -/* Global state */ - -extern FILE *sim_log; - -uint16 *M = NULL; /* memory */ -int32 REGFILE[6][2] = { 0 }; /* R0-R5, two sets */ -int32 STACKFILE[4] = { 0 }; /* SP, four modes */ -int32 saved_PC = 0; /* program counter */ -int32 R[8] = { 0 }; /* working registers */ -int32 PSW = 0; /* PSW */ - int32 cm = 0; /* current mode */ - int32 pm = 0; /* previous mode */ - int32 rs = 0; /* register set */ - int32 ipl = 0; /* int pri level */ - int32 tbit = 0; /* trace flag */ - int32 N = 0, Z = 0, V = 0, C = 0; /* condition codes */ -int32 wait_state = 0; /* wait state */ -int32 trap_req = 0; /* trap requests */ -int32 int_req[IPL_HLVL] = { 0 }; /* interrupt requests */ -int32 PIRQ = 0; /* programmed int req */ -int32 SR = 0; /* switch register */ -int32 DR = 0; /* display register */ -fpac_t FR[6] = { 0 }; /* fp accumulators */ -int32 FPS = 0; /* fp status */ -int32 FEC = 0; /* fp exception code */ -int32 FEA = 0; /* fp exception addr */ -int32 APRFILE[64] = { 0 }; /* PARs/PDRs */ -int32 MMR0 = 0; /* MMR0 - status */ -int32 MMR1 = 0; /* MMR1 - R+/-R */ -int32 MMR2 = 0; /* MMR2 - saved PC */ -int32 MMR3 = 0; /* MMR3 - 22b status */ -int32 ub_map[UBM_LNT_LW] = { 0 }; /* Unibus map array */ -int32 cpu_bme = 0; /* bus map enable */ -int32 cpu_18b = 0; /* 18b CPU config'd */ -int32 cpu_ubm = 0; /* bus map config'd */ -int32 cpu_rh11 = 0; /* RH11 config'd */ -int32 cpu_astop = 0; /* address stop */ -int32 isenable = 0, dsenable = 0; /* i, d space flags */ -int32 CPUERR = 0; /* CPU error reg */ -int32 MEMERR = 0; /* memory error reg */ -int32 CCR = 0; /* cache control reg */ -int32 HITMISS = 0; /* hit/miss reg */ -int32 MAINT = MAINT_Q | MAINT_NOFPA | MAINT_KDJ | MAINT_BPOK; /* maint reg */ -int32 stop_trap = 1; /* stop on trap */ -int32 stop_vecabort = 1; /* stop on vec abort */ -int32 stop_spabort = 1; /* stop on SP abort */ -int32 wait_enable = 0; /* wait state enable */ -int32 cpu_log = 0; /* logging */ -uint16 pcq[PCQ_SIZE] = { 0 }; /* PC queue */ -int32 pcq_p = 0; /* PC queue ptr */ -REG *pcq_r = NULL; /* PC queue reg ptr */ -int32 dev_enb = (-1) & ~INT_TS; /* dev enables */ -jmp_buf save_env; /* abort handler */ -int32 dsmask[4] = { MMR3_KDS, MMR3_SDS, 0, MMR3_UDS }; /* dspace enables */ - -extern int32 sim_interval; -extern UNIT *sim_clock_queue; -extern UNIT clk_unit, pclk_unit; -extern int32 sim_int_char; -extern int32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */ -extern DEVICE *sim_devices[]; - -/* Function declarations */ - -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_bus (UNIT *uptr, int32 val, char *cptr, void *desc); -int32 GeteaB (int32 spec); -int32 GeteaW (int32 spec); -int32 relocR (int32 addr); -int32 relocW (int32 addr); -int32 ReadW (int32 addr); -int32 ReadB (int32 addr); -int32 ReadMW (int32 addr); -int32 ReadMB (int32 addr); -void WriteW (int32 data, int32 addr); -void WriteB (int32 data, int32 addr); -void PWriteW (int32 data, int32 addr); -void PWriteB (int32 data, int32 addr); -t_stat CPU_rd (int32 *data, int32 addr, int32 access); -t_stat CPU_wr (int32 data, int32 addr, int32 access); -t_stat APR_rd (int32 *data, int32 addr, int32 access); -t_stat APR_wr (int32 data, int32 addr, int32 access); -t_stat SR_MMR012_rd (int32 *data, int32 addr, int32 access); -t_stat SR_MMR012_wr (int32 data, int32 addr, int32 access); -t_stat MMR3_rd (int32 *data, int32 addr, int32 access); -t_stat MMR3_wr (int32 data, int32 addr, int32 access); -t_stat ubm_rd (int32 *data, int32 addr, int32 access); -t_stat ubm_wr (int32 data, int32 addr, int32 access); -void set_r_display (int32 rs, int32 cm); - -extern t_stat build_dib_tab (int32 ubm); -extern t_stat show_iospace (FILE *st, UNIT *uptr, int32 val, void *desc); -extern t_stat iopageR (int32 *data, uint32 addr, int32 access); -extern t_stat iopageW (int32 data, uint32 addr, int32 access); -extern int32 calc_ints (int32 nipl, int32 trq); -extern int32 get_vector (int32 nipl); - -/* Trap data structures */ - -int32 trap_vec[TRAP_V_MAX] = { /* trap req to vector */ - VEC_RED, VEC_ODD, VEC_MME, VEC_NXM, - VEC_PAR, VEC_PRV, VEC_ILL, VEC_BPT, - VEC_IOT, VEC_EMT, VEC_TRAP, VEC_TRC, - VEC_YEL, VEC_PWRFL, VEC_FPE }; - -int32 trap_clear[TRAP_V_MAX] = { /* trap clears */ - TRAP_RED+TRAP_PAR+TRAP_YEL+TRAP_TRC+TRAP_ODD+TRAP_NXM, - TRAP_ODD+TRAP_PAR+TRAP_YEL+TRAP_TRC, - TRAP_MME+TRAP_PAR+TRAP_YEL+TRAP_TRC, - TRAP_NXM+TRAP_PAR+TRAP_YEL+TRAP_TRC, - TRAP_PAR+TRAP_TRC, TRAP_PRV+TRAP_TRC, - TRAP_ILL+TRAP_TRC, TRAP_BPT+TRAP_TRC, - TRAP_IOT+TRAP_TRC, TRAP_EMT+TRAP_TRC, - TRAP_TRAP+TRAP_TRC, TRAP_TRC, - TRAP_YEL, TRAP_PWRFL, TRAP_FPE }; - -/* Fixed I/O address table entries */ - -DIB cpu0_dib = { IOBA_CPU, IOLN_CPU, &CPU_rd, &CPU_wr, 0 }; -DIB cpu1_dib = { IOBA_APR, IOLN_APR, &APR_rd, &APR_wr, 0 }; -DIB cpu2_dib = { IOBA_APR1, IOLN_APR1, &APR_rd, &APR_wr, 0 }; -DIB cpu3_dib = { IOBA_SRMM, IOLN_SRMM, &SR_MMR012_rd, &SR_MMR012_wr, 0 }; -DIB cpu4_dib = { IOBA_MMR3, IOLN_MMR3, &MMR3_rd, &MMR3_wr, 0 }; -DIB ubm_dib = { IOBA_UBM, IOLN_UBM, &ubm_rd, &ubm_wr, 0 }; - -/* CPU data structures - - cpu_dev CPU device descriptor - cpu_unit CPU unit descriptor - cpu_reg CPU register list - cpu_mod CPU modifier list -*/ - -UNIT cpu_unit = { UDATA (NULL, UNIT_FIX + UNIT_BINK, INIMEMSIZE) }; - -REG cpu_reg[] = { - { ORDATA (PC, saved_PC, 16) }, - { ORDATA (R0, REGFILE[0][0], 16) }, - { ORDATA (R1, REGFILE[1][0], 16) }, - { ORDATA (R2, REGFILE[2][0], 16) }, - { ORDATA (R3, REGFILE[3][0], 16) }, - { ORDATA (R4, REGFILE[4][0], 16) }, - { ORDATA (R5, REGFILE[5][0], 16) }, - { ORDATA (SP, STACKFILE[MD_KER], 16) }, - { ORDATA (R00, REGFILE[0][0], 16) }, - { ORDATA (R01, REGFILE[1][0], 16) }, - { ORDATA (R02, REGFILE[2][0], 16) }, - { ORDATA (R03, REGFILE[3][0], 16) }, - { ORDATA (R04, REGFILE[4][0], 16) }, - { ORDATA (R05, REGFILE[5][0], 16) }, - { ORDATA (R10, REGFILE[0][1], 16) }, - { ORDATA (R11, REGFILE[1][1], 16) }, - { ORDATA (R12, REGFILE[2][1], 16) }, - { ORDATA (R13, REGFILE[3][1], 16) }, - { ORDATA (R14, REGFILE[4][1], 16) }, - { ORDATA (R15, REGFILE[5][1], 16) }, - { ORDATA (KSP, STACKFILE[MD_KER], 16) }, - { ORDATA (SSP, STACKFILE[MD_SUP], 16) }, - { ORDATA (USP, STACKFILE[MD_USR], 16) }, - { ORDATA (PSW, PSW, 16) }, - { GRDATA (CM, PSW, 8, 2, PSW_V_CM) }, - { GRDATA (PM, PSW, 8, 2, PSW_V_PM) }, - { FLDATA (RS, PSW, PSW_V_RS) }, - { GRDATA (IPL, PSW, 8, 3, PSW_V_IPL) }, - { FLDATA (T, PSW, PSW_V_TBIT) }, - { FLDATA (N, PSW, PSW_V_N) }, - { FLDATA (Z, PSW, PSW_V_Z) }, - { FLDATA (V, PSW, PSW_V_V) }, - { FLDATA (C, PSW, PSW_V_C) }, - { ORDATA (SR, SR, 16) }, - { ORDATA (DR, DR, 16) }, - { ORDATA (MEMERR, MEMERR, 16) }, - { ORDATA (CCR, CCR, 16) }, - { ORDATA (MAINT, MAINT, 16) }, - { ORDATA (HITMISS, HITMISS, 16) }, - { ORDATA (CPUERR, CPUERR, 16) }, - { BRDATA (IREQ, int_req, 8, 32, IPL_HLVL), REG_RO }, - { ORDATA (TRAPS, trap_req, TRAP_V_MAX) }, - { ORDATA (PIRQ, PIRQ, 16) }, - { FLDATA (WAIT, wait_state, 0) }, - { FLDATA (WAIT_ENABLE, wait_enable, 0) }, - { ORDATA (STOP_TRAPS, stop_trap, TRAP_V_MAX) }, - { FLDATA (STOP_VECA, stop_vecabort, 0) }, - { FLDATA (STOP_SPA, stop_spabort, 0) }, - { HRDATA (DBGLOG, cpu_log, 16), REG_HIDDEN }, - { ORDATA (FAC0H, FR[0].h, 32) }, - { ORDATA (FAC0L, FR[0].l, 32) }, - { ORDATA (FAC1H, FR[1].h, 32) }, - { ORDATA (FAC1L, FR[1].l, 32) }, - { ORDATA (FAC2H, FR[2].h, 32) }, - { ORDATA (FAC2L, FR[2].l, 32) }, - { ORDATA (FAC3H, FR[3].h, 32) }, - { ORDATA (FAC3L, FR[3].l, 32) }, - { ORDATA (FAC4H, FR[4].h, 32) }, - { ORDATA (FAC4L, FR[4].l, 32) }, - { ORDATA (FAC5H, FR[5].h, 32) }, - { ORDATA (FAC5L, FR[5].l, 32) }, - { ORDATA (FPS, FPS, 16) }, - { ORDATA (FEA, FEA, 16) }, - { ORDATA (FEC, FEC, 4) }, - { ORDATA (MMR0, MMR0, 16) }, - { ORDATA (MMR1, MMR1, 16) }, - { ORDATA (MMR2, MMR2, 16) }, - { ORDATA (MMR3, MMR3, 16) }, - { GRDATA (KIPAR0, APRFILE[000], 8, 16, 16) }, - { GRDATA (KIPDR0, APRFILE[000], 8, 16, 0) }, - { GRDATA (KIPAR1, APRFILE[001], 8, 16, 16) }, - { GRDATA (KIPDR1, APRFILE[001], 8, 16, 0) }, - { GRDATA (KIPAR2, APRFILE[002], 8, 16, 16) }, - { GRDATA (KIPDR2, APRFILE[002], 8, 16, 0) }, - { GRDATA (KIPAR3, APRFILE[003], 8, 16, 16) }, - { GRDATA (KIPDR3, APRFILE[003], 8, 16, 0) }, - { GRDATA (KIPAR4, APRFILE[004], 8, 16, 16) }, - { GRDATA (KIPDR4, APRFILE[004], 8, 16, 0) }, - { GRDATA (KIPAR5, APRFILE[005], 8, 16, 16) }, - { GRDATA (KIPDR5, APRFILE[005], 8, 16, 0) }, - { GRDATA (KIPAR6, APRFILE[006], 8, 16, 16) }, - { GRDATA (KIPDR6, APRFILE[006], 8, 16, 0) }, - { GRDATA (KIPAR7, APRFILE[007], 8, 16, 16) }, - { GRDATA (KIPDR7, APRFILE[007], 8, 16, 0) }, - { GRDATA (KDPAR0, APRFILE[010], 8, 16, 16) }, - { GRDATA (KDPDR0, APRFILE[010], 8, 16, 0) }, - { GRDATA (KDPAR1, APRFILE[011], 8, 16, 16) }, - { GRDATA (KDPDR1, APRFILE[011], 8, 16, 0) }, - { GRDATA (KDPAR2, APRFILE[012], 8, 16, 16) }, - { GRDATA (KDPDR2, APRFILE[012], 8, 16, 0) }, - { GRDATA (KDPAR3, APRFILE[013], 8, 16, 16) }, - { GRDATA (KDPDR3, APRFILE[013], 8, 16, 0) }, - { GRDATA (KDPAR4, APRFILE[014], 8, 16, 16) }, - { GRDATA (KDPDR4, APRFILE[014], 8, 16, 0) }, - { GRDATA (KDPAR5, APRFILE[015], 8, 16, 16) }, - { GRDATA (KDPDR5, APRFILE[015], 8, 16, 0) }, - { GRDATA (KDPAR6, APRFILE[016], 8, 16, 16) }, - { GRDATA (KDPDR6, APRFILE[016], 8, 16, 0) }, - { GRDATA (KDPAR7, APRFILE[017], 8, 16, 16) }, - { GRDATA (KDPDR7, APRFILE[017], 8, 16, 0) }, - { GRDATA (SIPAR0, APRFILE[020], 8, 16, 16) }, - { GRDATA (SIPDR0, APRFILE[020], 8, 16, 0) }, - { GRDATA (SIPAR1, APRFILE[021], 8, 16, 16) }, - { GRDATA (SIPDR1, APRFILE[021], 8, 16, 0) }, - { GRDATA (SIPAR2, APRFILE[022], 8, 16, 16) }, - { GRDATA (SIPDR2, APRFILE[022], 8, 16, 0) }, - { GRDATA (SIPAR3, APRFILE[023], 8, 16, 16) }, - { GRDATA (SIPDR3, APRFILE[023], 8, 16, 0) }, - { GRDATA (SIPAR4, APRFILE[024], 8, 16, 16) }, - { GRDATA (SIPDR4, APRFILE[024], 8, 16, 0) }, - { GRDATA (SIPAR5, APRFILE[025], 8, 16, 16) }, - { GRDATA (SIPDR5, APRFILE[025], 8, 16, 0) }, - { GRDATA (SIPAR6, APRFILE[026], 8, 16, 16) }, - { GRDATA (SIPDR6, APRFILE[026], 8, 16, 0) }, - { GRDATA (SIPAR7, APRFILE[027], 8, 16, 16) }, - { GRDATA (SIPDR7, APRFILE[027], 8, 16, 0) }, - { GRDATA (SDPAR0, APRFILE[030], 8, 16, 16) }, - { GRDATA (SDPDR0, APRFILE[030], 8, 16, 0) }, - { GRDATA (SDPAR1, APRFILE[031], 8, 16, 16) }, - { GRDATA (SDPDR1, APRFILE[031], 8, 16, 0) }, - { GRDATA (SDPAR2, APRFILE[032], 8, 16, 16) }, - { GRDATA (SDPDR2, APRFILE[032], 8, 16, 0) }, - { GRDATA (SDPAR3, APRFILE[033], 8, 16, 16) }, - { GRDATA (SDPDR3, APRFILE[033], 8, 16, 0) }, - { GRDATA (SDPAR4, APRFILE[034], 8, 16, 16) }, - { GRDATA (SDPDR4, APRFILE[034], 8, 16, 0) }, - { GRDATA (SDPAR5, APRFILE[035], 8, 16, 16) }, - { GRDATA (SDPDR5, APRFILE[035], 8, 16, 0) }, - { GRDATA (SDPAR6, APRFILE[036], 8, 16, 16) }, - { GRDATA (SDPDR6, APRFILE[036], 8, 16, 0) }, - { GRDATA (SDPAR7, APRFILE[037], 8, 16, 16) }, - { GRDATA (SDPDR7, APRFILE[037], 8, 16, 0) }, - { GRDATA (UIPAR0, APRFILE[060], 8, 16, 16) }, - { GRDATA (UIPDR0, APRFILE[060], 8, 16, 0) }, - { GRDATA (UIPAR1, APRFILE[061], 8, 16, 16) }, - { GRDATA (UIPDR1, APRFILE[061], 8, 16, 0) }, - { GRDATA (UIPAR2, APRFILE[062], 8, 16, 16) }, - { GRDATA (UIPDR2, APRFILE[062], 8, 16, 0) }, - { GRDATA (UIPAR3, APRFILE[063], 8, 16, 16) }, - { GRDATA (UIPDR3, APRFILE[063], 8, 16, 0) }, - { GRDATA (UIPAR4, APRFILE[064], 8, 16, 16) }, - { GRDATA (UIPDR4, APRFILE[064], 8, 16, 0) }, - { GRDATA (UIPAR5, APRFILE[065], 8, 16, 16) }, - { GRDATA (UIPDR5, APRFILE[065], 8, 16, 0) }, - { GRDATA (UIPAR6, APRFILE[066], 8, 16, 16) }, - { GRDATA (UIPDR6, APRFILE[066], 8, 16, 0) }, - { GRDATA (UIPAR7, APRFILE[067], 8, 16, 16) }, - { GRDATA (UIPDR7, APRFILE[067], 8, 16, 0) }, - { GRDATA (UDPAR0, APRFILE[070], 8, 16, 16) }, - { GRDATA (UDPDR0, APRFILE[070], 8, 16, 0) }, - { GRDATA (UDPAR1, APRFILE[071], 8, 16, 16) }, - { GRDATA (UDPDR1, APRFILE[071], 8, 16, 0) }, - { GRDATA (UDPAR2, APRFILE[072], 8, 16, 16) }, - { GRDATA (UDPDR2, APRFILE[072], 8, 16, 0) }, - { GRDATA (UDPAR3, APRFILE[073], 8, 16, 16) }, - { GRDATA (UDPDR3, APRFILE[073], 8, 16, 0) }, - { GRDATA (UDPAR4, APRFILE[074], 8, 16, 16) }, - { GRDATA (UDPDR4, APRFILE[074], 8, 16, 0) }, - { GRDATA (UDPAR5, APRFILE[075], 8, 16, 16) }, - { GRDATA (UDPDR5, APRFILE[075], 8, 16, 0) }, - { GRDATA (UDPAR6, APRFILE[076], 8, 16, 16) }, - { GRDATA (UDPDR6, APRFILE[076], 8, 16, 0) }, - { GRDATA (UDPAR7, APRFILE[077], 8, 16, 16) }, - { GRDATA (UDPDR7, APRFILE[077], 8, 16, 0) }, - { BRDATA (UBMAP, ub_map, 8, 22, UBM_LNT_LW) }, - { BRDATA (PCQ, pcq, 8, 16, PCQ_SIZE), REG_RO+REG_CIRC }, - { ORDATA (PCQP, pcq_p, 6), REG_HRO }, - { ORDATA (WRU, sim_int_char, 8) }, - { ORDATA (DEVENB, dev_enb, 32), REG_HRO }, - { NULL} }; - -MTAB cpu_mod[] = { - { UNIT_MAP, UNIT_18B, "18b addressing", "18B", NULL }, - { UNIT_MAP, UNIT_UBM, "22b Unibus + RH70", "URH70", &cpu_set_bus }, - { UNIT_MAP, UNIT_UBM + UNIT_RH11, "22b Unibus + RH11", "URH11", &cpu_set_bus }, - { UNIT_MAP, 0, "22b addressing", "22B", &cpu_set_bus }, - { UNIT_CIS, UNIT_CIS, "CIS", "CIS", NULL }, - { UNIT_CIS, 0, "no CIS", "NOCIS", NULL }, - { 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}, - { UNIT_MSIZE, 98304, NULL, "96K", &cpu_set_size}, - { UNIT_MSIZE, 131072, NULL, "128K", &cpu_set_size}, - { UNIT_MSIZE, 196608, NULL, "192K", &cpu_set_size}, - { UNIT_MSIZE, 262144, NULL, "256K", &cpu_set_size}, - { UNIT_MSIZE, 393216, NULL, "384K", &cpu_set_size}, - { UNIT_MSIZE, 524288, NULL, "512K", &cpu_set_size}, - { UNIT_MSIZE, 786432, NULL, "768K", &cpu_set_size}, - { UNIT_MSIZE, 1048576, NULL, "1024K", &cpu_set_size}, - { UNIT_MSIZE, 2097152, NULL, "2048K", &cpu_set_size}, - { UNIT_MSIZE, 3145728, NULL, "3072K", &cpu_set_size}, - { UNIT_MSIZE, 4186112, NULL, "4096K", &cpu_set_size}, - { UNIT_MSIZE, 1048576, NULL, "1M", &cpu_set_size}, - { UNIT_MSIZE, 2097152, NULL, "2M", &cpu_set_size}, - { UNIT_MSIZE, 3145728, NULL, "3M", &cpu_set_size}, - { UNIT_MSIZE, 4186112, NULL, "4M", &cpu_set_size}, - { MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, "IOSPACE", NULL, - NULL, &show_iospace }, - { 0 } }; - -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, DEV_DYNM, &cpu_set_size }; - -t_stat sim_instr (void) -{ -int abortval, i; -volatile int32 trapea; /* used by setjmp */ -t_stat reason; -void fp11 (int32 IR); -void cis11 (int32 IR); - -/* Restore register state - - 1. PSW components - 2. Active register file based on PSW - 3. Active stack pointer based on PSW - 4. Memory management control flags - 5. Interrupt system -*/ - -cpu_18b = cpu_unit.flags & UNIT_18B; /* export cnf flgs */ -cpu_ubm = cpu_unit.flags & UNIT_UBM; -cpu_rh11 = cpu_unit.flags & UNIT_RH11; -cpu_bme = (MMR3 & MMR3_BME) && cpu_ubm; -reason = build_dib_tab (cpu_ubm); /* build, chk dib_tab */ -if (reason != SCPE_OK) return reason; -cm = (PSW >> PSW_V_CM) & 03; /* call calc_is,ds */ -pm = (PSW >> PSW_V_PM) & 03; -rs = (PSW >> PSW_V_RS) & 01; -ipl = (PSW >> PSW_V_IPL) & 07; /* call calc_ints */ -tbit = (PSW >> PSW_V_TBIT) & 01; -N = (PSW >> PSW_V_N) & 01; -Z = (PSW >> PSW_V_Z) & 01; -V = (PSW >> PSW_V_V) & 01; -C = (PSW >> PSW_V_C) & 01; - -for (i = 0; i < 6; i++) R[i] = REGFILE[i][rs]; -SP = STACKFILE[cm]; -PC = saved_PC; - -isenable = calc_is (cm); -dsenable = calc_ds (cm); - -CPU_wr (PIRQ, 017777772, WRITE); /* rewrite PIRQ */ -trap_req = calc_ints (ipl, trap_req); /* upd int req */ -trapea = 0; -reason = 0; -sim_rtcn_init (clk_unit.wait, TMR_CLK); /* init line clock */ -sim_rtcn_init (pclk_unit.wait, TMR_PCLK); /* init prog clock */ - -/* Abort handling - - If an abort occurs in memory management or memory access, the lower - level routine executes a longjmp to this area OUTSIDE the main - simulation loop. The longjmp specifies a trap mask which is OR'd - into the trap_req register. Simulation then resumes at the fetch - phase, and the trap is sprung. - - Aborts which occur within a trap sequence (trapea != 0) require - special handling. If the abort occured on the stack pushes, and - the mode (encoded in trapea) is kernel, an "emergency" kernel - stack is created at 4, and a red zone stack trap taken. - - All variables used in setjmp processing, or assumed to be valid - after setjmp, must be volatile or global. -*/ - -abortval = setjmp (save_env); /* set abort hdlr */ -if (abortval != 0) { - trap_req = trap_req | abortval; /* or in trap flag */ - if ((trapea > 0) && (stop_vecabort)) reason = STOP_VECABORT; - if ((trapea < 0) && (stop_spabort)) reason = STOP_SPABORT; - if (trapea == ~MD_KER) { /* kernel stk abort? */ - setTRAP (TRAP_RED); - setCPUERR (CPUE_RED); - STACKFILE[MD_KER] = 4; - if (cm == MD_KER) SP = 4; } } - -/* Main instruction fetch/decode loop - - Check for traps or interrupts. If trap, locate the vector and check - for stop condition. If interrupt, locate the vector. -*/ - -while (reason == 0) { - -int32 IR, srcspec, srcreg, dstspec, dstreg; -int32 src, src2, dst, ea; -int32 i, t, sign, oldrs, trapnum; - -if (cpu_astop) { - cpu_astop = 0; - reason = SCPE_STOP; - break; } - -if (sim_interval <= 0) { /* intv cnt expired? */ - reason = sim_process_event (); /* process events */ - trap_req = calc_ints (ipl, trap_req); /* recalc int req */ - continue; - } /* end if sim_interval */ - -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*/ - if (trapea == 0) { /* nothing to do? */ - trap_req = calc_ints (ipl, 0); /* recalculate */ - continue; /* back to fetch */ - } /* end if trapea */ - -/* Process a trap or interrupt - - 1. Exit wait state - 2. Save the current SP and PSW - 3. Read the new PC, new PSW from trapea, kernel data space - 4. Get the mode and stack selected by the new PSW - 5. Push the old PC and PSW on the new stack - 6. Update SP, PSW, and PC - 7. If not stack overflow, check for stack overflow -*/ - - wait_state = 0; /* exit wait state */ - STACKFILE[cm] = SP; - PSW = (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); - oldrs = rs; - src = ReadW (trapea | calc_ds (MD_KER)); - src2 = ReadW ((trapea + 2) | calc_ds (MD_KER)); - t = (src2 >> PSW_V_CM) & 03; - trapea = ~t; /* flag pushes */ - WriteW (PSW, ((STACKFILE[t] - 2) & 0177777) | calc_ds (t)); - WriteW (PC, ((STACKFILE[t] - 4) & 0177777) | calc_ds (t)); - trapea = 0; /* clear trap flag */ - pm = cm; - cm = t; /* call calc_is,ds */ - rs = (src2 >> PSW_V_RS) & 01; - ipl = (src2 >> PSW_V_IPL) & 07; /* call calc_ints */ - 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; - if (rs != oldrs) { /* if rs chg, swap */ - 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); - dsenable = calc_ds (cm); - trap_req = calc_ints (ipl, trap_req); - if ((SP < STKLIM) && (cm == MD_KER) && - (trapnum != TRAP_V_RED) && (trapnum != TRAP_V_YEL)) { - setTRAP (TRAP_YEL); - setCPUERR (CPUE_YEL); } - continue; } /* end if traps */ - -/* Fetch and decode next instruction */ - -if (tbit) setTRAP (TRAP_TRC); -if (wait_state) { /* wait state? */ - if (sim_clock_queue != NULL) sim_interval = 0; /* force check */ - else reason = STOP_WAIT; - continue; } - -if (sim_brk_summ && sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */ - reason = STOP_IBKPT; /* stop simulation */ - continue; } - -if (update_MM) { /* if mm not frozen */ - MMR1 = 0; - MMR2 = PC; } -IR = ReadW (PC | isenable); /* fetch instruction */ -PC = (PC + 2) & 0177777; /* incr PC, mod 65k */ -sim_interval = sim_interval - 1; -srcspec = (IR >> 6) & 077; /* src, dst specs */ -dstspec = IR & 077; -srcreg = (srcspec <= 07); /* src, dst = rmode? */ -dstreg = (dstspec <= 07); -switch ((IR >> 12) & 017) { /* decode IR<15:12> */ - -/* Opcode 0: no operands, specials, branches, JSR, SOPs */ - -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 == MD_KER) && ((MAINT & MAINT_HTRAP) == 0)) - reason = STOP_HALT; - else { - setTRAP (TRAP_PRV); - setCPUERR (CPUE_HALT); } - break; - case 1: /* WAIT */ - if ((cm == MD_KER) && 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 == MD_KER) { - 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 == MD_KER) { - 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 */ - 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 == MD_KER) 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 */ - -/* Opcode 0: branches, JSR */ - - case 004: case 005: /* BR */ - BRANCH_F (IR); - break; - case 006: case 007: /* BR */ - BRANCH_B (IR); - break; - case 010: case 011: /* BNE */ - if (Z == 0) { BRANCH_F (IR); } - break; - case 012: case 013: /* BNE */ - if (Z == 0) { BRANCH_B (IR); } - break; - case 014: case 015: /* BEQ */ - if (Z) { BRANCH_F (IR); } - break; - case 016: case 017: /* BEQ */ - if (Z) { BRANCH_B (IR); } - break; - case 020: case 021: /* BGE */ - if ((N ^ V) == 0) { BRANCH_F (IR); } - break; - case 022: case 023: /* BGE */ - if ((N ^ V) == 0) { BRANCH_B (IR); } - break; - case 024: case 025: /* BLT */ - if (N ^ V) { BRANCH_F (IR); } - break; - case 026: case 027: /* BLT */ - if (N ^ V) { BRANCH_B (IR); } - break; - case 030: case 031: /* BGT */ - if ((Z | (N ^ V)) == 0) { BRANCH_F (IR); } - break; - case 032: case 033: /* BGT */ - if ((Z | (N ^ V)) == 0) { BRANCH_B (IR); } - break; - case 034: case 035: /* BLE */ - if (Z | (N ^ V)) { BRANCH_F (IR); } - break; - case 036: case 037: /* BLE */ - 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 == MD_KER)) { - 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; - 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; - 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; - 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; - 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; - 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; - -/* 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; - case 057: /* TST */ - 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; - 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; - 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; - 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; - -/* Opcode 0: SOPS, continued - - Notes: - - MxPI must mask GeteaW returned address to force ispace - - MxPI must set MMR1 for SP recovery in case of fault -*/ - - case 064: /* MARK */ - 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 == MD_USR))? 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 == MD_KER) && (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; - case 067: /* SXT */ - 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 == MD_KER)) - 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 (MD_SUP)); - WriteW (PC, ((SP - 4) & 0177777) | calc_ds (MD_SUP)); - WriteW (dst, ((SP - 6) & 0177777) | calc_ds (MD_SUP)); - SP = (SP - 6) & 0177777; - pm = cm; - cm = MD_SUP; - 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; - 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)); } - break; - default: - setTRAP (TRAP_ILL); - break; } /* end switch SOPs */ - break; /* end case 000 */ - -/* Opcodes 01 - 06: double operand word instructions - - J-11 (and F-11) optimize away register source operand decoding. - As a result, dop R,+/-(R) use the modified version of R as source. - Most (but not all) other PDP-11's fetch the source operand before - any destination operand decoding. - - Add: v = [sign (src) = sign (src2)] and [sign (src) != sign (result)] - Cmp: v = [sign (src) != sign (src2)] and [sign (src2) = sign (result)] -*/ - -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); } - N = GET_SIGN_W (dst); - Z = GET_Z (dst); - V = 0; - if (dstreg) R[dstspec] = dst; - else WriteW (dst, ea); - 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)); } - dst = (src - src2) & 0177777; - N = GET_SIGN_W (dst); - Z = GET_Z (dst); - V = GET_SIGN_W ((src ^ src2) & (~src2 ^ dst)); - C = (src < src2); - 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)); } - dst = src2 & src; - N = GET_SIGN_W (dst); - Z = GET_Z (dst); - V = 0; - 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)); } - dst = src2 & ~src; - N = GET_SIGN_W (dst); - Z = GET_Z (dst); - V = 0; - if (dstreg) R[dstspec] = dst; - else PWriteW (dst, last_pa); - 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)); } - dst = src2 | src; - N = GET_SIGN_W (dst); - Z = GET_Z (dst); - V = 0; - if (dstreg) R[dstspec] = dst; - else PWriteW (dst, last_pa); - 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)); } - dst = (src2 + src) & 0177777; - N = GET_SIGN_W (dst); - Z = GET_Z (dst); - V = GET_SIGN_W ((~src ^ src2) & (src ^ dst)); - C = (dst < src); - if (dstreg) R[dstspec] = dst; - else PWriteW (dst, last_pa); - break; - -/* Opcode 07: EIS, FIS (not implemented), CIS - - Notes: - - The code assumes that the host int length is at least 32 bits. - - MUL carry: C is set if the (signed) result doesn't fit in 16 bits. - - Divide has three error cases: - 1. Divide by zero. - 2. Divide largest negative number by -1. - 3. (Signed) quotient doesn't fit in 16 bits. - Cases 1 and 2 must be tested in advance, to avoid C runtime errors. - - ASHx left: overflow if the bits shifted out do not equal the sign - of the result (convert shift out to 1/0, xor against sign). - - ASHx right: if right shift sign extends, then the shift and - conditional or of shifted -1 is redundant. If right shift zero - extends, then the shift and conditional or does sign extension. -*/ - -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; - 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; - -/* 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; - 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; - -/* 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; - case 5: /* FIS - not impl */ - setTRAP (TRAP_ILL); - break; - case 6: /* CIS */ - 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 */ - break; /* end case 007 */ - -/* Opcode 10: branches, traps, SOPs */ - -case 010: - switch ((IR >> 6) & 077) { /* decode IR<11:6> */ - case 000: case 001: /* BPL */ - if (N == 0) { BRANCH_F (IR); } - break; - case 002: case 003: /* BPL */ - if (N == 0) { BRANCH_B (IR); } - break; - case 004: case 005: /* BMI */ - if (N) { BRANCH_F (IR); } - break; - case 006: case 007: /* BMI */ - if (N) { BRANCH_B (IR); } - break; - case 010: case 011: /* BHI */ - if ((C | Z) == 0) { BRANCH_F (IR); } - break; - case 012: case 013: /* BHI */ - if ((C | Z) == 0) { BRANCH_B (IR); } - break; - case 014: case 015: /* BLOS */ - if (C | Z) { BRANCH_F (IR); } - break; - case 016: case 017: /* BLOS */ - if (C | Z) { BRANCH_B (IR); } - break; - case 020: case 021: /* BVC */ - if (V == 0) { BRANCH_F (IR); } - break; - case 022: case 023: /* BVC */ - if (V == 0) { BRANCH_B (IR); } - break; - case 024: case 025: /* BVS */ - if (V) { BRANCH_F (IR); } - break; - case 026: case 027: /* BVS */ - if (V) { BRANCH_B (IR); } - break; - case 030: case 031: /* BCC */ - if (C == 0) { BRANCH_F (IR); } - break; - case 032: case 033: /* BCC */ - if (C == 0) { BRANCH_B (IR); } - break; - case 034: case 035: /* BCS */ - if (C) { BRANCH_F (IR); } - break; - case 036: case 037: /* BCS */ - if (C) { BRANCH_B (IR); } - break; - case 040: case 041: case 042: case 043: /* EMT */ - setTRAP (TRAP_EMT); - break; - case 044: case 045: case 046: case 047: /* TRAP */ - 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; - 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; - 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; - 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; - 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; - 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; - -/* 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; - case 057: /* TSTB */ - 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; - 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; - 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; - 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; - -/* Opcode 10: SOPs, continued - - Notes: - - MTPS cannot alter the T bit - - MxPD must mask GeteaW returned address, dspace is from cm not pm - - MxPD must set MMR1 for SP recovery in case of fault -*/ - - case 064: /* MTPS */ - dst = dstreg? R[dstspec]: ReadB (GeteaB (dstspec)); - if (cm == MD_KER) { - 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 == MD_KER) && (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; - 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; - default: - setTRAP (TRAP_ILL); - break; } /* end switch SOPs */ - break; /* end case 010 */ - -/* Opcodes 11 - 16: double operand byte instructions - - Cmp: v = [sign (src) != sign (src2)] and [sign (src2) = sign (result)] - Sub: v = [sign (src) != sign (src2)] and [sign (src) = sign (result)] -*/ - -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); } - N = GET_SIGN_B (dst); - Z = GET_Z (dst); - V = 0; - if (dstreg) R[dstspec] = (dst & 0200)? 0177400 | dst: dst; - else WriteB (dst, ea); - 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)); } - dst = (src - src2) & 0377; - N = GET_SIGN_B (dst); - Z = GET_Z (dst); - V = GET_SIGN_B ((src ^ src2) & (~src2 ^ dst)); - C = (src < src2); - 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)); } - dst = (src2 & src) & 0377; - N = GET_SIGN_B (dst); - Z = GET_Z (dst); - V = 0; - 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)); } - dst = (src2 & ~src) & 0377; - N = GET_SIGN_B (dst); - Z = GET_Z (dst); - V = 0; - if (dstreg) R[dstspec] = (R[dstspec] & 0177400) | dst; - else PWriteB (dst, last_pa); - 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)); } - dst = (src2 | src) & 0377; - N = GET_SIGN_B (dst); - Z = GET_Z (dst); - V = 0; - if (dstreg) R[dstspec] = (R[dstspec] & 0177400) | dst; - else PWriteB (dst, last_pa); - 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)); } - dst = (src2 - src) & 0177777; - N = GET_SIGN_W (dst); - Z = GET_Z (dst); - V = GET_SIGN_W ((src ^ src2) & (~src ^ dst)); - C = (src2 < src); - if (dstreg) R[dstspec] = dst; - else PWriteW (dst, last_pa); - break; - -/* Opcode 17: floating point */ - -case 017: - fp11 (IR); /* floating point */ - break; /* end case 017 */ - } /* end switch op */ -} /* end main loop */ - -/* Simulation halted */ - -PSW = (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); -for (i = 0; i < 6; i++) REGFILE[i][rs] = R[i]; -STACKFILE[cm] = SP; -saved_PC = PC & 0177777; -pcq_r->qptr = pcq_p; /* update pc q ptr */ -set_r_display (rs, cm); -return reason; -} - -/* Effective address calculations - - Inputs: - spec = specifier <5:0> - Outputs: - ea = effective address - <15:0> = virtual address - <16> = instruction/data data space - <18:17> = mode - - Data space calculation: the PDP-11 features both instruction and data - spaces. Instruction space contains the instruction and any sequential - add ons (eg, immediates, absolute addresses). Data space contains all - data operands and indirect addresses. If data space is enabled, then - memory references are directed according to these rules: - - Mode Index ref Indirect ref Direct ref - 10..16 na na data - 17 na na instruction - 20..26 na na data - 27 na na instruction - 30..36 na data data - 37 na instruction (absolute) data - 40..46 na na data - 47 na na instruction - 50..56 na data data - 57 na instruction data - 60..67 instruction na data - 70..77 instruction data data - - According to the PDP-11 Architecture Handbook, MMR1 records all - autoincrement and autodecrement operations, including those which - explicitly reference the PC. For the J-11, this is only true for - autodecrement operands, autodecrement deferred operands, and - autoincrement destination operands that involve a write to memory. - The simulator follows the Handbook, for simplicity. - - Notes: - - - dsenable will direct a reference to data space if data space is enabled - - ds will direct a reference to data space if data space is enabled AND if - the specifier register is not PC; this is used for 17, 27, 37, 47, 57 - - Modes 2x, 3x, 4x, and 5x must update MMR1 if updating enabled - - Modes 46 and 56 must check for stack overflow if kernel mode -*/ - -/* Effective address calculation for words */ - -int32 GeteaW (int32 spec) -{ -int32 adr, reg, ds; - -reg = spec & 07; /* register number */ -ds = (reg == 7)? isenable: dsenable; /* dspace if not PC */ -switch (spec >> 3) { /* decode spec<5:3> */ -default: /* can't get here */ -case 1: /* (R) */ - return (R[reg] | ds); -case 2: /* (R)+ */ - R[reg] = ((adr = R[reg]) + 2) & 0177777; - if (update_MM) MMR1 = calc_MMR1 (020 | reg); - return (adr | ds); -case 3: /* @(R)+ */ - R[reg] = ((adr = R[reg]) + 2) & 0177777; - if (update_MM) MMR1 = calc_MMR1 (020 | reg); - adr = ReadW (adr | ds); - return (adr | dsenable); -case 4: /* -(R) */ - adr = R[reg] = (R[reg] - 2) & 0177777; - if (update_MM) MMR1 = calc_MMR1 (0360 | reg); - if ((adr < STKLIM) && (reg == 6) && (cm == MD_KER)) { - 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 == MD_KER)) { - setTRAP (TRAP_YEL); - setCPUERR (CPUE_YEL); } - adr = ReadW (adr | ds); - return (adr | dsenable); -case 6: /* d(r) */ - adr = ReadW (PC | isenable); - PC = (PC + 2) & 0177777; - return (((R[reg] + adr) & 0177777) | dsenable); -case 7: /* @d(R) */ - adr = ReadW (PC | isenable); - PC = (PC + 2) & 0177777; - adr = ReadW (((R[reg] + adr) & 0177777) | dsenable); - return (adr | dsenable); - } /* end switch */ -} - -/* Effective address calculation for bytes */ - -int32 GeteaB (int32 spec) -{ -int32 adr, reg, ds, delta; - -reg = spec & 07; /* reg number */ -ds = (reg == 7)? isenable: dsenable; /* dspace if not PC */ -switch (spec >> 3) { /* decode spec<5:3> */ -default: /* can't get here */ -case 1: /* (R) */ - return (R[reg] | ds); -case 2: /* (R)+ */ - delta = 1 + (reg >= 6); /* 2 if R6, PC */ - R[reg] = ((adr = R[reg]) + delta) & 0177777; - if (update_MM) MMR1 = calc_MMR1 ((delta << 3) | reg); - return (adr | ds); -case 3: /* @(R)+ */ - R[reg] = ((adr = R[reg]) + 2) & 0177777; - if (update_MM) MMR1 = calc_MMR1 (020 | reg); - adr = ReadW (adr | ds); - return (adr | dsenable); -case 4: /* -(R) */ - delta = 1 + (reg >= 6); /* 2 if R6, PC */ - adr = R[reg] = (R[reg] - delta) & 0177777; - if (update_MM) MMR1 = calc_MMR1 ((((-delta) & 037) << 3) | reg); - if ((adr < STKLIM) && (reg == 6) && (cm == MD_KER)) { - 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 == MD_KER)) { - setTRAP (TRAP_YEL); - setCPUERR (CPUE_YEL); } - adr = ReadW (adr | ds); - return (adr | dsenable); -case 6: /* d(r) */ - adr = ReadW (PC | isenable); - PC = (PC + 2) & 0177777; - return (((R[reg] + adr) & 0177777) | dsenable); -case 7: /* @d(R) */ - adr = ReadW (PC | isenable); - PC = (PC + 2) & 0177777; - adr = ReadW (((R[reg] + adr) & 0177777) | dsenable); - return (adr | dsenable); - } /* end switch */ -} - -/* Read byte and word routines, read only and read-modify-write versions - - Inputs: - va = virtual address, <18:16> = mode, I/D space - Outputs: - data = data read from memory or I/O space -*/ - -int32 ReadW (int32 va) -{ -int32 pa, data; - -if (va & 1) { /* odd address? */ - setCPUERR (CPUE_ODD); - ABORT (TRAP_ODD); } -pa = relocR (va); /* relocate */ -if (ADDR_IS_MEM (pa)) return (M[pa >> 1]); /* memory address? */ -if (pa < IOPAGEBASE) { /* I/O address? */ - setCPUERR (CPUE_NXM); - ABORT (TRAP_NXM); } -if (iopageR (&data, pa, READ) != SCPE_OK) { /* invalid I/O addr? */ - setCPUERR (CPUE_TMO); - ABORT (TRAP_NXM); } -return data; -} - -int32 ReadB (int32 va) -{ -int32 pa, data; - -pa = relocR (va); /* relocate */ -if (ADDR_IS_MEM (pa)) return (va & 1? M[pa >> 1] >> 8: M[pa >> 1]) & 0377; -if (pa < IOPAGEBASE) { /* I/O address? */ - setCPUERR (CPUE_NXM); - ABORT (TRAP_NXM); } -if (iopageR (&data, pa, READ) != SCPE_OK) { /* invalid I/O addr? */ - setCPUERR (CPUE_TMO); - ABORT (TRAP_NXM); } -return ((va & 1)? data >> 8: data) & 0377; -} - -int32 ReadMW (int32 va) -{ -int32 data; - -if (va & 1) { /* odd address? */ - setCPUERR (CPUE_ODD); - ABORT (TRAP_ODD); } -last_pa = relocW (va); /* reloc, wrt chk */ -if (ADDR_IS_MEM (last_pa)) return (M[last_pa >> 1]); /* memory address? */ -if (last_pa < IOPAGEBASE) { /* I/O address? */ - setCPUERR (CPUE_NXM); - ABORT (TRAP_NXM); } -if (iopageR (&data, last_pa, READ) != SCPE_OK) { /* invalid I/O addr? */ - setCPUERR (CPUE_TMO); - ABORT (TRAP_NXM); } -return data; -} - -int32 ReadMB (int32 va) -{ -int32 data; - -last_pa = relocW (va); /* reloc, wrt chk */ -if (ADDR_IS_MEM (last_pa)) - return (va & 1? M[last_pa >> 1] >> 8: M[last_pa >> 1]) & 0377; -if (last_pa < IOPAGEBASE) { /* I/O address? */ - setCPUERR (CPUE_NXM); - ABORT (TRAP_NXM); } -if (iopageR (&data, last_pa, READ) != SCPE_OK) { /* invalid I/O addr? */ - setCPUERR (CPUE_TMO); - ABORT (TRAP_NXM); } -return ((va & 1)? data >> 8: data) & 0377; -} - -/* Write byte and word routines - - Inputs: - data = data to be written - va = virtual address, <18:16> = mode, I/D space, or - pa = physical address - Outputs: none -*/ - -void WriteW (int32 data, int32 va) -{ -int32 pa; - -if (va & 1) { /* odd address? */ - setCPUERR (CPUE_ODD); - ABORT (TRAP_ODD); } -pa = relocW (va); /* relocate */ -if (ADDR_IS_MEM (pa)) { /* memory address? */ - M[pa >> 1] = data; - return; } -if (pa < IOPAGEBASE) { /* I/O address? */ - setCPUERR (CPUE_NXM); - ABORT (TRAP_NXM); } -if (iopageW (data, pa, WRITE) != SCPE_OK) { /* invalid I/O addr? */ - setCPUERR (CPUE_TMO); - ABORT (TRAP_NXM); } -return; -} - -void WriteB (int32 data, int32 va) -{ -int32 pa; - -pa = relocW (va); /* relocate */ -if (ADDR_IS_MEM (pa)) { /* memory address? */ - if (va & 1) M[pa >> 1] = (M[pa >> 1] & 0377) | (data << 8); - else M[pa >> 1] = (M[pa >> 1] & ~0377) | data; - return; } -if (pa < IOPAGEBASE) { /* I/O address? */ - setCPUERR (CPUE_NXM); - ABORT (TRAP_NXM); } -if (iopageW (data, pa, WRITEB) != SCPE_OK) { /* invalid I/O addr? */ - setCPUERR (CPUE_TMO); - ABORT (TRAP_NXM); } -return; -} - -void PWriteW (int32 data, int32 pa) -{ -if (ADDR_IS_MEM (pa)) { /* memory address? */ - M[pa >> 1] = data; - return; } -if (pa < IOPAGEBASE) { /* I/O address? */ - setCPUERR (CPUE_NXM); - ABORT (TRAP_NXM); } -if (iopageW (data, pa, WRITE) != SCPE_OK) { /* invalid I/O addr? */ - setCPUERR (CPUE_TMO); - ABORT (TRAP_NXM); } -return; -} - -void PWriteB (int32 data, int32 pa) -{ -if (ADDR_IS_MEM (pa)) { /* memory address? */ - if (pa & 1) M[pa >> 1] = (M[pa >> 1] & 0377) | (data << 8); - else M[pa >> 1] = (M[pa >> 1] & ~0377) | data; - return; } -if (pa < IOPAGEBASE) { /* I/O address? */ - setCPUERR (CPUE_NXM); - ABORT (TRAP_NXM); } -if (iopageW (data, pa, WRITEB) != SCPE_OK) { /* invalid I/O addr? */ - setCPUERR (CPUE_TMO); - ABORT (TRAP_NXM); } -return; -} - -/* Relocate virtual address, read access - - Inputs: - va = virtual address, <18:16> = mode, I/D space - Outputs: - pa = physical address - On aborts, this routine aborts back to the top level simulator - with an appropriate trap code. - - Notes: - - APRFILE[UNUSED] is all zeroes, forcing non-resident abort - - Aborts must update MMR0<15:13,6:1> if updating is enabled -*/ - -int32 relocR (int32 va) -{ -int32 dbn, plf, apridx, apr, pa; - -if (MMR0 & MMR0_MME) { /* if mmgt */ - apridx = (va >> VA_V_APF) & 077; /* index into APR */ - apr = APRFILE[apridx]; /* with va<18:13> */ - 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 ((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 */ - pa = ((va & VA_DF) + ((apr >> 10) & 017777700)) & PAMASK; - if ((MMR3 & MMR3_M22E) == 0) { - pa = pa & 0777777; - if (pa >= 0760000) pa = 017000000 | pa; } } -else { pa = va & 0177777; /* mmgt off */ - if (pa >= 0160000) pa = 017600000 | pa; } -return pa; -} - -/* Relocate virtual address, write access - - Inputs: - va = virtual address, <18:16> = mode, I/D space - Outputs: - pa = physical address - On aborts, this routine aborts back to the top level simulator - with an appropriate trap code. - - Notes: - - APRFILE[UNUSED] is all zeroes, forcing non-resident abort - - Aborts must update MMR0<15:13,6:1> if updating is enabled -*/ - -int32 relocW (int32 va) -{ -int32 dbn, plf, apridx, apr, pa; - -if (MMR0 & MMR0_MME) { /* if mmgt */ - apridx = (va >> VA_V_APF) & 077; /* index into APR */ - apr = APRFILE[apridx]; /* with va<18:13> */ - 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 ((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 ((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 */ - 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; } } -else { pa = va & 0177777; /* mmgt off */ - if (pa >= 0160000) pa = 017600000 | pa; } -return pa; -} - -/* Relocate virtual address, console access - - Inputs: - va = virtual address - sw = switches - Outputs: - pa = physical address - On aborts, this routine returns MAXMEMSIZE -*/ - -int32 relocC (int32 va, int32 sw) -{ -int32 mode, dbn, plf, apridx, apr, pa; - -if (MMR0 & MMR0_MME) { /* if mmgt */ - if (sw & SWMASK ('K')) mode = MD_KER; - else if (sw & SWMASK ('S')) mode = MD_SUP; - else if (sw & SWMASK ('U')) mode = MD_USR; - else if (sw & SWMASK ('P')) mode = (PSW >> PSW_V_PM) & 03; - else mode = (PSW >> PSW_V_CM) & 03; - va = va | ((sw & SWMASK ('D'))? calc_ds (mode): calc_is (mode)); - apridx = (va >> VA_V_APF) & 077; /* index into APR */ - apr = APRFILE[apridx]; /* with va<18:13> */ - dbn = va & VA_BN; /* extr block num */ - plf = (apr & PDR_PLF) >> 2; /* extr page length */ - if ((apr & PDR_PRD) == 0) return MAXMEMSIZE; /* not readable? */ - 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; } } -else { pa = va & 0177777; /* mmgt off */ - if (pa >= 0160000) pa = 017600000 | pa; } -return pa; -} - -/* I/O page routines for CPU registers - - Switch register and memory management registers - - SR 17777570 read only - MMR0 17777572 read/write, certain bits unimplemented or read only - MMR1 17777574 read only - MMR2 17777576 read only - MMR3 17777516 read/write, certain bits unimplemented -*/ - -t_stat SR_MMR012_rd (int32 *data, int32 pa, int32 access) -{ -switch ((pa >> 1) & 3) { /* decode pa<2:1> */ -case 0: /* SR */ - *data = SR; - break; -case 1: /* MMR0 */ - *data = MMR0 & MMR0_IMP; - break; -case 2: /* MMR1 */ - *data = MMR1; - break; -case 3: /* MMR2 */ - *data = MMR2; - break; } /* end switch pa */ -return SCPE_OK; -} - -t_stat SR_MMR012_wr (int32 data, int32 pa, int32 access) -{ -switch ((pa >> 1) & 3) { /* decode pa<2:1> */ -case 0: /* DR */ - DR = data; - return SCPE_OK; -case 1: /* MMR0 */ - if (access == WRITEB) data = (pa & 1)? - (MMR0 & 0377) | (data << 8): (MMR0 & ~0377) | data; - MMR0 = (MMR0 & ~MMR0_RW) | (data & MMR0_RW); - return SCPE_OK; -default: /* MMR1, MMR2 */ - return SCPE_OK; } /* end switch pa */ -} - -t_stat MMR3_rd (int32 *data, int32 pa, int32 access) /* MMR3 */ -{ -*data = MMR3 & MMR3_IMP; -return SCPE_OK; -} - -t_stat MMR3_wr (int32 data, int32 pa, int32 access) /* MMR3 */ -{ -if (pa & 1) return SCPE_OK; -MMR3 = data & MMR3_RW; -if (cpu_unit.flags & UNIT_18B) - MMR3 = MMR3 & ~(MMR3_BME + MMR3_M22E); /* for UNIX V6 */ -cpu_bme = (MMR3 & MMR3_BME) && cpu_ubm; -dsenable = calc_ds (cm); -return SCPE_OK; -} - -/* PARs and PDRs. These are grouped in I/O space as follows: - - 17772200 - 17772276 supervisor block - 17772300 - 17772376 kernel block - 17777600 - 17777676 user block - - Within each block, the subblocks are I PDR's, D PDR's, I PAR's, D PAR's - - Thus, the algorithm for converting between I/O space addresses and - APRFILE indices is as follows: - - idx<3:0> = dspace'page = pa<4:1> - par = PDR vs PAR = pa<5> - idx<5:4> = ker/sup/user = pa<8>'~pa<6> - - Note that the W bit is read only; it is cleared by any write to an APR -*/ - -t_stat APR_rd (int32 *data, int32 pa, int32 access) -{ -t_stat left, idx; - -idx = (pa >> 1) & 017; /* dspace'page */ -left = (pa >> 5) & 1; /* PDR vs PAR */ -if ((pa & 0100) == 0) idx = idx | 020; /* 1 for super, user */ -if (pa & 0400) idx = idx | 040; /* 1 for user only */ -*data = left? (APRFILE[idx] >> 16) & 0177777: APRFILE[idx] & PDR_IMP; -return SCPE_OK; -} - -t_stat APR_wr (int32 data, int32 pa, int32 access) -{ -int32 left, idx, curr; - -idx = (pa >> 1) & 017; /* dspace'page */ -left = (pa >> 5) & 1; /* PDR vs PAR */ -if ((pa & 0100) == 0) idx = idx | 020; /* 1 for super, user */ -if (pa & 0400) idx = idx | 040; /* 1 for user only */ -curr = left? (APRFILE[idx] >> 16) & 0177777: APRFILE[idx] & PDR_IMP; -if (access == WRITEB) data = (pa & 1)? - (curr & 0377) | (data << 8): (curr & ~0377) | data; -if (left) APRFILE[idx] = - ((APRFILE[idx] & 0177777) | (((uint32) data) << 16)) & ~PDR_W; -else APRFILE[idx] = - ((APRFILE[idx] & ~PDR_RW) | (data & PDR_RW)) & ~PDR_W; -return SCPE_OK; -} - -/* CPU control registers - - MEMERR 17777744 read only, clear on write - CCR 17777746 read/write - MAINT 17777750 read only - HITMISS 17777752 read only - CPUERR 17777766 read only, clear on write - PIRQ 17777772 read/write, with side effects - PSW 17777776 read/write, with side effects -*/ - -t_stat CPU_rd (int32 *data, int32 pa, int32 access) -{ -switch ((pa >> 1) & 017) { /* decode pa<4:1> */ -case 2: /* MEMERR */ - *data = MEMERR; - return SCPE_OK; -case 3: /* CCR */ - *data = CCR; - return SCPE_OK; -case 4: /* MAINT */ - if (cpu_ubm) *data = MAINT | MAINT_U; - else *data = MAINT & ~MAINT_U; - return SCPE_OK; -case 5: /* Hit/miss */ - *data = HITMISS; - return SCPE_OK; -case 013: /* CPUERR */ - *data = CPUERR & CPUE_IMP; - return SCPE_OK; -case 015: /* PIRQ */ - *data = PIRQ; - return SCPE_OK; -case 017: /* PSW */ - if (access == READC) *data = PSW; - else *data = (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); - return SCPE_OK; } /* end switch PA */ -return SCPE_NXM; /* unimplemented */ -} - -/* CPU control registers, continued */ - -t_stat CPU_wr (int32 data, int32 pa, int32 access) -{ -int32 i, pl, curr, oldrs; - -switch ((pa >> 1) & 017) { /* decode pa<4:1> */ -case 2: /* MEMERR */ - MEMERR = 0; - return SCPE_OK; -case 3: /* CCR */ - if (access == WRITEB) data = (pa & 1)? - (CCR & 0377) | (data << 8): (CCR & ~0377) | data; - CCR = data; - return SCPE_OK; -case 4: /* MAINT */ - return SCPE_OK; -case 5: /* Hit/miss */ - return SCPE_OK; -case 013: /* CPUERR */ - CPUERR = 0; - return SCPE_OK; -case 015: /* PIRQ */ - if (access == WRITEB) { - if (pa & 1) data = data << 8; - else return SCPE_OK; } - PIRQ = data & PIRQ_RW; - pl = 0; - if (PIRQ & PIRQ_PIR1) { SET_INT (PIR1); pl = 0042; } - else CLR_INT (PIR1); - if (PIRQ & PIRQ_PIR2) { SET_INT (PIR2); pl = 0104; } - else CLR_INT (PIR2); - if (PIRQ & PIRQ_PIR3) { SET_INT (PIR3); pl = 0146; } - else CLR_INT (PIR3); - if (PIRQ & PIRQ_PIR4) { SET_INT (PIR4); pl = 0210; } - else CLR_INT (PIR4); - if (PIRQ & PIRQ_PIR5) { SET_INT (PIR5); pl = 0252; } - else CLR_INT (PIR5); - if (PIRQ & PIRQ_PIR6) { SET_INT (PIR6); pl = 0314; } - else CLR_INT (PIR6); - if (PIRQ & PIRQ_PIR7) { SET_INT (PIR7); pl = 0356; } - else CLR_INT (PIR7); - PIRQ = PIRQ | pl; - return SCPE_OK; - -/* CPU control registers, continued - - Note: Explicit writes to the PSW do not modify the T bit -*/ - -case 017: /* PSW */ - if (access == WRITEC) { /* console access? */ - 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 = (curr & ~PSW_RW) | (data & PSW_RW); - oldrs = rs; - cm = (curr >> PSW_V_CM) & 03; /* call calc_is,ds */ - pm = (curr >> PSW_V_PM) & 03; - rs = (curr >> PSW_V_RS) & 01; - ipl = (curr >> PSW_V_IPL) & 07; - N = (curr >> PSW_V_N) & 01; - Z = (curr >> PSW_V_Z) & 01; - 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]; } } - SP = STACKFILE[cm]; - isenable = calc_is (cm); - dsenable = calc_ds (cm); - return SCPE_OK; } /* end switch pa */ -return SCPE_NXM; /* unimplemented */ -} - -/* Reset routine */ - -t_stat cpu_reset (DEVICE *dptr) -{ -int32 i; - -PIRQ = MMR0 = MMR1 = MMR2 = MMR3 = 0; -cpu_bme = 0; -DR = CPUERR = MEMERR = CCR = HITMISS = 0; -PSW = 000340; -trap_req = 0; -wait_state = 0; -if (M == NULL) M = calloc (MEMSIZE >> 1, sizeof (unsigned int16)); -if (M == NULL) return SCPE_MEM; -pcq_r = find_reg ("PCQ", NULL, dptr); -if (pcq_r) pcq_r->qptr = 0; -else return SCPE_IERR; -for (i = 0; i < UBM_LNT_LW; i++) ub_map[i] = 0; -sim_brk_types = sim_brk_dflt = SWMASK ('E'); -set_r_display (0, MD_KER); -return SCPE_OK; -} - -/* Memory examine */ - -t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) -{ -int32 iodata; -t_stat stat; - -if (vptr == NULL) return SCPE_ARG; -if (sw & SWMASK ('V')) { /* -v */ - if (addr >= VASIZE) return SCPE_NXM; - addr = relocC (addr, sw); /* relocate */ - if (addr >= MAXMEMSIZE) return SCPE_REL; } -if (addr < MEMSIZE) { - *vptr = M[addr >> 1] & 0177777; - return SCPE_OK; } -if (addr < IOPAGEBASE) return SCPE_NXM; -stat = iopageR (&iodata, addr, READC); -*vptr = iodata; -return stat; -} - -/* Memory deposit */ - -t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw) -{ -if (sw & SWMASK ('V')) { /* -v */ - if (addr >= VASIZE) return SCPE_NXM; - addr = relocC (addr, sw); /* relocate */ - if (addr >= MAXMEMSIZE) return SCPE_REL; } -if (addr < MEMSIZE) { - M[addr >> 1] = val & 0177777; - return SCPE_OK; } -if (addr < IOPAGEBASE) return SCPE_NXM; -return iopageW ((int32) val, addr, WRITEC); -} - -/* Memory allocation */ - -t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -int32 mc = 0; -uint32 i, clim; -unsigned int16 *nM; - -if ((val <= 0) || (val > MAXMEMSIZE) || ((val & 07777) != 0)) - 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; -nM = calloc (val >> 1, sizeof (unsigned int16)); -if (nM == NULL) return SCPE_MEM; -clim = (((t_addr) val) < MEMSIZE)? val: MEMSIZE; -for (i = 0; i < clim; i = i + 2) nM[i >> 1] = M[i >> 1]; -free (M); -M = nM; -MEMSIZE = val; -return cpu_set_bus (uptr, (cpu_unit.flags & UNIT_MAP) | 1, cptr, desc); } - -/* Bus configuration, disable Unibus or Qbus devices */ - -t_stat cpu_set_bus (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -DEVICE *dptr; -uint32 i, target; - -if ((MEMSIZE <= UNIMEMSIZE) || (val & UNIT_18B) || - (!(val & 1) && ((uint32) val == (cpu_unit.flags & UNIT_MAP)))) return SCPE_OK; -if (val & UNIT_MAP) target = DEV_QBUS; /* going to Ubus? */ -else target = DEV_UBUS; /* going to Qbus */ -for (i = 0; (dptr = sim_devices[i]) != NULL; i++) { - if ((dptr->flags & DEV_DISABLE) && /* disable-able? */ - !(dptr->flags & DEV_DIS) && /* enabled? */ - ((dptr->flags & (DEV_QBUS|DEV_UBUS)) == target)) { - printf ("Disabling %s\n", sim_dname (dptr)); - if (sim_log) fprintf (sim_log, "Disabling %s\n", sim_dname (dptr)); - dptr->flags = dptr->flags | DEV_DIS; } } -return SCPE_OK; -} - -/* Set R, SP register display addresses */ - -void set_r_display (int32 rs, int32 cm) -{ -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 < 6; i++, rptr++) rptr->loc = (void *) ®FILE[i][rs]; -rptr->loc = (void *) &STACKFILE[cm]; -return; -} diff --git a/PDP11/pdp11_defs.h b/PDP11/pdp11_defs.h deleted file mode 100644 index 2c460e80..00000000 --- a/PDP11/pdp11_defs.h +++ /dev/null @@ -1,593 +0,0 @@ -/* pdp11_defs.h: PDP-11 simulator definitions - - 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. - - The author gratefully acknowledges the help of Max Burnet, Megan Gentry, - and John Wilson in resolving questions about the PDP-11 - - 19-May-03 RMS Revised for new conditional compilation - 05-Apr-03 RMS Fixed bug in MMR1 update (found by Tim Stark) - 28-Feb-03 RMS Added TM logging support - 19-Jan-03 RMS Changed mode definitions for Apple Dev Kit conflict - 11-Nov-02 RMS Changed log definitions to be VAX compatible - 10-Oct-02 RMS Added vector information to DIB - Changed DZ11 vector to Unibus standard - Added DEQNA/DELQA, DEUNA/DELUA support - Added multiple RQDX3, autoconfigure support - 12-Sep-02 RMS Added TMSCP, KW11P,and RX211 support - 28-Apr-02 RMS Clarified PDF ACF mnemonics - 22-Apr-02 RMS Added HTRAP, BPOK maint register flags, MT_MAXFR - 06-Mar-02 RMS Changed system type to KDJ11A - 20-Jan-02 RMS Added multiboard DZ11 support - 09-Nov-01 RMS Added bus map support - 07-Nov-01 RMS Added RQDX3 support - 26-Oct-01 RMS Added symbolic definitions for IO page - 19-Oct-01 RMS Added DZ definitions - 15-Oct-01 RMS Added logging capabilities - 07-Sep-01 RMS Revised for multilevel interrupts - 01-Jun-01 RMS Added DZ11 support - 23-Apr-01 RMS Added RK611 support - 05-Apr-01 RMS Added TS11/TSV05 support - 10-Feb-01 RMS Added DECtape support -*/ - -#ifndef _PDP11_DEFS_H -#define _PDP11_DEFS_H 0 - -#ifndef VM_PDP11 -#define VM_PDP11 0 -#endif - -#include "sim_defs.h" /* simulator defns */ -#include - -/* Architectural constants */ - -#define STKLIM 0400 /* stack limit */ -#define VASIZE 0200000 /* 2**16 */ -#define VAMASK (VASIZE - 1) /* 2**16 - 1 */ -#define INIMEMSIZE 001000000 /* 2**18 */ -#define UNIMEMSIZE 001000000 /* 2**18 */ -#define UNIMASK (UNIMEMSIZE - 1) /* 2**18 - 1 */ -#define IOPAGEBASE 017760000 /* 2**22 - 2**13 */ -#define MAXMEMSIZE 020000000 /* 2**22 */ -#define PAMASK (MAXMEMSIZE - 1) /* 2**22 - 1 */ -#define MEMSIZE (cpu_unit.capac) -#define ADDR_IS_MEM(x) (((t_addr) (x)) < MEMSIZE) -#define DMASK 0177777 - -/* Protection modes */ - -#define MD_KER 0 -#define MD_SUP 1 -#define MD_UND 2 -#define MD_USR 3 - -/* I/O access modes */ - -#define READ 0 -#define READC 1 /* read console */ -#define WRITE 2 -#define WRITEC 3 /* write console */ -#define WRITEB 4 - -/* PSW */ - -#define PSW_V_C 0 /* condition codes */ -#define PSW_V_V 1 -#define PSW_V_Z 2 -#define PSW_V_N 3 -#define PSW_V_TBIT 4 /* trace trap */ -#define PSW_V_IPL 5 /* int priority */ -#define PSW_V_RS 11 /* register set */ -#define PSW_V_PM 12 /* previous mode */ -#define PSW_V_CM 14 /* current mode */ -#define PSW_RW 0174357 /* read/write bits */ - -/* FPS */ - -#define FPS_V_C 0 /* condition codes */ -#define FPS_V_V 1 -#define FPS_V_Z 2 -#define FPS_V_N 3 -#define FPS_V_T 5 /* truncate */ -#define FPS_V_L 6 /* long */ -#define FPS_V_D 7 /* double */ -#define FPS_V_IC 8 /* ic err int */ -#define FPS_V_IV 9 /* overflo err int */ -#define FPS_V_IU 10 /* underflo err int */ -#define FPS_V_IUV 11 /* undef var err int */ -#define FPS_V_ID 14 /* int disable */ -#define FPS_V_ER 15 /* error */ - -/* PIRQ */ - -#define PIRQ_PIR1 0001000 -#define PIRQ_PIR2 0002000 -#define PIRQ_PIR3 0004000 -#define PIRQ_PIR4 0010000 -#define PIRQ_PIR5 0020000 -#define PIRQ_PIR6 0040000 -#define PIRQ_PIR7 0100000 -#define PIRQ_IMP 0177356 /* implemented bits */ -#define PIRQ_RW 0177000 /* read/write bits */ - -/* MMR0 */ - -#define MMR0_MME 0000001 /* mem mgt enable */ -#define MMR0_V_PAGE 1 /* offset to pageno */ -#define MMR0_M_PAGE 077 /* mask for pageno */ -#define MMR0_PAGE (MMR0_M_PAGE << MMR0_V_PAGE) -#define MMR0_RO 0020000 /* read only error */ -#define MMR0_PL 0040000 /* page lnt error */ -#define MMR0_NR 0100000 /* no access error */ -#define MMR0_FREEZE 0160000 /* if set, no update */ -#define MMR0_IMP 0160177 /* implemented bits */ -#define MMR0_RW 0160001 /* read/write bits */ - -/* MMR3 */ - -#define MMR3_UDS 001 /* user dspace enbl */ -#define MMR3_SDS 002 /* super dspace enbl */ -#define MMR3_KDS 004 /* krnl dspace enbl */ -#define MMR3_CSM 010 /* CSM enable */ -#define MMR3_M22E 020 /* 22b mem mgt enbl */ -#define MMR3_BME 040 /* DMA bus map enbl */ -#define MMR3_IMP 077 /* implemented bits */ -#define MMR3_RW 077 /* read/write bits */ - -/* PDR */ - -#define PDR_PRD 0000002 /* page readable */ -#define PDR_PWR 0000004 /* page writeable */ -#define PDR_ED 0000010 /* expansion dir */ -#define PDR_W 0000100 /* written flag */ -#define PDR_PLF 0077400 /* page lnt field */ -#define PDR_IMP 0177516 /* implemented bits */ -#define PDR_RW 0177416 /* read/write bits */ - -/* Virtual address */ - -#define VA_DF 0017777 /* displacement */ -#define VA_BN 0017700 /* block number */ -#define VA_V_APF 13 /* offset to APF */ -#define VA_V_DS 16 /* offset to space */ -#define VA_V_MODE 17 /* offset to mode */ -#define VA_DS (1u << VA_V_DS) /* data space flag */ - -/* Unibus map (if present) */ - -#define UBM_LNT_LW 32 /* size in LW */ -#define UBM_V_PN 13 /* page number */ -#define UBM_M_PN 037 -#define UBM_V_OFF 0 /* offset */ -#define UBM_M_OFF 017777 -#define UBM_GETPN(x) (((x) >> UBM_V_PN) & UBM_M_PN) -#define UBM_GETOFF(x) ((x) & UBM_M_OFF) - -/* CPUERR */ - -#define CPUE_RED 0004 /* red stack */ -#define CPUE_YEL 0010 /* yellow stack */ -#define CPUE_TMO 0020 /* IO page nxm */ -#define CPUE_NXM 0040 /* memory nxm */ -#define CPUE_ODD 0100 /* odd address */ -#define CPUE_HALT 0200 /* HALT not kernel */ -#define CPUE_IMP 0374 /* implemented bits */ - -/* Maintenance register */ - -#define MAINT_V_UQ 9 /* Q/U flag */ -#define MAINT_Q (0 << MAINT_V_UQ) /* Qbus */ -#define MAINT_U (1 << MAINT_V_UQ) -#define MAINT_V_FPA 8 /* FPA flag */ -#define MAINT_NOFPA (0 << MAINT_V_FPA) -#define MAINT_FPA (1 << MAINT_V_FPA) -#define MAINT_V_TYP 4 /* system type */ -#define MAINT_KDJ (1 << MAINT_V_TYP) /* KDJ11A */ -#define MAINT_V_HTRAP 3 /* trap 4 on HALT */ -#define MAINT_HTRAP (1 << MAINT_V_HTRAP) -#define MAINT_V_BPOK 0 /* power OK */ -#define MAINT_BPOK (1 << MAINT_V_BPOK) - -/* Floating point accumulators */ - -struct fpac { - unsigned int32 l; /* low 32b */ - unsigned int32 h; /* high 32b */ -}; -typedef struct fpac fpac_t; - -/* Device CSRs */ - -#define CSR_V_GO 0 /* go */ -#define CSR_V_IE 6 /* interrupt enable */ -#define CSR_V_DONE 7 /* done */ -#define CSR_V_BUSY 11 /* busy */ -#define CSR_V_ERR 15 /* error */ -#define CSR_GO (1u << CSR_V_GO) -#define CSR_IE (1u << CSR_V_IE) -#define CSR_DONE (1u << CSR_V_DONE) -#define CSR_BUSY (1u << CSR_V_BUSY) -#define CSR_ERR (1u << CSR_V_ERR) - -/* Trap masks, descending priority order, following J-11 - An interrupt summary bit is kept with traps, to minimize overhead -*/ - -#define TRAP_V_RED 0 /* red stk abort 4 */ -#define TRAP_V_ODD 1 /* odd address 4 */ -#define TRAP_V_MME 2 /* mem mgt 250 */ -#define TRAP_V_NXM 3 /* nx memory 4 */ -#define TRAP_V_PAR 4 /* parity err 114 */ -#define TRAP_V_PRV 5 /* priv inst 4 */ -#define TRAP_V_ILL 6 /* illegal inst 10 */ -#define TRAP_V_BPT 7 /* BPT 14 */ -#define TRAP_V_IOT 8 /* IOT 20 */ -#define TRAP_V_EMT 9 /* EMT 30 */ -#define TRAP_V_TRAP 10 /* TRAP 34 */ -#define TRAP_V_TRC 11 /* T bit 14 */ -#define TRAP_V_YEL 12 /* stack 4 */ -#define TRAP_V_PWRFL 13 /* power fail 24 */ -#define TRAP_V_FPE 14 /* fpe 244 */ -#define TRAP_V_MAX 15 /* intr = max trp # */ -#define TRAP_RED (1u << TRAP_V_RED) -#define TRAP_ODD (1u << TRAP_V_ODD) -#define TRAP_MME (1u << TRAP_V_MME) -#define TRAP_NXM (1u << TRAP_V_NXM) -#define TRAP_PAR (1u << TRAP_V_PAR) -#define TRAP_PRV (1u << TRAP_V_PRV) -#define TRAP_ILL (1u << TRAP_V_ILL) -#define TRAP_BPT (1u << TRAP_V_BPT) -#define TRAP_IOT (1u << TRAP_V_IOT) -#define TRAP_EMT (1u << TRAP_V_EMT) -#define TRAP_TRAP (1u << TRAP_V_TRAP) -#define TRAP_TRC (1u << TRAP_V_TRC) -#define TRAP_YEL (1u << TRAP_V_YEL) -#define TRAP_PWRFL (1u << TRAP_V_PWRFL) -#define TRAP_FPE (1u << TRAP_V_FPE) -#define TRAP_INT (1u << TRAP_V_MAX) -#define TRAP_ALL ((1u << TRAP_V_MAX) - 1) /* all traps */ - -#define VEC_RED 0004 /* trap vectors */ -#define VEC_ODD 0004 -#define VEC_MME 0250 -#define VEC_NXM 0004 -#define VEC_PAR 0114 -#define VEC_PRV 0004 -#define VEC_ILL 0010 -#define VEC_BPT 0014 -#define VEC_IOT 0020 -#define VEC_EMT 0030 -#define VEC_TRAP 0034 -#define VEC_TRC 0014 -#define VEC_YEL 0004 -#define VEC_PWRFL 0024 -#define VEC_FPE 0244 - -/* Simulator stop codes; codes 1:TRAP_V_MAX correspond to traps 0:TRAPMAX-1 */ - -#define STOP_HALT (TRAP_V_MAX + 1) /* HALT instruction */ -#define STOP_IBKPT (TRAP_V_MAX + 2) /* instruction bkpt */ -#define STOP_WAIT (TRAP_V_MAX + 3) /* wait, no events */ -#define STOP_VECABORT (TRAP_V_MAX + 4) /* abort vector read */ -#define STOP_SPABORT (TRAP_V_MAX + 5) /* abort trap push */ -#define STOP_RQ (TRAP_V_MAX + 6) /* RQDX3 panic */ -#define STOP_SANITY (TRAP_V_MAX + 7) /* sanity timer exp */ -#define IORETURN(f,v) ((f)? (v): SCPE_OK) /* cond error return */ - -/* Timers */ - -#define TMR_CLK 0 /* line clock */ -#define TMR_PCLK 1 /* KW11P */ - -/* IO parameters */ - -#define DZ_MUXES 4 /* max # of muxes */ -#define DZ_LINES 8 /* lines per mux */ -#define MT_MAXFR (1 << 16) /* magtape max rec */ -#define AUTO_LNT 34 /* autoconfig ranks */ -#define DIB_MAX 100 /* max DIBs */ - -#define DEV_V_UBUS (DEV_V_UF + 0) /* Unibus */ -#define DEV_V_QBUS (DEV_V_UF + 1) /* Qbus */ -#define DEV_V_FLTA (DEV_V_UF + 2) /* flt addr */ -#define DEV_UBUS (1u << DEV_V_UBUS) -#define DEV_QBUS (1u << DEV_V_QBUS) -#define DEV_FLTA (1u << DEV_V_FLTA) - -#define UNIBUS (cpu_18b || cpu_ubm) /* T if 18b */ - -#define MAP 1 /* mapped */ -#define NOMAP 0 /* not mapped */ - -#define DEV_RDX 8 /* default device radix */ - -/* Device information block */ - -#define VEC_DEVMAX 4 /* max device vec */ - -struct pdp_dib { - uint32 ba; /* base addr */ - uint32 lnt; /* length */ - t_stat (*rd)(int32 *dat, int32 ad, int32 md); - t_stat (*wr)(int32 dat, int32 ad, int32 md); - int32 vnum; /* vectors: number */ - int32 vloc; /* locator */ - int32 vec; /* value */ - int32 (*ack[VEC_DEVMAX])(void); /* ack routines */ -}; - -typedef struct pdp_dib DIB; - -/* I/O page layout - RQB,RQC,RQD float based on number of DZ's */ - -#define IOBA_DZ (IOPAGEBASE + 000100) /* DZ11 */ -#define IOLN_DZ 010 -#define IOBA_RQB (IOPAGEBASE + 000334 + (020 * (DZ_MUXES / 2))) -#define IOLN_RQB 004 -#define IOBA_RQC (IOPAGEBASE + IOBA_RQB + IOLN_RQB) -#define IOLN_RQC 004 -#define IOBA_RQD (IOPAGEBASE + IOBA_RQC + IOLN_RQC) -#define IOLN_RQD 004 -#define IOBA_UBM (IOPAGEBASE + 010200) /* Unibus map */ -#define IOLN_UBM (UBM_LNT_LW * sizeof (int32)) -#define IOBA_RQ (IOPAGEBASE + 012150) /* RQDX3 */ -#define IOLN_RQ 004 -#define IOBA_APR (IOPAGEBASE + 012200) /* APRs */ -#define IOLN_APR 0200 -#define IOBA_MMR3 (IOPAGEBASE + 012516) /* MMR3 */ -#define IOLN_MMR3 002 -#define IOBA_TM (IOPAGEBASE + 012520) /* TM11 */ -#define IOLN_TM 014 -#define IOBA_TS (IOPAGEBASE + 012520) /* TS11 */ -#define IOLN_TS 004 -#define IOBA_PCLK (IOPAGEBASE + 012540) /* KW11P */ -#define IOLN_PCLK 006 -#define IOBA_RL (IOPAGEBASE + 014400) /* RL11 */ -#define IOLN_RL 012 -#define IOBA_XQ (IOPAGEBASE + 014440) /* DEQNA/DELQA */ -#define IOLN_XQ 020 -#define IOBA_XQB (IOPAGEBASE + 014460) /* 2nd DEQNA/DELQA */ -#define IOLN_XQB 020 -#define IOBA_TQ (IOPAGEBASE + 014500) /* TMSCP */ -#define IOLN_TQ 004 -#define IOBA_XU (IOPAGEBASE + 014510) /* DEUNA/DELUA */ -#define IOLN_XU 010 -#define IOBA_RP (IOPAGEBASE + 016700) /* RP/RM */ -#define IOLN_RP 054 -#define IOBA_RX (IOPAGEBASE + 017170) /* RX11 */ -#define IOLN_RX 004 -#define IOBA_RY (IOPAGEBASE + 017170) /* RY11 */ -#define IOLN_RY 004 -#define IOBA_TC (IOPAGEBASE + 017340) /* TC11 */ -#define IOLN_TC 012 -#define IOBA_RK (IOPAGEBASE + 017400) /* RK11 */ -#define IOLN_RK 020 -#define IOBA_HK (IOPAGEBASE + 017440) /* RK611 */ -#define IOLN_HK 040 -#define IOBA_LPT (IOPAGEBASE + 017514) /* LP11 */ -#define IOLN_LPT 004 -#define IOBA_CLK (IOPAGEBASE + 017546) /* KW11L */ -#define IOLN_CLK 002 -#define IOBA_PTR (IOPAGEBASE + 017550) /* PC11 reader */ -#define IOLN_PTR 004 -#define IOBA_PTP (IOPAGEBASE + 017554) /* PC11 punch */ -#define IOLN_PTP 004 -#define IOBA_TTI (IOPAGEBASE + 017560) /* DL11 rcv */ -#define IOLN_TTI 004 -#define IOBA_TTO (IOPAGEBASE + 017564) /* DL11 xmt */ -#define IOLN_TTO 004 -#define IOBA_SRMM (IOPAGEBASE + 017570) /* SR, MMR0-2 */ -#define IOLN_SRMM 010 -#define IOBA_APR1 (IOPAGEBASE + 017600) /* APRs */ -#define IOLN_APR1 0100 -#define IOBA_CPU (IOPAGEBASE + 017740) /* CPU reg */ -#define IOLN_CPU 040 - -/* Interrupt assignments; within each level, priority is right to left */ - -#define IPL_HLVL 8 /* # int levels */ - -#define INT_V_PIR7 0 /* BR7 */ - -#define INT_V_CLK 0 /* BR6 */ -#define INT_V_PCLK 1 -#define INT_V_DTA 2 -#define INT_V_PIR6 3 - -#define INT_V_RK 0 /* BR5 */ -#define INT_V_RL 1 -#define INT_V_RX 2 -#define INT_V_TM 3 -#define INT_V_RP 4 -#define INT_V_TS 5 -#define INT_V_HK 6 -#define INT_V_RQ 7 -#define INT_V_DZRX 8 -#define INT_V_DZTX 9 -#define INT_V_TQ 10 -#define INT_V_RY 11 -#define INT_V_XQ 12 -#define INT_V_XU 13 -#define INT_V_PIR5 14 - -#define INT_V_TTI 0 /* BR4 */ -#define INT_V_TTO 1 -#define INT_V_PTR 2 -#define INT_V_PTP 3 -#define INT_V_LPT 4 -#define INT_V_PIR4 5 - -#define INT_V_PIR3 0 /* BR3 */ -#define INT_V_PIR2 0 /* BR2 */ -#define INT_V_PIR1 0 /* BR1 */ - -#define INT_PIR7 (1u << INT_V_PIR7) -#define INT_CLK (1u << INT_V_CLK) -#define INT_PCLK (1u << INT_V_PCLK) -#define INT_DTA (1u << INT_V_DTA) -#define INT_PIR6 (1u << INT_V_PIR6) -#define INT_RK (1u << INT_V_RK) -#define INT_RL (1u << INT_V_RL) -#define INT_RX (1u << INT_V_RX) -#define INT_TM (1u << INT_V_TM) -#define INT_RP (1u << INT_V_RP) -#define INT_TS (1u << INT_V_TS) -#define INT_HK (1u << INT_V_HK) -#define INT_RQ (1u << INT_V_RQ) -#define INT_DZRX (1u << INT_V_DZRX) -#define INT_DZTX (1u << INT_V_DZTX) -#define INT_TQ (1u << INT_V_TQ) -#define INT_RY (1u << INT_V_RY) -#define INT_XQ (1u << INT_V_XQ) -#define INT_XU (1u << INT_V_XU) -#define INT_PIR5 (1u << INT_V_PIR5) -#define INT_PTR (1u << INT_V_PTR) -#define INT_PTP (1u << INT_V_PTP) -#define INT_TTI (1u << INT_V_TTI) -#define INT_TTO (1u << INT_V_TTO) -#define INT_LPT (1u << INT_V_LPT) -#define INT_PIR4 (1u << INT_V_PIR4) -#define INT_PIR3 (1u << INT_V_PIR3) -#define INT_PIR2 (1u << INT_V_PIR2) -#define INT_PIR1 (1u << INT_V_PIR1) - -#define IPL_CLK 6 /* int pri levels */ -#define IPL_PCLK 6 -#define IPL_DTA 6 -#define IPL_RK 5 -#define IPL_RL 5 -#define IPL_RX 5 -#define IPL_TM 5 -#define IPL_RP 5 -#define IPL_TS 5 -#define IPL_HK 5 -#define IPL_RQ 5 -#define IPL_DZRX 5 -#define IPL_DZTX 5 -#define IPL_TQ 5 -#define IPL_RY 5 -#define IPL_XQ 5 -#define IPL_XU 5 -#define IPL_PTR 4 -#define IPL_PTP 4 -#define IPL_TTI 4 -#define IPL_TTO 4 -#define IPL_LPT 4 - -#define IPL_PIR7 7 -#define IPL_PIR6 6 -#define IPL_PIR5 5 -#define IPL_PIR4 4 -#define IPL_PIR3 3 -#define IPL_PIR2 2 -#define IPL_PIR1 1 - -/* Device vectors */ - -#define VEC_Q 0000 /* vector base */ -#define VEC_PIRQ 0240 -#define VEC_TTI 0060 -#define VEC_TTO 0064 -#define VEC_PTR 0070 -#define VEC_PTP 0074 -#define VEC_CLK 0100 -#define VEC_PCLK 0104 -#define VEC_XQ 0120 -#define VEC_XU 0120 -#define VEC_RQ 0154 -#define VEC_RL 0160 -#define VEC_LPT 0200 -#define VEC_HK 0210 -#define VEC_RK 0220 -#define VEC_DTA 0214 -#define VEC_TM 0224 -#define VEC_TS 0224 -#define VEC_RP 0254 -#define VEC_TQ 0260 -#define VEC_RX 0264 -#define VEC_RY 0264 -#define VEC_DZRX 0300 -#define VEC_DZTX 0304 - -/* Autoconfigure ranks */ - -#define RANK_DZ 8 -#define RANK_RL 14 -#define RANK_RX 18 -#define RANK_XU 25 -#define RANK_RQ 26 -#define RANK_TQ 30 - -/* Interrupt macros */ - -#define IVCL(dv) ((IPL_##dv * 32) + INT_V_##dv) -#define IREQ(dv) int_req[IPL_##dv] -#define SET_INT(dv) int_req[IPL_##dv] = int_req[IPL_##dv] | (INT_##dv) -#define CLR_INT(dv) int_req[IPL_##dv] = int_req[IPL_##dv] & ~(INT_##dv) - -/* CPU and FPU macros */ - -#define update_MM ((MMR0 & MMR0_FREEZE) == 0) -#define setTRAP(name) trap_req = trap_req | (name) -#define setCPUERR(name) CPUERR = CPUERR | (name) -#define ABORT(val) longjmp (save_env, (val)) -#define SP R[6] -#define PC R[7] - -/* Logging */ - -#define LOG_CPU_I 0x0001 -#define LOG_TM 0x0008 -#define LOG_RP 0x0010 -#define LOG_TS 0x0020 -#define LOG_RQ 0x0040 -#define LOG_TQ 0x0080 -#define LOG_XQ0 0x0100 -#define LOG_XQ1 0x0200 -#define LOG_XQ2 0x0400 -#define LOG_XQ3 0x0800 -#define LOG_TC_MS 0x1000 -#define LOG_TC_RW 0x2000 -#define LOG_TC_BL 0x4000 -#define LOG_HK 0x8000 - -#define DBG_LOG(x) (sim_log && (cpu_log & (x))) - -/* Function prototypes */ - -t_bool Map_Addr (uint32 qa, uint32 *ma); -int32 Map_ReadB (uint32 ba, int32 bc, uint8 *buf, t_bool map); -int32 Map_ReadW (uint32 ba, int32 bc, uint16 *buf, t_bool map); -int32 Map_WriteB (uint32 ba, int32 bc, uint8 *buf, t_bool map); -int32 Map_WriteW (uint32 ba, int32 bc, uint16 *buf, t_bool map); -t_stat set_addr (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat show_addr (FILE *st, UNIT *uptr, int32 val, void *desc); -t_stat set_addr_flt (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat set_vec (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat show_vec (FILE *st, UNIT *uptr, int32 val, void *desc); -t_stat auto_config (uint32 rank, uint32 num); - -#endif diff --git a/PDP11/pdp11_doc.txt b/PDP11/pdp11_doc.txt deleted file mode 100644 index 1acebe08..00000000 --- a/PDP11/pdp11_doc.txt +++ /dev/null @@ -1,1330 +0,0 @@ -To: Users -From: Bob Supnik -Subj: PDP-11 Simulator Usage -Date: 15-Sep-2003 - - COPYRIGHT NOTICE - -The following copyright notice applies to both the SIMH source and binary: - - 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"), - 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-11 simulator. - - -1. Simulator Files - -To compile the PDP-11, you must define VM_PDP11 as part of the compilation -command line. If you want expanded file support, you must also define USE_INT64 -and USE_ADDR64 as part of the compilation command line. - -sim/ sim_defs.h - sim_ether.h - sim_rev.h - sim_sock.h - sim_tape.h - sim_tmxr.h - scp.c - scp_tty.c - sim_ether.c - sim_sock.c - sim_tape.c - sim_tmxr.c - -sim/pdp11/ pdp11_defs.h - pdp11_mscp.h - pdp11_uqssp.h - pdp11_xq.h - pdp11_xq_bootrom.h - pdp11_cpu.c - pdp11_dz.c - pdp11_fp.c - pdp11_hk.c - pdp11_io.c - pdp11_lp.c - pdp11_pclk.c - pdp11_pt.c - pdp11_rk.c - pdp11_rl.c - pdp11_rp.c - pdp11_rq.c - pdp11_tq.c - pdp11_rx.c - pdp11_ry.c - pdp11_stddev.c - pdp11_sys.c - pdp11_tc.c - pdp11_tm.c - pdp11_ts.c - pdp11_xq.c - pdp11_xu.c - -2. PDP-11 Features - -The PDP-11 simulator is configured as follows: - -device simulates -name(s) - -CPU J-11 CPU with 256KB of memory -- FP11 floating point unit (FPA) -- CIS11 commercial instruction set (CIS, off by default) -PTR,PTP PC11 paper tape reader/punch -TTI,TTO DL11 console terminal -LPT LP11 line printer -CLK line frequency clock -PCLK KW11P programmable clock -DZ DZ11 8-line terminal multiplexor (up to 4) -RK RK11/RK05 cartridge disk controller with eight drives -HK RK611/RK06(7) cartridge disk controller with eight drives -RL RLV12/RL01(2) cartridge disk controller with four drives -RP RM02/03/05/80, RP04/05/06/07 Massbus style controller - with eight drives -RQ RQDX3 MSCP controller with four drives -RQB second RQDX3 MSCP controller with four drives -RQC third RQDX3 MSCP controller with four drives -RQD fourth RQDX3 MSCP controller with four drives -RX RX11/RX01 floppy disk controller with two drives -RY RX211/RX01 floppy disk controller with two drives -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 Qbus Ethernet controller -XQB second 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, XQ, XQB, -and XU devices can be set DISABLED. RQB, RQC, RQD, RY, TS, XQB, and XU are -disabled by default. - -The PDP-11 simulator implements several unique stop conditions: - - - abort during exception vector fetch, and register STOP_VEC is set - - abort during exception stack push, and register STOP_SPA is set - - trap condition 'n' occurs, and register STOP_TRAP is set - - wait state entered, and no I/O operations outstanding - (ie, no interrupt can ever occur) - -The PDP-11 loader supports standard binary format tapes. The DUMP command -is not implemented. - -2.1 CPU - -The CPU options include CPU mapping configuration (18b Unibus, 22b Unibus -with RH70-style controllers, 22b Unibus with RH11 style controllers, and -22b Qbus), the CIS instruction set, and the size of main memory. - - SET CPU 18B 18b addressing, no I/O map - SET CPU URH11 22b addresssing, Unibus I/O map, - 18b mapped RH11 controller - SET CPU URH70 22b addressing, Unibus I/O map, - 22b unmapped RH70 controller - SET CPU 22B 22b addressing, no I/O map (Qbus) - SET CPU NOCIS disable CIS instructions (default) - SET CPU CIS enable CIS instructions - SET CPU 16K set memory size = 16KB - SET CPU 32K set memory size = 32KB - SET CPU 48K set memory size = 48KB - SET CPU 64K set memory size = 64KB - SET CPU 96K set memory size = 96KB - SET CPU 128K set memory size = 128KB - SET CPU 192K set memory size = 192KB - SET CPU 256K set memory size = 256KB - SET CPU 384K set memory size = 384KB - SET CPU 512K set memory size = 512KB - SET CPU 768K set memory size = 768KB - SET CPU 1024K (or 1M) set memory size = 1024KB - SET CPU 2048K (or 2M) set memory size = 2048KB - SET CPU 3072K (or 3M) set memory size = 3072KB - SET CPU 4096K (or 4M) set memory size = 4096KB - -The CPU implements a show command to display the I/O address space map: - - SHOW CPU IOSPACE show I/O space address map - -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 256KB. If memory size -is being increased to more than 256KB, or the bus structue is being changed, -the simulator asks whether it should disable peripherals that can't run -in the current bus structure. - -DMA peripherals function differently, depending on whether the CPU is -configured for 18B, URH11, URH70, or 22B addressing and I/O: - - peripheral 18B URH11 URH70 22B - - RK 18b 18b 18b won't work, disabled - HK 18b 18b 18b SC02/C 22b, works - only with Ultrix-11 - RL 18b 18b 18b 22b RLV12 - RP 18b 18b 22b 22b third party - RQ 18b 18b 18b 22b RQDX3 - RY 18b 18b 18b won't work, disabled - TC 18b 18b 18b won't work, disabled - TM 18b 18b 18b won't work, disabled - TS 18b 18b 18b 22b TSV05 - TQ 18b 18b 18b 22b TQK50 - XQ 18b won't work, 22b DELQA - disabled - XU 18b 18b 18b won't work, disabled - -Non-DMA peripherals work the same in all configurations. Unibus-only -peripherals should be disabled in a Qbus (22B) configuration with more -than 256KB of memory, and Qbus-only peripherals should be disabled in -a Unibus (URH11 or URH70) configuration with more than 256KB of memory. - -These switches are recognized when examining or depositing in CPU memory: - - -v interpret address as virtual - -d if mem mgt enabled, force data space - -k if mem mgt enabled, force kernel mode - -s if mem mgt enabled, force supervisor mode - -u if mem mgt enabled, force user mode - -p if mem mgt enabled, force previous mode - -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..R5 16 R0..R5, current register set - SP 16 stack pointer, current mode - R00..R05 16 R0..R5, register set 0 - R10..R15 16 R0..R5, register set 1 - KSP 16 kernel stack pointer - SSP 16 supervisor stack pointer - USP 16 user stack pointer - PSW 16 processor status word - CM 2 current mode, PSW<15:14> - PM 2 previous mode, PSW<13:12> - RS 2 register set, PSW<11> - IPL 3 interrupt priority level, PSW<7:5> - T 1 trace bit, PSW<4> - N 1 negative flag, PSW<3> - Z 1 zero flag, PSW<2> - V 1 overflow flag, PSW<1> - C 1 carry flag, PSW<0> - SR 16 front panel switches - DR 16 front panel display - MEMERR 16 memory error register - CCR 16 cache control register - MAINT 16 maintenance register - HITMISS 16 hit/miss register - CPUERR 16 CPU error register - PIRQ 16 programmed interrupt requests - FAC0H..FAC5H 32 FAC0..FAC5, high 32 bits - FAC0L..FAC5L 32 FAC0..FAC5, low 32 bits - FPS 16 floating point status - FEA 16 floating exception address - FEC 4 floating exception code - MMR0..3 16 memory management registers 0..3 - {K/S/U}{I/D}{PAR/PDR}{0..7} - 16 memory management registers - UBMAP[0:63] 16 Unibus map registers - INT 32 interrupt pending flags - TRAP 18 trap pending flags - WAIT 0 wait state flag - WAIT_ENABLE 0 wait state enable flag - STOP_TRAPS 18 stop on trap flags - STOP_VECA 1 stop on read abort in trap or interrupt - STOP_SPA 1 stop on stack push abort in trap or interrupt - PCQ[0:63] 16 PC prior to last jump, branch, or interrupt; - most recent PC change first - WRU 8 interrupt character - -2.2 I/O Device Addressing - -PDP-11 I/O space is not large enough to allow all possible devices to be -configured simultaneously at fixed addresses. Instead, many devices have -floating addresses; that is, the assigned device address depends on the -presense of other devices in the configuration: - - DZ11 all instances have floating addresses - RL11 first instance has fixed address, rest floating - RX11/RX211 first instance has fixed address, rest floating - DEUNA/DELUA first instance has fixed address, rest floating - MSCP disk first instance has fixed address, rest floating - TMSCP tape first instance has fixed address, rest floating - -To maintain addressing consistency as the configuration changes, the -simulator implements DEC's standard I/O address and vector autoconfiguration -algorithms for devices DZ, RL, RX, RY, XU, RQ, and TQ. This allows the -user to enable or disable devices without needing to manage I/O addresses -and vectors. For example, if RY is enabled while RX is present, RY is -assigned an I/O address in the floating I/O space range; but if RX is -disabled and then RY is enabled, RY is assigned the fixed "first instance" -I/O address for floppy disks. - -Autoconfiguration cannot solve address conflicts between devices with -overlapping fixed addresses. For example, with default I/O page addressing, -the PDP-11 can support either a TM11 or a TS11, but not both, since they use -the same I/O addresses. - -In addition to autoconfiguration, most devices support the SET ADDRESS -command, which allows the I/O page address of the device to be changed, -and the SET VECTOR command, which allows the vector of the device to be -changed. Explicitly setting the I/O address of a device which normally -uses autoconfiguration DISABLES autoconfiguration for that device. As -a consequence, the user may have to manually configure all other -autoconfigured devices, because the autoconfiguration algorithm no -longer recognizes the explicitly configured device. A device can be -reset to autoconfigure with the SET AUTOCONFIGURE command. - -The current I/O map can be displayed with the SHOW CPU IOSPACE command. -Addresses that have set by autoconfiguration are marked with an asterisk (*). - -All devices support the SHOW ADDRESS and SHOW VECTOR commands, which display -the device address and vector, respectively. - -2.3 Programmed I/O Devices - -2.3.1 PC11 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 8 last data item processed - CSR 16 control/status register - INT 1 interrupt pending flag - ERR 1 error flag (CSR<15>) - BUSY 1 busy flag (CSR<11>) - DONE 1 device done flag (CSR<7>) - IE 1 interrupt enable flag (CSR<6>) - 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.3.2 PC11 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 8 last data item processed - CSR 16 control/status register - INT 1 interrupt pending flag - ERR 1 error flag (CSR<15>) - DONE 1 device done flag (CSR<7>) - IE 1 interrupt enable flag (CSR<6>) - 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.3.3 DL11 Terminal Input (TTI) - -The terminal interfaces (TTI, TTO) can be set to one of two modes: -7B or 8B. In 7B mode, input and output characters are masked to 7 -bits. In 8B mode, characters are not modified. Changing the mode -of either interface changes both. The default mode is 8B. - -The terminal input (TTI) polls the console keyboard for input. It -implements these registers: - - name size comments - - BUF 8 last data item processed - CSR 16 control/status register - INT 1 interrupt pending flag - ERR 1 error flag (CSR<15>) - DONE 1 device done flag (CSR<7>) - IE 1 interrupt enable flag (CSR<6>) - POS 32 number of characters input - TIME 24 keyboard polling interval - -If the simulator is compiled under Windows Visual C++, typing ^C to the -terminal input causes a fatal run-time error. Use the following command -to simulate typing ^C: - - SET TTI CTRL-C - -2.3.4 DL11 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 - CSR 16 control/status register - INT 1 interrupt pending flag - ERR 1 error flag (CSR<15>) - DONE 1 device done flag (CSR<7>) - IE 1 interrupt enable flag (CSR<6>) - POS 32 number of characters input - TIME 24 time from I/O initiation to interrupt - -2.3.5 LP11 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 8 last data item processed - CSR 16 control/status register - INT 1 interrupt pending flag - ERR 1 error flag (CSR<15>) - DONE 1 device done flag (CSR<7>) - IE 1 interrupt enable flag (CSR<6>) - 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 paper - - OS I/O error x report error and stop - -2.3.6 Line-Time Clock (CLK) - -The line-time clock (CLK) frequency can be adjusted as follows: - - SET CLK 60HZ set frequency to 60Hz - SET CLK 50HZ set frequency to 50Hz - -The default is 60Hz. - -The line-time clock implements these registers: - - name size comments - - CSR 16 control/status register - INT 1 interrupt pending flag - DONE 1 device done flag (CSR<7>) - IE 1 interrupt enable flag (CSR<6>) - TIME 24 clock interval - -The line-time clock autocalibrates; the clock interval is adjusted up -or down so that the clock tracks actual elapsed time. - -2.3.7 Programmable Clock (PCLK) - -The programmable clock (PCLK) line frequency can be adjusted as follows: - - SET PCLK 60HZ set frequency to 60Hz - SET PCLK 50HZ set frequency to 50Hz - -The default is 60Hz. - -The programmable clock implements these registers: - - name size comments - - CSR 16 control/status register - CSB 16 count set buffer - CNT 16 current count - INT 1 interrupt pending flag - OVFL 1 overflow (error) flag (CSR<15>) - DONE 1 device done flag (CSR<7>) - IE 1 interrupt enable flag (CSR<6>) - UPDN 1 up/down count mode (CSR<4>) - MODE 1 single/repeat mode (CSR<3>) - RUN 1 clock run (CSR<0>) - TIME[0..3] 32 clock interval, rates 0..3 - TPS[0..3] 32 ticks per second, rates 0..3 - -The programmable clock autocalibrates; the clock interval is adjusted -up or down so that the clock tracks actual elapsed time. Operation at -the highest clock rate (100Khz) is not recommended. The programmable -clock is disabled by default. - -2.3.8 DZ11 Terminal Multiplexor (DZ) - -The DZ11 is an 8-line terminal multiplexor. Up to 4 DZ11's (32 lines) -are supported. The number of lines can be changed with the command - - SET DZ LINES=n set line count to n - -The line count must be a multiple of 8, with a maximum of 32. - -The DZ11 supports 8-bit input and output of characters. 8-bit output -may be incompatible with certain operating systems. The command - - SET DZ 7B - -forces output characters (only) to be masked to 7 bits. - -The terminal lines perform input and output through Telnet sessions -connected to a user-specified port. The ATTACH command specifies -the port to be used: - - ATTACH {-am} DZ set up listening port - -where port is a decimal number between 1 and 65535 that is not being used -for other TCP/IP activities. The optional switch -m turns on the DZ11's -modem controls; the optional switch -a turns on active disconnects -(disconnect session if computer clears Data Terminal Ready). Without -modem control, the DZ behaves as though terminals were directly connected; -disconnecting the Telnet session does not cause any operating system- -visible change in line status. - -Once the DZ is attached and the simulator is running, the DZ will listen -for connections on the specified port. It assumes that the incoming -connections are Telnet connections. The connection remains open until -disconnected by the simulated program, the Telnet client, a SET DZ -DISCONNECT command, or a DETACH DZ command. - -The SHOW DZ CONNECTIONS command displays the current connections to the DZ. -The SHOW DZ STATISTICS command displays statistics for active connections. -The SET DZ DISCONNECT=linenumber disconnects the specified line. - -The DZ11 implements these registers: - - name size comments - - CSR[0:3] 16 control/status register, boards 0..3 - RBUF[0:3] 16 receive buffer, boards 0..3 - LPR[0:3] 16 line parameter register, boards 0..3 - TCR[0:3] 16 transmission control register, boards 0..3 - MSR[0:3] 16 modem status register, boards 0..3 - TDR[0:3] 16 transmit data register, boards 0..3 - SAENB[0:3] 1 silo alarm enabled, boards 0..3 - RXINT 4 receive interrupts, boards 3..0 - TXINT 4 transmit interrupts, boards 3..0 - MDMTCL 1 modem control enabled - AUTODS 1 autodisconnect enabled - -The DZ11 does not support save and restore. All open connections are -lost when the simulator shuts down or the DZ is detached. - -2.4 Floppy Disk Drives - -2.4.1 RX11/RX01 Floppy Disk (RX) - -RX11 options include the ability to set units write enabled or write locked: - - SET RXn LOCKED set unit n write locked - SET RXn WRITEENABLED set unit n write enabled - -The RX11 supports the BOOT command. - -The RX11 implements these registers: - - name size comments - - RXCS 12 status - RXDB 8 data buffer - RXES 8 error status - RXERR 8 error code - RXTA 8 current track - RXSA 8 current sector - STAPTR 3 controller state - BUFPTR 3 buffer pointer - INT 1 interrupt pending flag - ERR 1 error flag (CSR<15>) - TR 1 transfer ready flag (CSR<7>) - IE 1 interrupt enable flag (CSR<6>) - DONE 1 device done flag (CSR<5>) - CTIME 24 command completion time - STIME 24 seek time, per track - XTIME 24 transfer ready delay - STOP_IOE 1 stop on I/O error - SBUF[0:127] 8 sector buffer array - -Error handling is as follows: - - error STOP_IOE processed as - - not attached 1 report error and stop - 0 disk not ready - -RX01 data files are buffered in memory; therefore, end of file and OS -I/O errors cannot occur. - -2.4.2 RX211/RX02 Floppy Disk (RY) - -RX211 options include the ability to set units write enabled or write -locked, single or double density, or autosized: - - SET RYn LOCKED set unit n write locked - SET RYn WRITEENABLED set unit n write enabled - SET RYn SINGLE set unit n single density - SET RYn DOUBLE set unit n double density (default) - SET RYn AUTOSIZE set unit n autosized - -The RX211 supports the BOOT command. The RX211 will not function -properly in a Qbus (22B) system with more than 256KB of memory. - -The RX211 implements these registers: - - name size comments - - RYCS 16 status - RYBA 16 buffer address - RYWC 8 word count - RYDB 16 data buffer - RYES 12 error status - RYERR 8 error code - RYTA 8 current track - RYSA 8 current sector - STAPTR 4 controller state - INT 1 interrupt pending flag - ERR 1 error flag (CSR<15>) - TR 1 transfer ready flag (CSR<7>) - IE 1 interrupt enable flag (CSR<6>) - DONE 1 device done flag (CSR<5>) - CTIME 24 command completion time - STIME 24 seek time, per track - XTIME 24 transfer ready delay - STOP_IOE 1 stop on I/O error - SBUF[0:255] 8 sector buffer array - -Error handling is as follows: - - error STOP_IOE processed as - - not attached 1 report error and stop - 0 disk not ready - -RX02 data files are buffered in memory; therefore, end of file and OS -I/O errors cannot occur. - -2.5 Cartridge Disk Drives - -2.5.1 RK11/RK05 Cartridge Disk (RK) - -RK11 options include the ability to make units write enabled or write -locked: - - SET RKn LOCKED set unit n write locked - SET RKn WRITEENABLED set unit n write enabled - -Units can also be set ONLINE or OFFLINE. The RK11 supports the BOOT -command. The RK11 will not function properly in a Qbus (22B) system -with more than 256KB of memory. - -The RK11 implements these registers: - - name size comments - - RKCS 16 control/status - RKDA 16 disk address - RKBA 16 memory address - RKWC 16 word count - RKDS 16 drive status - RKER 16 error status - INTQ 9 interrupt queue - DRVN 3 number of last selected drive - INT 1 interrupt pending flag - ERR 1 error flag (CSR<15>) - DONE 1 device done flag (CSR<7>) - IE 1 interrupt enable flag (CSR<6>) - INT 1 interrupt pending flag - STIME 24 seek time, per cylinder - RTIME 24 rotational delay - 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 - -2.5.2 RK611/RK06,RK07 Cartridge Disk (HK) - -RK611 options include the ability to set units write enabled or write -locked, to set the drive size to RK06, RK07, or autosize, and to write -a DEC standard 044 compliant bad block table on the last track: - - SET HKn LOCKED set unit n write locked - SET HKn WRITEENABLED set unit n write enabled - SET HKn RK06 set size to RK06 - SET HKn RK07 set size to RK07 - SET HKn AUTOSIZE set size based on file size at attach - SET HKn BADBLOCK write bad block table on last track - -The size options can be used only when a unit is not attached to a file. -The bad block option can be used only when a unit is attached to a file. -Units can be set ONLINE or OFFLINE. The RK611 supports the BOOT command. -The RK611 will not function properly in a Qbus (22B) system with more -than 256KB of memory using standard DEC software. The simulator implements -a third-party extension of addressing capability to 22b; this is only -supported by Ultrix-11. - -The RK611 implements these registers: - - name size comments - - HKCS1 16 control/status 1 - HKWC 16 word count - HKBA 16 bus address - HKDA 16 desired surface, sector - HKCS2 16 control/status 2 - HKDS[0:7] 16 drive status, drives 0-7 - HKER[0:7] 16 drive errors, drives 0-7 - HKDB[0:2] 16 data buffer silo - HKDC 16 desired cylinder - HKOF 8 offset - HKMR 16 maintenance register - HKSPR 16 spare register - INT 1 interrupt pending flag - ERR 1 error flag (CSR<15>) - DONE 1 device done flag (CSR1<7>) - IE 1 interrupt enable flag (CSR1<6>) - STIME 24 seek time, per cylinder - RTIME 24 rotational delay - 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 - -2.5.3 RL11(V12)/RL01,RL02 Cartridge Disk (RL) - -RL11 options include the ability to set units write enabled or write -locked, to set the drive size to RL01, RL02, or autosize, and to write -a DEC standard 044 compliant bad block table on the last track: - - SET RLn LOCKED set unit n write locked - SET RLn WRITEENABLED set unit n write enabled - SET RLn RL01 set size to RL01 - SET RLn RL02 set size to RL02 - SET RLn AUTOSIZE set size based on file size at attach - SET RLn BADBLOCK write bad block table on last track - -The size options can be used only when a unit is not attached to a file. -The bad block option can be used only when a unit is attached to a file. -Units can be set ONLINE or OFFLINE. The RL11 supports the BOOT command. -In an 18B or Unibus system, the RL behaves like an RL11 with 18b -addressing; in a Qbus (22B) system, the RL behaves like the RLV12 with -22b addressing. - -The RL11 implements these registers: - - name size comments - - RLCS 16 control/status - RLDA 16 disk address - RLBA 16 memory address - RLBAE 6 memory address extension (RLV12) - RLMP..RLMP2 16 multipurpose register queue - INT 1 interrupt pending flag - ERR 1 error flag (CSR<15>) - DONE 1 device done flag (CSR<7>) - IE 1 interrupt enable flag (CSR<6>) - STIME 24 seek time, per cylinder - RTIME 24 rotational delay - 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 - -2.6 RM02/03/05/80, RP04/05/06/07 Disk Pack Drives (RP) - -The RP controller implements a "Massbus style" 22b direct interface -for large disk drives. It is more abstract than other device simulators, -with just enough detail to run operating system drivers. In addition, -the RP controller conflates the details of the RM series controllers -with the RP series controllers, although there were detailed differences. - -RP options include the ability to set units write enabled or write -locked, to set the drive type to one of six disk types, or autosize, -and to write a DEC standard 044 compliant bad block table on the last -track: - - SET RPn LOCKED set unit n write locked - SET RPn WRITEENABLED set unit n write enabled - SET RPn RM03 set type to RM03 - SET RPn RM05 set type to RM05 - SET RPn RM80 set type to RM80 - SET RPn RP04 set type to RP04 - SET RPn RP06 set type to RP06 - SET RPn RP07 set type to RP07 - SET RPn AUTOSIZE set type based on file size at attach - SET RPn BADBLOCK write bad block table on last track - -The type options can be used only when a unit is not attached to a file. -The bad block option can be used only when a unit is attached to a file. -Units can be set ONLINE or OFFLINE. The RP controller supports the -BOOT command. In a Unibus system, the RP can implement either 18b -(RH11) addressing or 22b (RH70) addressing. In a Qbus (22B) system, -the RP always implements 22b addressing. - -The RP controller implements these registers: - - name size comments - - RPCS1 16 control/status 1 - RPWC 16 word count - RPBA 16 bus address - RPDA 16 desired surface, sector - RPCS2 16 control/status 2 - RPDS[0:7] 16 drive status, drives 0-7 - RPER1[0:7] 16 drive errors, drives 0-7 - RPOF 16 offset - RPDC 16 desired cylinder - RPER2 16 error status 2 - RPER3 16 error status 3 - RPEC1 16 ECC syndrome 1 - RPEC2 16 ECC syndrome 2 - RPMR 16 maintenance register - RPDB 16 data buffer - RPBAE 6 bus address extension - RPCS3 16 control/status 3 - IFF 1 transfer complete interrupt request flop - INT 1 interrupt pending flag - SC 1 special condition (CSR1<15>) - DONE 1 device done flag (CSR1<7>) - IE 1 interrupt enable flag (CSR1<6>) - STIME 24 seek time, per cylinder - RTIME 24 rotational delay - 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 - -2.7 RQDX3 MSCP Disk Controllers (RQ, RQB, RQC, RQD) - -The simulator implements four MSCP disk controllers, RQ, RQB, RQC, RQD. -Initially, RQB, RQC, and RQD are disabled. Each RQ controller simulates -an RQDX3 MSCP disk controller. RQ options include the ability to set -units write enabled or write locked, and to set the drive type to one -of many disk types: - - SET RQn LOCKED set unit n write locked - SET RQn WRITEENABLED set unit n write enabled - SET RQn RX50 set type to RX50 - SET RQn RX33 set type to RX33 - SET RQn RD51 set type to RD51 - SET RQn RD52 set type to RD52 - SET RQn RD53 set type to RD53 - SET RQn RD54 set type to RD54 - SET RQn RD31 set type to RD31 - SET RQn RA82 set type to RA82 - SET RQn RA72 set type to RA72 - SET RQn RA90 set type to RA90 - SET RQn RA92 set type to RA92 - SET RQn RRD40 set type to RRD40 (CD ROM) - SET RQn RAUSER{=n} set type to RA81 with n LBNs - -The type options can be used only when a unit is not attached to a file. -RAUSER is a "user specified" disk; the user can specify the size of the -disk in logical block numbers (LBN's, 512 bytes each). The minimum size -is 50MB; the maximum size is 2GB. - -Units can also be set ONLINE or OFFLINE. Each RQ controller supports the -BOOT command. In a Unibus system, an RQ supports 18b addressing. In -a Qbus (22B) system, an RQ supports 22b addressing. - -Each RQ controller implements the following special SHOW commands: - - SHOW RQn TYPE show drive type - SHOW RQ RINGS show command and response rings - SHOW RQ FREEQ show packet free queue - SHOW RQ RESPQ show packet response queue - SHOW RQ UNITQ show unit queues - SHOW RQ ALL show all ring and queue state - SHOW RQn UNITQ show unit queues for unit n - -Each RQ controller implements these registers: - - name size comments - - SA 16 status/address register - S1DAT 16 step 1 init host data - CQBA 22 command queue base address - CQLNT 8 command queue length - CQIDX 8 command queue index - RQBA 22 request queue base address - RQLNT 8 request queue length - RQIDX 8 request queue index - FREE 5 head of free packet list - RESP 5 head of response packet list - PBSY 5 number of busy packets - CFLGS 16 controller flags - CSTA 4 controller state - PERR 9 port error number - CRED 5 host credits - HAT 17 host available timer - HTMO 17 host timeout value - CPKT[0:3] 5 current packet, units 0-3 - PKTQ[0:3] 5 packet queue, units 0-3 - UFLG[0:3] 16 unit flags, units 0-3 - INT 1 interrupt request - ITIME 1 response time for initialization steps - (except for step 4) - QTIME 24 response time for 'immediate' packets - XTIME 24 response time for data transfers - PKTS[33*32] 16 packet buffers, 33W each, - 32 entries - -Some DEC operating systems, notably RSX11M/M+, are very sensitive to -the timing parameters. Changing the default values may cause M/M+ to -crash on boot or to hang during operation. - -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.8 TC11/TU56 DECtape (DT) - -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 LOCKED set unit n write locked - SET DTn WRITEENABLED set unit n write enabled - -Units can be set ONLINE or OFFLINE. The TC11 supports the BOOT command. -The TC11 will not function properly in a 22B (Qbus) system with more -than 256KB of memory. - -The TC11 supports 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 TC controller implements these registers: - - name size comments - - TCST 16 status register - TCCM 16 command register - TCWC 16 word count register - TCBA 16 bus address register - TCDT 16 data register - INT 1 interrupt pending flag - ERR 1 error flag - DONE 1 done flag - IE 1 interrupt enable flag - CTIME 31 time to complete transport stop - 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] 31 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.9 Magnetic Tape Controllers - -2.9.1 TM11 Magnetic Tape (TM) - -TM options include the ability to make units write enabled or write -locked. - - SET TMn LOCKED set unit n write locked - SET TMn WRITEENABLED set unit n write enabled - -Units can be set ONLINE or OFFLINE. - -The TM11 supports the BOOT command. The bootstrap supports both original -and DEC standard boot formats. Originally, a tape bootstrap read and -executed the first record on tape. To allow for ANSI labels, the DEC -standard bootstrap skipped the first record and read and executed the -second. The DEC standard is the default; to bootstrap an original format -tape, use the -o switch. - -The TM11 will not function properly in a Qbus (22B) system with more -than 256KB of memory - -The TM controller implements these registers: - - name size comments - - MTS 16 status - MTC 16 command - MTCMA 16 memory address - MTBRC 16 byte/record count - INT 1 interrupt pending flag - ERR 1 error flag - DONE 1 device done flag - IE 1 interrupt enable flag - STOP_IOE 1 stop on I/O error - TIME 24 delay - UST[0:7] 16 unit status, units 0-7 - POS[0:7] 32 position, units 0-7 - -Error handling is as follows: - - error processed as - - not attached tape not ready; if STOP_IOE, stop - - end of file bad tape - - OS I/O error parity error; if STOP_IOE, stop - -2.9.2 TS11/TSV05 Magnetic Tape (TS) - -The TS actually implements the TSV05, with 22-bit addressing, but will -work with TS11 drivers. TS options include the ability to make the unit -write enabled or write locked. - - SET TS LOCKED set unit write locked - SET TS WRITEENABLED set unit write enabled - -The TS11 supports the BOOT command. The bootstrap supports only DEC -standard boot formats. To allow for ANSI labels, the DEC standard -bootstrap skipped the first record and read and executed the second. -In a Unibus system, the TS behaves like the TS11 and implements 18b -addresses. In a Qbus (22B) system, the TS behaves like the TSV05 -and implements 22b addresses. - -The TS controller implements these registers: - - name size comments - - TSSR 16 status register - TSBA 16 bus address register - TSDBX 16 data buffer extension register - CHDR 16 command packet header - CADL 16 command packet low address or count - CADH 16 command packet high address - CLNT 16 command packet length - MHDR 16 message packet header - MRFC 16 message packet residual frame count - MXS0 16 message packet extended status 0 - MXS1 16 message packet extended status 1 - MXS2 16 message packet extended status 2 - MXS3 16 message packet extended status 3 - MXS4 16 message packet extended status 4 - WADL 16 write char packet low address - WADH 16 write char packet high address - WLNT 16 write char packet length - WOPT 16 write char packet options - WXOPT 16 write char packet extended options - ATTN 1 attention message pending - BOOT 1 boot request pending - OWNC 1 if set, tape owns command buffer - OWNM 1 if set, tape owns message buffer - TIME 24 delay - POS 32 position - -Error handling is as follows: - - error processed as - - not attached tape not ready - - end of file bad tape - - OS I/O error fatal tape error - -2.9.3 TQK50 TMSCP Disk Controller (TQ) - -The TQ controller simulates the TQK50 TMSCP disk controller. TQ options -include the ability to set units write enabled or write locked, and to -specify the controller type and tape length: - - SET TQn LOCKED set unit n write locked - SET TQn WRITEENABLED set unit n write enabled - SET TQ TK50 set controller type to TK50 - SET TQ TK70 set controller type to TK70 - SET TQ TU81 set controller type to TU81 - SET TQ TKUSER{=n} set controller type to TK50 with - tape capacity of n MB - -User-specified capacity must be between 50 and 2000 MB. - -The TQ controller supports the BOOT command. In a Unibus system, the -TQ supports 18b addressing. In a Qbus (22B) system, the TQ supports -22b addressing. - -The TQ controller implements the following special SHOW commands: - - SHOW TQ TYPE show controller type - SHOW TQ RINGS show command and response rings - SHOW TQ FREEQ show packet free queue - SHOW TQ RESPQ show packet response queue - SHOW TQ UNITQ show unit queues - SHOW TQ ALL show all ring and queue state - SHOW TQn UNITQ show unit queues for unit n - -The TQ controller implements these registers: - - name size comments - - SA 16 status/address register - S1DAT 16 step 1 init host data - CQBA 22 command queue base address - CQLNT 8 command queue length - CQIDX 8 command queue index - RQBA 22 request queue base address - RQLNT 8 request queue length - RQIDX 8 request queue index - FREE 5 head of free packet list - RESP 5 head of response packet list - PBSY 5 number of busy packets - CFLGS 16 controller flags - CSTA 4 controller state - PERR 9 port error number - CRED 5 host credits - HAT 17 host available timer - HTMO 17 host timeout value - CPKT[0:3] 5 current packet, units 0-3 - PKTQ[0:3] 5 packet queue, units 0-3 - UFLG[0:3] 16 unit flags, units 0-3 - POS[0:3] 32 tape position, units 0-3 - OBJP[0:3] 32 object position, units 0-3 - INT 1 interrupt request - ITIME 1 response time for initialization steps - (except for step 4) - QTIME 24 response time for 'immediate' packets - XTIME 24 response time for data transfers - PKTS[33*32] 16 packet buffers, 33W each, - 32 entries - -Some DEC operating systems, notably RSX11M/M+, are very sensitive to -the timing parameters. Changing the default values may cause M/M+ to -crash on boot or to hang during operation. - -Error handling is as follows: - - error processed as - - not attached tape not ready - - end of file end of medium - - OS I/O error fatal tape error - -2.10 DELQA/DEQNA Qbus Ethernet Controllers (XQ, XQB) - -The simulator implements two DELQA/DEQNA Qbus Ethernet controllers (XQ, -XQB). Initially, XQ is enabled, and XQB is disabled. Options allow -control of the MAC address, the controller mode, and the sanity timer. - - SET XQ MAC= ex. 08-00-2B-AA-BB-CC - SHOW XQ MAC - -These commands are used to change or display the MAC address. -is a valid ethernet MAC, delimited by dashes or periods. The controller -defaults to 08-00-2B-AA-BB-CC, which should be sufficient if there is -only one SIMH controller on your LAN. Two cards with the same MAC address -will see each other's packets, resulting in a serious mess. - - SET XQ TYPE={DEQNA|[DELQA]} - SHOW XQ TYPE - -These commands are used to change or display the controller mode. DELQA -mode is better and faster but may not be usable by older or non-DEC OS's. -Also, be aware that DEQNA mode is not supported by many modern OS's. The -DEQNA-LOCK mode of the DELQA card is emulated by setting the the controller -to DEQNA - there is no need for a separate mode. DEQNA-LOCK mode behaves -exactly like a DEQNA, except for the operation of the VAR and MOP processing. - - SET XQ SANITY={ON|[OFF]} - SHOW XQ SANITY - -These commands change or display the INITIALIZATION sanity timer (DEQNA -jumper W3/DELQA switch S4). The INITIALIZATION sanity timer has a default -timeout of 4 minutes, and cannot be turned off, just reset. The normal -sanity timer can be set by operating system software regardless of the -state of this switch. Note that only the DEQNA (or the DELQA in DEQNA- -LOCK mode (=DEQNA)) supports the sanity timer - it is ignored by a DELQA -in Normal mode, which uses switch S4 for a different purpose. - -To access the network, the simulated Ethernet controller must be attached -to a real Ethernet interface: - - ATTACH XQ0 {ethX|} ex. eth0 or /dev/era0 - SHOW XQ ETH - -where X in 'ethX' is the number of the ethernet controller to attach, or -the real device name. The X number is system dependant. If you only have -one ethernet controller, the number will probably be 0. To find out what -your system thinks the ethernet numbers are, use the SHOW XQ ETH command. -The device list can be quite cryptic, depending on the host system, but -is probably better than guessing. If you do not attach the device, the -controller will behave as though the ethernet cable were unplugged. - -XQ has the following registers: - - name size comments - - SA0 16 station address word 0 - SA1 16 station address word 1 - SA2 16 station address word 2 - SA3 16 station address word 3 - SA4 16 station address word 4 - SA5 16 station address word 5 - CSR 16 control status register - VAR 16 vector address register - RBDL 32 receive buffer descriptor list - XBDL 32 trans(X)mit buffer descriptorlList - -One final note: because of it's asynchronous nature, the XQ controller is -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 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: - - -a display as ASCII character - -c display as two character ASCII 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 ASCII string - alphabetic instruction mnemonic - numeric octal number - -Instruction input uses standard PDP-11 assembler syntax. There are sixteen -instruction classes: - -class operands examples comments - -no operands none HALT, RESET -3b literal literal, 0 - 7 SPL -6b literal literal, 0 - 077 MARK -8b literal literal, 0 - 0377 EMT, TRAP -register register RTS -sop specifier SWAB, CLR, ASL -reg-sop register, specifier JSR, XOR, MUL -fop flt specifier ABSf, NEGf -ac-fop flt reg, flt specifier LDf, MULf -ac-sop flt reg, specifier LDEXP, STEXP -ac-moded sop flt reg, specifier LDCif, STCfi -dop specifier, specifier MOV, ADD, BIC -cond branch address BR, BCC, BNE -sob register, address SOB -cc clear cc clear instructions CLC, CLV, CLZ, CLN combinable -cc set cc set instructions SEC, SEV, SEZ, SEN combinable - -For floating point opcodes, F and D variants, and I and L variants, may be -specified regardless of the state of FPS. - -The syntax for specifiers is as follows: - -syntax specifier displacement comments - -Rn 0n - -Fn 0n - only in flt reg classes -(Rn) 1n - -@(Rn) 7n 0 equivalent to @0(Rn) -(Rn)+ 2n - -@(Rn)+ 3n - --(Rn) 4n - -@-(Rn) 5n - -{+/-}d(Rn) 6n {+/-}d -@{+/-}d(Rn) 7n {+/-}d -#n 27 n -@#n 37 n -.+/-n 67 +/-n - 4 -@.+/-n 77 +/-n - 4 -{+/-}n 67 {+/-}n - PC - 4 if on disk, 37 and n -@{+/-}n 77 {+/-}n - PC - 4 if on disk, invalid diff --git a/PDP11/pdp11_dz.c b/PDP11/pdp11_dz.c deleted file mode 100644 index 6b6c33bb..00000000 --- a/PDP11/pdp11_dz.c +++ /dev/null @@ -1,633 +0,0 @@ -/* pdp11_dz.c: DZ11 terminal multiplexor 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. - - dz DZ11 terminal multiplexor - - 19-May-03 RMS Revised for new conditional compilation scheme - 09-May-03 RMS Added network device flag - 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 - Added variable vector support - New data structures - 22-Apr-02 RMS Updated for changes in sim_tmxr - 28-Apr-02 RMS Fixed interrupt acknowledge, fixed SHOW DZ ADDRESS - 14-Jan-02 RMS Added multiboard support - 30-Dec-01 RMS Added show statistics, set disconnect - Removed statistics registers - 03-Dec-01 RMS Modified for extended SET/SHOW - 09-Nov-01 RMS Added VAX support - 20-Oct-01 RMS Moved getchar from sim_tmxr, changed interrupt - logic to use tmxr_rqln - 06-Oct-01 RMS Fixed bug in carrier detect logic - 03-Oct-01 RMS Added support for BSD-style "ringless" modems - 27-Sep-01 RMS Fixed bug in xmte initialization - 17-Sep-01 RMS Added separate autodisconnect switch - 16-Sep-01 RMS Fixed modem control bit offsets -*/ - -#if defined (VM_PDP10) /* PDP10 version */ -#include "pdp10_defs.h" -#define RANK_DZ 0 /* no autoconfig */ -#define DZ_8B_DFLT 0 -extern int32 int_req; -extern int32 int_vec[32]; - -#elif defined (VM_VAX) /* VAX version */ -#include "vax_defs.h" -#define DZ_8B_DFLT UNIT_8B -extern int32 int_req[IPL_HLVL]; -extern int32 int_vec[IPL_HLVL][32]; - -#else /* PDP-11 version */ -#include "pdp11_defs.h" -#define DZ_8B_DFLT UNIT_8B -extern int32 int_req[IPL_HLVL]; -extern int32 int_vec[IPL_HLVL][32]; -#endif - -#include "sim_sock.h" -#include "sim_tmxr.h" - -#if !defined (DZ_MUXES) -#define DZ_MUXES 1 -#endif -#if !defined (DZ_LINES) -#define DZ_LINES 8 -#endif - -#define UNIT_V_8B (UNIT_V_UF + 0) /* 8b output */ -#define UNIT_8B (1 << UNIT_V_8B) - -#define DZ_MNOMASK (DZ_MUXES - 1) /* mask for mux no */ -#define DZ_LNOMASK (DZ_LINES - 1) /* mask for lineno */ -#define DZ_LMASK ((1 << DZ_LINES) - 1) /* mask of lines */ -#define DZ_SILO_ALM 16 /* silo alarm level */ - -/* DZCSR - 160100 - control/status register */ - -#define CSR_MAINT 0000010 /* maint - NI */ -#define CSR_CLR 0000020 /* clear */ -#define CSR_MSE 0000040 /* master scan enb */ -#define CSR_RIE 0000100 /* rcv int enb */ -#define CSR_RDONE 0000200 /* rcv done - RO */ -#define CSR_V_TLINE 8 /* xmit line - RO */ -#define CSR_TLINE (DZ_LNOMASK << CSR_V_TLINE) -#define CSR_SAE 0010000 /* silo alm enb */ -#define CSR_SA 0020000 /* silo alm - RO */ -#define CSR_TIE 0040000 /* xmit int enb */ -#define CSR_TRDY 0100000 /* xmit rdy - RO */ -#define CSR_RW (CSR_MSE | CSR_RIE | CSR_SAE | CSR_TIE) -#define CSR_MBZ (0004003 | CSR_CLR | CSR_MAINT) - -#define CSR_GETTL(x) (((x) >> CSR_V_TLINE) & DZ_LNOMASK) -#define CSR_PUTTL(x,y) x = ((x) & ~CSR_TLINE) | (((y) & DZ_LNOMASK) << CSR_V_TLINE) - -/* DZRBUF - 160102 - receive buffer, read only */ - -#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 */ -#define RBUF_OVRE 0040000 /* overrun err - NI */ -#define RBUF_VALID 0100000 /* rcv valid */ -#define RBUF_MBZ 0004000 - -/* DZLPR - 160102 - line parameter register, write only, word access only */ - -#define LPR_V_LINE 0 /* line */ -#define LPR_LPAR 0007770 /* line pars - NI */ -#define LPR_RCVE 0010000 /* receive enb */ -#define LPR_GETLN(x) (((x) >> LPR_V_LINE) & DZ_LNOMASK) - -/* DZTCR - 160104 - transmission control register */ - -#define TCR_V_XMTE 0 /* xmit enables */ -#define TCR_V_DTR 8 /* DTRs */ - -/* DZMSR - 160106 - modem status register, read only */ - -#define MSR_V_RI 0 /* ring indicators */ -#define MSR_V_CD 8 /* carrier detect */ - -/* DZTDR - 160106 - transmit data, write only */ - -#define TDR_CHAR 0000377 /* xmit char */ -#define TDR_V_TBR 8 /* xmit break - NI */ - -extern int32 IREQ (HLVL); -extern int32 sim_switches; -extern FILE *sim_log; -extern int32 tmxr_poll; /* calibrated delay */ - -uint16 dz_csr[DZ_MUXES] = { 0 }; /* csr */ -uint16 dz_rbuf[DZ_MUXES] = { 0 }; /* rcv buffer */ -uint16 dz_lpr[DZ_MUXES] = { 0 }; /* line param */ -uint16 dz_tcr[DZ_MUXES] = { 0 }; /* xmit control */ -uint16 dz_msr[DZ_MUXES] = { 0 }; /* modem status */ -uint16 dz_tdr[DZ_MUXES] = { 0 }; /* xmit data */ -uint8 dz_sae[DZ_MUXES] = { 0 }; /* silo alarm enabled */ -uint32 dz_rxi = 0; /* rcv interrupts */ -uint32 dz_txi = 0; /* xmt interrupts */ -int32 dz_mctl = 0; /* modem ctrl enabled */ -int32 dz_auto = 0; /* autodiscon enabled */ -TMLN dz_ldsc[DZ_MUXES * DZ_LINES] = { 0 }; /* line descriptors */ -TMXR dz_desc = { DZ_MUXES * DZ_LINES, 0, 0, NULL }; /* mux descriptor */ - -DEVICE dz_dev; -t_stat dz_rd (int32 *data, int32 PA, int32 access); -t_stat dz_wr (int32 data, int32 PA, int32 access); -int32 dz_rxinta (void); -int32 dz_txinta (void); -t_stat dz_svc (UNIT *uptr); -t_stat dz_reset (DEVICE *dptr); -t_stat dz_attach (UNIT *uptr, char *cptr); -t_stat dz_detach (UNIT *uptr); -t_stat dz_clear (int32 dz, t_bool flag); -int32 dz_getc (int32 dz); -void dz_update_rcvi (void); -void dz_update_xmti (void); -void dz_clr_rxint (int32 dz); -void dz_set_rxint (int32 dz); -void dz_clr_txint (int32 dz); -void dz_set_txint (int32 dz); -t_stat dz_summ (FILE *st, UNIT *uptr, int32 val, void *desc); -t_stat dz_show (FILE *st, UNIT *uptr, int32 val, void *desc); -t_stat dz_show_vec (FILE *st, UNIT *uptr, int32 val, void *desc); -t_stat dz_setnl (UNIT *uptr, int32 val, char *cptr, void *desc); - -/* DZ data structures - - dz_dev DZ device descriptor - dz_unit DZ unit list - dz_reg DZ register list -*/ - -DIB dz_dib = { IOBA_DZ, IOLN_DZ * DZ_MUXES, &dz_rd, &dz_wr, - 2, IVCL (DZRX), VEC_DZRX, { &dz_rxinta, &dz_txinta } }; - -UNIT dz_unit = { UDATA (&dz_svc, UNIT_ATTABLE + DZ_8B_DFLT, 0) }; - -REG dz_nlreg = { DRDATA (NLINES, dz_desc.lines, 6), PV_LEFT }; - -REG dz_reg[] = { - { BRDATA (CSR, dz_csr, DEV_RDX, 16, DZ_MUXES) }, - { BRDATA (RBUF, dz_rbuf, DEV_RDX, 16, DZ_MUXES) }, - { BRDATA (LPR, dz_lpr, DEV_RDX, 16, DZ_MUXES) }, - { BRDATA (TCR, dz_tcr, DEV_RDX, 16, DZ_MUXES) }, - { BRDATA (MSR, dz_msr, DEV_RDX, 16, DZ_MUXES) }, - { BRDATA (TDR, dz_tdr, DEV_RDX, 16, DZ_MUXES) }, - { BRDATA (SAENB, dz_sae, DEV_RDX, 1, DZ_MUXES) }, - { GRDATA (RXINT, dz_rxi, DEV_RDX, DZ_MUXES, 0) }, - { GRDATA (TXINT, dz_txi, DEV_RDX, DZ_MUXES, 0) }, - { FLDATA (MDMCTL, dz_mctl, 0) }, - { FLDATA (AUTODS, dz_auto, 0) }, - { GRDATA (DEVADDR, dz_dib.ba, DEV_RDX, 32, 0), REG_HRO }, - { GRDATA (DEVVEC, dz_dib.vec, DEV_RDX, 16, 0), REG_HRO }, - { NULL } }; - -MTAB dz_mod[] = { - { UNIT_8B, 0, "7b", "7B", NULL }, - { UNIT_8B, UNIT_8B, "8b", "8B", NULL }, - { MTAB_XTD | MTAB_VDV, 1, NULL, "DISCONNECT", - &tmxr_dscln, NULL, &dz_desc }, - { UNIT_ATT, UNIT_ATT, "connections", NULL, NULL, &dz_summ }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "CONNECTIONS", NULL, - NULL, &dz_show, NULL }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "STATISTICS", NULL, - NULL, &dz_show, NULL }, - { MTAB_XTD|MTAB_VDV, 010, "ADDRESS", "ADDRESS", - &set_addr, &show_addr, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "VECTOR", "VECTOR", - &set_vec, &dz_show_vec, NULL }, -#if !defined (VM_PDP10) - { MTAB_XTD | MTAB_VDV, 0, NULL, "AUTOCONFIGURE", - &set_addr_flt, NULL, NULL }, -#endif - { MTAB_XTD | MTAB_VDV | MTAB_VAL, 0, "lines", "LINES", - &dz_setnl, NULL, &dz_nlreg }, - { 0 } }; - -DEVICE dz_dev = { - "DZ", &dz_unit, dz_reg, dz_mod, - 1, DEV_RDX, 8, 1, DEV_RDX, 8, - &tmxr_ex, &tmxr_dep, &dz_reset, - NULL, &dz_attach, &dz_detach, - &dz_dib, DEV_FLTA | DEV_DISABLE | DEV_NET | DEV_UBUS | DEV_QBUS }; - -/* IO dispatch routines, I/O addresses 177601x0 - 177601x7 */ - -t_stat dz_rd (int32 *data, int32 PA, int32 access) -{ -int32 dz = ((PA - dz_dib.ba) >> 3) & DZ_MNOMASK; /* get mux num */ - -switch ((PA >> 1) & 03) { /* case on PA<2:1> */ -case 00: /* CSR */ - *data = dz_csr[dz] = dz_csr[dz] & ~CSR_MBZ; - break; -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 */ - *data = dz_rbuf[dz]; - break; -case 02: /* TCR */ - *data = dz_tcr[dz]; - break; -case 03: /* MSR */ - *data = dz_msr[dz]; - break; } -return SCPE_OK; -} - -t_stat dz_wr (int32 data, int32 PA, int32 access) -{ -int32 dz = ((PA - dz_dib.ba) >> 3) & DZ_MNOMASK; /* get mux num */ -int32 i, line; -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; - 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); - 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_csr[dz] = (dz_csr[dz] & ~CSR_RW) | (data & CSR_RW); - break; -case 01: /* LPR */ - dz_lpr[dz] = data; - line = (dz * DZ_LINES) + LPR_GETLN (data); /* get line num */ - lp = &dz_ldsc[line]; /* get line desc */ - if (dz_lpr[dz] & LPR_RCVE) lp->rcve = 1; /* rcv enb? on */ - else lp->rcve = 0; /* else line off */ - tmxr_poll_rx (&dz_desc); /* poll input */ - dz_update_rcvi (); /* update rx intr */ - break; -case 02: /* TCR */ - if (access == WRITEB) data = (PA & 1)? /* byte? merge */ - (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_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] = 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 */ - break; } -return SCPE_OK; -} - -/* Unit service routine - - The DZ11 polls to see if asynchronous activity has occurred and now - needs to be processed. The polling interval is controlled by the clock - simulator, so for most environments, it is calibrated to real time. - Typical polling intervals are 50-60 times per second. - - The simulator assumes that software enables all of the multiplexors, - or none of them. -*/ - -t_stat dz_svc (UNIT *uptr) -{ -int32 dz, t, newln; - -for (dz = t = 0; dz < DZ_MUXES; dz++) /* check enabled */ - t = t | (dz_csr[dz] & CSR_MSE); -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 */ - tmxr_poll_rx (&dz_desc); /* poll input */ - dz_update_rcvi (); /* upd rcv intr */ - tmxr_poll_tx (&dz_desc); /* poll output */ - dz_update_xmti (); /* upd xmt intr */ - sim_activate (uptr, tmxr_poll); } /* reactivate */ -return SCPE_OK; -} - -/* Get first available character for mux, if any */ - -int32 dz_getc (int32 dz) -{ -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; -} - -/* Update receive interrupts */ - -void dz_update_rcvi (void) -{ -int32 i, dz, line, scnt[DZ_MUXES]; -TMLN *lp; - -for (dz = 0; dz < DZ_MUXES; dz++) { /* loop thru muxes */ - scnt[dz] = 0; /* clr input count */ - for (i = 0; i < DZ_LINES; i++) { /* poll lines */ - line = (dz * DZ_LINES) + i; /* get line num */ - lp = &dz_ldsc[line]; /* get line desc */ - scnt[dz] = scnt[dz] + tmxr_rqln (lp); /* sum buffers */ - if (dz_mctl && !lp->conn) /* if disconn */ - dz_msr[dz] &= ~(1 << (i + MSR_V_CD)); /* reset car det */ - } - } -for (dz = 0; dz < DZ_MUXES; dz++) { /* loop thru muxes */ - if (scnt[dz] && (dz_csr[dz] & CSR_MSE)) { /* input & enabled? */ - dz_csr[dz] |= CSR_RDONE; /* set done */ - if (dz_sae[dz] && (scnt[dz] >= DZ_SILO_ALM)) { /* alm enb & cnt hi? */ - dz_csr[dz] |= CSR_SA; /* set status */ - dz_sae[dz] = 0; } } /* disable alarm */ - else dz_csr[dz] &= ~CSR_RDONE; /* no, clear done */ - if ((dz_csr[dz] & CSR_RIE) && /* int enable */ - ((dz_csr[dz] & CSR_SAE)? - (dz_csr[dz] & CSR_SA): (dz_csr[dz] & CSR_RDONE))) - dz_set_rxint (dz); /* and alm/done? */ - else dz_clr_rxint (dz); /* no, clear int */ - } -return; -} - -/* Update transmit interrupts */ - -void dz_update_xmti (void) -{ -int32 dz, linemask, i, j, line; - -for (dz = 0; dz < DZ_MUXES; dz++) { /* loop thru muxes */ - linemask = dz_tcr[dz] & DZ_LMASK; /* enabled lines */ - dz_csr[dz] &= ~CSR_TRDY; /* assume not rdy */ - j = CSR_GETTL (dz_csr[dz]); /* start at current */ - for (i = 0; i < DZ_LINES; i++) { /* loop thru lines */ - j = (j + 1) & DZ_LNOMASK; /* next line */ - line = (dz * DZ_LINES) + j; /* get line num */ - if ((linemask & (1 << j)) && dz_ldsc[line].xmte) { - CSR_PUTTL (dz_csr[dz], j); /* put ln in csr */ - dz_csr[dz] |= CSR_TRDY; /* set xmt rdy */ - break; } } - if ((dz_csr[dz] & CSR_TIE) && (dz_csr[dz] & CSR_TRDY)) /* ready plus int? */ - dz_set_txint (dz); - else dz_clr_txint (dz); /* no int req */ - } -return; -} - -/* Interrupt routines */ - -void dz_clr_rxint (int32 dz) -{ -dz_rxi = dz_rxi & ~(1 << dz); /* clr mux rcv int */ -if (dz_rxi == 0) CLR_INT (DZRX); /* all clr? */ -else SET_INT (DZRX); /* no, set intr */ -return; -} - -void dz_set_rxint (int32 dz) -{ -dz_rxi = dz_rxi | (1 << dz); /* set mux rcv int */ -SET_INT (DZRX); /* set master intr */ -return; -} - -int32 dz_rxinta (void) -{ -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 */ -return 0; -} - -void dz_clr_txint (int32 dz) -{ -dz_txi = dz_txi & ~(1 << dz); /* clr mux xmt int */ -if (dz_txi == 0) CLR_INT (DZTX); /* all clr? */ -else SET_INT (DZTX); /* no, set intr */ -return; -} - -void dz_set_txint (int32 dz) -{ -dz_txi = dz_txi | (1 << dz); /* set mux xmt int */ -SET_INT (DZTX); /* set master intr */ -return; -} - -int32 dz_txinta (void) -{ -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 */ -return 0; -} - -/* Device reset */ - -t_stat dz_clear (int32 dz, t_bool flag) -{ -int32 i, line; - -dz_csr[dz] = 0; /* clear CSR */ -dz_rbuf[dz] = 0; /* silo empty */ -dz_lpr[dz] = 0; /* no params */ -if (flag) dz_tcr[dz] = 0; /* INIT? clr all */ -else dz_tcr[dz] &= ~0377; /* else save dtr */ -dz_tdr[dz] = 0; -dz_sae[dz] = 1; /* alarm on */ -dz_clr_rxint (dz); /* clear int */ -dz_clr_txint (dz); -for (i = 0; i < DZ_LINES; i++) { /* loop thru lines */ - line = (dz * DZ_LINES) + i; - if (!dz_ldsc[line].conn) dz_ldsc[line].xmte = 1;/* set xmt enb */ - dz_ldsc[line].rcve = 0; } /* clr rcv enb */ -return SCPE_OK; -} - -t_stat dz_reset (DEVICE *dptr) -{ -int32 i, ndev; - -for (i = 0; i < (DZ_MUXES * DZ_LINES); i++) /* init mux desc */ - dz_desc.ldsc[i] = &dz_ldsc[i]; -for (i = 0; i < DZ_MUXES; i++) dz_clear (i, TRUE); /* init muxes */ -dz_rxi = dz_txi = 0; /* clr master int */ -CLR_INT (DZRX); -CLR_INT (DZTX); -sim_cancel (&dz_unit); /* stop poll */ -ndev = ((dptr->flags & DEV_DIS)? 0: (dz_desc.lines / DZ_LINES)); -return auto_config (RANK_DZ, ndev); /* auto config */ -} - -/* Attach */ - -t_stat dz_attach (UNIT *uptr, char *cptr) -{ -t_stat r; -extern int32 sim_switches; - -dz_mctl = dz_auto = 0; /* modem ctl off */ -r = tmxr_attach (&dz_desc, uptr, cptr); /* attach mux */ -if (r != SCPE_OK) return r; /* error? */ -if (sim_switches & SWMASK ('M')) { /* modem control? */ - dz_mctl = 1; - 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"); - } - } -return SCPE_OK; -} - -/* Detach */ - -t_stat dz_detach (UNIT *uptr) -{ -return tmxr_detach (&dz_desc, uptr); -} - -/* Show summary processor */ - -t_stat dz_summ (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -int32 i, t; - -for (i = t = 0; i < dz_desc.lines; i++) { /* get num conn */ - if (dz_ldsc[i].conn) t = t + 1; } -if (t == 1) fprintf (st, "1 connection"); -else fprintf (st, "%d connections", t); -return SCPE_OK; -} - -/* SHOW CONN/STAT processor */ - -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 (t == 0) fprintf (st, "all disconnected\n"); -return SCPE_OK; -} - -/* SET LINES processor */ - -t_stat dz_setnl (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -int32 newln, i, t, ndev; -t_stat r; - -if (cptr == NULL) return SCPE_ARG; -newln = (int32) get_uint (cptr, 10, (DZ_MUXES * DZ_LINES), &r); -if ((r != SCPE_OK) || (newln == dz_desc.lines)) return r; -if ((newln == 0) || (newln % DZ_LINES)) return SCPE_ARG; -if (newln < dz_desc.lines) { - for (i = newln, t = 0; i < dz_desc.lines; i++) t = t | dz_ldsc[i].conn; - if (t && !get_yn ("This will disconnect users; proceed [N]?", FALSE)) - return SCPE_OK; - for (i = newln; i < dz_desc.lines; i++) { - if (dz_ldsc[i].conn) { - tmxr_msg (dz_ldsc[i].conn, "\r\nOperator disconnected line\r\n"); - tmxr_reset_ln (&dz_ldsc[i]); } /* reset line */ - if ((i % DZ_LINES) == (DZ_LINES - 1)) - dz_clear (i / DZ_LINES, TRUE); } /* reset mux */ - } -dz_dib.lnt = (newln / DZ_LINES) * IOLN_DZ; /* set length */ -dz_desc.lines = newln; -ndev = ((dz_dev.flags & DEV_DIS)? 0: (dz_desc.lines / DZ_LINES)); -return auto_config (RANK_DZ, ndev); /* auto config */ -} - -/* SHOW VECTOR processor */ - -t_stat dz_show_vec (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -return show_vec (st, uptr, ((dz_desc.lines * 2) / DZ_LINES), desc); -} diff --git a/PDP11/pdp11_fp.c b/PDP11/pdp11_fp.c deleted file mode 100644 index 50185330..00000000 --- a/PDP11/pdp11_fp.c +++ /dev/null @@ -1,1008 +0,0 @@ -/* pdp11_fp.c: PDP-11 floating point simulator (32b version) - - 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. - - 19-Jan-03 RMS Changed mode definitions for Apple Dev Kit conflict - 08-Oct-02 RMS Fixed macro definitions - 05-Jun-98 RMS Fixed implementation specific shift bugs - 20-Apr-98 RMS Fixed bug in MODf integer truncation - 17-Apr-98 RMS Fixed bug in STCfi range check - 16-Apr-98 RMS Fixed bugs in STEXP, STCfi, round/pack - 09-Apr-98 RMS Fixed bug in LDEXP - 04-Apr-98 RMS Fixed bug in MODf condition codes - - This module simulates the PDP-11 floating point unit (FP11 series). - It is called from the instruction decoder for opcodes 170000:177777. - - The floating point unit recognizes three instruction formats: - - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ no operand - | 1 1 1 1| 0 0 0 0 0 0| opcode | 170000: - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 170077 - - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ one operand - | 1 1 1 1| 0 0 0| opcode | dest spec | 170100: - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 170777 - - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ register + operand - | 1 1 1 1| opcode | fac | dest spec | 171000: - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 177777 - - The instruction space is further extended through use of the floating - point status register (FPS) mode bits. Three mode bits affect how - instructions are interpreted: - - FPS_D if 0, floating registers are single precision - if 1, floating registers are double precision - - FPS_L if 0, integer operands are word - if 1, integer operands are longword - - FPS_T if 0, floating operations are rounded - if 1, floating operations are truncated - - FPS also contains the condition codes for the floating point unit, - and exception enable bits for individual error conditions. Exceptions - cause a trap through 0244, unless the individual exception, or all - exceptions, are disabled. Illegal address mode, undefined variable, - and divide by zero abort the current instruction; all other exceptions - permit the instruction to complete. (Aborts are implemented as traps - that request an "interrupt" trap. If an interrupt is pending, it is - serviced; if not, trap_req is updated and processing continues.) - - Floating point specifiers are similar to integer specifiers, with - the length of the operand being up to 8 bytes. In two specific cases, - the floating point unit reads or writes only two bytes, rather than - the length specified by the operand type: - - register for integers, only 16b are accessed; if the - operand is 32b, these are the high order 16b - of the operand - - immediate for integers or floating point, only 16b are - accessed; if the operand is 32b or 64b, these - are the high order 16b of the operand -*/ - -#include "pdp11_defs.h" - -/* Floating point status register */ - -#define FPS_ER (1u << FPS_V_ER) /* error */ -#define FPS_ID (1u << FPS_V_ID) /* interrupt disable */ -#define FPS_IUV (1u << FPS_V_IUV) /* int on undef var */ -#define FPS_IU (1u << FPS_V_IU) /* int on underflow */ -#define FPS_IV (1u << FPS_V_IV) /* int on overflow */ -#define FPS_IC (1u << FPS_V_IC) /* int on conv error */ -#define FPS_D (1u << FPS_V_D) /* single/double */ -#define FPS_L (1u << FPS_V_L) /* word/long */ -#define FPS_T (1u << FPS_V_T) /* round/truncate */ -#define FPS_N (1u << FPS_V_N) -#define FPS_Z (1u << FPS_V_Z) -#define FPS_V (1u << FPS_V_V) -#define FPS_C (1u << FPS_V_C) -#define FPS_CC (FPS_N + FPS_Z + FPS_V + FPS_C) -#define FPS_RW (FPS_ER + FPS_ID + FPS_IUV + FPS_IU + FPS_IV + \ - FPS_IC + FPS_D + FPS_L + FPS_T + FPS_CC) - -/* Floating point exception codes */ - -#define FEC_OP 2 /* illegal op/mode */ -#define FEC_DZRO 4 /* divide by zero */ -#define FEC_ICVT 6 /* conversion error */ -#define FEC_OVFLO 8 /* overflow */ -#define FEC_UNFLO 10 /* underflow */ -#define FEC_UNDFV 12 /* undef variable */ - -/* Floating point format, all assignments 32b relative */ - -#define FP_V_SIGN (63 - 32) /* high lw: sign */ -#define FP_V_EXP (55 - 32) /* exponent */ -#define FP_V_HB FP_V_EXP /* hidden bit */ -#define FP_V_F0 (48 - 32) /* fraction 0 */ -#define FP_V_F1 (32 - 32) /* fraction 1 */ -#define FP_V_FROUND (31 - 32) /* f round point */ -#define FP_V_F2 16 /* low lw: fraction 2 */ -#define FP_V_F3 0 /* fraction 3 */ -#define FP_V_DROUND (-1) /* d round point */ -#define FP_M_EXP 0377 -#define FP_SIGN (1u << FP_V_SIGN) -#define FP_EXP (FP_M_EXP << FP_V_EXP) -#define FP_HB (1u << FP_V_HB) -#define FP_FRACH ((1u << FP_V_HB) - 1) -#define FP_FRACL 0xFFFFFFFF -#define FP_BIAS 0200 /* exponent bias */ -#define FP_GUARD 3 /* guard bits */ - -/* Data lengths */ - -#define WORD 2 -#define LONG 4 -#define QUAD 8 - -/* Double precision operations on 64b quantities */ - -#define F_LOAD(qd,ac,ds) ds.h = ac.h; ds.l = (qd)? ac.l: 0 -#define F_LOAD_P(qd,ac,ds) ds->h = ac.h; ds->l = (qd)? ac.l: 0 -#define F_LOAD_FRAC(qd,ac,ds) ds.h = (ac.h & FP_FRACH) | FP_HB; \ - ds.l = (qd)? ac.l: 0 -#define F_STORE(qd,sr,ac) ac.h = sr.h; if ((qd)) ac.l = sr.l -#define F_STORE_P(qd,sr,ac) ac.h = sr->h; if ((qd)) ac.l = sr->l -#define F_GET_FRAC_P(sr,ds) ds.l = sr->l; \ - ds.h = (sr->h & FP_FRACH) | FP_HB -#define F_ADD(s2,s1,ds) ds.l = (s1.l + s2.l) & 0xFFFFFFFF; \ - ds.h = (s1.h + s2.h + (ds.l < s2.l)) & 0xFFFFFFFF -#define F_SUB(s2,s1,ds) ds.h = (s1.h - s2.h - (s1.l < s2.l)) & 0xFFFFFFFF; \ - ds.l = (s1.l - s2.l) & 0xFFFFFFFF -#define F_LT(x,y) ((x.h < y.h) || ((x.h == y.h) && (x.l < y.l))) -#define F_LT_AP(x,y) (((x->h & ~FP_SIGN) < (y->h & ~FP_SIGN)) || \ - (((x->h & ~FP_SIGN) == (y->h & ~FP_SIGN)) && (x->l < y->l))) -#define F_LSH_V(sr,n,ds) \ - ds.h = (((n) >= 32)? (sr.l << ((n) - 32)): \ - (sr.h << (n)) | ((sr.l >> (32 - (n))) & and_mask[n])) \ - & 0xFFFFFFFF; \ - ds.l = ((n) >= 32)? 0: (sr.l << (n)) & 0xFFFFFFFF -#define F_RSH_V(sr,n,ds) \ - ds.l = (((n) >= 32)? (sr.h >> ((n) - 32)) & and_mask[64 - (n)]: \ - ((sr.l >> (n)) & and_mask[32 - (n)]) | \ - (sr.h << (32 - (n)))) & 0xFFFFFFFF; \ - ds.h = ((n) >= 32)? 0: \ - ((sr.h >> (n)) & and_mask[32 - (n)]) & 0xFFFFFFFF - -/* For the constant shift macro, arguments must in the range [2,31] */ - -#define F_LSH_1(ds) ds.h = ((ds.h << 1) | ((ds.l >> 31) & 1)) & 0xFFFFFFFF; \ - ds.l = (ds.l << 1) & 0xFFFFFFFF -#define F_RSH_1(ds) ds.l = ((ds.l >> 1) & 0x7FFFFFFF) | ((ds.h & 1) << 31); \ - ds.h = ((ds.h >> 1) & 0x7FFFFFFF) -#define F_LSH_K(sr,n,ds) \ - ds.h = ((sr.h << (n)) | ((sr.l >> (32 - (n))) & and_mask[n])) \ - & 0xFFFFFFFF; \ - ds.l = (sr.l << (n)) & 0xFFFFFFFF -#define F_RSH_K(sr,n,ds) \ - ds.l = (((sr.l >> (n)) & and_mask[32 - (n)]) | \ - (sr.h << (32 - (n)))) & 0xFFFFFFFF; \ - ds.h = ((sr.h >> (n)) & and_mask[32 - (n)]) & 0xFFFFFFFF -#define F_LSH_GUARD(ds) F_LSH_K(ds,FP_GUARD,ds) -#define F_RSH_GUARD(ds) F_RSH_K(ds,FP_GUARD,ds) - -#define GET_BIT(ir,n) (((ir) >> (n)) & 1) -#define GET_SIGN(ir) GET_BIT((ir), FP_V_SIGN) -#define GET_EXP(ir) (((ir) >> FP_V_EXP) & FP_M_EXP) -#define GET_SIGN_L(ir) GET_BIT((ir), 31) -#define GET_SIGN_W(ir) GET_BIT((ir), 15) - -extern jmp_buf save_env; -extern int32 FEC, FEA, FPS; -extern int32 CPUERR, trap_req; -extern int32 N, Z, V, C; -extern int32 R[8]; -extern fpac_t FR[6]; - -fpac_t zero_fac = { 0, 0 }; -fpac_t one_fac = { 1, 0 }; -fpac_t fround_fac = { (1u << (FP_V_FROUND + 32)), 0 }; -fpac_t fround_guard_fac = { 0, (1u << (FP_V_FROUND + FP_GUARD)) }; -fpac_t dround_guard_fac = { (1u << (FP_V_DROUND + FP_GUARD)), 0 }; -fpac_t fmask_fac = { 0xFFFFFFFF, (1u << (FP_V_HB + FP_GUARD + 1)) - 1 }; -static const uint32 and_mask[33] = { 0, - 0x1, 0x3, 0x7, 0xF, - 0x1F, 0x3F, 0x7F, 0xFF, - 0x1FF, 0x3FF, 0x7FF, 0xFFF, - 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF, - 0x1FFFF, 0x3FFFF, 0x7FFFF, 0xFFFFF, - 0x1FFFFF, 0x3FFFFF, 0x7FFFFF, 0xFFFFFF, - 0x1FFFFFF, 0x3FFFFFF, 0x7FFFFFF, 0xFFFFFFF, - 0x1FFFFFFF, 0x3FFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF }; -int32 backup_PC; -int32 fpnotrap (int32 code); -int32 GeteaFP (int32 spec, int32 len); - -unsigned int32 ReadI (int32 addr, int32 spec, int32 len); -void ReadFP (fpac_t *fac, int32 addr, int32 spec, int32 len); -void WriteI (int32 data, int32 addr, int32 spec, int32 len); -void WriteFP (fpac_t *data, int32 addr, int32 spec, int32 len); -int32 setfcc (int32 old_status, int32 result_high, int32 newV); -int32 addfp11 (fpac_t *src1, fpac_t *src2); -int32 mulfp11 (fpac_t *src1, fpac_t *src2); -int32 divfp11 (fpac_t *src1, fpac_t *src2); -int32 modfp11 (fpac_t *src1, fpac_t *src2, fpac_t *frac); -void frac_mulfp11 (fpac_t *src1, fpac_t *src2); -int32 roundfp11 (fpac_t *src); -int32 round_and_pack (fpac_t *fac, int32 exp, fpac_t *frac, int r); - -extern int32 GeteaW (int32 spec); -extern int32 ReadW (int32 addr); -extern void WriteW (int32 data, int32 addr); - -/* Set up for instruction decode and execution */ - -void fp11 (int32 IR) -{ -int32 dst, ea, ac, dstspec; -int32 i, qdouble, lenf, leni; -int32 newV, exp, sign; -fpac_t fac, fsrc, modfrac; -static const unsigned int32 i_limit[2][2] = - { { 0x80000000, 0x80010000 }, { 0x80000000, 0x80000001 } }; - -backup_PC = PC; /* save PC for FEA */ -ac = (IR >> 6) & 03; /* fac is IR<7:6> */ -dstspec = IR & 077; -qdouble = FPS & FPS_D; -lenf = qdouble? QUAD: LONG; -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; - case 1: /* LDFPS */ - 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; - case 3: /* STST */ - 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 */ - -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; - case 1: /* TSTf */ - 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; - 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> */ - break; /* end case 1 */ -case 5: /* LDf */ - ReadFP (&fsrc, GeteaFP (dstspec, lenf), dstspec, lenf); - F_STORE (qdouble, fsrc, FR[ac]); - FPS = setfcc (FPS, fsrc.h, 0); - break; -case 010: /* STf */ - F_LOAD (qdouble, FR[ac], fac); - WriteFP (&fac, GeteaFP (dstspec, lenf), dstspec, lenf); - break; -case 017: /* LDCff' */ - ReadFP (&fsrc, GeteaFP (dstspec, 12 - lenf), dstspec, 12 - lenf); - if (GET_EXP (fsrc.h) == 0) fsrc = zero_fac; - if ((FPS & (FPS_D + FPS_T)) == 0) newV = roundfp11 (&fsrc); - else newV = 0; - F_STORE (qdouble, fsrc, FR[ac]); - FPS = setfcc (FPS, fsrc.h, newV); - break; -case 014: /* STCff' */ - F_LOAD (qdouble, FR[ac], fac); - if (GET_EXP (fac.h) == 0) fac = zero_fac; - if ((FPS & (FPS_D + FPS_T)) == FPS_D) newV = roundfp11 (&fac); - else newV = 0; - WriteFP (&fac, GeteaFP (dstspec, 12 - lenf), dstspec, 12 - lenf); - FPS = setfcc (FPS, fac.h, newV); - break; - -/* Compare instruction */ - -case 7: /* CMPf */ - ReadFP (&fsrc, GeteaFP (dstspec, lenf), dstspec, lenf); - F_LOAD (qdouble, FR[ac], fac); - 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) | ((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; - break; - -/* Load and store exponent instructions */ - -case 015: /* LDEXP */ - dst = (dstspec <= 07)? R[dstspec]: ReadW (GeteaW (dstspec)); - F_LOAD (qdouble, FR[ac], fac); - 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; } } - F_STORE (qdouble, fac, FR[ac]); - FPS = setfcc (FPS, fac.h, newV); - break; -case 012: /* STEXP */ - dst = (GET_EXP (FR[ac].h) - FP_BIAS) & 0177777; - N = GET_SIGN_W (dst); - Z = (dst == 0); - V = 0; - C = 0; - FPS = (FPS & ~FPS_CC) | (N << PSW_V_N) | (Z << PSW_V_Z); - if (dstspec <= 07) R[dstspec] = dst; - else WriteW (dst, GeteaW (dstspec)); - break; - -/* Integer convert instructions */ - -case 016: /* LDCif */ - leni = FPS & FPS_L? LONG: WORD; - if (dstspec <= 07) fac.l = R[dstspec] << 16; - 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); } - F_STORE (qdouble, fac, FR[ac]); - FPS = setfcc (FPS, fac.h, 0); - break; -case 013: /* STCfi */ - sign = GET_SIGN (FR[ac].h); /* get sign, */ - 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; } - 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 { - 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); - if (dstspec <= 07) R[dstspec] = (dst >> 16) & 0177777; - else WriteI (dst, GeteaFP (dstspec, leni), dstspec, leni); - break; - -/* Calculation instructions */ - -case 2: /* MULf */ - ReadFP (&fsrc, GeteaFP (dstspec, lenf), dstspec, lenf); - F_LOAD (qdouble, FR[ac], fac); - newV = mulfp11 (&fac, &fsrc); - F_STORE (qdouble, fac, FR[ac]); - FPS = setfcc (FPS, fac.h, newV); - break; -case 3: /* MODf */ - ReadFP (&fsrc, GeteaFP (dstspec, lenf), dstspec, lenf); - F_LOAD (qdouble, FR[ac], fac); - newV = modfp11 (&fac, &fsrc, &modfrac); - F_STORE (qdouble, fac, FR[ac | 1]); - F_STORE (qdouble, modfrac, FR[ac]); - FPS = setfcc (FPS, modfrac.h, newV); - break; -case 4: /* ADDf */ - ReadFP (&fsrc, GeteaFP (dstspec, lenf), dstspec, lenf); - F_LOAD (qdouble, FR[ac], fac); - newV = addfp11 (&fac, &fsrc); - F_STORE (qdouble, fac, FR[ac]); - FPS = setfcc (FPS, fac.h, newV); - break; -case 6: /* SUBf */ - ReadFP (&fsrc, GeteaFP (dstspec, lenf), dstspec, lenf); - F_LOAD (qdouble, FR[ac], fac); - if (GET_EXP (fsrc.h) != 0) fsrc.h = fsrc.h ^ FP_SIGN; - newV = addfp11 (&fac, &fsrc); - F_STORE (qdouble, fac, FR[ac]); - FPS = setfcc (FPS, fac.h, newV); - break; -case 011: /* DIVf */ - ReadFP (&fsrc, GeteaFP (dstspec, lenf), dstspec, lenf); - F_LOAD (qdouble, FR[ac], fac); - newV = divfp11 (&fac, &fsrc); - F_STORE (qdouble, fac, FR[ac]); - FPS = setfcc (FPS, fac.h, newV); - break; } /* end switch fop */ -return; -} - -/* Effective address calculation for fp operands - - Inputs: - spec = specifier - len = length - Outputs: - VA = virtual address - - Warnings: - - Do not call this routine for integer mode 0 operands - - Do not call this routine more than once per instruction -*/ - -int32 GeteaFP (int32 spec, int32 len) -{ -int32 adr, reg, ds; -extern int32 cm, isenable, dsenable, MMR0, MMR1; - -reg = spec & 07; /* reg number */ -ds = (reg == 7)? isenable: dsenable; /* dspace if not PC */ -switch (spec >> 3) { /* case on spec */ -case 0: /* floating AC */ - if (reg >= 06) { fpnotrap (FEC_OP); ABORT (TRAP_INT); } - return 0; -case 1: /* (R) */ - return (R[reg] | ds); -case 2: /* (R)+ */ - if (reg == 7) len = 2; - R[reg] = ((adr = R[reg]) + len) & 0177777; - if (update_MM) MMR1 = (len << 3) | reg; - return (adr | ds); -case 3: /* @(R)+ */ - R[reg] = ((adr = R[reg]) + 2) & 0177777; - if (update_MM) MMR1 = 020 | reg; - adr = ReadW (adr | ds); - return (adr | dsenable); -case 4: /* -(R) */ - adr = R[reg] = (R[reg] - len) & 0177777; - if (update_MM) MMR1 = (((-len) & 037) << 3) | reg; - if ((adr < STKLIM) && (reg == 6) && (cm == MD_KER)) { - 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 == MD_KER)) { - setTRAP (TRAP_YEL); - setCPUERR (CPUE_YEL); } - adr = ReadW (adr | ds); - return (adr | dsenable); -case 6: /* d(r) */ - adr = ReadW (PC | isenable); - PC = (PC + 2) & 0177777; - return (((R[reg] + adr) & 0177777) | dsenable); -case 7: /* @d(R) */ - adr = ReadW (PC | isenable); - PC = (PC + 2) & 0177777; - adr = ReadW (((R[reg] + adr) & 0177777) | dsenable); - return (adr | dsenable); } /* end switch */ -return 0; -} - -/* Read integer operand - - Inputs: - VA = virtual address, VA<18:16> = mode, I/D space - spec = specifier - len = length (2/4 bytes) - Outputs: - data = data read from memory or I/O space -*/ - -unsigned int32 ReadI (int32 VA, int32 spec, int32 len) -{ -if ((len == WORD) || (spec == 027)) return (ReadW (VA) << 16); -return ((ReadW (VA) << 16) | ReadW ((VA & ~0177777) | ((VA + 2) & 0177777))); -} - -/* Read floating operand - - Inputs: - fptr = pointer to output - VA = virtual address, VA<18:16> = mode, I/D space - spec = specifier - len = length (4/8 bytes) -*/ - -void ReadFP (fpac_t *fptr, int32 VA, int32 spec, int32 len) -{ -int32 exta; - -if (spec <= 07) { - F_LOAD_P (len == QUAD, FR[spec], fptr); - return; } -if (spec == 027) { - fptr->h = (ReadW (VA) << FP_V_F0); - fptr->l = 0; } -else { exta = VA & ~0177777; - fptr->h = (ReadW (VA) << FP_V_F0) | - (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); - else fptr->l = 0; } -if ((GET_SIGN (fptr->h) != 0) && (GET_EXP (fptr->h) == 0) && - (fpnotrap (FEC_UNDFV) == 0)) ABORT (TRAP_INT); -return; -} - -/* Write integer result - - Inputs: - data = data to be written - VA = virtual address, VA<18:16> = mode, I/D space - spec = specifier - len = length - Outputs: none -*/ - -void WriteI (int32 data, int32 VA, int32 spec, int32 len) -{ -WriteW ((data >> 16) & 0177777, VA); -if ((len == WORD) || (spec == 027)) return; -WriteW (data & 0177777, (VA & ~0177777) | ((VA + 2) & 0177777)); -return; -} - -/* Write floating result - - Inputs: - fptr = pointer to data to be written - VA = virtual address, VA<18:16> = mode, I/D space - spec = specifier - len = length - Outputs: none -*/ - -void WriteFP (fpac_t *fptr, int32 VA, int32 spec, int32 len) -{ -int32 exta; - -if (spec <= 07) { - F_STORE_P (len == QUAD, fptr, FR[spec]); - return; } -WriteW ((fptr->h >> FP_V_F0) & 0177777, VA); -if (spec == 027) return; -exta = VA & ~0177777; -WriteW ((fptr->h >> FP_V_F1) & 0177777, exta | ((VA + 2) & 0177777)); -if (len == LONG) return; -WriteW ((fptr->l >> FP_V_F2) & 0177777, exta | ((VA + 4) & 0177777)); -WriteW ((fptr->l >> FP_V_F3) & 0177777, exta | ((VA + 6) & 0177777)); -return; -} - -/* Floating point add - - Inputs: - facp = pointer to src1 (output) - fsrcp = pointer to src2 - Outputs: - ovflo = overflow variable -*/ - -int32 addfp11 (fpac_t *facp, fpac_t *fsrcp) -{ -int32 facexp, fsrcexp, ediff; -fpac_t facfrac, fsrcfrac; - -if (F_LT_AP (facp, fsrcp)) { /* if !fac! < !fsrc! */ - facfrac = *facp; - *facp = *fsrcp; /* swap operands */ - *fsrcp = facfrac; } -facexp = GET_EXP (facp->h); /* get exponents */ -fsrcexp = GET_EXP (fsrcp->h); -if (facexp == 0) { /* fac = 0? */ - *facp = fsrcexp? *fsrcp: zero_fac; /* result fsrc or 0 */ - return 0; } -if (fsrcexp == 0) return 0; /* fsrc = 0? no op */ -ediff = facexp - fsrcexp; /* exponent diff */ -if (ediff >= 60) return 0; /* too big? no op */ -F_GET_FRAC_P (facp, facfrac); /* get fractions */ -F_GET_FRAC_P (fsrcp, fsrcfrac); -F_LSH_GUARD (facfrac); /* guard fractions */ -F_LSH_GUARD (fsrcfrac); -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; } - 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; } } - while (GET_BIT (facfrac.h, FP_V_HB + FP_GUARD) == 0) { - 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; } } -return round_and_pack (facp, facexp, &facfrac, 1); -} - -/* Floating point multiply - - Inputs: - facp = pointer to src1 (output) - fsrcp = pointer to src2 - Outputs: - ovflo = overflow indicator -*/ - -int32 mulfp11 (fpac_t *facp, fpac_t *fsrcp) -{ -int32 facexp, fsrcexp; -fpac_t facfrac, fsrcfrac; - -facexp = GET_EXP (facp->h); /* get exponents */ -fsrcexp = GET_EXP (fsrcp->h); -if ((facexp == 0) || (fsrcexp == 0)) { /* test for zero */ - *facp = zero_fac; - return 0; } -F_GET_FRAC_P (facp, facfrac); /* get fractions */ -F_GET_FRAC_P (fsrcp, fsrcfrac); -facexp = facexp + fsrcexp - FP_BIAS; /* calculate exp */ -facp->h = facp->h ^ fsrcp->h; /* calculate sign */ -frac_mulfp11 (&facfrac, &fsrcfrac); /* multiply fracs */ - -/* Multiplying two numbers in the range [.5,1) produces a result in the - range [.25,1). Therefore, at most one bit of normalization is required - to bring the result back to the range [.5,1). -*/ - -if (GET_BIT (facfrac.h, FP_V_HB + FP_GUARD) == 0) { - F_LSH_1 (facfrac); - facexp = facexp - 1; } -return round_and_pack (facp, facexp, &facfrac, 1); -} - -/* Floating point mod - - Inputs: - facp = pointer to src1 (integer result) - fsrcp = pointer to src2 - fracp = pointer to fractional result - Outputs: - ovflo = overflow indicator - - See notes on multiply for initial operation -*/ - -int32 modfp11 (fpac_t *facp, fpac_t *fsrcp, fpac_t *fracp) -{ -int32 facexp, fsrcexp; -fpac_t facfrac, fsrcfrac, fmask; - -facexp = GET_EXP (facp->h); /* get exponents */ -fsrcexp = GET_EXP (fsrcp->h); -if ((facexp == 0) || (fsrcexp == 0)) { /* test for zero */ - *fracp = zero_fac; - *facp = zero_fac; - return 0; } -F_GET_FRAC_P (facp, facfrac); /* get fractions */ -F_GET_FRAC_P (fsrcp, fsrcfrac); -facexp = facexp + fsrcexp - FP_BIAS; /* calculate exp */ -fracp->h = facp->h = facp->h ^ fsrcp->h; /* calculate sign */ -frac_mulfp11 (&facfrac, &fsrcfrac); /* multiply fracs */ - -/* Multiplying two numbers in the range [.5,1) produces a result in the - range [.25,1). Therefore, at most one bit of normalization is required - to bring the result back to the range [.5,1). -*/ - -if (GET_BIT (facfrac.h, FP_V_HB + FP_GUARD) == 0) { - F_LSH_1 (facfrac); - facexp = facexp - 1; } - -/* There are three major cases of MODf: - - 1. Exp <= FP_BIAS (all fraction). Return 0 as integer, product as - fraction. Underflow can occur. - 2. Exp > FP_BIAS + #fraction bits (all integer). Return product as - integer, 0 as fraction. Overflow can occur. - 3. FP_BIAS < exp <= FP_BIAS + #fraction bits. Separate integer and - fraction and return both. Neither overflow nor underflow can occur. -*/ - - if (facexp <= FP_BIAS) { /* case 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); } - 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); } - facfrac.l = facfrac.l & ~fmask.l; - facfrac.h = facfrac.h & ~fmask.h; - return round_and_pack (facp, facexp, &facfrac, 0); -} - -/* Fraction multiply - - Inputs: - f1p = pointer to multiplier (output) - f2p = pointer to multiplicand fraction - - Note: the inputs are unguarded; the output is guarded. - - This routine performs a classic shift-and-add multiply. The low - order bit of the multiplier is tested; if 1, the multiplicand is - added into the high part of the double precision result. The - result and the multiplier are both shifted right 1. - - For the 24b x 24b case, this routine develops 48b of result. - For the 56b x 56b case, this routine only develops the top 64b - of the the result. Because the inputs are normalized fractions, - the interesting part of the result is the high 56+guard bits. - Everything shifted off to the right, beyond 64b, plays no part - in rounding or the result. - - There are many possible optimizations in this routine: scanning - for groups of zeroes, particularly in the 56b x 56b case; using - "extended multiply" capability if available in the hardware. -*/ - -void frac_mulfp11 (fpac_t *f1p, fpac_t *f2p) -{ -fpac_t result, mpy, mpc; -int32 i; - -result = zero_fac; /* clear result */ -mpy = *f1p; /* get operands */ -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; } } -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); } - F_RSH_1 (result); - mpy.h = mpy.h >> 1; } } -*f1p = result; -return; -} - -/* Floating point divide - - Inputs: - facp = pointer to dividend (output) - fsrcp = pointer to divisor - Outputs: - ovflo = overflow indicator -*/ - -int32 divfp11 (fpac_t *facp, fpac_t *fsrcp) -{ -int32 facexp, fsrcexp, i, count, qd; -fpac_t facfrac, fsrcfrac, quo; - -fsrcexp = GET_EXP (fsrcp->h); /* get divisor exp */ -if (fsrcexp == 0) { /* divide by zero? */ - fpnotrap (FEC_DZRO); - ABORT (TRAP_INT); } -facexp = GET_EXP (facp->h); /* get dividend exp */ -if (facexp == 0) { /* test for zero */ - *facp = zero_fac; /* result zero */ - return 0; } -F_GET_FRAC_P (facp, facfrac); /* get fractions */ -F_GET_FRAC_P (fsrcp, fsrcfrac); -F_LSH_GUARD (facfrac); /* guard fractions */ -F_LSH_GUARD (fsrcfrac); -facexp = facexp - fsrcexp + FP_BIAS + 1; /* calculate exp */ -facp->h = facp->h ^ fsrcp->h; /* calculate sign */ -qd = FPS & FPS_D; -count = FP_V_HB + FP_GUARD + (qd? 33: 1); /* count = 56b/24b */ - -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_LSH_1 (facfrac); } /* shift divd */ -if (i > 0) { F_LSH_V (quo, i, quo); } /* early exit? */ - -/* Dividing two numbers in the range [.5,1) produces a result in the - range [.5,2). Therefore, at most one bit of normalization is required - to bring the result back to the range [.5,1). The choice of counts - and quotient bit positions makes this work correctly. -*/ - -if (GET_BIT (quo.h, FP_V_HB + FP_GUARD) == 0) { - F_LSH_1 (quo); - facexp = facexp - 1; } -return round_and_pack (facp, facexp, &quo, 1); -} - -/* Update floating condition codes - Note that FC is only set by STCfi via the integer condition codes - - Inputs: - oldst = current status - result = high result - newV = new V - Outputs: - newst = new status -*/ - -int32 setfcc (int32 oldst, int32 result, int32 newV) -{ -oldst = (oldst & ~FPS_CC) | newV; -if (GET_SIGN (result)) oldst = oldst | FPS_N; -if (GET_EXP (result) == 0) oldst = oldst | FPS_Z; -return oldst; -} - -/* Round (in place) floating point number to f_floating - - Inputs: - fptr = pointer to floating number - Outputs: - ovflow = overflow -*/ - -int32 roundfp11 (fpac_t *fptr) -{ -fpac_t outf; - -outf = *fptr; /* get argument */ -F_ADD (fround_fac, outf, outf); /* round */ -if (GET_SIGN (outf.h ^ fptr->h)) { /* flipped sign? */ - outf.h = (outf.h ^ FP_SIGN) & 0xFFFFFFFF; /* restore sign */ - if (fpnotrap (FEC_OVFLO)) *fptr = zero_fac; /* if no int, clear */ - else *fptr = outf; /* return rounded */ - return FPS_V; } /* overflow */ -else { *fptr = outf; /* round was ok */ - return 0; } /* no overflow */ -} - -/* Round result of calculation, test overflow, pack - - Input: - facp = pointer to result, sign in place - exp = result exponent, right justified - fracp = pointer to result fraction, right justified with - guard bits - r = round (1) or truncate (0) - Outputs: - ovflo = overflow indicator -*/ - -int32 round_and_pack (fpac_t *facp, int32 exp, fpac_t *fracp, int r) -{ -fpac_t frac; - -frac = *fracp; /* get fraction */ -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_GUARD (frac); -facp->l = frac.l & FP_FRACL; -facp->h = (facp->h & FP_SIGN) | ((exp & FP_M_EXP) << FP_V_EXP) | - (frac.h & FP_FRACH); -if (exp > 0377) { - if (fpnotrap (FEC_OVFLO)) *facp = zero_fac; - return FPS_V; } -if ((exp <= 0) && (fpnotrap (FEC_UNFLO))) *facp = zero_fac; -return 0; -} - -/* Process floating point exception - - Inputs: - code = exception code - Outputs: - int = FALSE if interrupt enabled, TRUE if disabled -*/ - -int32 fpnotrap (int32 code) -{ -static const int32 test_code[] = { 0, 0, 0, FPS_IC, FPS_IV, FPS_IU, FPS_IUV }; - -if ((code >= FEC_ICVT) && (code <= FEC_UNDFV) && - ((FPS & test_code[code >> 1]) == 0)) return TRUE; -FPS = FPS | FPS_ER; -FEC = code; -FEA = (backup_PC - 2) & 0177777; -if ((FPS & FPS_ID) == 0) setTRAP (TRAP_FPE); -return FALSE; -} diff --git a/PDP11/pdp11_hk.c b/PDP11/pdp11_hk.c deleted file mode 100644 index 31f35e52..00000000 --- a/PDP11/pdp11_hk.c +++ /dev/null @@ -1,1134 +0,0 @@ -/* pdp11_hk.c - RK611/RK06/RK07 disk controller - - 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 PUHKOSE 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. - - hk RK611/RK06/RK07 disk - - 25-Apr-03 RMS Revised for extended file support - - This is a somewhat abstracted implementation of the RK611, more closely - modelled on third party clones than DEC's own implementation. In particular, - the drive-to-controller serial communications system is simulated only at - a level equal to the Emulex SC21. - - The RK611 functions only in 18b Unibus systems with I/O maps. The Emulex - SC02/C was a Qbus work-alike with a unique extension to 22b addressing. It - was only supported in Ultrix-11 and other third party software. - - This module includes ideas from a previous implementation by Fred Van Kempen. -*/ - -#include "pdp11_defs.h" - -#define HK_RDX 8 -#define HK_WID 16 -extern int32 cpu_18b, cpu_ubm; - -extern uint16 *M; - -#define HK_NUMDR 8 /* #drives */ -#define HK_NUMCY6 411 /* cyl/drive */ -#define HK_NUMCY7 815 /* cyl/drive */ -#define HK_NUMSF 3 /* tracks/cyl */ -#define HK_NUMSC 22 /* sectors/track */ -#define HK_NUMWD 256 /* words/sector */ -#define RK06_SIZE (HK_NUMCY6*HK_NUMSF*HK_NUMSC*HK_NUMWD) -#define RK07_SIZE (HK_NUMCY7*HK_NUMSF*HK_NUMSC*HK_NUMWD) -#define HK_SIZE(x) (((x)->flags & UNIT_DTYPE)? RK07_SIZE: RK06_SIZE) -#define HK_CYL(x) (((x)->flags & UNIT_DTYPE)? HK_NUMCY7: HK_NUMCY6) -#define HK_MAXFR (1 << 16) - -/* Flags in the unit flags word */ - -#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */ -#define UNIT_V_DTYPE (UNIT_V_UF + 1) /* disk type */ -#define UNIT_V_AUTO (UNIT_V_UF + 2) /* autosize */ -#define UNIT_V_DUMMY (UNIT_V_UF + 3) /* dummy flag */ -#define UNIT_WLK (1 << UNIT_V_WLK) -#define UNIT_DTYPE (1 << UNIT_V_DTYPE) -#define UNIT_RK06 (0 << UNIT_V_DTYPE) -#define UNIT_RK07 (1 << UNIT_V_DTYPE) -#define UNIT_AUTO (1 << UNIT_V_AUTO) -#define UNIT_DUMMY (1 << UNIT_V_DUMMY) -#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write prot */ - -/* Parameters in the unit descriptor */ - -#define CYL u3 /* current cylinder */ -#define FNC u4 /* function */ - -/* HKCS1 - 177440 - control/status 1 */ - -#define CS1_GO CSR_GO /* go */ -#define CS1_V_FNC 1 /* function pos */ -#define CS1_M_FNC 017 /* function mask */ -#define CS1_FNC (CS1_M_FNC << CS1_V_FNC) -#define FNC_NOP 000 /* no operation */ -#define FNC_PACK 001 /* pack acknowledge */ -#define FNC_DCLR 002 /* drive clear */ -#define FNC_UNLOAD 003 /* unload */ -#define FNC_START 004 /* start */ -#define FNC_RECAL 005 /* recalibrate */ -#define FNC_OFFSET 006 /* offset */ -#define FNC_SEEK 007 /* seek */ -#define FNC_XFER 010 -#define FNC_READ 010 /* read */ -#define FNC_WRITE 011 /* write */ -#define FNC_WRITEH 013 /* write w/ headers */ -#define FNC_READH 012 /* read w/ headers */ -#define FNC_WCHK 014 /* write check */ -#define FNC_2ND 020 /* 2nd state flag */ -#define CS1_SPA 0000040 /* spare */ -#define CS1_IE CSR_IE /* int enable */ -#define CS1_DONE CSR_DONE /* ready */ -#define CS1_V_UAE 8 /* Unibus addr ext */ -#define CS1_M_UAE 03 -#define CS1_UAE (CS1_M_UAE << CS1_V_UAE) -#define CS1_DT 0002000 /* drive type */ -#define CS1_CTO 0004000 /* ctrl timeout NI */ -#define CS1_FMT 0010000 /* 16b/18b NI */ -#define CS1_PAR 0020000 /* par err NI */ -#define CS1_DI 0040000 /* drive intr */ -#define CS1_ERR 0100000 /* error */ -#define CS1_CCLR 0100000 /* ctrl clear */ -#define CS1_RW (CS1_DT|CS1_UAE|CS1_IE|CS1_SPA|CS1_FNC|CS1_GO) -#define GET_FNC(x) (((x) >> CS1_V_FNC) & CS1_M_FNC) -#define GET_UAE(x) (((x) >> CS1_V_UAE) & CS1_M_UAE) -#define PUT_UAE(x,n) (((x) & ~ CS1_UAE) | (((n) << CS1_V_UAE) & CS1_UAE)) - -/* HKWC - 177442 - word count */ - -/* HKBA - 177444 - base address */ - -#define BA_MBZ 0000001 /* must be zero */ - -/* HKDA - 177446 - sector/track */ - -#define DA_V_SC 0 /* sector pos */ -#define DA_M_SC 037 /* sector mask */ -#define DA_V_SF 8 /* track pos */ -#define DA_M_SF 007 /* track mask */ -#define DA_MBZ 0174340 -#define GET_SC(x) (((x) >> DA_V_SC) & DA_M_SC) -#define GET_SF(x) (((x) >> DA_V_SF) & DA_M_SF) - -/* HKCS2 - 177450 - control/status 2 */ - -#define CS2_V_UNIT 0 /* unit pos */ -#define CS2_M_UNIT 07 /* unit mask */ -#define CS2_UNIT (CS2_M_UNIT << CS2_V_UNIT) -#define CS2_RLS 0000010 /* release NI */ -#define CS2_UAI 0000020 /* addr inhibit */ -#define CS2_CLR 0000040 /* controller clear */ -#define CS2_IR 0000100 /* input ready */ -#define CS2_OR 0000200 /* output ready */ -#define CS2_UFE 0000400 /* unit field err NI */ -#define CS2_MDS 0001000 /* multidrive sel NI */ -#define CS2_PGE 0002000 /* program err */ -#define CS2_NEM 0004000 /* nx mem err */ -#define CS2_NED 0010000 /* nx drive err */ -#define CS2_PE 0020000 /* parity err NI */ -#define CS2_WCE 0040000 /* write check err */ -#define CS2_DLT 0100000 /* data late NI */ -#define CS2_MBZ (CS2_CLR) -#define CS2_RW 0000037 -#define CS2_ERR (CS2_UFE | CS2_MDS | CS2_PGE | CS2_NEM | \ - CS2_NED | CS2_PE | CS2_WCE | CS2_DLT ) -#define GET_UNIT(x) (((x) >> CS2_V_UNIT) & CS2_M_UNIT) - -/* HKDS - 177452 - drive status ^ = calculated dynamically */ - -#define DS_DRA 0000001 /* ^drive avail */ -#define DS_OF 0000004 /* ^offset mode */ -#define DS_ACLO 0000010 /* ^AC LO NI */ -#define DS_SPLS 0000020 /* ^speed loss NI */ -#define DS_DOT 0000040 /* ^off track NI */ -#define DS_VV 0000100 /* volume valid */ -#define DS_RDY 0000200 /* ^drive ready */ -#define DS_DT 0000400 /* ^drive type */ -#define DS_WRL 0004000 /* ^write locked */ -#define DS_PIP 0020000 /* pos in progress */ -#define DS_ATA 0040000 /* attention active */ -#define DS_VLD 0100000 /* ^status valid */ -#define DS_MBZ 0013002 - -/* HKER - 177454 - error status */ - -#define ER_ILF 0000001 /* illegal func */ -#define ER_SKI 0000002 /* seek incomp */ -#define ER_NXF 0000004 /* non-exec func */ -#define ER_PAR 0000010 /* parity err */ -#define ER_FER 0000020 /* format err NI */ -#define ER_DTY 0000040 /* drive type err */ -#define ER_ECH 0000100 /* ECC hard err NI */ -#define ER_BSE 0000200 /* bad sector err NI */ -#define ER_HCR 0000400 /* hdr CRC err NI */ -#define ER_AOE 0001000 /* addr ovflo err */ -#define ER_IAE 0002000 /* invalid addr err */ -#define ER_WLE 0004000 /* write lock err */ -#define ER_DTE 0010000 /* drive time err NI */ -#define ER_OPI 0020000 /* op incomplete */ -#define ER_UNS 0040000 /* drive unsafe */ -#define ER_DCK 0100000 /* data check NI */ - -/* HKAS - 177456 - attention summary/offset */ - -#define AS_U0 0000400 /* unit 0 flag */ -#define AS_OF 0000277 /* offset mask */ - -/* HKDC - 177460 - desired cylinder */ - -#define DC_V_CY 0 /* cylinder pos */ -#define DC_M_CY 0001777 /* cylinder mask */ -#define DC_MBZ 0176000 -#define GET_CY(x) (((x) >> DC_V_CY) & DC_M_CY) -#define GET_DA(c,fs) ((((GET_CY (c) * HK_NUMSF) + \ - GET_SF (fs)) * HK_NUMSC) + GET_SC (fs)) - -/* Spare - 177462 - read/write */ - -#define XM_KMASK 0177700 /* Qbus XM key mask */ -#define XM_KEY 0022000 /* Qbus XM "key" */ -#define XM_MMASK 0000077 /* Qbus XM mask */ -#define SC02C (!UNIBUS && ((hkspr & XM_KMASK) == XM_KEY)) - -/* HKDB - 177464 - read/write */ - -/* HKMR - 177466 - maintenance register 1 */ - -#define MR_V_MS 0 /* message select */ -#define MR_M_MS 03 -#define MR_MS (MR_M_MS << MR_V_MS) -#define GET_MS(x) (((x) >> MR_V_MS) & MR_M_MS) -#define MR_PAR 0000020 /* force even parity */ -#define MR_DMD 0000040 /* diagnostic mode */ -#define MR_RW 0001777 - -/* HKEC1 - 177470 - ECC status 1 - always reads as 0 */ -/* HKEC2 - 177472 - ECC status 2 - always reads as 0 */ - -/* HKMR2 - 177474 - maintenance register 2 */ - -#define AX_V_UNIT 0 /* unit #, all msgs */ -#define AX_PAR 0100000 /* parity, all msgs */ - -#define A0_DRA 0000040 /* drive avail */ -#define A0_VV 0000100 /* vol valid */ -#define A0_RDY 0000200 /* drive ready */ -#define A0_DT 0000400 /* drive type */ -#define A0_FMT 0001000 /* format NI */ -#define A0_OF 0002000 /* offset mode */ -#define A0_WRL 0004000 /* write lock */ -#define A0_SPO 0010000 /* spindle on */ -#define A0_PIP 0020000 /* pos in prog */ -#define A0_ATA 0040000 /* attention */ - -#define A1_SRV 0000020 /* servo */ -#define A1_HHM 0000040 /* heads home */ -#define A1_BHM 0000100 /* brushes home */ -#define A1_DOR 0000200 /* door latched */ -#define A1_CAR 0000400 /* cartridge present */ -#define A1_SPD 0001000 /* speed ok */ -#define A1_FWD 0002000 /* seek fwd */ -#define A1_REV 0004000 /* seek rev */ -#define A1_LDH 0010000 /* loading heads NI */ -#define A1_RTZ 0020000 /* return to zero */ -#define A1_UNL 0040000 /* unloading heads */ - -#define A2_V_DIF 4 /* cyl diff */ -#define A2_M_DIF 0777 - -#define A3_V_SNO 3 /* serial # */ - -/* HKMR3 - 177476 - maintenance register 3 */ - -#define B0_IAE 0000040 /* invalid addr */ -#define B0_ACLO 0000100 /* AC LO NI */ -#define B0_FLT 0000200 /* fault */ -#define B0_NXF 0000400 /* non exec fnc */ -#define B0_CDP 0001000 /* msg parity err */ -#define B0_SKI 0002000 /* seek incomp */ -#define B0_WLE 0004000 /* write lock err */ -#define B0_SLO 0010000 /* speed low NI */ -#define B0_OFT 0020000 /* off track NI */ -#define B0_UNS 0040000 /* rw unsafe NI */ - -#define B1_SCE 0000020 /* sector err NI */ -#define B1_NWC 0000040 /* no write curr NI */ -#define B1_NWT 0000100 /* no write trans NI */ -#define B1_HFL 0000200 /* head fault NI */ -#define B1_MHS 0000400 /* multiselect NI */ -#define B1_IDX 0001000 /* index err NI */ -#define B1_TRI 0002000 /* tribit err NI */ -#define B1_SVE 0004000 /* servo err NI */ -#define B1_SKI 0010000 /* seek no mot */ -#define B1_LIM 0020000 /* seek limit NI */ -#define B1_SVU 0040000 /* servo unsafe NI */ - -#define B2_V_CYL 4 /* cylinder */ - -#define B3_V_SEC 4 /* sector */ -#define B3_V_DHA 9 /* decoded head */ - -/* Read header */ - -#define RDH1_V_CYL 0 /* cylinder */ -#define RDH2_V_SEC 0 /* sector */ -#define RDH2_V_DHA 5 /* decoded head */ -#define RDH2_GOOD 0140000 /* good sector flags */ - -extern int32 int_req[IPL_HLVL]; -extern int32 int_vec[IPL_HLVL][32]; -extern int32 cpu_log; -extern FILE *sim_log; - -uint16 *hkxb = NULL; /* xfer buffer */ -int32 hkcs1 = 0; /* control/status 1 */ -int32 hkwc = 0; /* word count */ -int32 hkba = 0; /* bus address */ -int32 hkda = 0; /* track/sector */ -int32 hkcs2 = 0; /* control/status 2 */ -int32 hkds[HK_NUMDR] = { 0 }; /* drive status */ -int32 hker[HK_NUMDR] = { 0 }; /* error status */ -int32 hkof = 0; /* offset */ -int32 hkmr = 0; /* maint registers */ -int32 hkmr2 = 0; -int32 hkmr3 = 0; -int32 hkdc = 0; /* cylinder */ -int32 hkspr = 0; /* spare */ -int32 hk_stopioe = 1; /* stop on error */ -int32 hk_cwait = 5; /* command time */ -int32 hk_swait = 10; /* seek time */ -int32 hk_rwait = 10; /* rotate time */ -int16 hkdb[3] = { 0 }; /* data buffer silo */ -int16 hk_off[HK_NUMDR] = { 0 }; /* saved offset */ -int16 hk_dif[HK_NUMDR] = { 0 }; /* cylinder diff */ -static int32 reg_in_drive[16] = { - 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - -DEVICE hk_dev; -t_stat hk_rd (int32 *data, int32 PA, int32 access); -t_stat hk_wr (int32 data, int32 PA, int32 access); -t_stat hk_svc (UNIT *uptr); -t_stat hk_reset (DEVICE *dptr); -t_stat hk_boot (int32 unitno, DEVICE *dptr); -t_stat hk_attach (UNIT *uptr, char *cptr); -t_stat hk_detach (UNIT *uptr); -int32 hk_rdmr2 (int32 msg); -int32 hk_rdmr3 (int32 msg); -void update_hkcs (int32 flags, int32 drv); -void update_hkds (int32 drv); -void hk_cmderr (int32 err, int32 drv); -void hk_go (int32 drv); -t_stat hk_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat hk_set_bad (UNIT *uptr, int32 val, char *cptr, void *desc); - -extern t_stat pdp11_bad_block (UNIT *uptr, int32 sec, int32 wds); - -/* HK data structures - - hk_dev HK device descriptor - hk_unit HK unit list - hk_reg HK register list - hk_mod HK modifier list -*/ - -DIB hk_dib = { IOBA_HK, IOLN_HK, &hk_rd, &hk_wr, - 1, IVCL (HK), VEC_HK, { NULL } }; - -UNIT hk_unit[] = { - { UDATA (&hk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+ - UNIT_ROABLE+UNIT_RK06, RK06_SIZE) }, - { UDATA (&hk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+ - UNIT_ROABLE+UNIT_RK06, RK06_SIZE) }, - { UDATA (&hk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+ - UNIT_ROABLE+UNIT_RK06, RK06_SIZE) }, - { UDATA (&hk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+ - UNIT_ROABLE+UNIT_RK06, RK06_SIZE) }, - { UDATA (&hk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+ - UNIT_ROABLE+UNIT_RK06, RK06_SIZE) }, - { UDATA (&hk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+ - UNIT_ROABLE+UNIT_RK06, RK06_SIZE) }, - { UDATA (&hk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+ - UNIT_ROABLE+UNIT_RK06, RK06_SIZE) }, - { UDATA (&hk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+ - UNIT_ROABLE+UNIT_RK06, RK06_SIZE) } }; - -REG hk_reg[] = { - { GRDATA (HKCS1, hkcs1, HK_RDX, 16, 0) }, - { GRDATA (HKWC, hkwc, HK_RDX, 16, 0) }, - { GRDATA (HKBA, hkba, HK_RDX, 16, 0) }, - { GRDATA (HKDA, hkda, HK_RDX, 16, 0) }, - { GRDATA (HKCS2, hkcs2, HK_RDX, 16, 0) }, - { BRDATA (HKDS, hkds, HK_RDX, 16, HK_NUMDR) }, - { BRDATA (HKER, hker, HK_RDX, 16, HK_NUMDR) }, - { BRDATA (HKDB, hkdb, HK_RDX, 16, 3) }, - { GRDATA (HKDC, hkdc, HK_RDX, 16, 0) }, - { GRDATA (HKOF, hkof, HK_RDX, 8, 0) }, - { GRDATA (HKMR, hkmr, HK_RDX, 16, 0) }, - { GRDATA (HKMR2, hkmr2, HK_RDX, 16, 0), REG_RO }, - { GRDATA (HKMR3, hkmr3, HK_RDX, 16, 0), REG_RO }, - { GRDATA (HKSPR, hkspr, HK_RDX, 16, 0) }, - { FLDATA (INT, IREQ (HK), INT_V_HK) }, - { FLDATA (ERR, hkcs1, CSR_V_ERR) }, - { FLDATA (DONE, hkcs1, CSR_V_DONE) }, - { FLDATA (IE, hkcs1, CSR_V_IE) }, - { DRDATA (STIME, hk_swait, 24), REG_NZ + PV_LEFT }, - { DRDATA (RTIME, hk_rwait, 24), REG_NZ + PV_LEFT }, - { URDATA (FNC, hk_unit[0].FNC, HK_RDX, 5, 0, - HK_NUMDR, REG_HRO) }, - { URDATA (CYL, hk_unit[0].CYL, HK_RDX, 10, 0, - HK_NUMDR, REG_HRO) }, - { BRDATA (OFFSET, hk_off, HK_RDX, 16, HK_NUMDR), REG_HRO }, - { BRDATA (CYLDIF, hk_dif, HK_RDX, 16, HK_NUMDR), REG_HRO }, - { URDATA (CAPAC, hk_unit[0].capac, 10, T_ADDR_W, 0, - HK_NUMDR, PV_LEFT | REG_HRO) }, - { FLDATA (STOP_IOE, hk_stopioe, 0) }, - { GRDATA (DEVADDR, hk_dib.ba, HK_RDX, 32, 0), REG_HRO }, - { GRDATA (DEVVEC, hk_dib.vec, HK_RDX, 16, 0), REG_HRO }, - { NULL } }; - -MTAB hk_mod[] = { - { UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL }, - { UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL }, - { UNIT_DUMMY, 0, NULL, "BADBLOCK", &hk_set_bad }, - { (UNIT_DTYPE+UNIT_ATT), UNIT_RK06 + UNIT_ATT, - "RK06", NULL, NULL }, - { (UNIT_DTYPE+UNIT_ATT), UNIT_RK07 + UNIT_ATT, - "RK07", NULL, NULL }, - { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), UNIT_RK06, - "RK06", NULL, NULL }, - { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), UNIT_RK07, - "RK07", NULL, NULL }, - { (UNIT_AUTO+UNIT_ATT), UNIT_AUTO, "autosize", NULL, NULL }, - { UNIT_AUTO, UNIT_AUTO, NULL, "AUTOSIZE", NULL }, - { (UNIT_AUTO+UNIT_DTYPE), UNIT_RK06, - NULL, "RK06", &hk_set_size }, - { (UNIT_AUTO+UNIT_DTYPE), UNIT_RK07, - NULL, "RK07", &hk_set_size }, - { MTAB_XTD|MTAB_VDV, 0040, "ADDRESS", "ADDRESS", - &set_addr, &show_addr, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "VECTOR", "VECTOR", - &set_vec, &show_vec, NULL }, - { 0 } }; - -DEVICE hk_dev = { - "HK", hk_unit, hk_reg, hk_mod, - HK_NUMDR, HK_RDX, 24, 1, HK_RDX, HK_WID, - NULL, NULL, &hk_reset, - &hk_boot, &hk_attach, &hk_detach, - &hk_dib, DEV_DISABLE | DEV_UBUS }; - -/* I/O dispatch routines, I/O addresses 17777440 - 17777476 */ - -t_stat hk_rd (int32 *data, int32 PA, int32 access) -{ -int32 drv, i, j; - -drv = GET_UNIT (hkcs2); /* get current unit */ -j = (PA >> 1) & 017; /* get reg offset */ -if (reg_in_drive[j] && (hk_unit[drv].flags & UNIT_DIS)) { /* nx disk */ - hkcs2 = hkcs2 | CS2_NED; /* set error flag */ - update_hkcs (0, drv); - *data = 0; - return SCPE_OK; } - -update_hkcs (0, drv); /* update status */ -switch (j) { /* decode PA<4:1> */ -case 000: /* HKCS1 */ - *data = hkcs1; - break; -case 001: /* HKWC */ - *data = hkwc; - break; -case 002: /* HKBA */ - *data = hkba = hkba & ~BA_MBZ; - break; -case 003: /* HKDA */ - *data = hkda = hkda & ~DA_MBZ; - break; -case 004: /* HKCS2 */ - *data = hkcs2 = (hkcs2 & ~CS2_MBZ) | CS2_IR | CS2_OR; - break; -case 005: /* HKDS */ - *data = hkds[drv]; - break; -case 006: /* HKER */ - *data = hker[drv]; - break; -case 007: /* HKAS */ - *data = hkof; - for (i = 0; i < HK_NUMDR; i++) - if (hkds[i] & DS_ATA) *data = *data | (AS_U0 << i); - break; -case 010: /* HKDC */ - *data = hkdc = hkdc & ~DC_MBZ; - break; -case 011: /* spare */ - *data = hkspr; - break; -case 012: /* HKDB */ - *data = hkdb[0]; /* top of silo */ - hkdb[0] = hkdb[1]; /* ripple silo */ - hkdb[1] = hkdb[2]; - hkdb[2] = 0; /* just for READH */ - break; -case 013: /* HKMR */ - *data = hkmr; - break; -case 014: /* HKEC1 */ -case 015: /* HKEC2 */ - *data = 0; /* no ECC */ - break; -case 016: /* HKMR2 */ - *data = hkmr2 = hk_rdmr2 (GET_MS (hkmr)); - break; -case 017: /* HKMR3 */ - *data = hkmr3 = hk_rdmr3 (GET_MS (hkmr)); - break; } -return SCPE_OK; -} - -t_stat hk_wr (int32 data, int32 PA, int32 access) -{ -int32 drv, i, j; -UNIT *uptr; - -drv = GET_UNIT (hkcs2); /* get current unit */ -uptr = hk_dev.units + drv; /* get unit */ -j = (PA >> 1) & 017; /* get reg offset */ -if ((hkcs1 & CS1_GO) && /* busy? */ - !(((j == 0) && (data & CS1_CCLR)) || /* not cclr or sclr? */ - ((j == 4) && (data & CS2_CLR)))) { - hkcs2 = hkcs2 | CS2_PGE; /* prog error */ - update_hkcs (0, drv); - return SCPE_OK; } - -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; } - if (data & CS1_IE) { /* setting 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); } - break; -case 001: /* HKWC */ - hkwc = data; - break; -case 002: /* HKBA */ - hkba = data & ~BA_MBZ; - break; -case 003: /* HKDA */ - hkda = data & ~DA_MBZ; - break; -case 004: /* HKCS2 */ - if (data & CS2_CLR) hk_reset (&hk_dev); /* init? */ - else hkcs2 = (hkcs2 & ~CS2_RW) | (data & CS2_RW) | CS2_IR | CS2_OR; - drv = GET_UNIT (hkcs2); - break; -case 007: /* HKAS */ - hkof = data & AS_OF; - break; -case 010: /* HKDC */ - hkdc = data & ~DC_MBZ; - break; -case 011: /* spare */ - hkspr = data; - if (SC02C) hkcs1 = PUT_UAE (hkcs1, hkspr & 03); /* SC02C? upd UAE */ - break; -case 012: /* HKDB */ - hkdb[0] = data; - break; -case 013: /* HKMR */ - hkmr = data & MR_RW; - break; -default: /* all others RO */ - break; } /* end switch */ -update_hkcs (0, drv); /* update status */ -return SCPE_OK; -} - -/* Initiate operation - unit not busy, function set */ - -void hk_go (int32 drv) -{ - -int32 fnc, t; -UNIT *uptr; -static int32 fnc_nxf[16] = { - 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0 }; -static int32 fnc_att[16] = { - 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 }; -static int32 fnc_rdy[16] = { - 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 }; -static int32 fnc_cyl[16] = { - 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0 }; - -fnc = GET_FNC (hkcs1); -if (DBG_LOG (LOG_HK)) fprintf (sim_log, - ">>HK%d: fnc=%o, ds=%o, cyl=%o, da=%o, ba=%o, wc=%o\n", - drv, fnc, hkds[drv], hkdc, hkda, hkba, hkwc); -uptr = hk_dev.units + drv; /* get unit */ -if (fnc != FNC_NOP) hkmr = hkmr & ~MR_MS; /* !nop, clr msg sel */ -if (uptr->flags & UNIT_DIS) { /* nx unit? */ - hkcs2 = hkcs2 | CS2_NED; /* set error flag */ - update_hkcs (CS1_DONE, drv); /* done */ - return; } -if (((hkcs1 & CS1_DT) != 0) != /* dtype mismatch? */ - ((uptr->flags & UNIT_DTYPE) != 0)) { - hk_cmderr (ER_DTY, drv); /* type error */ - return; } -if (fnc_nxf[fnc] && ((hkds[drv] & DS_VV) == 0)) { /* need vol valid? */ - hk_cmderr (ER_NXF, drv); /* non exec func */ - return; } -if (fnc_att[fnc] && ((uptr->flags & UNIT_ATT) == 0)) { /* need attached? */ - hk_cmderr (ER_UNS, drv); /* unsafe */ - return; } -if (fnc_rdy[fnc] && sim_is_active (uptr)) { /* need inactive? */ - hkcs1 = (hkcs1 | CS1_DONE) & ~CS1_GO; /* ignore if busy */ - return; } -if (fnc_cyl[fnc] && /* need valid cyl */ - ((GET_CY (hkdc) >= HK_CYL (uptr)) || /* bad cylinder */ - (GET_SF (hkda) >= HK_NUMSF) || /* bad surface */ - (GET_SC (hkda) >= HK_NUMSC))) { /* or bad sector? */ - hk_cmderr (ER_IAE, drv); /* illegal addr */ - return; } - -hkcs1 = hkcs1 & ~CS1_DONE; /* clear done */ -hkds[drv] = hkds[drv] & ~DS_ATA; /* clear attention */ -uptr->FNC = fnc; /* save function */ -switch (fnc) { /* case on function */ - -/* "Fast functions" finish in less than 15 usec */ - -case FNC_NOP: /* no operation */ -case FNC_DCLR: /* drive clear */ -case FNC_START: /* start spindle */ -case FNC_UNLOAD: /* unload */ -case FNC_PACK: /* pack acknowledge */ - sim_activate (uptr, hk_cwait); /* schedule */ - return; - -/* Positioning functions provide two interrupts - an immediate interrupt - on ctrl done and a second one (if ctrl ready) when the seek is complete */ - -case FNC_OFFSET: /* offset mode */ -case FNC_RECAL: /* recalibrate */ -case FNC_SEEK: /* seek */ - hkds[drv] = hkds[drv] | DS_PIP; /* set positioning */ - sim_activate (uptr, hk_cwait); /* schedule */ - return; - -/* Data transfer functions lock the controller for the duration */ - -case FNC_WRITEH: /* write headers */ -case FNC_WRITE: /* write */ - hk_off[drv] = 0; /* clr offset */ -case FNC_WCHK: /* write check */ -case FNC_READ: /* read */ -case FNC_READH: /* read headers */ - hk_dif[drv] = hkdc - uptr->CYL; /* cyl diff */ - t = abs (hk_dif[drv]); /* |cyl diff| */ - sim_activate (uptr, hk_rwait + (hk_swait * t)); /* Schedule */ - uptr->CYL = hkdc; /* update cyl */ - return; - -default: - hk_cmderr (ER_ILF, drv); /* not supported */ - break; } -return; -} - -/* Service unit timeout - - Complete movement or data transfer command - Unit must exist - can't remove an active unit - Unit must be attached - detach cancels in progress operations -*/ - -t_stat hk_svc (UNIT *uptr) -{ -int32 i, t, dc, drv, fnc, err; -int32 wc, awc, da; -uint32 ba; -uint16 comp; - -drv = uptr - hk_dev.units; /* get drv number */ -fnc = uptr->FNC & CS1_M_FNC; /* get function */ -switch (fnc) { /* case on function */ - -/* Fast commands and other NOPs - start spindle only provides one interrupt - because ATTACH implicitly spins up the drive */ - -case FNC_DCLR: /* drive clear */ - hker[drv] = 0; /* clear errors */ - update_hkcs (CS1_DONE, drv); /* done */ - break; - -case FNC_PACK: /* pack acknowledge */ - hkds[drv] = hkds[drv] | DS_VV; /* set volume valid */ - update_hkcs (CS1_DONE, drv); /* done */ - break; - -case FNC_UNLOAD: /* unload */ - hk_detach (uptr); /* detach unit */ -case FNC_START: /* start spindle */ -case FNC_NOP: /* select */ - update_hkcs (CS1_DONE, drv); /* done */ - break; - -/* Positioning commands provide two interrupts, an immediate controller done - and a delayed drive interrupt */ - -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 */ - 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 */ - break; - -/* Data transfer commands only generate one interrupt */ - -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; - 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; } -case FNC_WCHK: /* write check */ -case FNC_READ: /* read */ - if (SC02C) ba = ((hkspr & XM_MMASK) << 16) | hkba; /* 22b addr? */ - else ba = (GET_UAE (hkcs1) << 16) | hkba; /* no, 18b addr */ - da = GET_DA (hkdc, hkda) * HK_NUMWD; /* get disk addr */ - wc = 0200000 - hkwc; /* get true wc */ - - if ((da + wc) > HK_SIZE (uptr)) { /* disk overrun? */ - hker[drv] = hker[drv] | ER_AOE; /* set err */ - wc = HK_SIZE (uptr) - da; /* trim xfer */ - if (da >= HK_SIZE (uptr)) { /* none left? */ - update_hkcs (CS1_DONE, drv); /* then done */ - break; } } - - err = fseek (uptr->fileref, da * sizeof (int16), SEEK_SET); - if (uptr->FNC == FNC_WRITE) { /* write? */ - if (hkcs2 & CS2_UAI) { /* no addr inc? */ - if (t = Map_ReadW (ba, 2, &comp, MAP)) { /* get 1st wd */ - wc = 0; /* NXM, no xfr */ - hkcs2 = hkcs2 | CS2_NEM; } /* set nxm err */ - for (i = 0; i < wc; i++) hkxb[i] = comp; } - else { /* normal */ - if (t = Map_ReadW (ba, wc << 1, hkxb, MAP)) { /* get buf */ - wc = wc - (t >> 1); /* NXM, adj wc */ - hkcs2 = hkcs2 | CS2_NEM; } /* set nxm err */ - ba = ba + (wc << 1); } /* adv ba */ - awc = (wc + (HK_NUMWD - 1)) & ~(HK_NUMWD - 1); - for (i = wc; i < awc; i++) hkxb[i] = 0; /* fill buf */ - if (wc && !err) { /* write buf */ - fxwrite (hkxb, sizeof (uint16), wc, uptr->fileref); - err = ferror (uptr->fileref); } - } /* end if wr */ - else if (uptr->FNC == FNC_READ) { /* read? */ - i = fxread (hkxb, sizeof (uint16), wc, uptr->fileref); - err = ferror (uptr->fileref); - for ( ; i < wc; i++) hkxb[i] = 0; /* fill buf */ - if (hkcs2 & CS2_UAI) { /* no addr inc? */ - if (t = Map_WriteW (ba, 2, &hkxb[wc - 1], MAP)) { - wc = 0; /* NXM, no xfr */ - hkcs2 = hkcs2 | CS2_NEM; } } /* set nxm err */ - else { /* normal */ - if (t = Map_WriteW (ba, wc << 1, hkxb, MAP)) { /* put buf */ - wc = wc - (t >> 1); /* NXM, adj wc */ - hkcs2 = hkcs2 | CS2_NEM; } /* set nxm err */ - ba = ba + (wc << 1); } /* adv ba */ - } /* end if read */ - else { /* wchk */ - i = fxread (hkxb, sizeof (uint16), wc, uptr->fileref); - err = ferror (uptr->fileref); - for ( ; i < wc; i++) hkxb[i] = 0; /* fill buf */ - 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; } - if (comp != hkxb[wc]) { /* compare wd */ - hkcs2 = hkcs2 | CS2_WCE; /* set error */ - break; } - if ((hkcs2 & CS2_UAI) == 0) ba = ba + 2; } - } /* end else wchk */ - - hkwc = (hkwc + wc) & 0177777; /* final word count */ - 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); - da = da + wc + (HK_NUMWD - 1); - da = da / HK_NUMWD; - hkda = da % HK_NUMSC; - da = da / HK_NUMSC; - hkda = hkda | ((da % HK_NUMSF) << DA_V_SF); - 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; } - -case FNC_WRITEH: /* write headers stub */ - update_hkcs (CS1_DONE, drv); /* set done */ - break; } /* end case func */ -return SCPE_OK; -} - -/* Controller status update - - Check for done transition - Update drive status - Update HKCS1 - Update interrupt request -*/ - -void update_hkcs (int32 flag, int32 drv) -{ -int32 i; - -update_hkds (drv); /* upd drv status */ -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); } -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 */ - if (hkds[i] & DS_ATA) hkcs1 = hkcs1 | CS1_DI; } -if (hker[drv] | (hkcs1 & (CS1_PAR | CS1_CTO)) | /* if err, set ERR */ - (hkcs2 & CS2_ERR)) hkcs1 = hkcs1 | CS1_ERR; -return; -} - -/* Drive status update */ - -void update_hkds (drv) -{ -if (hk_unit[drv].flags & UNIT_DIS) { /* disabled? */ - hkds[drv] = hker[drv] = 0; /* all clear */ - return; } -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 */ - 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 */ -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; -return; -} - -/* Set error and abort command */ - -void hk_cmderr (int32 err, int32 drv) -{ -hker[drv] = hker[drv] | err; /* set error */ -hkds[drv] = hkds[drv] | DS_ATA; /* set attn */ -hkcs1 = hkcs1 & ~CS1_GO; /* clear go */ -update_hkcs (CS1_DONE, drv); /* set done */ -return; -} - -/* Diagnostic registers - - It's unclear whether the drivers actually use these values, but the - Emulex controller bothers to implement them, so we will too */ - -int32 hk_mrpar (int32 v) -{ -int32 bit, wrk; - -wrk = v & 077777; /* par on 15b */ -v = wrk | ((hkmr & MR_PAR)? 0: AX_PAR); /* even/odd */ -while (wrk) { /* while 1's */ - bit = wrk & (-wrk); /* lowest 1 */ - wrk = wrk & ~bit; /* clear */ - v = v ^ AX_PAR; } /* xor parity */ -return v; -} - -int32 hk_rdmr2 (int32 msg) -{ -int32 drv = GET_UNIT (hkcs2); -int32 v = drv << AX_V_UNIT; -UNIT *uptr = hk_dev.units + drv; -int32 fnc = uptr->FNC & CS1_M_FNC; - -switch (msg) { -case 0: /* message A0 */ - v = v | ((hkds[drv] & DS_ATA)? A0_ATA: 0) | - ((hkds[drv] & DS_PIP)? A0_PIP: 0) | - ((uptr->flags & UNIT_WPRT)? A0_WRL: 0) | - ((hk_off[drv])? A0_OF: 0) | - ((uptr->flags & UNIT_RK07)? A0_DT: 0) | - ((hkds[drv] & DS_VV)? A0_VV: 0) | A0_DRA; - if (uptr->flags & UNIT_ATT) v = v | A0_SPO | - (!sim_is_active (uptr)? A0_RDY: 0); - break; -case 1: /* message A1 */ - if (uptr->flags & UNIT_ATT) { - if (sim_is_active (uptr)) { - if (fnc == FNC_UNLOAD) v = v | A1_UNL; - else if (fnc == FNC_RECAL) v = v | A1_RTZ; - else if (fnc == FNC_SEEK) { - if (hk_dif[drv] < 0) v = v | A1_REV; - if (hk_dif[drv] > 0) v = v | A1_FWD; } } - v = v | (A1_SPD|A1_CAR|A1_DOR|A1_HHM|A1_SRV); } - else v = v | A1_HHM; - break; -case 2: /* message A2 */ - if (hkds[drv] & DS_OF) - v = v | ((hk_off[drv] & A2_M_DIF) << A2_V_DIF); - else v = v | ((hk_dif[drv] & A2_M_DIF) << A2_V_DIF); - break; -case 3: /* message A3 */ - v = v | ((012340 + v) << A3_V_SNO); - break; } -return hk_mrpar (v); -} - -int32 hk_rdmr3 (int32 msg) -{ -int32 drv = GET_UNIT (hkcs2); -int32 v = msg & 03; - -switch (msg) { -case 0: /* message B0 */ - v = v | ((hker[drv] & ER_WLE)? (B0_WLE | B0_FLT): 0) | - ((hker[drv] & ER_SKI)? (B0_SKI | B0_FLT): 0) | - ((hker[drv] & ER_NXF)? (B0_NXF | B0_FLT): 0) | - ((hker[drv] & ER_IAE)? (B0_IAE | B0_FLT): 0); - break; -case 1: /* message B1 */ - v = v | ((hker[drv] & ER_SKI)? B1_SKI: 0) | - ((hker[drv] & ER_UNS)? B1_SVE: 0); - break; -case 2: /* message B2 */ - v = v | (hk_unit[drv].CYL << B2_V_CYL); - break; -case 3: /* message B3 */ - v = v | (GET_SC (hkda) << B3_V_SEC) | - (1 << (GET_SF (hkda) + B3_V_DHA)); - break; } -return hk_mrpar (v); -} - -/* Device reset */ - -t_stat hk_reset (DEVICE *dptr) -{ -int32 i; -UNIT *uptr; - -hkcs1 = CS1_DONE; /* set done */ -hkcs2 = CS2_IR | CS2_OR; /* clear state */ -hkmr = hkmr2 = hkmr3 = 0; -hkda = hkdc = 0; -hkba = hkwc = 0; -hkof = hkspr = 0; -CLR_INT (HK); /* clear intr req */ -for (i = 0; i < HK_NUMDR; i++) { /* stop operations */ - uptr = hk_dev.units + i; - sim_cancel (uptr); - if (uptr->flags & UNIT_ATT) hkds[i] = hkds[i] & DS_VV; - else hkds[i] = 0; - uptr->CYL = uptr->FNC = 0; /* clear state */ - hk_dif[i] = 0; - hk_off[i] = 0; - hker[i] = 0; } /* clear errors */ -if (hkxb == NULL) hkxb = calloc (HK_MAXFR, sizeof (unsigned int16)); -if (hkxb == NULL) return SCPE_MEM; -return SCPE_OK; -} - -/* Device attach */ - -t_stat hk_attach (UNIT *uptr, char *cptr) -{ -uint32 drv, p; -t_stat r; - -uptr->capac = HK_SIZE (uptr); -r = attach_unit (uptr, cptr); /* attach unit */ -if (r != SCPE_OK) return r; /* error? */ -drv = uptr - hk_dev.units; /* get drv number */ -hkds[drv] = DS_ATA | DS_RDY | ((uptr->flags & UNIT_WPRT)? DS_WRL: 0); -hker[drv] = 0; /* upd drv status */ -hk_off[drv] = 0; -hk_dif[drv] = 0; -uptr->CYL = 0; -update_hkcs (CS1_DI, drv); /* upd ctlr status */ - -if (fseek (uptr->fileref, 0, SEEK_END)) return SCPE_OK; /* seek to end */ -if ((p = ftell (uptr->fileref)) == 0) { /* new disk image? */ - if (uptr->flags & UNIT_RO) return SCPE_OK; - return pdp11_bad_block (uptr, HK_NUMSC, HK_NUMWD); } -if ((uptr->flags & UNIT_AUTO) == 0) return SCPE_OK; /* autosize? */ -if (p > (RK06_SIZE * sizeof (int16))) { - uptr->flags = uptr->flags | UNIT_RK07; - uptr->capac = RK07_SIZE; } -else { uptr->flags = uptr->flags & ~UNIT_RK07; - uptr->capac = RK06_SIZE; } -return SCPE_OK; -} - -/* Device detach */ - -t_stat hk_detach (UNIT *uptr) -{ -int32 drv; - -drv = uptr - hk_dev.units; /* get drv number */ -hkds[drv] = (hkds[drv] & ~(DS_RDY | DS_WRL | DS_VV | DS_OF)) | DS_ATA; -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 */ -update_hkcs (CS1_DI, drv); /* request intr */ -return detach_unit (uptr); -} - -/* Set size command validation routine */ - -t_stat hk_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -if (uptr->flags & UNIT_ATT) return SCPE_ALATT; -uptr->capac = val? RK07_SIZE: RK06_SIZE; -return SCPE_OK; -} - -/* Set bad block routine */ - -t_stat hk_set_bad (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -return pdp11_bad_block (uptr, HK_NUMSC, HK_NUMWD); -} - -/* Device bootstrap - does not clear CSR when done */ - -#define BOOT_START 02000 /* start */ -#define BOOT_ENTRY (BOOT_START + 002) /* entry */ -#define BOOT_UNIT (BOOT_START + 010) /* unit number */ -#define BOOT_CSR (BOOT_START + 014) /* CSR */ -#define BOOT_LEN (sizeof (boot_rom) / sizeof (int16)) - -static const uint16 boot_rom[] = { - 0042115, /* "MD" */ - 0012706, BOOT_START, /* mov #boot_start, sp */ - 0012700, 0000000, /* mov #unit, r0 */ - 0012701, 0177440, /* mov #HKCS1, r1 */ - 0012761, 0000040, 0000010, /* mov #CS2_CLR, 10(r1) ; reset */ - 0010061, 0000010, /* mov r0, 10(r1) ; set unit */ - 0016102, 0000012, /* mov 12(r1), r2 ; drv typ */ - 0100375, /* bpl .-4 ; valid? */ - 0042702, 0177377, /* bic #177377, r2 ; clr rest */ - 0006302, /* asl r2 ; move */ - 0006302, /* asl r2 */ - 0012703, 0000003, /* mov #pack+go, r3 */ - 0050203, /* bis r2, r3 ; merge type */ - 0010311, /* mov r3, (r1); ; pack ack */ - 0105711, /* tstb (r1) ; wait */ - 0100376, /* bpl .-2 */ - 0012761, 0177000, 0000002, /* mov #-512.,2(r1) ; set wc */ - 0005061, 0000004, /* clr 4(r1) ; clr ba */ - 0005061, 0000006, /* clr 6(r1) ; clr da */ - 0005061, 0000020, /* clr 20(r1) ; clr cyl */ - 0012703, 0000021, /* mov #read+go, r3 */ - 0050203, /* bis r2, r3 ; merge type */ - 0010311, /* mov r3, (r1); ; read */ - 0105711, /* tstb (r1) ; wait */ - 0100376, /* bpl .-2 */ - 0005002, /* clr R2 */ - 0005003, /* clr R3 */ - 0012704, BOOT_START+020, /* mov #start+020, r4 */ - 0005005, /* clr R5 */ - 0005007 /* clr PC */ -}; - -t_stat hk_boot (int32 unitno, DEVICE *dptr) -{ -int32 i; -extern int32 saved_PC; - -for (i = 0; i < BOOT_LEN; i++) M[(BOOT_START >> 1) + i] = boot_rom[i]; -M[BOOT_UNIT >> 1] = unitno & CS2_M_UNIT; -M[BOOT_CSR >> 1] = hk_dib.ba & DMASK; -saved_PC = BOOT_ENTRY; -return SCPE_OK; -} diff --git a/PDP11/pdp11_io.c b/PDP11/pdp11_io.c deleted file mode 100644 index bae93443..00000000 --- a/PDP11/pdp11_io.c +++ /dev/null @@ -1,603 +0,0 @@ -/* pdp11_io.c: PDP-11 I/O simulator - - 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. - - 12-Mar-03 RMS Added logical name support - 08-Oct-02 RMS Trimmed I/O bus addresses - Added support for dynamic tables - Added show I/O space, autoconfigure routines - 12-Sep-02 RMS Added support for TMSCP, KW11P, RX211 - 26-Jan-02 RMS Revised for multiple DZ's - 06-Jan-02 RMS Revised I/O access, enable/disable support - 11-Dec-01 RMS Moved interrupt debug code - 08-Nov-01 RMS Cloned from cpu sources -*/ - -#include "pdp11_defs.h" - -extern uint16 *M; -extern int32 int_req[IPL_HLVL]; -extern int32 ub_map[UBM_LNT_LW]; -extern UNIT cpu_unit; -extern int32 cpu_bme, cpu_18b, cpu_ubm; -extern int32 trap_req, ipl; -extern int32 cpu_log; -extern FILE *sim_log; -extern DEVICE *sim_devices[]; - -int32 calc_ints (int32 nipl, int32 trq); - -extern DIB cpu0_dib, cpu1_dib, cpu2_dib; -extern DIB cpu3_dib, cpu4_dib, ubm_dib; - -/* I/O data structures */ - -DIB *dib_tab[DIB_MAX]; /* run time DIBs */ - -int32 int_vec[IPL_HLVL][32]; /* int req to vector */ - -int32 (*int_ack[IPL_HLVL][32])(void); /* int ack routines */ - -static DIB *std_dib[] = { /* standard DIBs */ - &cpu0_dib, - &cpu1_dib, - &cpu2_dib, - &cpu3_dib, - &cpu4_dib, - NULL }; - -static int32 pirq_vloc[7] = { - IVCL (PIR7), IVCL (PIR6), IVCL (PIR5), IVCL (PIR4), - IVCL (PIR3), IVCL (PIR2), IVCL (PIR1) }; - -/* I/O page lookup and linkage routines - - Inputs: - *data = pointer to data to read, if READ - data = data to store, if WRITE or WRITEB - pa = address - access = READ, WRITE, or WRITEB - Outputs: - status = SCPE_OK or SCPE_NXM -*/ - -t_stat iopageR (int32 *data, uint32 pa, int32 access) -{ -int32 i; -DIB *dibp; -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; } } -return SCPE_NXM; -} - -t_stat iopageW (int32 data, uint32 pa, int32 access) -{ -int32 i; -DIB *dibp; -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; } } -return SCPE_NXM; -} - -/* Calculate interrupt outstanding */ - -int32 calc_ints (int32 nipl, int32 trq) -{ -int32 i; - -for (i = IPL_HLVL - 1; i > nipl; i--) { - if (int_req[i]) return (trq | TRAP_INT); } -return (trq & ~TRAP_INT); -} - -/* Find vector for highest priority interrupt */ - -int32 get_vector (int32 nipl) -{ -int32 i, j, t, vec; - -for (i = IPL_HLVL - 1; i > nipl; i--) { /* loop thru lvls */ - t = int_req[i]; /* get level */ - for (j = 0; t && (j < 32); j++) { /* srch level */ - if ((t >> j) & 1) { /* irq found? */ - int_req[i] = int_req[i] & ~(1u << j); /* clr irq */ - if (int_ack[i][j]) vec = int_ack[i][j](); - else vec = int_vec[i][j]; - if (DBG_LOG (LOG_CPU_I)) fprintf (sim_log, - ">>INT: lvl=%d, flag=%d, vec=%o\n", i, j, vec); - return vec; /* return vector */ - } /* end if t */ - } /* end for j */ - } /* end for i */ -return 0; -} - -/* Read and write Unibus map registers - - In any even/odd pair - even = low 16b, bit <0> clear - odd = high 6b - - The Unibus map is stored as an array of longwords -*/ - -t_stat ubm_rd (int32 *data, int32 addr, int32 access) -{ -if (cpu_ubm) { - int32 pg = (addr >> 2) & UBM_M_PN; - *data = (addr & 2)? ((ub_map[pg] >> 16) & 077): - (ub_map[pg] & 0177776); - return SCPE_OK; } -return SCPE_NXM; -} - -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); } - ub_map[pg] = ub_map[pg] & 017777776; - return SCPE_OK; } -return SCPE_NXM; -} - -/* Mapped memory access routines for DMA devices */ - -#define BUSMASK(m) ((cpu_18b || (cpu_ubm && (m)))? UNIMASK: PAMASK) - -/* Map I/O address to memory address */ - -t_bool Map_Addr (uint32 ba, uint32 *ma) -{ -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 */ - else *ma = (IOPAGEBASE + off) & PAMASK; } /* yes, use fixed */ -else *ma = ba; /* else physical */ -return TRUE; -} - -/* I/O buffer routines, aligned access - - Map_ReadB - fetch byte buffer from memory - Map_ReadW - fetch word buffer from memory - Map_WriteB - store byte buffer into memory - Map_WriteW - store word buffer into memory -*/ - -int32 Map_ReadB (uint32 ba, int32 bc, uint8 *buf, t_bool map) -{ -uint32 alim, lim, ma; - -ba = ba & BUSMASK (map); /* trim address */ -lim = ba + bc; -if (map && cpu_bme) { /* map req & on? */ - for ( ; ba < lim; ba++) { /* by bytes */ - Map_Addr (ba, &ma); /* map addr */ - if (!ADDR_IS_MEM (ma)) return (lim - ba); /* NXM? err */ - if (ma & 1) *buf++ = (M[ma >> 1] >> 8) & 0377; /* get byte */ - else *buf++ = M[ma >> 1] & 0377; } - return 0; } -else { /* physical */ - if (ADDR_IS_MEM (lim)) alim = lim; /* end ok? */ - else if (ADDR_IS_MEM (ba)) alim = MEMSIZE; /* no, strt ok? */ - else return bc; /* no, err */ - for ( ; ba < alim; ba++) { /* by bytes */ - if (ba & 1) *buf++ = (M[ba >> 1] >> 8) & 0377; /* get byte */ - else *buf++ = M[ba >> 1] & 0377; } - return (lim - alim); } -} - -int32 Map_ReadW (uint32 ba, int32 bc, uint16 *buf, t_bool map) -{ -uint32 alim, lim, ma; - -ba = (ba & BUSMASK (map)) & ~01; /* trim, align addr */ -lim = ba + (bc & ~01); -if (map && cpu_bme) { /* map req & on? */ - for (; ba < lim; ba = ba + 2) { /* by words */ - Map_Addr (ba, &ma); /* map addr */ - if (!ADDR_IS_MEM (ma)) return (lim - ba); /* NXM? err */ - *buf++ = M[ma >> 1]; } - return 0; } -else { /* physical */ - if (ADDR_IS_MEM (lim)) alim = lim; /* end ok? */ - else if (ADDR_IS_MEM (ba)) alim = MEMSIZE; /* no, strt ok? */ - else return bc; /* no, err */ - for ( ; ba < alim; ba = ba + 2) { /* by words */ - *buf++ = M[ba >> 1]; } - return (lim - alim); } -} - -int32 Map_WriteB (uint32 ba, int32 bc, uint8 *buf, t_bool map) -{ -uint32 alim, lim, ma; - -ba = ba & BUSMASK (map); /* trim address */ -lim = ba + bc; -if (map && cpu_bme) { /* map req & on? */ - for ( ; ba < lim; ba++) { /* by bytes */ - Map_Addr (ba, &ma); /* map addr */ - if (!ADDR_IS_MEM (ma)) return (lim - ba); /* NXM? err */ - if (ma & 1) M[ma >> 1] = (M[ma >> 1] & 0377) | - ((uint16) *buf++ << 8); - else M[ma >> 1] = (M[ma >> 1] & ~0377) | *buf++; } - return 0; } -else { /* physical */ - if (ADDR_IS_MEM (lim)) alim = lim; /* end ok? */ - else if (ADDR_IS_MEM (ba)) alim = MEMSIZE; /* no, strt ok? */ - else return bc; /* no, err */ - for ( ; ba < alim; ba++) { /* by bytes */ - if (ba & 1) M[ba >> 1] = (M[ba >> 1] & 0377) | - ((uint16) *buf++ << 8); - else M[ba >> 1] = (M[ba >> 1] & ~0377) | *buf++; } - return (lim - alim); } -} - -int32 Map_WriteW (uint32 ba, int32 bc, uint16 *buf, t_bool map) -{ -uint32 alim, lim, ma; - -ba = (ba & BUSMASK (map)) & ~01; /* trim, align addr */ -lim = ba + (bc & ~01); -if (map && cpu_bme) { /* map req & on? */ - for (; ba < lim; ba = ba + 2) { /* by words */ - Map_Addr (ba, &ma); /* map addr */ - if (!ADDR_IS_MEM (ma)) return (lim - ba); /* NXM? err */ - M[ma >> 1] = *buf++; } /* store word */ - return 0; } -else { /* physical */ - if (ADDR_IS_MEM (lim)) alim = lim; /* end ok? */ - else if (ADDR_IS_MEM (ba)) alim = MEMSIZE; /* no, strt ok? */ - else return bc; /* no, err */ - for ( ; ba < alim; ba = ba + 2) { /* by words */ - M[ba >> 1] = *buf++; } - return (lim - alim); } -} - -/* Change device address */ - -t_stat set_addr (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -DEVICE *dptr; -DIB *dibp; -uint32 newba; -t_stat r; - -if (cptr == NULL) return SCPE_ARG; -if ((val == 0) || (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; -newba = get_uint (cptr, 8, PAMASK, &r); /* get new */ -if (r != SCPE_OK) return r; /* error? */ -if ((newba <= IOPAGEBASE) || /* > IO page base? */ - (newba % ((uint32) val))) return SCPE_ARG; /* check modulus */ -dibp->ba = newba; /* store */ -dptr->flags = dptr->flags & ~DEV_FLTA; /* not floating */ -return auto_config (0, 0); /* autoconfigure */ -} - -/* Show device address */ - -t_stat show_addr (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->ba <= IOPAGEBASE)) return SCPE_IERR; -fprintf (st, "address=%08o", dibp->ba); -if (dibp->lnt > 1) - fprintf (st, "-%08o", dibp->ba + dibp->lnt - 1); -if (dptr->flags & DEV_FLTA) fprintf (st, "*"); -return SCPE_OK; -} - -/* Set address floating */ - -t_stat set_addr_flt (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -DEVICE *dptr; - -if (cptr != NULL) return SCPE_ARG; -if (uptr == NULL) return SCPE_IERR; -dptr = find_dev_from_unit (uptr); -if (dptr == NULL) return SCPE_IERR; -dptr->flags = dptr->flags | DEV_FLTA; /* floating */ -return auto_config (0, 0); /* autoconfigure */ -} - -/* Change device vector */ - -t_stat set_vec (UNIT *uptr, int32 arg, char *cptr, void *desc) -{ -DEVICE *dptr; -DIB *dibp; -uint32 newvec; -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; -newvec = get_uint (cptr, 8, VEC_Q + 01000, &r); -if ((r != SCPE_OK) || (newvec <= VEC_Q) || - ((newvec + (dibp->vnum * 4)) >= (VEC_Q + 01000)) || - (newvec & ((dibp->vnum > 1)? 07: 03))) return SCPE_ARG; -dibp->vec = newvec; -return SCPE_OK; -} - -/* Show device vector */ - -t_stat show_vec (FILE *st, UNIT *uptr, int32 arg, void *desc) -{ -DEVICE *dptr; -DIB *dibp; -uint32 vec, numvec; - -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; -vec = dibp->vec; -if (arg) numvec = arg; -else numvec = dibp->vnum; -if (vec == 0) fprintf (st, "no vector"); -else { fprintf (st, "vector=%o", vec); - if (numvec > 1) fprintf (st, "-%o", vec + (4 * (numvec - 1))); } -return SCPE_OK; -} - -/* Test for conflict in device addresses */ - -t_bool dev_conflict (DIB *curr) -{ -uint32 i, end; -DEVICE *dptr; -DIB *dibp; - -end = curr->ba + curr->lnt - 1; /* get end */ -for (i = 0; (dptr = sim_devices[i]) != NULL; i++) { /* loop thru dev */ - dibp = (DIB *) dptr->ctxt; /* get DIB */ - if ((dibp == NULL) || (dibp == curr) || - (dptr->flags & DEV_DIS)) continue; - if (((curr->ba >= dibp->ba) && /* overlap start? */ - (curr->ba < (dibp->ba + dibp->lnt))) || - ((end >= dibp->ba) && /* overlap end? */ - (end < (dibp->ba + dibp->lnt)))) { - printf ("Device %s address conflict at %08o\n", - sim_dname (dptr), dibp->ba); - if (sim_log) fprintf (sim_log, - "Device %s address conflict at %08o\n", - sim_dname (dptr), dibp->ba); - return TRUE; } } -return FALSE; -} - -/* Build interrupt tables */ - -void build_int_vec (int32 vloc, int32 ivec, int32 (*iack)(void) ) -{ -int32 ilvl = vloc / 32; -int32 ibit = vloc % 32; - -if (iack != NULL) int_ack[ilvl][ibit] = iack; -else int_vec[ilvl][ibit] = ivec; -return; -} - -/* Build dib_tab from device list */ - -t_stat build_dib_tab (int32 ubm) -{ -int32 i, j, k; -DEVICE *dptr; -DIB *dibp; - -for (i = 0; i < IPL_HLVL; i++) { /* clear int tables */ - for (j = 0; j < 32; j++) { - int_vec[i][j] = 0; - int_ack[i][j] = NULL; } } -for (i = j = 0; (dptr = sim_devices[i]) != NULL; i++) { /* loop thru dev */ - dibp = (DIB *) dptr->ctxt; /* get DIB */ - if (dibp && !(dptr->flags & DEV_DIS)) { /* defined, enabled? */ - if (dibp->vnum > VEC_DEVMAX) return SCPE_IERR; - for (k = 0; k < dibp->vnum; k++) /* loop thru vec */ - build_int_vec (dibp->vloc + k, /* add vector */ - dibp->vec + (k * 4), dibp->ack[k]); - if (dibp->lnt != 0) { /* I/O addresses? */ - dib_tab[j++] = dibp; /* add DIB to dib_tab */ - if (j >= DIB_MAX) return SCPE_IERR; } /* too many? */ - } /* end if enabled */ - } /* end for */ -for (i = 0; (dibp = std_dib[i]) != NULL; i++) { /* loop thru std */ - dib_tab[j++] = dibp; /* add to dib_tab */ - if (j >= DIB_MAX) return SCPE_IERR; } /* too many? */ -if (ubm) { /* Unibus map? */ - dib_tab[j++] = &ubm_dib; /* add to dib_tab */ - if (j >= DIB_MAX) return SCPE_IERR; } /* too many? */ -dib_tab[j] = NULL; /* end with NULL */ -for (i = 0; i < 7; i++) /* add PIRQ intr */ - build_int_vec (pirq_vloc[i], VEC_PIRQ, NULL); -for (i = 0; (dibp = dib_tab[i]) != NULL; i++) { /* test built dib_tab */ - if (dev_conflict (dibp)) { - return SCPE_STOP; } } /* for conflicts */ -return SCPE_OK; -} - -/* Show dib_tab */ - -t_stat show_iospace (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -int32 i, j, done = 0; -DEVICE *dptr; -DIB *dibt; - -build_dib_tab (cpu_ubm); /* build table */ -while (done == 0) { /* sort ascending */ - done = 1; /* assume done */ - for (i = 0; dib_tab[i + 1] != NULL; i++) { /* check table */ - if (dib_tab[i]->ba > dib_tab[i + 1]->ba) { /* out of order? */ - dibt = dib_tab[i]; /* interchange */ - dib_tab[i] = dib_tab[i + 1]; - dib_tab[i + 1] = dibt; - done = 0; } } /* not done */ - } /* end while */ -for (i = 0; dib_tab[i] != NULL; i++) { /* print table */ - for (j = 0, dptr = NULL; sim_devices[j] != NULL; j++) { - if (((DIB*) sim_devices[j]->ctxt) == dib_tab[i]) { - dptr = sim_devices[j]; - break; } } - fprintf (st, "%08o - %08o%c\t%s\n", dib_tab[i]->ba, - dib_tab[i]->ba + dib_tab[i]->lnt - 1, - (dptr && (dptr->flags & DEV_FLTA))? '*': ' ', - dptr? sim_dname (dptr): "CPU"); - } -return SCPE_OK; -} - -/* Autoconfiguration */ - -#define AUTO_DYN 0001 -#define AUTO_VEC 0002 -#define AUTO_MAXC 4 -#define AUTO_CSRBASE 0010 -#define AUTO_VECBASE 0300 - -struct auto_con { - uint32 amod; - uint32 vmod; - uint32 flags; - uint32 num; - uint32 fix; - char *dnam[AUTO_MAXC]; }; - -struct auto_con auto_tab[AUTO_LNT + 1] = { - { 0x7, 0x7 }, /* DJ11 */ - { 0xf, 0x7 }, /* DH11 */ - { 0x7, 0x7 }, /* DQ11 */ - { 0x7, 0x7 }, /* DU11 */ - { 0x7, 0x7 }, /* DUP11 */ - { 0x7, 0x7 }, /* LK11A */ - { 0x7, 0x7 }, /* DMC11 */ - { 0x7, 0x7, AUTO_VEC, DZ_MUXES, 0, { "DZ" } }, - - { 0x7, 0x7 }, /* KMC11 */ - { 0x7, 0x7 }, /* LPP11 */ - { 0x7, 0x7 }, /* VMV21 */ - { 0xf, 0x7 }, /* VMV31 */ - { 0x7, 0x7 }, /* DWR70 */ - { 0x7, 0x3, AUTO_DYN|AUTO_VEC, 0, IOBA_RL, { "RL", "RLB" } }, - { 0xf, 0x7 }, /* LPA11K */ - { 0x7, 0x7 }, /* KW11C */ - - { 0x7, 0 }, /* reserved */ - { 0x7, 0x3, AUTO_DYN|AUTO_VEC, 0, IOBA_RX, { "RX", "RY" } }, - { 0x7, 0x3 }, /* DR11W */ - { 0x7, 0x3 }, /* DR11B */ - { 0x7, 0x7 }, /* DMP11 */ - { 0x7, 0x7 }, /* DPV11 */ - { 0x7, 0x7 }, /* ISB11 */ - { 0xf, 0x7 }, /* DMV11 */ - - { 0x7, 0x3, AUTO_DYN|AUTO_VEC, 0, IOBA_XU, { "XU", "XUB" } }, - { 0x3, 0x3, AUTO_DYN|AUTO_VEC, 0, IOBA_RQ, { "RQ", "RQB", "RQC", "RQD" } }, - { 0x1f, 0x3 }, /* DMF32 */ - { 0xf, 0x7 }, /* KMS11 */ - { 0xf, 0x3 }, /* VS100 */ - { 0x3, 0x3, AUTO_DYN|AUTO_VEC, 0, IOBA_TQ, { "TQ", "TQB" } }, - { 0xf, 0x7 }, /* KMV11 */ - { 0xf, 0x7 }, /* DHU11/DHQ11 */ - - { 0x1f, 0x7 }, /* DMZ32 */ - { 0x1f, 0x7 }, /* CP132 */ - { 0 }, /* padding */ -}; - -t_stat auto_config (uint32 rank, uint32 nctrl) -{ -uint32 csr = IOPAGEBASE + AUTO_CSRBASE; -uint32 vec = VEC_Q + AUTO_VECBASE; -struct auto_con *autp; -DEVICE *dptr; -DIB *dibp; -int32 i, j, k; -extern DEVICE *find_dev (char *ptr); - -if (rank > AUTO_LNT) return SCPE_IERR; /* legal rank? */ -if (rank) auto_tab[rank - 1].num = nctrl; /* update num? */ -for (i = 0, autp = auto_tab; i < AUTO_LNT; i++) { /* loop thru table */ - for (j = k = 0; (j < AUTO_MAXC) && autp->dnam[j]; j++) { - dptr = find_dev (autp->dnam[j]); /* find ctrl */ - if ((dptr == NULL) || (dptr->flags & DEV_DIS) || - !(dptr->flags & DEV_FLTA)) continue; /* enabled, floating? */ - dibp = (DIB *) dptr->ctxt; /* get DIB */ - if ((k++ == 0) && autp->fix) /* 1st & fixed? */ - dibp->ba = autp->fix; /* gets fixed CSR */ - else { /* no, float */ - dibp->ba = csr; /* set CSR */ - csr = (csr + autp->amod + 1) & ~autp->amod; /* next CSR */ - if ((autp->flags & AUTO_DYN) == 0) /* static? */ - csr = csr + ((autp->num - 1) * (autp->amod + 1)); - if (autp->flags & AUTO_VEC) { /* vectors too? */ - dibp->vec = (vec + autp->vmod) & ~autp->vmod; - if (autp->flags & AUTO_DYN) vec = vec + autp->vmod + 1; - else vec = vec + (autp->num * (autp->vmod + 1)); } - } /* end else flt */ - } /* end for j */ - autp++; - csr = (csr + autp->amod + 1) & ~autp->amod; /* gap */ - } /* end for i */ -return SCPE_OK; -} diff --git a/PDP11/pdp11_lp.c b/PDP11/pdp11_lp.c deleted file mode 100644 index 022497a9..00000000 --- a/PDP11/pdp11_lp.c +++ /dev/null @@ -1,184 +0,0 @@ -/* pdp11_lp.c: PDP-11 line printer simulator - - 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. - - lpt LP11 line printer - - 19-May-03 RMS Revised for new conditional compilation scheme - 25-Apr-03 RMS Revised for extended file support - 29-Sep-02 RMS Added vector change/display support - New data structures - 30-May-02 RMS Widened POS to 32b - 06-Jan-02 RMS Added enable/disable support - 09-Nov-01 RMS Added VAX support - 07-Sep-01 RMS Revised interrupt mechanism - 30-Oct-00 RMS Standardized register naming -*/ - -#if defined (VM_PDP10) /* PDP10 version */ -#error "LP11 is not supported on the PDP-10!" - -#elif defined (VM_VAX) /* VAX version */ -#include "vax_defs.h" -extern int32 int_req[IPL_HLVL]; -extern int32 int_vec[IPL_HLVL][32]; - -#else /* PDP-11 version */ -#include "pdp11_defs.h" -extern int32 int_req[IPL_HLVL]; -extern int32 int_vec[IPL_HLVL][32]; -#endif - -#define LPTCSR_IMP (CSR_ERR + CSR_DONE + CSR_IE) /* implemented */ -#define LPTCSR_RW (CSR_IE) /* read/write */ - -extern int32 int_req[IPL_HLVL]; -extern int32 int_vec[IPL_HLVL][32]; - -int32 lpt_csr = 0; /* control/status */ -int32 lpt_stopioe = 0; /* stop on error */ - -DEVICE lpt_dev; -t_stat lpt_rd (int32 *data, int32 PA, int32 access); -t_stat lpt_wr (int32 data, int32 PA, int32 access); -t_stat lpt_svc (UNIT *uptr); -t_stat lpt_reset (DEVICE *dptr); -t_stat lpt_attach (UNIT *uptr, char *ptr); -t_stat lpt_detach (UNIT *uptr); - -/* LPT data structures - - lpt_dev LPT device descriptor - lpt_unit LPT unit descriptor - lpt_reg LPT register list -*/ - -DIB lpt_dib = { IOBA_LPT, IOLN_LPT, &lpt_rd, &lpt_wr, - 1, IVCL (LPT), VEC_LPT, { NULL } }; - -UNIT lpt_unit = { - UDATA (&lpt_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT }; - -REG lpt_reg[] = { - { GRDATA (BUF, lpt_unit.buf, DEV_RDX, 8, 0) }, - { GRDATA (CSR, lpt_csr, DEV_RDX, 16, 0) }, - { FLDATA (INT, IREQ (LPT), INT_V_LPT) }, - { FLDATA (ERR, lpt_csr, CSR_V_ERR) }, - { FLDATA (DONE, lpt_csr, CSR_V_DONE) }, - { FLDATA (IE, lpt_csr, CSR_V_IE) }, - { DRDATA (POS, lpt_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, lpt_unit.wait, 24), PV_LEFT }, - { FLDATA (STOP_IOE, lpt_stopioe, 0) }, - { GRDATA (DEVADDR, lpt_dib.ba, DEV_RDX, 32, 0), REG_HRO }, - { GRDATA (DEVVEC, lpt_dib.vec, DEV_RDX, 16, 0), REG_HRO }, - { NULL } }; - -MTAB lpt_mod[] = { - { MTAB_XTD|MTAB_VDV, 004, "ADDRESS", "ADDRESS", - &set_addr, &show_addr, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "VECTOR", "VECTOR", - &set_vec, &show_vec, NULL }, - { 0 } }; - -DEVICE lpt_dev = { - "LPT", &lpt_unit, lpt_reg, lpt_mod, - 1, 10, 31, 1, DEV_RDX, 8, - NULL, NULL, &lpt_reset, - NULL, &lpt_attach, &lpt_detach, - &lpt_dib, DEV_DISABLE | DEV_UBUS | DEV_QBUS }; - -/* Line printer routines - - lpt_rd I/O page read - lpt_wr I/O page write - lpt_svc process event (printer ready) - lpt_reset process reset - lpt_attach process attach - lpt_detach process detach -*/ - -t_stat lpt_rd (int32 *data, int32 PA, int32 access) -{ -if ((PA & 02) == 0) *data = lpt_csr & LPTCSR_IMP; /* csr */ -else *data = lpt_unit.buf; /* buffer */ -return SCPE_OK; -} - -t_stat lpt_wr (int32 data, int32 PA, int32 access) -{ -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); - 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; - CLR_INT (LPT); - if ((lpt_unit.buf == 015) || (lpt_unit.buf == 014) || - (lpt_unit.buf == 012)) sim_activate (&lpt_unit, lpt_unit.wait); - else sim_activate (&lpt_unit, 0); } -return SCPE_OK; -} - -t_stat lpt_svc (UNIT *uptr) -{ -lpt_csr = lpt_csr | CSR_ERR | CSR_DONE; -if (lpt_csr & CSR_IE) SET_INT (LPT); -if ((lpt_unit.flags & UNIT_ATT) == 0) - return IORETURN (lpt_stopioe, SCPE_UNATT); -if (putc (lpt_unit.buf & 0177, lpt_unit.fileref) == EOF) { - perror ("LPT I/O error"); - clearerr (lpt_unit.fileref); - return SCPE_IOERR; } -lpt_csr = lpt_csr & ~CSR_ERR; -lpt_unit.pos = lpt_unit.pos + 1; -return SCPE_OK; -} - -t_stat lpt_reset (DEVICE *dptr) -{ -lpt_unit.buf = 0; -lpt_csr = CSR_DONE; -if ((lpt_unit.flags & UNIT_ATT) == 0) lpt_csr = lpt_csr | CSR_ERR; -CLR_INT (LPT); -sim_cancel (&lpt_unit); /* deactivate unit */ -return SCPE_OK; -} - -t_stat lpt_attach (UNIT *uptr, char *cptr) -{ -t_stat reason; - -lpt_csr = lpt_csr & ~CSR_ERR; -reason = attach_unit (uptr, cptr); -if ((lpt_unit.flags & UNIT_ATT) == 0) lpt_csr = lpt_csr | CSR_ERR; -return reason; -} - -t_stat lpt_detach (UNIT *uptr) -{ -lpt_csr = lpt_csr | CSR_ERR; -return detach_unit (uptr); -} diff --git a/PDP11/pdp11_mscp.h b/PDP11/pdp11_mscp.h deleted file mode 100644 index cc1fb214..00000000 --- a/PDP11/pdp11_mscp.h +++ /dev/null @@ -1,514 +0,0 @@ -/* pdp11_mscp.h: DEC MSCP and TMSCP definitionsn - - 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 - 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. - - 09-Jan-03 RMS Tape read/write end pkt is longer than disk read/write - 20-Sep-02 RMS Merged TMSCP definitions -*/ - -#ifndef _PDP11_MSCP_H_ -#define _PDP11_MSCP_H_ 0 - -/* Misc constants */ - -#define UID_DISK 2 /* disk class */ -#define UID_TAPE 3 /* tape class */ - -/* Opcodes */ - -#define OP_ABO 1 /* b: abort */ -#define OP_GCS 2 /* b: get command status */ -#define OP_GUS 3 /* b: get unit status */ -#define OP_SCC 4 /* b: set controller char */ -#define OP_AVL 8 /* b: available */ -#define OP_ONL 9 /* b: online */ -#define OP_SUC 10 /* b: set unit char */ -#define OP_DAP 11 /* b: det acc paths - nop */ -#define OP_ACC 16 /* b: access */ -#define OP_CCD 17 /* d: compare - nop */ -#define OP_ERS 18 /* b: erase */ -#define OP_FLU 19 /* d: flush - nop */ -#define OP_ERG 22 /* t: erase gap */ -#define OP_CMP 32 /* b: compare */ -#define OP_RD 33 /* b: read */ -#define OP_WR 34 /* b: write */ -#define OP_WTM 36 /* t: write tape mark */ -#define OP_POS 37 /* t: reposition */ -#define OP_FMT 47 /* d: format */ -#define OP_AVA 64 /* b: unit now avail */ -#define OP_END 0x80 /* b: end flag */ - -/* Modifiers */ - -#define MD_EXP 0x8000 /* d: express NI */ -#define MD_CMP 0x4000 /* b: compare NI */ -#define MD_CSE 0x2000 /* b: clr ser err */ -#define MD_ERR 0x1000 /* d: force error NI*/ -#define MD_CDL 0x1000 /* t: clr data lost NI*/ -#define MD_SCH 0x0800 /* t: supr cache NI */ -#define MD_SEC 0x0200 /* b: supr err corr NI */ -#define MD_SER 0x0100 /* b: supr err rec NI */ -#define MD_DLE 0x0080 /* t: detect LEOT */ -#define MD_IMM 0x0040 /* t: immediate NI */ -#define MD_EXA 0x0020 /* b: excl access NI */ -#define MD_SHD 0x0010 /* d: shadow NI */ -#define MD_UNL 0x0010 /* t avl: unload */ -#define MD_ERW 0x0008 /* t wr: enb rewrite */ -#define MD_REV 0x0008 /* t rd, pos: reverse */ -#define MD_SWP 0x0004 /* b suc: enb set wrp */ -#define MD_OBC 0x0004 /* t: pos: obj count */ -#define MD_IMF 0x0002 /* d onl: ign fmte NI */ -#define MD_RWD 0x0002 /* t pos: rewind */ -#define MD_ACL 0x0002 /* t avl: all class NI */ -#define MD_NXU 0x0001 /* b gus: next unit */ -#define MD_RIP 0x0001 /* d onl: allow rip NI */ - -/* End flags */ - -#define EF_LOG 0x0020 /* b: error log */ -#define EF_SXC 0x0010 /* b: serious exc */ -#define EF_EOT 0x0008 /* end of tape */ -#define EF_PLS 0x0004 /* pos lost */ -#define EF_DLS 0x0002 /* cached data lost NI */ - -/* Controller flags */ - -#define CF_RPL 0x8000 /* ctrl bad blk repl */ -#define CF_ATN 0x0080 /* enb attention */ -#define CF_MSC 0x0040 /* enb misc msgs */ -#define CF_OTH 0x0020 /* enb othr host msgs */ -#define CF_THS 0x0010 /* enb this host msgs */ -#define CF_MSK (CF_ATN|CF_MSC|CF_OTH|CF_THS) - -/* Unit flags */ - -#define UF_RPL 0x8000 /* d: ctrl bad blk repl */ -#define UF_CAC 0x8000 /* t: cache write back */ -#define UF_WPH 0x2000 /* b: wr prot hwre */ -#define UF_WPS 0x1000 /* b: wr prot swre */ -#define UF_SCH 0x0800 /* t: supr cache NI */ -#define UF_EXA 0x0400 /* b: exclusive NI */ -#define UF_WPD 0x0100 /* b: wr prot data NI */ -#define UF_RMV 0x0080 /* d: removable */ -#define UF_WBN 0x0040 /* t: write back NI */ -#define UF_VSS 0x0020 /* t: supr var speed NI */ -#define UF_VSU 0x0010 /* t: var speed unit NI */ -#define UF_EWR 0x0008 /* t: enh wr recovery NI */ -#define UF_CMW 0x0002 /* cmp writes NI */ -#define UF_CMR 0x0001 /* cmp reads NI */ - -/* Error log flags */ - -#define LF_SUC 0x0080 /* b: successful */ -#define LF_CON 0x0040 /* b: continuing */ -#define LF_BBR 0x0020 /* d: bad blk repl NI */ -#define LF_RCT 0x0010 /* d: err in repl NI */ -#define LF_SNR 0x0001 /* b: seq # reset */ - -/* Error log formats */ - -#define FM_CNT 0 /* b: port lf err */ -#define FM_BAD 1 /* b: bad host addr */ -#define FM_DSK 2 /* d: disk xfer */ -#define FM_SDI 3 /* d: SDI err */ -#define FM_SDE 4 /* d: sm disk err */ -#define FM_TAP 5 /* t: tape errors */ -#define FM_RPL 9 /* d: bad blk repl */ - -/* Status codes */ - -#define ST_SUC 0 /* b: successful */ -#define ST_CMD 1 /* b: invalid cmd */ -#define ST_ABO 2 /* b: aborted cmd */ -#define ST_OFL 3 /* b: unit offline */ -#define ST_AVL 4 /* b: unit avail */ -#define ST_MFE 5 /* b: media fmt err */ -#define ST_WPR 6 /* b: write prot err */ -#define ST_CMP 7 /* b: compare err */ -#define ST_DAT 8 /* b: data err */ -#define ST_HST 9 /* b: host acc err */ -#define ST_CNT 10 /* b: ctrl err */ -#define ST_DRV 11 /* b: drive err */ -#define ST_FMT 12 /* t: formatter err */ -#define ST_BOT 13 /* t: BOT encountered */ -#define ST_TMK 14 /* t: tape mark */ -#define ST_RDT 16 /* t: record trunc */ -#define ST_POL 17 /* t: pos lost */ -#define ST_SXC 18 /* b: serious exc */ -#define ST_LED 19 /* t: LEOT detect */ -#define ST_BBR 20 /* d: bad block */ -#define ST_DIA 31 /* b: diagnostic */ -#define ST_V_SUB 5 /* subcode */ -#define ST_V_INV 8 /* invalid op */ - -/* Status subcodes */ - -#define SB_SUC_IGN (1 << ST_V_SUB) /* t: unload ignored */ -#define SB_SUC_ON (8 << ST_V_SUB) /* b: already online */ -#define SB_SUC_EOT (32 << ST_V_SUB) /* t: EOT encountered */ -#define SB_SUC_RO (128 << ST_V_SUB) /* t: read only */ -#define SB_OFL_NV (1 << ST_V_SUB) /* b: no volume */ -#define SB_OFL_INOP (2 << ST_V_SUB) /* t: inoperative */ -#define SB_AVL_INU (32 << ST_V_SUB) /* b: in use */ -#define SB_WPR_SW (128 << ST_V_SUB) /* b: swre wlk */ -#define SB_WPR_HW (256 << ST_V_SUB) /* b: hwre wlk */ -#define SB_HST_OA (1 << ST_V_SUB) /* b: odd addr */ -#define SB_HST_OC (2 << ST_V_SUB) /* d: odd count */ -#define SB_HST_NXM (3 << ST_V_SUB) /* b: nx memory */ -#define SB_HST_PAR (4 << ST_V_SUB) /* b: parity err */ -#define SB_HST_PTE (5 << ST_V_SUB) /* b: mapping err */ -#define SB_DAT_RDE (7 << ST_V_SUB) /* t: read err */ - -/* Status invalid command subcodes */ - -#define I_OPCD (8 << ST_V_INV) /* inv opcode */ -#define I_FLAG (9 << ST_V_INV) /* inv flags */ -#define I_MODF (10 << ST_V_INV) /* inv modifier */ -#define I_BCNT (12 << ST_V_INV) /* inv byte cnt */ -#define I_LBN (28 << ST_V_INV) /* inv LBN */ -#define I_VRSN (12 << ST_V_INV) /* inv version */ -#define I_FMTI (28 << ST_V_INV) /* inv format */ - -/* Tape format flags */ - -#define TF_9TK 0x0100 /* 9 track */ -#define TF_9TK_NRZ 0x0001 /* 800 bpi */ -#define TF_9TK_PE 0x0002 /* 1600 bpi */ -#define TF_9TK_GRP 0x0004 /* 6250 bpi */ -#define TF_CTP 0x0200 /* TK50 */ -#define TF_CTP_LO 0x0001 /* low density */ -#define TF_CTP_HI 0x0002 /* hi density */ -#define TF_3480 0x0300 /* 3480 */ -#define TF_WOD 0x0400 /* RV80 */ - -/* Packet formats - note that all packet lengths must be multiples of 4 bytes */ - -/* Command packet header */ - -#define CMD_REFL 2 /* ref # */ -#define CMD_REFH 3 -#define CMD_UN 4 /* unit # */ -/* 5 /* reserved */ -#define CMD_OPC 6 /* opcode */ -#define CMD_MOD 7 /* modifier */ - -#define CMD_OPC_V_OPC 0 /* opcode */ -#define CMD_OPC_M_OPC 0xFF -#define CMD_OPC_V_CAA 8 /* cache NI */ -#define CMD_OPC_M_CAA 0xFF -#define CMD_OPC_V_FLG 8 /* flags */ -#define CMD_OPC_M_FLG 0xFF - -/* Response packet header */ - -#define RSP_LNT 12 -#define RSP_REFL 2 /* ref # */ -#define RSP_REFH 3 -#define RSP_UN 4 /* unit # */ -#define RSP_RSV 5 /* reserved */ -#define RSP_OPF 6 /* opcd,flg */ -#define RSP_STS 7 /* modifiers */ - -#define RSP_OPF_V_OPC 0 /* opcode */ -#define RSP_OPF_V_FLG 8 /* flags */ - -/* Abort packet - 2 W parameter, 2 W status */ - -#define ABO_LNT 16 -#define ABO_REFL 8 /* ref # */ -#define ABO_REFH 9 - -/* Avail packet - min size */ - -#define AVL_LNT 12 - -/* Erase packet - min size */ - -#define ERS_LNT 12 - -/* Erase gap - min size */ - -#define ERG_LNT 12 - -/* 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 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 status */ - -#define GCS_LNT 20 -#define GCS_REFL 8 /* ref # */ -#define GCS_REFH 9 -#define GCS_STSL 10 /* status */ -#define GCS_STSH 11 - -/* Format packet - 8 W parameters, none returned */ - -#define FMT_LNT 12 -#define FMT_IH 17 /* magic bit */ - -/* Get unit status packet - 18 W status (disk), 16W status (tape) */ - -#define GUS_LNT_D 48 -#define GUS_LNT_T 44 -#define GUS_MLUN 8 /* mlun */ -#define GUS_UFL 9 /* flags */ -#define GUS_RSVL 10 /* reserved */ -#define GUS_RSVH 11 -#define GUS_UIDA 12 /* unit ID */ -#define GUS_UIDB 13 -#define GUS_UIDC 14 -#define GUS_UIDD 15 -#define GUS_MEDL 16 /* media ID */ -#define GUS_MEDH 17 -#define GUS_UVER 23 /* unit version */ - -/* Disk specific status */ - -#define GUS_SHUN 18 /* shadowing */ -#define GUS_SHST 19 -#define GUS_TRK 20 /* track */ -#define GUS_GRP 21 /* group */ -#define GUS_CYL 22 /* cylinder */ -#define GUS_RCTS 24 /* RCT size */ -#define GUS_RBSC 25 /* RBNs, copies */ - -/* Tape specific status */ - -#define GUS_FMT 18 /* format */ -#define GUS_SPEED 19 /* speed */ -#define GUS_MENU 20 /* menu */ -#define GUS_CAP 21 /* capacity */ -#define GUS_FVER 22 /* fmtr version */ - -#define GUS_UIDD_V_MOD 0 /* unit model */ -#define GUS_UIDD_V_CLS 8 /* unit class */ -#define GUS_RB_V_RBNS 0 /* RBNs/track */ -#define GUS_RB_V_RCTC 8 /* RCT copies */ - -/* Unit online - 2 W parameter, 16 W status (disk or tape) */ - -#define ONL_LNT 44 -#define ONL_MLUN 8 /* mlun */ -#define ONL_UFL 9 /* flags */ -#define ONL_RSVL 10 /* reserved */ -#define ONL_RSVH 11 -#define ONL_UIDA 12 /* unit ID */ -#define ONL_UIDB 13 -#define ONL_UIDC 14 -#define ONL_UIDD 15 -#define ONL_MEDL 16 /* media ID */ -#define ONL_MEDH 17 - -/* Disk specific status */ - -#define ONL_SHUN 18 /* shadowing */ -#define ONL_SHST 19 -#define ONL_SIZL 20 /* size */ -#define ONL_SIZH 21 -#define ONL_VSNL 22 /* vol ser # */ -#define ONL_VSNH 23 - -/* Tape specific status */ - -#define ONL_FMT 18 /* format */ -#define ONL_SPD 19 /* speed */ -#define ONL_MAXL 20 /* max rec size */ -#define ONL_MAXH 21 -#define ONL_NREC 22 /* noise rec */ -#define ONL_RSVE 23 /* reserved */ - -#define ONL_UIDD_V_MOD 0 /* unit model */ -#define ONL_UIDD_V_CLS 8 /* unit class */ - -/* Set controller characteristics packet - 8 W parameters, 10 W status */ - -#define SCC_LNT 32 -#define SCC_MSV 8 /* MSCP version */ -#define SCC_CFL 9 /* flags */ -#define SCC_TMO 10 /* timeout */ -#define SCC_VER 11 /* ctrl version */ -#define SCC_CIDA 12 /* ctrl ID */ -#define SCC_CIDB 13 -#define SCC_CIDC 14 -#define SCC_CIDD 15 -#define SCC_MBCL 16 /* max byte count */ -#define SCC_MBCH 17 - -#define SCC_VER_V_SVER 0 /* swre vrsn */ -#define SCC_VER_V_HVER 8 /* hwre vrsn */ -#define SCC_CIDD_V_MOD 0 /* ctrl model */ -#define SCC_CIDD_V_CLS 8 /* ctrl class */ - -/* Set unit characteristics - 2 W parameter, 16 W status - same as ONL */ - -#define SUC_LNT 44 - -/* Reposition - 4 W parameters, 10 W status */ - -#define POS_LNT 32 -#define POS_RCL 8 /* record cnt */ -#define POS_RCH 9 -#define POS_TMCL 10 /* tape mk cnt */ -#define POS_TMCH 11 -/* reserved 12 - 15 */ -#define POS_POSL 16 /* position */ -#define POS_POSH 17 - -/* Data transfer packet - 10 W parameters (disk), 6W parameters (tape), - 10 W status (disk), 12W status (tape) */ - -#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 */ -#define RW_BAH 11 -#define RW_MAPL 12 /* map table */ -#define RW_MAPH 13 -/* 14 /* reserved */ -/* 15 /* reserved */ - -/* Disk specific parameters */ - -#define RW_LBNL 16 /* LBN */ -#define RW_LBNH 17 -#define RW_WBCL 18 /* working bc */ -#define RW_WBCH 19 -#define RW_WBAL 20 /* working ba */ -#define RW_WBAH 21 -#define RW_WBLL 22 /* working lbn */ -#define RW_WBLH 23 - -/* Tape specific status */ - -#define RW_POSL 16 /* position */ -#define RW_POSH 17 -#define RW_RSZL 18 /* record size */ -#define RW_RSZH 19 - -/* Error log packet header */ - -#define ELP_REFL 2 /* ref # */ -#define ELP_REFH 3 -#define ELP_UN 4 /* unit */ -#define ELP_SEQ 5 -#define ELP_FF 6 /* fmt,flg */ -#define ELP_EVT 7 /* event */ - -#define ELP_EV_V_FMT 0 /* format */ -#define ELP_EV_V_FLG 8 /* flag */ - -/* Port last failure error log packet - 6 W status */ - -#define PLF_LNT 24 /* length */ -#define PLF_CIDA 8 /* ctrl ID */ -#define PLF_CIDB 9 -#define PLF_CIDC 10 -#define PLF_CIDD 11 -#define PLF_VER 12 /* ctrl version */ -#define PLF_ERR 13 /* err */ - -#define PLF_CIDD_V_MOD 0 /* ctrl model */ -#define PLF_CIDD_V_CLS 8 /* ctrl class */ -#define PLF_VER_V_SVER 0 /* swre ver */ -#define PLF_VER_V_HVER 8 /* hwre ver */ - -/* Disk transfer error log packet - 18 W status */ - -#define DTE_LNT 48 -#define DTE_CIDA 8 /* ctrl ID */ -#define DTE_CIDB 9 -#define DTE_CIDC 10 -#define DTE_CIDD 11 -#define DTE_VER 12 /* version */ -#define DTE_MLUN 13 /* mlun */ -#define DTE_UIDA 14 /* unit ID */ -#define DTE_UIDB 15 -#define DTE_UIDC 16 -#define DTE_UIDD 17 -#define DTE_UVER 18 -#define DTE_D2 23 -#define DTE_D3 24 -#define DTE_D4 25 - -/* Disk specific status */ - -#define DTE_SCYL 19 /* cylinder */ -#define DTE_VSNL 20 /* vol ser # */ -#define DTE_VSNH 21 -#define DTE_D1 22 /* dev params */ - -/* Tape specific status */ - -#define DTE_RETR 19 /* retry */ -#define DTE_POSL 20 /* position */ -#define DTE_POSH 21 -#define DTE_FVER 22 /* formatter ver */ - -#define DTE_CIDD_V_MOD 0 /* ctrl model */ -#define DTE_CIDD_V_CLS 8 /* ctrl class */ -#define DTE_VER_V_SVER 0 /* ctrl swre ver */ -#define DTE_VER_V_HVER 8 /* ctrl hwre ver */ -#define DTE_UIDD_V_MOD 0 /* unit model */ -#define DTE_UIDD_V_CLS 8 /* unit class */ -#define DTE_D2_V_SECT 8 -#define DTE_D3_V_SURF 0 -#define DTE_D3_V_CYL 8 - -/* Host bus error log packet - 8 W status */ - -#define HBE_LNT 28 -#define HBE_CIDA 8 /* ctrl ID */ -#define HBE_CIDB 9 -#define HBE_CIDC 10 -#define HBE_CIDD 11 -#define HBE_VER 12 /* ctrl version */ -#define HBE_RSV 13 /* reserved */ -#define HBE_BADL 14 /* bad address */ -#define HBE_BADH 15 - -#define HBE_CIDD_V_MOD 0 /* ctrl model */ -#define HBE_CIDD_V_CLS 8 /* ctrl class */ -#define HBE_VER_V_SVER 0 /* ctrl swre ver */ -#define HBE_VER_V_HVER 8 /* ctrl hwre ver */ - -/* Unit now available attention message - 10 W status, same as - first 10 W of status from get unit status -*/ - -#define UNA_LNT 32 - -#endif diff --git a/PDP11/pdp11_pclk.c b/PDP11/pdp11_pclk.c deleted file mode 100644 index af088679..00000000 --- a/PDP11/pdp11_pclk.c +++ /dev/null @@ -1,293 +0,0 @@ -/* pdp11_pclk.c: KW11P programmable clock simulator - - Copyright (c) 1993-2003, Robert M Supnik - Written by John Dundas, used with his gracious permission - - 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. - - pclk KW11P line frequency clock -*/ - -/* KW11-P Programmable Clock - - I/O Page Registers: - - CSR 17 772 540 - CSB 17 772 542 - CNT 17 772 544 - - Vector: 0104 - - Priority: BR6 - - ** Theory of Operation ** - - A real KW11-P is built around the following major components: - - 16-bit up/down counter - - 16-bit count set buffer - - 9-bit control and status register - - clocks: crystal controlled (1) 100 kHz and (2) 10 kHz clocks, - (3) a 50/60 Hz line frequency clock, and (4) an analog signal - input trigger - This software emulator for SIMH implements all of the above with - the exception of the external input trigger, which is arbitrarily - wired to 10Hz. - - Operation of this emulator is rather simplistic as compared to the - actual device. The register read and write routines are responsible - for copying internal state from the simulated device to the operating - program. Clock state variables are altered in the write routine - as well as the desired clock ticking rate. Possible rates are - given in the table below. - - Rate Bit 2 Bit 1 - 100 kHz 0 0 - 10 kHz 0 1 - Line frequency 1 0 - External 1 1 - - I think SIMH would have a hard time actually keeping up with a 100 - kHz ticking rate. I haven't tried this to verify, though. - - The clock service routine (pclk_svc) is responsible for ticking - the clock. The routine does implement up/down, repeat vs. - single-interrupt, and single clocking (maintenance). The routine - updates the internal state according to the options selected and - signals interrupts when appropriate. - - For a complete description of the device, please see DEC-11-HPWB-D - KW11-P Programmable Real-Time Clock Manual. - - ** Notes ** - - 1. The device is disabled by default. - - 2. Use XXDP V2.5 test program ZKWBJ1.BIC; loads at 1000, starts at - 1100? Seems to execute the first few tests correctly then waits - for input from the console. I don't have a description of how this - diagnostic works and thus don't know how to proceed from that point. - - 3. The read and write routines don't do anything with odd address - accesses. The manual says that byte writes don't work. - - 4. RSTS can use this clock in place of the standard KW11-L line - frequency clock. In order to do this, use the DEFAULT response in - the OPTION: dialog. To the Preferred clock prompt answer "P". - Then you have the option of line frequency "L" or some multiple of - 50 between 50 and 1000 to use the programmable portion of the clock. - - 5. This is really a Unibus peripheral and thus doesn't actually make - sense within a J-11 system as there never was a Qbus version of - this to the best of my knowledge. However the OSs I have tried - don't appear to exhibit any dissonance between this option and the - processor/bus emulation. I think the options that would make - somewhat more sense in a Qbus environment the KWV11-C and/or KWV11-S. - I don't know if any of the -11 OSs contained support for using - these as the system clock, though. -*/ - -#include "pdp11_defs.h" - -#define PCLKCSR_RDMASK 0100377 /* readable */ -#define PCLKCSR_WRMASK 0000137 /* writeable */ - -#define UNIT_V_LINE50HZ (UNIT_V_UF + 0) -#define UNIT_LINE50HZ (1 << UNIT_V_LINE50HZ) - -/* CSR - 17772540 */ - -#define CSR_V_FIX 5 /* single tick */ -#define CSR_V_UPDN 4 /* down/up */ -#define CSR_V_MODE 3 /* single/repeat */ -#define CSR_FIX (1u << CSR_V_FIX) -#define CSR_UPDN (1u << CSR_V_UPDN) -#define CSR_MODE (1u << CSR_V_MODE) -#define CSR_V_RATE 1 /* rate */ -#define CSR_M_RATE 03 -#define CSR_GETRATE(x) (((x) >> CSR_V_RATE) & CSR_M_RATE) - -extern int32 int_req[IPL_HLVL]; -extern int32 int_vec[IPL_HLVL][32]; - -uint32 pclk_csr = 0; /* control/status */ -uint32 pclk_csb = 0; /* count set buffer */ -uint32 pclk_ctr = 0; /* counter */ -static uint32 rate[4] = { 100000, 10000, 60, 10 }; /* ticks per second */ -static uint32 xtim[4] = { 10, 100, 16000, 100000 }; /* nominal time delay */ - -DEVICE pclk_dev; -t_stat pclk_rd (int32 *data, int32 PA, int32 access); -t_stat pclk_wr (int32 data, int32 PA, int32 access); -t_stat pclk_svc (UNIT *uptr); -t_stat pclk_reset (DEVICE *dptr); -t_stat pclk_set_line (UNIT *uptr, int32 val, char *cptr, void *desc); -void pclk_tick (void); - -/* PCLK data structures - - pclk_dev PCLK device descriptor - pclk_unit PCLK unit descriptor - pclk_reg PCLK register list -*/ - -DIB pclk_dib = { IOBA_PCLK, IOLN_PCLK, &pclk_rd, &pclk_wr, - 1, IVCL (PCLK), VEC_PCLK, { NULL } }; - -UNIT pclk_unit = { UDATA (&pclk_svc, 0, 0) }; - -REG pclk_reg[] = { - { ORDATA (CSR, pclk_csr, 16) }, - { ORDATA (CSB, pclk_csb, 16) }, - { ORDATA (CNT, pclk_ctr, 16) }, - { FLDATA (INT, IREQ (PCLK), INT_V_PCLK) }, - { FLDATA (OVFL, pclk_csr, CSR_V_ERR) }, - { FLDATA (DONE, pclk_csr, CSR_V_DONE) }, - { FLDATA (IE, pclk_csr, CSR_V_IE) }, - { FLDATA (UPDN, pclk_csr, CSR_V_UPDN) }, - { FLDATA (MODE, pclk_csr, CSR_V_MODE) }, - { FLDATA (RUN, pclk_csr, CSR_V_GO) }, - { BRDATA (TIME, xtim, 10, 32, 4), REG_NZ + PV_LEFT }, - { BRDATA (TPS, rate, 10, 32, 4), REG_NZ + PV_LEFT }, - { DRDATA (CURTIM, pclk_unit.wait, 32), REG_HRO }, - { ORDATA (DEVADDR, pclk_dib.ba, 32), REG_HRO }, - { ORDATA (DEVVEC, pclk_dib.vec, 16), REG_HRO }, - { NULL } }; - -MTAB pclk_mod[] = { - { UNIT_LINE50HZ, UNIT_LINE50HZ, "50 Hz", "50HZ", &pclk_set_line }, - { UNIT_LINE50HZ, 0, "60 Hz", "60HZ", &pclk_set_line }, - { MTAB_XTD|MTAB_VDV, 0, "ADDRESS", NULL, - NULL, &show_addr, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "VECTOR", "VECTOR", - &set_vec, &show_vec, NULL }, - { 0 } }; - -DEVICE pclk_dev = { - "PCLK", &pclk_unit, pclk_reg, pclk_mod, - 1, 0, 0, 0, 0, 0, - NULL, NULL, &pclk_reset, - NULL, NULL, NULL, - &pclk_dib, DEV_DISABLE | DEV_DIS | DEV_UBUS | DEV_QBUS }; - -/* Clock I/O address routines */ - -t_stat pclk_rd (int32 *data, int32 PA, int32 access) -{ -switch ((PA >> 1) & 03) { -case 00: /* CSR */ - *data = pclk_csr & PCLKCSR_RDMASK; /* return CSR */ - pclk_csr = pclk_csr & ~(CSR_ERR | CSR_DONE); /* clr err, done */ - CLR_INT (PCLK); /* clr intr */ - break; -case 01: /* buffer */ - *data = 0; /* read only */ - break; -case 02: /* counter */ - *data = pclk_ctr & DMASK; /* return counter */ - break; } -return SCPE_OK; -} - -t_stat pclk_wr (int32 data, int32 PA, int32 access) -{ -int32 old_csr = pclk_csr; -int32 rv; - -switch ((PA >> 1) & 03) { -case 00: /* CSR */ - pclk_csr = data & PCLKCSR_WRMASK; /* clear and write */ - CLR_INT (PCLK); /* clr intr */ - 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 */ - 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)); - } - break; -case 01: /* buffer */ - pclk_csb = pclk_ctr = data; /* store ctr */ - pclk_csr = pclk_csr & ~(CSR_ERR | CSR_DONE); /* clr err, done */ - CLR_INT (PCLK); /* clr intr */ - break; -case 02: /* counter */ - break; } /* read only */ -return SCPE_OK; -} - -/* Clock tick (automatic or manual) */ - -void pclk_tick (void) -{ -if (pclk_csr & CSR_UPDN) /* up or down? */ - pclk_ctr = (pclk_ctr + 1) & DMASK; /* 1 = up */ -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 */ - 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 */ -return; -} - -/* Clock service */ - -t_stat pclk_svc (UNIT *uptr) -{ -int32 rv; - -pclk_tick (); /* tick clock */ -if ((pclk_csr & CSR_GO) == 0) return SCPE_OK; /* done? */ -rv = CSR_GETRATE (pclk_csr); /* get rate */ -sim_activate (&pclk_unit, sim_rtcn_calb (rate[rv], TMR_PCLK)); -return SCPE_OK; -} - -/* Clock reset */ - -t_stat pclk_reset (DEVICE *dptr) -{ -pclk_csr = 0; /* clear reg */ -pclk_csb = 0; -pclk_ctr = 0; -CLR_INT (PCLK); /* clear int */ -sim_cancel (&pclk_unit); /* cancel */ -pclk_unit.wait = xtim[0]; /* reset delay */ -return SCPE_OK; -} - -/* Set line frequency */ - -t_stat pclk_set_line (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -if (val == UNIT_LINE50HZ) rate[2] = 50; -else rate[2] = 60; -return SCPE_OK; -} diff --git a/PDP11/pdp11_pt.c b/PDP11/pdp11_pt.c deleted file mode 100644 index 169c4d4c..00000000 --- a/PDP11/pdp11_pt.c +++ /dev/null @@ -1,324 +0,0 @@ -/* pdp11_pt.c: PC11 paper tape reader/punch simulator - - 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. - - ptr paper tape reader - ptp paper tape punch - - 19-May-03 RMS Revised for new conditional compilation scheme - 25-Apr-03 RMS Revised for extended file support - 12-Sep-02 RMS Split off from pdp11_stddev.c -*/ - -#if defined (VM_PDP10) /* PDP10 version */ -#include "pdp10_defs.h" -#define PT_DIS DEV_DIS -extern int32 int_req; -extern int32 int_vec[32]; - -#elif defined (VM_VAX) /* VAX version */ -#include "vax_defs.h" -#define PT_DIS DEV_DIS -extern int32 int_req[IPL_HLVL]; -extern int32 int_vec[IPL_HLVL][32]; - -#else /* PDP-11 version */ -#include "pdp11_defs.h" -#define PT_DIS 0 -extern int32 int_req[IPL_HLVL]; -extern int32 int_vec[IPL_HLVL][32]; -#endif - -#define PTRCSR_IMP (CSR_ERR+CSR_BUSY+CSR_DONE+CSR_IE) /* paper tape reader */ -#define PTRCSR_RW (CSR_IE) -#define PTPCSR_IMP (CSR_ERR + CSR_DONE + CSR_IE) /* paper tape punch */ -#define PTPCSR_RW (CSR_IE) - -int32 ptr_csr = 0; /* control/status */ -int32 ptr_stopioe = 0; /* stop on error */ -int32 ptp_csr = 0; /* control/status */ -int32 ptp_stopioe = 0; /* stop on error */ - -DEVICE ptr_dev, ptp_dev; -t_stat ptr_rd (int32 *data, int32 PA, int32 access); -t_stat ptr_wr (int32 data, int32 PA, int32 access); -t_stat ptr_svc (UNIT *uptr); -t_stat ptr_reset (DEVICE *dptr); -t_stat ptr_attach (UNIT *uptr, char *ptr); -t_stat ptr_detach (UNIT *uptr); -t_stat ptp_rd (int32 *data, int32 PA, int32 access); -t_stat ptp_wr (int32 data, int32 PA, int32 access); -t_stat ptp_svc (UNIT *uptr); -t_stat ptp_reset (DEVICE *dptr); -t_stat ptp_attach (UNIT *uptr, char *ptr); -t_stat ptp_detach (UNIT *uptr); - -/* PTR data structures - - ptr_dev PTR device descriptor - ptr_unit PTR unit descriptor - ptr_reg PTR register list -*/ - -DIB ptr_dib = { IOBA_PTR, IOLN_PTR, &ptr_rd, &ptr_wr, - 1, IVCL (PTR), VEC_PTR, { NULL } }; - -UNIT ptr_unit = { - UDATA (&ptr_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0), - SERIAL_IN_WAIT }; - -REG ptr_reg[] = { - { GRDATA (BUF, ptr_unit.buf, DEV_RDX, 8, 0) }, - { GRDATA (CSR, ptr_csr, DEV_RDX, 16, 0) }, - { FLDATA (INT, int_req, INT_V_PTR) }, - { FLDATA (ERR, ptr_csr, CSR_V_ERR) }, - { FLDATA (BUSY, ptr_csr, CSR_V_BUSY) }, - { FLDATA (DONE, ptr_csr, CSR_V_DONE) }, - { FLDATA (IE, ptr_csr, CSR_V_IE) }, - { DRDATA (POS, ptr_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, ptr_unit.wait, 24), PV_LEFT }, - { FLDATA (STOP_IOE, ptr_stopioe, 0) }, - { FLDATA (DEVDIS, ptr_dev.flags, DEV_V_DIS), REG_HRO }, - { NULL } }; - -MTAB ptr_mod[] = { - { MTAB_XTD|MTAB_VDV, 0, "ADDRESS", NULL, - NULL, &show_addr, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "VECTOR", NULL, - NULL, &show_vec, NULL }, - { 0 } }; - -DEVICE ptr_dev = { - "PTR", &ptr_unit, ptr_reg, ptr_mod, - 1, 10, 31, 1, DEV_RDX, 8, - NULL, NULL, &ptr_reset, - NULL, &ptr_attach, &ptr_detach, - &ptr_dib, DEV_DISABLE | PT_DIS | DEV_UBUS | DEV_QBUS }; - -/* PTP data structures - - ptp_dev PTP device descriptor - ptp_unit PTP unit descriptor - ptp_reg PTP register list -*/ - -DIB ptp_dib = { IOBA_PTP, IOLN_PTP, &ptp_rd, &ptp_wr, - 1, IVCL (PTP), VEC_PTP, { NULL } }; - -UNIT ptp_unit = { - UDATA (&ptp_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT }; - -REG ptp_reg[] = { - { GRDATA (BUF, ptp_unit.buf, DEV_RDX, 8, 0) }, - { GRDATA (CSR, ptp_csr, DEV_RDX, 16, 0) }, - { FLDATA (INT, int_req, INT_V_PTP) }, - { FLDATA (ERR, ptp_csr, CSR_V_ERR) }, - { FLDATA (DONE, ptp_csr, CSR_V_DONE) }, - { FLDATA (IE, ptp_csr, CSR_V_IE) }, - { DRDATA (POS, ptp_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, ptp_unit.wait, 24), PV_LEFT }, - { FLDATA (STOP_IOE, ptp_stopioe, 0) }, - { NULL } }; - -MTAB ptp_mod[] = { - { MTAB_XTD|MTAB_VDV, 0, "ADDRESS", NULL, - NULL, &show_addr, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "VECTOR", NULL, - NULL, &show_vec, NULL }, - { 0 } }; - -DEVICE ptp_dev = { - "PTP", &ptp_unit, ptp_reg, ptp_mod, - 1, 10, 31, 1, DEV_RDX, 8, - NULL, NULL, &ptp_reset, - NULL, &ptp_attach, &ptp_detach, - &ptp_dib, DEV_DISABLE | PT_DIS | DEV_UBUS | DEV_QBUS }; - -/* Paper tape reader I/O address routines */ - -t_stat ptr_rd (int32 *data, int32 PA, int32 access) -{ -switch ((PA >> 1) & 01) { /* decode PA<1> */ -case 0: /* ptr csr */ - *data = ptr_csr & PTRCSR_IMP; - return SCPE_OK; -case 1: /* ptr buf */ - ptr_csr = ptr_csr & ~CSR_DONE; - CLR_INT (PTR); - *data = ptr_unit.buf & 0377; - return SCPE_OK; } -return SCPE_NXM; /* can't get here */ -} - -t_stat ptr_wr (int32 data, int32 PA, int32 access) -{ -switch ((PA >> 1) & 01) { /* decode PA<1> */ -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); - 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 & ~PTRCSR_RW) | (data & PTRCSR_RW); - return SCPE_OK; -case 1: /* ptr buf */ - return SCPE_OK; } /* end switch PA */ -return SCPE_NXM; /* can't get here */ -} - -/* Paper tape reader service */ - -t_stat ptr_svc (UNIT *uptr) -{ -int32 temp; - -ptr_csr = (ptr_csr | CSR_ERR) & ~CSR_BUSY; -if (ptr_csr & CSR_IE) SET_INT (PTR); -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; } - else perror ("PTR I/O error"); - clearerr (ptr_unit.fileref); - return SCPE_IOERR; } -ptr_csr = (ptr_csr | CSR_DONE) & ~CSR_ERR; -ptr_unit.buf = temp & 0377; -ptr_unit.pos = ptr_unit.pos + 1; -return SCPE_OK; -} - -/* Paper tape reader support routines */ - -t_stat ptr_reset (DEVICE *dptr) -{ -ptr_unit.buf = 0; -ptr_csr = 0; -if ((ptr_unit.flags & UNIT_ATT) == 0) ptr_csr = ptr_csr | CSR_ERR; -CLR_INT (PTR); -sim_cancel (&ptr_unit); -return SCPE_OK; -} - -t_stat ptr_attach (UNIT *uptr, char *cptr) -{ -t_stat reason; - -reason = attach_unit (uptr, cptr); -if ((ptr_unit.flags & UNIT_ATT) == 0) ptr_csr = ptr_csr | CSR_ERR; -else ptr_csr = ptr_csr & ~CSR_ERR; -return reason; -} - -t_stat ptr_detach (UNIT *uptr) -{ -ptr_csr = ptr_csr | CSR_ERR; -return detach_unit (uptr); -} - -/* Paper tape punch I/O address routines */ - -t_stat ptp_rd (int32 *data, int32 PA, int32 access) -{ -switch ((PA >> 1) & 01) { /* decode PA<1> */ -case 0: /* ptp csr */ - *data = ptp_csr & PTPCSR_IMP; - return SCPE_OK; -case 1: /* ptp buf */ - *data = ptp_unit.buf; - return SCPE_OK; } -return SCPE_NXM; /* can't get here */ -} - -t_stat ptp_wr (int32 data, int32 PA, int32 access) -{ -switch ((PA >> 1) & 01) { /* decode PA<1> */ -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); - ptp_csr = (ptp_csr & ~PTPCSR_RW) | (data & PTPCSR_RW); - return SCPE_OK; -case 1: /* ptp buf */ - if ((PA & 1) == 0) ptp_unit.buf = data & 0377; - 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); - else sim_activate (&ptp_unit, 0); /* error if not */ - return SCPE_OK; } /* end switch PA */ -return SCPE_NXM; /* can't get here */ -} - -/* Paper tape punch service */ - -t_stat ptp_svc (UNIT *uptr) -{ -ptp_csr = ptp_csr | CSR_ERR | CSR_DONE; -if (ptp_csr & CSR_IE) SET_INT (PTP); -if ((ptp_unit.flags & UNIT_ATT) == 0) - return IORETURN (ptp_stopioe, SCPE_UNATT); -if (putc (ptp_unit.buf, ptp_unit.fileref) == EOF) { - perror ("PTP I/O error"); - clearerr (ptp_unit.fileref); - return SCPE_IOERR; } -ptp_csr = ptp_csr & ~CSR_ERR; -ptp_unit.pos = ptp_unit.pos + 1; -return SCPE_OK; -} - -/* Paper tape punch support routines */ - -t_stat ptp_reset (DEVICE *dptr) -{ -ptp_unit.buf = 0; -ptp_csr = CSR_DONE; -if ((ptp_unit.flags & UNIT_ATT) == 0) ptp_csr = ptp_csr | CSR_ERR; -CLR_INT (PTP); -sim_cancel (&ptp_unit); /* deactivate unit */ -return SCPE_OK; -} - -t_stat ptp_attach (UNIT *uptr, char *cptr) -{ -t_stat reason; - -reason = attach_unit (uptr, cptr); -if ((ptp_unit.flags & UNIT_ATT) == 0) ptp_csr = ptp_csr | CSR_ERR; -else ptp_csr = ptp_csr & ~CSR_ERR; -return reason; -} - -t_stat ptp_detach (UNIT *uptr) -{ -ptp_csr = ptp_csr | CSR_ERR; -return detach_unit (uptr); -} diff --git a/PDP11/pdp11_rk.c b/PDP11/pdp11_rk.c deleted file mode 100644 index 5dc8b1e2..00000000 --- a/PDP11/pdp11_rk.c +++ /dev/null @@ -1,615 +0,0 @@ -/* pdp11_rk.c: RK11 cartridge disk simulator - - 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. - - rk RK11/RK05 cartridge disk - - 29-Sep-02 RMS Added variable address support to bootstrap - Added vector change/display support - Revised mapping mnemonics - New data structures - 26-Jan-02 RMS Revised bootstrap to conform to M9312 - 06-Jan-02 RMS Revised enable/disable support - 30-Nov-01 RMS Added read only unit, extended SET/SHOW support - 24-Nov-01 RMS Converted FLG to array - 09-Nov-01 RMS Added bus map support - 07-Sep-01 RMS Revised device disable and interrupt mechanisms - 26-Apr-01 RMS Added device enable/disable support - 25-Mar-01 RMS Fixed block fill calculation - 15-Feb-01 RMS Corrected bootstrap string - 29-Jun-96 RMS Added unit disable support - - The RK11 is an eight drive cartridge disk subsystem. An RK05 drive - consists of 203 cylinders, each with 2 surfaces containing 12 sectors - of 512 bytes. - - The most complicated part of the RK11 controller is the concept of - interrupt "polling". While only one read or write can occur at a - time, the controller supports multiple seeks. When a seek completes, - if done is set the drive attempts to interrupt. If an interrupt is - already pending, the interrupt is "queued" until it can be processed. - When an interrupt occurs, RKDS<15:13> is loaded with the number of the - interrupting drive. - - To implement this structure, and to assure that read/write interrupts - take priority over seek interrupts, the controller contains an - interrupt queue, rkintq, with a bit for a controller interrupt and - then one for each drive. In addition, the drive number of the last - non-seeking drive is recorded in last_drv. -*/ - -#include "pdp11_defs.h" - -/* Constants */ - -#define RK_NUMWD 256 /* words/sector */ -#define RK_NUMSC 12 /* sectors/surface */ -#define RK_NUMSF 2 /* surfaces/cylinder */ -#define RK_NUMCY 203 /* cylinders/drive */ -#define RK_NUMTR (RK_NUMCY * RK_NUMSF) /* tracks/drive */ -#define RK_NUMDR 8 /* drives/controller */ -#define RK_M_NUMDR 07 -#define RK_SIZE (RK_NUMCY * RK_NUMSF * RK_NUMSC * RK_NUMWD) /* words/drive */ -#define RK_CTLI 1 /* controller int */ -#define RK_SCPI(x) (2u << (x)) /* drive int */ -#define RK_MAXFR (1 << 16) /* max transfer */ - -/* Flags in the unit flags word */ - -#define UNIT_V_HWLK (UNIT_V_UF + 0) /* hwre write lock */ -#define UNIT_V_SWLK (UNIT_V_UF + 1) /* swre write lock */ -#define UNIT_HWLK (1u << UNIT_V_HWLK) -#define UNIT_SWLK (1u << UNIT_V_SWLK) -#define UNIT_WPRT (UNIT_HWLK|UNIT_SWLK|UNIT_RO) /* write prot */ - -/* Parameters in the unit descriptor */ - -#define CYL u3 /* current cylinder */ -#define FUNC u4 /* function */ - -/* RKDS */ - -#define RKDS_SC 0000017 /* sector counter */ -#define RKDS_ON_SC 0000020 /* on sector */ -#define RKDS_WLK 0000040 /* write locked */ -#define RKDS_RWS 0000100 /* rd/wr/seek ready */ -#define RKDS_RDY 0000200 /* drive ready */ -#define RKDS_SC_OK 0000400 /* SC valid */ -#define RKDS_INC 0001000 /* seek incomplete */ -#define RKDS_UNSAFE 0002000 /* unsafe */ -#define RKDS_RK05 0004000 /* RK05 */ -#define RKDS_PWR 0010000 /* power low */ -#define RKDS_ID 0160000 /* drive ID */ -#define RKDS_V_ID 13 - -/* RKER */ - -#define RKER_WCE 0000001 /* write check */ -#define RKER_CSE 0000002 /* checksum */ -#define RKER_NXS 0000040 /* nx sector */ -#define RKER_NXC 0000100 /* nx cylinder */ -#define RKER_NXD 0000200 /* nx drive */ -#define RKER_TE 0000400 /* timing error */ -#define RKER_DLT 0001000 /* data late */ -#define RKER_NXM 0002000 /* nx memory */ -#define RKER_PGE 0004000 /* programming error */ -#define RKER_SKE 0010000 /* seek error */ -#define RKER_WLK 0020000 /* write lock */ -#define RKER_OVR 0040000 /* overrun */ -#define RKER_DRE 0100000 /* drive error */ -#define RKER_IMP 0177743 /* implemented */ -#define RKER_SOFT (RKER_WCE+RKER_CSE) /* soft errors */ -#define RKER_HARD 0177740 /* hard errors */ - -/* RKCS */ - -#define RKCS_M_FUNC 0000007 /* function */ -#define RKCS_CTLRESET 0 -#define RKCS_WRITE 1 -#define RKCS_READ 2 -#define RKCS_WCHK 3 -#define RKCS_SEEK 4 -#define RKCS_RCHK 5 -#define RKCS_DRVRESET 6 -#define RKCS_WLK 7 -#define RKCS_V_FUNC 1 -#define RKCS_MEX 0000060 /* memory extension */ -#define RKCS_V_MEX 4 -#define RKCS_SSE 0000400 /* stop on soft err */ -#define RKCS_FMT 0002000 /* format */ -#define RKCS_INH 0004000 /* inhibit increment */ -#define RKCS_SCP 0020000 /* search complete */ -#define RKCS_HERR 0040000 /* hard error */ -#define RKCS_ERR 0100000 /* error */ -#define RKCS_REAL 0026776 /* kept here */ -#define RKCS_RW 0006576 /* read/write */ -#define GET_FUNC(x) (((x) >> RKCS_V_FUNC) & RKCS_M_FUNC) - -/* RKDA */ - -#define RKDA_V_SECT 0 /* sector */ -#define RKDA_M_SECT 017 -#define RKDA_V_TRACK 4 /* track */ -#define RKDA_M_TRACK 0777 -#define RKDA_V_CYL 5 /* cylinder */ -#define RKDA_M_CYL 0377 -#define RKDA_V_DRIVE 13 /* drive */ -#define RKDA_M_DRIVE 07 -#define RKDA_DRIVE (RKDA_M_DRIVE << RKDA_V_DRIVE) -#define GET_SECT(x) (((x) >> RKDA_V_SECT) & RKDA_M_SECT) -#define GET_CYL(x) (((x) >> RKDA_V_CYL) & RKDA_M_CYL) -#define GET_TRACK(x) (((x) >> RKDA_V_TRACK) & RKDA_M_TRACK) -#define GET_DRIVE(x) (((x) >> RKDA_V_DRIVE) & RKDA_M_DRIVE) -#define GET_DA(x) ((GET_TRACK (x) * RK_NUMSC) + GET_SECT (x)) - -/* RKBA */ - -#define RKBA_IMP 0177776 /* implemented */ - -#define RK_MIN 10 -#define MAX(x,y) (((x) > (y))? (x): (y)) - -extern uint16 *M; /* memory */ -extern int32 int_req[IPL_HLVL]; -extern int32 int_vec[IPL_HLVL][32]; - -uint16 *rkxb = NULL; /* xfer buffer */ -int32 rkcs = 0; /* control/status */ -int32 rkds = 0; /* drive status */ -int32 rkba = 0; /* memory address */ -int32 rkda = 0; /* disk address */ -int32 rker = 0; /* error status */ -int32 rkwc = 0; /* word count */ -int32 rkintq = 0; /* interrupt queue */ -int32 last_drv = 0; /* last r/w drive */ -int32 rk_stopioe = 1; /* stop on error */ -int32 rk_swait = 10; /* seek time */ -int32 rk_rwait = 10; /* rotate time */ - -DEVICE rk_dev; -t_stat rk_rd (int32 *data, int32 PA, int32 access); -t_stat rk_wr (int32 data, int32 PA, int32 access); -int32 rk_inta (void); -t_stat rk_svc (UNIT *uptr); -t_stat rk_reset (DEVICE *dptr); -void rk_go (void); -void rk_set_done (int32 error); -void rk_clr_done (void); -t_stat rk_boot (int32 unitno, DEVICE *dptr); - -/* RK11 data structures - - rk_dev RK device descriptor - rk_unit RK unit list - rk_reg RK register list - rk_mod RK modifier list -*/ - -DIB rk_dib = { IOBA_RK, IOLN_RK, &rk_rd, &rk_wr, - 1, IVCL (RK), VEC_RK, { &rk_inta } }; - -UNIT rk_unit[] = { - { UDATA (&rk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE, RK_SIZE) }, - { UDATA (&rk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE, RK_SIZE) }, - { UDATA (&rk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE, RK_SIZE) }, - { UDATA (&rk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE, RK_SIZE) }, - { UDATA (&rk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE, RK_SIZE) }, - { UDATA (&rk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE, RK_SIZE) }, - { UDATA (&rk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE, RK_SIZE) }, - { UDATA (&rk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE, RK_SIZE) } }; - -REG rk_reg[] = { - { ORDATA (RKCS, rkcs, 16) }, - { ORDATA (RKDA, rkda, 16) }, - { ORDATA (RKBA, rkba, 16) }, - { ORDATA (RKWC, rkwc, 16) }, - { ORDATA (RKDS, rkds, 16) }, - { ORDATA (RKER, rker, 16) }, - { ORDATA (INTQ, rkintq, 9) }, - { ORDATA (DRVN, last_drv, 3) }, - { FLDATA (INT, IREQ (RK), INT_V_RK) }, - { FLDATA (ERR, rkcs, CSR_V_ERR) }, - { FLDATA (DONE, rkcs, CSR_V_DONE) }, - { FLDATA (IE, rkcs, CSR_V_IE) }, - { DRDATA (STIME, rk_swait, 24), PV_LEFT }, - { DRDATA (RTIME, rk_rwait, 24), PV_LEFT }, - { FLDATA (STOP_IOE, rk_stopioe, 0) }, - { ORDATA (DEVADDR, rk_dib.ba, 32), REG_HRO }, - { ORDATA (DEVVEC, rk_dib.vec, 16), REG_HRO }, - { NULL } }; - -MTAB rk_mod[] = { - { UNIT_HWLK, 0, "write enabled", "WRITEENABLED", NULL }, - { UNIT_HWLK, UNIT_HWLK, "write locked", "LOCKED", NULL }, - { MTAB_XTD|MTAB_VDV, 020, "ADDRESS", "ADDRESS", - &set_addr, &show_addr, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "VECTOR", "VECTOR", - &set_vec, &show_vec, NULL }, - { 0 } }; - -DEVICE rk_dev = { - "RK", rk_unit, rk_reg, rk_mod, - RK_NUMDR, 8, 24, 1, 8, 16, - NULL, NULL, &rk_reset, - &rk_boot, NULL, NULL, - &rk_dib, DEV_DISABLE | DEV_UBUS }; - -/* I/O dispatch routine, I/O addresses 17777400 - 17777416 - - 17777400 RKDS read only, constructed from "id'd drive" - plus current drive status flags - 17777402 RKER read only, set as operations progress, - cleared by INIT or CONTROL RESET - 17777404 RKCS read/write - 17777406 RKWC read/write - 17777410 RKBA read/write - 17777412 RKDA read/write - 17777414 RKMR read/write, unimplemented - 17777416 RKDB read only, unimplemented -*/ - -t_stat rk_rd (int32 *data, int32 PA, int32 access) -{ -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 */ - 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? */ - if (uptr->flags & UNIT_WPRT) rkds = rkds | RKDS_WLK; - if (GET_SECT (rkda) == (rkds & RKDS_SC)) rkds = rkds | RKDS_ON_SC; - *data = rkds; - return SCPE_OK; -case 1: /* RKER: read only */ - *data = rker & RKER_IMP; - return SCPE_OK; -case 2: /* RKCS */ - rkcs = rkcs & RKCS_REAL; - if (rker) rkcs = rkcs | RKCS_ERR; /* update err flags */ - if (rker & RKER_HARD) rkcs = rkcs | RKCS_HERR; - *data = rkcs; - return SCPE_OK; -case 3: /* RKWC */ - *data = rkwc; - return SCPE_OK; -case 4: /* RKBA */ - *data = rkba & RKBA_IMP; - return SCPE_OK; -case 5: /* RKDA */ - *data = rkda; - return SCPE_OK; -default: - *data = 0; - return SCPE_OK; } /* end switch */ -} - -t_stat rk_wr (int32 data, int32 PA, int32 access) -{ -switch ((PA >> 1) & 07) { /* decode PA<3:1> */ -case 0: /* RKDS: read only */ - return SCPE_OK; -case 1: /* RKER: read only */ - return SCPE_OK; -case 2: /* RKCS */ - rkcs = rkcs & RKCS_REAL; - if (access == WRITEB) data = (PA & 1)? - (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 */ - else if ((rkcs & (CSR_DONE + CSR_IE)) == CSR_DONE) { - 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 = data; - return SCPE_OK; -case 4: /* RKBA */ - if (access == WRITEB) data = (PA & 1)? - (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 = data; - return SCPE_OK; -default: - return SCPE_OK; } /* end switch */ -} - -/* Initiate new function */ - -void rk_go (void) -{ -int32 i, sect, cyl, func; -UNIT *uptr; - -func = GET_FUNC (rkcs); /* get function */ -if (func == RKCS_CTLRESET) { /* control reset? */ - rker = 0; /* clear errors */ - rkda = 0; - rkba = 0; - rkcs = CSR_DONE; - rkintq = 0; /* clr int queue */ - CLR_INT (RK); /* clr int request */ - return; } -rker = rker & ~RKER_SOFT; /* clear soft errors */ -if (rker == 0) rkcs = rkcs & ~RKCS_ERR; /* redo summary */ -rkcs = rkcs & ~RKCS_SCP; /* clear sch compl*/ -rk_clr_done (); /* clear done */ -last_drv = GET_DRIVE (rkda); /* get drive no */ -uptr = rk_dev.units + last_drv; /* select unit */ -if (uptr->flags & UNIT_DIS) { /* not present? */ - rk_set_done (RKER_NXD); - return; } -if (((uptr->flags & UNIT_ATT) == 0) || sim_is_active (uptr)) { - rk_set_done (RKER_DRE); /* not att or busy */ - return; } -if (rkcs & (RKCS_INH + RKCS_FMT)) { /* format? */ - rk_set_done (RKER_PGE); - return; } -if ((func == RKCS_WRITE) && (uptr->flags & UNIT_WPRT)) { - rk_set_done (RKER_WLK); /* write and locked? */ - return; } -if (func == RKCS_WLK) { /* write lock? */ - uptr->flags = uptr->flags | UNIT_SWLK; - rk_set_done (0); - return; } -if (func == RKCS_DRVRESET) { /* drive reset? */ - uptr->flags = uptr->flags & ~UNIT_SWLK; - cyl = sect = 0; - func = RKCS_SEEK; } -else { sect = GET_SECT (rkda); - cyl = GET_CYL (rkda); } -if (sect >= RK_NUMSC) { /* bad sector? */ - rk_set_done (RKER_NXS); - return; } -if (cyl >= RK_NUMCY) { /* bad cyl? */ - rk_set_done (RKER_NXC); - return; } -i = abs (cyl - uptr->CYL) * rk_swait; /* seek time */ -if (func == RKCS_SEEK) { /* seek? */ - rk_set_done (0); /* set done */ - sim_activate (uptr, MAX (RK_MIN, i)); } /* schedule */ -else sim_activate (uptr, i + rk_rwait); -uptr->FUNC = func; /* save func */ -uptr->CYL = cyl; /* put on cylinder */ -return; -} - -/* Service unit timeout - - If seek in progress, complete seek command - Else complete data transfer command - - The unit control block contains the function and disk address for - the current command. -*/ - -t_stat rk_svc (UNIT *uptr) -{ -int32 i, drv, err, awc, wc, t; -int32 da, track, sect; -uint32 ma; -uint16 comp; - -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 */ - return SCPE_OK; } - -if ((uptr->flags & UNIT_ATT) == 0) { /* attached? */ - rk_set_done (RKER_DRE); - return IORETURN (rk_stopioe, SCPE_UNATT); } -ma = ((rkcs & RKCS_MEX) << (16 - RKCS_V_MEX)) | rkba; /* get mem addr */ -da = GET_DA (rkda) * RK_NUMWD; /* get disk addr */ -wc = 0200000 - rkwc; /* get wd cnt */ - -err = fseek (uptr->fileref, da * sizeof (int16), SEEK_SET); - -if ((uptr->FUNC == RKCS_READ) && (err == 0)) { /* read? */ - i = fxread (rkxb, sizeof (int16), wc, uptr->fileref); - 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 */ - } /* end read */ - -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 */ - 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); } - } /* end write */ - -if ((uptr->FUNC == RKCS_WCHK) && (err == 0)) { /* write check? */ - i = fxread (rkxb, sizeof (int16), wc, uptr->fileref); - err = ferror (uptr->fileref); - 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; } } - } /* end wcheck */ - -rkwc = (rkwc + wc) & 0177777; /* final word count */ -ma = ma + (wc << 1); /* final byte addr */ -rkba = ma & RKBA_IMP; /* lower 16b */ -rkcs = (rkcs & ~RKCS_MEX) | ((ma >> (16 - RKCS_V_MEX)) & RKCS_MEX); -da = da + wc + (RK_NUMWD - 1); -track = (da / RK_NUMWD) / RK_NUMSC; -sect = (da / RK_NUMWD) % RK_NUMSC; -rkda = (rkda & RKDA_DRIVE) | (track << RKDA_V_TRACK) | (sect << RKDA_V_SECT); -rk_set_done (0); - -if (err != 0) { /* error? */ - perror ("RK I/O error"); - clearerr (uptr->fileref); - return SCPE_IOERR; } -return SCPE_OK; -} - -/* Interrupt state change routines - - rk_set_done set done and possibly errors - rk_clr_done clear done - rk_inta acknowledge intererupt -*/ - -void rk_set_done (int32 error) -{ -rkcs = rkcs | CSR_DONE; /* set done */ -if (error != 0) { - rker = rker | error; /* update error */ - if (rker) rkcs = rkcs | RKCS_ERR; /* update err flags */ - if (rker & RKER_HARD) rkcs = rkcs | RKCS_HERR; } -if (rkcs & CSR_IE) { /* int enable? */ - rkintq = rkintq | RK_CTLI; /* set ctrl int */ - SET_INT (RK); } /* request int */ -else { rkintq = 0; /* clear queue */ - CLR_INT (RK); } -return; -} - -void rk_clr_done (void) -{ -rkcs = rkcs & ~CSR_DONE; /* clear done */ -rkintq = rkintq & ~RK_CTLI; /* clear ctl int */ -CLR_INT (RK); /* clear int req */ -return; -} - -int32 rk_inta (void) -{ -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 = 0; /* clear queue */ -return 0; /* passive release */ -} - -/* Device reset */ - -t_stat rk_reset (DEVICE *dptr) -{ -int32 i; -UNIT *uptr; - -rkcs = CSR_DONE; -rkda = rkba = rker = rkds = 0; -rkintq = last_drv = 0; -CLR_INT (RK); -for (i = 0; i < RK_NUMDR; i++) { - uptr = rk_dev.units + i; - sim_cancel (uptr); - uptr->CYL = uptr->FUNC = 0; - uptr->flags = uptr->flags & ~UNIT_SWLK; } -if (rkxb == NULL) rkxb = calloc (RK_MAXFR, sizeof (unsigned int16)); -if (rkxb == NULL) return SCPE_MEM; -return SCPE_OK; -} - -/* Device bootstrap */ - -#define BOOT_START 02000 /* start */ -#define BOOT_ENTRY (BOOT_START + 002) /* entry */ -#define BOOT_UNIT (BOOT_START + 010) /* unit number */ -#define BOOT_CSR (BOOT_START + 032) /* CSR */ -#define BOOT_LEN (sizeof (boot_rom) / sizeof (int16)) - -static const uint16 boot_rom[] = { - 0042113, /* "KD" */ - 0012706, BOOT_START, /* MOV #boot_start, SP */ - 0012700, 0000000, /* MOV #unit, R0 ; unit number */ - 0010003, /* MOV R0, R3 */ - 0000303, /* SWAB R3 */ - 0006303, /* ASL R3 */ - 0006303, /* ASL R3 */ - 0006303, /* ASL R3 */ - 0006303, /* ASL R3 */ - 0006303, /* ASL R3 */ - 0012701, 0177412, /* MOV #RKDA, R1 ; csr */ - 0010311, /* MOV R3, (R1) ; load da */ - 0005041, /* CLR -(R1) ; clear ba */ - 0012741, 0177000, /* MOV #-256.*2, -(R1) ; load wc */ - 0012741, 0000005, /* MOV #READ+GO, -(R1) ; read & go */ - 0005002, /* CLR R2 */ - 0005003, /* CLR R3 */ - 0012704, BOOT_START+020, /* MOV #START+20, R4 */ - 0005005, /* CLR R5 */ - 0105711, /* TSTB (R1) */ - 0100376, /* BPL .-2 */ - 0105011, /* CLRB (R1) */ - 0005007 /* CLR PC */ -}; - -t_stat rk_boot (int32 unitno, DEVICE *dptr) -{ -int32 i; -extern int32 saved_PC; - -for (i = 0; i < BOOT_LEN; i++) M[(BOOT_START >> 1) + i] = boot_rom[i]; -M[BOOT_UNIT >> 1] = unitno & RK_M_NUMDR; -M[BOOT_CSR >> 1] = (rk_dib.ba & DMASK) + 012; -saved_PC = BOOT_ENTRY; -return SCPE_OK; -} diff --git a/PDP11/pdp11_rl.c b/PDP11/pdp11_rl.c deleted file mode 100644 index 67932ae4..00000000 --- a/PDP11/pdp11_rl.c +++ /dev/null @@ -1,653 +0,0 @@ -/* pdp11_rl.c: RL11 (RLV12) cartridge disk simulator - - 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. - - rl RL11(RLV12)/RL01/RL02 cartridge disk - - 19-May-03 RMS Revised for new conditional compilation scheme - 25-Apr-03 RMS Revised for extended file support - 29-Sep-02 RMS Added variable address support to bootstrap - Added vector change/display support - Revised mapping nomenclature - New data structures - 26-Jan-02 RMS Revised bootstrap to conform to M9312 - 06-Jan-02 RMS Revised enable/disable support - 30-Nov-01 RMS Added read only, extended SET/SHOW support - 26-Nov-01 RMS Fixed per-drive error handling - 24-Nov-01 RMS Converted FLG, CAPAC to arrays - 19-Nov-01 RMS Fixed signed/unsigned mismatch in write check - 09-Nov-01 RMS Added bus map, VAX support - 07-Sep-01 RMS Revised device disable and interrupt mechanisms - 20-Aug-01 RMS Added bad block option in attach - 17-Jul-01 RMS Fixed warning from VC++ 6.0 - 26-Apr-01 RMS Added device enable/disable support - 25-Mar-01 RMS Fixed block fill calculation - 15-Feb-01 RMS Corrected bootstrap string - 12-Nov-97 RMS Added bad block table command - 25-Nov-96 RMS Default units to autosize - 29-Jun-96 RMS Added unit disable support - - The RL11 is a four drive cartridge disk subsystem. An RL01 drive - consists of 256 cylinders, each with 2 surfaces containing 40 sectors - of 256 bytes. An RL02 drive has 512 cylinders. The RLV12 is a - controller variant which supports 22b direct addressing. - - The most complicated part of the RL11 controller is the way it does - seeks. Seeking is relative to the current disk address; this requires - keeping accurate track of the current cylinder. The RL11 will not - switch heads or cross cylinders during transfers. - - The RL11 functions in three environments: - - - PDP-11 Q22 systems - the I/O map is one for one, so it's safe to - go through the I/O map - - PDP-11 Unibus 22b systems - the RL11 behaves as an 18b Unibus - peripheral and must go through the I/O map - - VAX Q22 systems - the RL11 must go through the I/O map -*/ - -#if defined (VM_PDP10) /* PDP10 version */ -#error "RL11 is not supported on the PDP-10!" - -#elif defined (VM_VAX) /* VAX version */ -#include "vax_defs.h" -extern int32 int_req[IPL_HLVL]; -extern int32 int_vec[IPL_HLVL][32]; - -#else /* PDP-11 version */ -#include "pdp11_defs.h" -extern int32 int_req[IPL_HLVL]; -extern int32 int_vec[IPL_HLVL][32]; -extern int32 cpu_18b, cpu_ubm; -#endif - -/* Constants */ - -#define RL_NUMWD 128 /* words/sector */ -#define RL_NUMSC 40 /* sectors/surface */ -#define RL_NUMSF 2 /* surfaces/cylinder */ -#define RL_NUMCY 256 /* cylinders/drive */ -#define RL_NUMDR 4 /* drives/controller */ -#define RL_MAXFR (1 << 16) /* max transfer */ -#define RL01_SIZE (RL_NUMCY * RL_NUMSF * RL_NUMSC * RL_NUMWD) /* words/drive */ -#define RL02_SIZE (RL01_SIZE * 2) /* words/drive */ - -/* Flags in the unit flags word */ - -#define UNIT_V_WLK (UNIT_V_UF + 0) /* hwre write lock */ -#define UNIT_V_RL02 (UNIT_V_UF + 1) /* RL01 vs RL02 */ -#define UNIT_V_AUTO (UNIT_V_UF + 2) /* autosize enable */ -#define UNIT_V_DUMMY (UNIT_V_UF + 3) /* dummy flag */ -#define UNIT_DUMMY (1 << UNIT_V_DUMMY) -#define UNIT_WLK (1u << UNIT_V_WLK) -#define UNIT_RL02 (1u << UNIT_V_RL02) -#define UNIT_AUTO (1u << UNIT_V_AUTO) -#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protected */ - -/* Parameters in the unit descriptor */ - -#define TRK u3 /* current track */ -#define STAT u4 /* status */ - -/* RLDS, NI = not implemented, * = kept in STAT, ^ = kept in TRK */ - -#define RLDS_LOAD 0 /* no cartridge */ -#define RLDS_LOCK 5 /* lock on */ -#define RLDS_BHO 0000010 /* brushes home NI */ -#define RLDS_HDO 0000020 /* heads out NI */ -#define RLDS_CVO 0000040 /* cover open NI */ -#define RLDS_HD 0000100 /* head select ^ */ -#define RLDS_RL02 0000200 /* RL02 */ -#define RLDS_DSE 0000400 /* drv sel err NI */ -#define RLDS_VCK 0001000 /* vol check * */ -#define RLDS_WGE 0002000 /* wr gate err * */ -#define RLDS_SPE 0004000 /* spin err * */ -#define RLDS_STO 0010000 /* seek time out NI */ -#define RLDS_WLK 0020000 /* wr locked */ -#define RLDS_HCE 0040000 /* hd curr err NI */ -#define RLDS_WDE 0100000 /* wr data err NI */ -#define RLDS_ATT (RLDS_HDO+RLDS_BHO+RLDS_LOCK) /* att status */ -#define RLDS_UNATT (RLDS_CVO+RLDS_LOAD) /* unatt status */ -#define RLDS_ERR (RLDS_WDE+RLDS_HCE+RLDS_STO+RLDS_SPE+RLDS_WGE+ \ - RLDS_VCK+RLDS_DSE) /* errors bits */ - -/* RLCS */ - -#define RLCS_DRDY 0000001 /* drive ready */ -#define RLCS_M_FUNC 0000007 /* function */ -#define RLCS_NOP 0 -#define RLCS_WCHK 1 -#define RLCS_GSTA 2 -#define RLCS_SEEK 3 -#define RLCS_RHDR 4 -#define RLCS_WRITE 5 -#define RLCS_READ 6 -#define RLCS_RNOHDR 7 -#define RLCS_V_FUNC 1 -#define RLCS_M_MEX 03 /* memory extension */ -#define RLCS_V_MEX 4 -#define RLCS_MEX (RLCS_M_MEX << RLCS_V_MEX) -#define RLCS_M_DRIVE 03 -#define RLCS_V_DRIVE 8 -#define RLCS_INCMP 0002000 /* incomplete */ -#define RLCS_CRC 0004000 /* CRC error */ -#define RLCS_HDE 0010000 /* header error */ -#define RLCS_NXM 0020000 /* non-exist memory */ -#define RLCS_DRE 0040000 /* drive error */ -#define RLCS_ERR 0100000 /* error summary */ -#define RLCS_ALLERR (RLCS_ERR+RLCS_DRE+RLCS_NXM+RLCS_HDE+RLCS_CRC+RLCS_INCMP) -#define RLCS_RW 0001776 /* read/write */ -#define GET_FUNC(x) (((x) >> RLCS_V_FUNC) & RLCS_M_FUNC) -#define GET_DRIVE(x) (((x) >> RLCS_V_DRIVE) & RLCS_M_DRIVE) - -/* RLDA */ - -#define RLDA_SK_DIR 0000004 /* direction */ -#define RLDA_GS_CLR 0000010 /* clear errors */ -#define RLDA_SK_HD 0000020 /* head select */ - -#define RLDA_V_SECT 0 /* sector */ -#define RLDA_M_SECT 077 -#define RLDA_V_TRACK 6 /* track */ -#define RLDA_M_TRACK 01777 -#define RLDA_HD0 (0 << RLDA_V_TRACK) -#define RLDA_HD1 (1u << RLDA_V_TRACK) -#define RLDA_V_CYL 7 /* cylinder */ -#define RLDA_M_CYL 0777 -#define RLDA_TRACK (RLDA_M_TRACK << RLDA_V_TRACK) -#define RLDA_CYL (RLDA_M_CYL << RLDA_V_CYL) -#define GET_SECT(x) (((x) >> RLDA_V_SECT) & RLDA_M_SECT) -#define GET_CYL(x) (((x) >> RLDA_V_CYL) & RLDA_M_CYL) -#define GET_TRACK(x) (((x) >> RLDA_V_TRACK) & RLDA_M_TRACK) -#define GET_DA(x) ((GET_TRACK (x) * RL_NUMSC) + GET_SECT (x)) - -/* RLBA */ - -#define RLBA_IMP 0177776 /* implemented */ - -/* RLBAE */ - -#define RLBAE_IMP 0000077 /* implemented */ - -extern uint16 *M; -extern int32 int_req[IPL_HLVL]; -extern int32 int_vec[IPL_HLVL][32]; - -uint16 *rlxb = NULL; /* xfer buffer */ -int32 rlcs = 0; /* control/status */ -int32 rlba = 0; /* memory address */ -int32 rlbae = 0; /* mem addr extension */ -int32 rlda = 0; /* disk addr */ -int32 rlmp = 0, rlmp1 = 0, rlmp2 = 0; /* mp register queue */ -int32 rl_swait = 10; /* seek wait */ -int32 rl_rwait = 10; /* rotate wait */ -int32 rl_stopioe = 1; /* stop on error */ - -DEVICE rl_dev; -t_stat rl_rd (int32 *data, int32 PA, int32 access); -t_stat rl_wr (int32 data, int32 PA, int32 access); -t_stat rl_svc (UNIT *uptr); -t_stat rl_reset (DEVICE *dptr); -void rl_set_done (int32 error); -t_stat rl_boot (int32 unitno, DEVICE *dptr); -t_stat rl_attach (UNIT *uptr, char *cptr); -t_stat rl_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat rl_set_bad (UNIT *uptr, int32 val, char *cptr, void *desc); -extern t_stat pdp11_bad_block (UNIT *uptr, int32 sec, int32 wds); - -/* RL11 data structures - - rl_dev RL device descriptor - rl_unit RL unit list - rl_reg RL register list - rl_mod RL modifier list -*/ - -DIB rl_dib = { IOBA_RL, IOLN_RL, &rl_rd, &rl_wr, - 1, IVCL (RL), VEC_RL, { NULL } }; - -UNIT rl_unit[] = { - { UDATA (&rl_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+UNIT_AUTO, RL01_SIZE) }, - { UDATA (&rl_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+UNIT_AUTO, RL01_SIZE) }, - { UDATA (&rl_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+UNIT_AUTO, RL01_SIZE) }, - { UDATA (&rl_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+UNIT_AUTO, RL01_SIZE) } }; - -REG rl_reg[] = { - { GRDATA (RLCS, rlcs, DEV_RDX, 16, 0) }, - { GRDATA (RLDA, rlda, DEV_RDX, 16, 0) }, - { GRDATA (RLBA, rlba, DEV_RDX, 16, 0) }, - { GRDATA (RLBAE, rlbae, DEV_RDX, 6, 0) }, - { GRDATA (RLMP, rlmp, DEV_RDX, 16, 0) }, - { GRDATA (RLMP1, rlmp1, DEV_RDX, 16, 0) }, - { GRDATA (RLMP2, rlmp2, DEV_RDX, 16, 0) }, - { FLDATA (INT, IREQ (RL), INT_V_RL) }, - { FLDATA (ERR, rlcs, CSR_V_ERR) }, - { FLDATA (DONE, rlcs, CSR_V_DONE) }, - { FLDATA (IE, rlcs, CSR_V_IE) }, - { DRDATA (STIME, rl_swait, 24), PV_LEFT }, - { DRDATA (RTIME, rl_rwait, 24), PV_LEFT }, - { URDATA (CAPAC, rl_unit[0].capac, 10, T_ADDR_W, 0, - RL_NUMDR, PV_LEFT + REG_HRO) }, - { FLDATA (STOP_IOE, rl_stopioe, 0) }, - { GRDATA (DEVADDR, rl_dib.ba, DEV_RDX, 32, 0), REG_HRO }, - { GRDATA (DEVVEC, rl_dib.vec, DEV_RDX, 16, 0), REG_HRO }, - { NULL } }; - -MTAB rl_mod[] = { - { UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL }, - { UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL }, - { UNIT_DUMMY, 0, NULL, "BADBLOCK", &rl_set_bad }, - { (UNIT_RL02+UNIT_ATT), UNIT_ATT, "RL01", NULL, NULL }, - { (UNIT_RL02+UNIT_ATT), (UNIT_RL02+UNIT_ATT), "RL02", NULL, NULL }, - { (UNIT_AUTO+UNIT_RL02+UNIT_ATT), 0, "RL01", NULL, NULL }, - { (UNIT_AUTO+UNIT_RL02+UNIT_ATT), UNIT_RL02, "RL02", NULL, NULL }, - { (UNIT_AUTO+UNIT_ATT), UNIT_AUTO, "autosize", NULL, NULL }, - { UNIT_AUTO, UNIT_AUTO, NULL, "AUTOSIZE", NULL }, - { (UNIT_AUTO+UNIT_RL02), 0, NULL, "RL01", &rl_set_size }, - { (UNIT_AUTO+UNIT_RL02), UNIT_RL02, NULL, "RL02", &rl_set_size }, - { MTAB_XTD|MTAB_VDV, 010, "ADDRESS", "ADDRESS", - &set_addr, &show_addr, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "VECTOR", "VECTOR", - &set_vec, &show_vec, NULL }, - { 0 } }; - -DEVICE rl_dev = { - "RL", rl_unit, rl_reg, rl_mod, - RL_NUMDR, DEV_RDX, 24, 1, DEV_RDX, 16, - NULL, NULL, &rl_reset, - &rl_boot, &rl_attach, NULL, - &rl_dib, DEV_DISABLE | DEV_UBUS | DEV_QBUS }; - -/* I/O dispatch routine, I/O addresses 17774400 - 17774407 - - 17774400 RLCS read/write - 17774402 RLBA read/write - 17774404 RLDA read/write - 17774406 RLMP read/write - 17774410 RLBAE read/write -*/ - -t_stat rl_rd (int32 *data, int32 PA, int32 access) -{ -UNIT *uptr; - -switch ((PA >> 1) & 07) { /* decode PA<2:1> */ -case 0: /* RLCS */ - rlcs = (rlcs & ~RLCS_MEX) | ((rlbae & RLCS_M_MEX) << RLCS_V_MEX); - if (rlcs & RLCS_ALLERR) rlcs = rlcs | RLCS_ERR; - uptr = rl_dev.units + GET_DRIVE (rlcs); - if (sim_is_active (uptr)) rlcs = rlcs & ~RLCS_DRDY; - else rlcs = rlcs | RLCS_DRDY; /* see if ready */ - *data = rlcs; - break; -case 1: /* RLBA */ - *data = rlba & RLBA_IMP; - break; -case 2: /* RLDA */ - *data = rlda; - break; -case 3: /* RLMP */ - *data = rlmp; - rlmp = rlmp1; /* ripple data */ - rlmp1 = rlmp2; - break; -case 4: /* RLBAE */ - if (UNIBUS) return SCPE_NXM; /* not in RL11 */ - *data = rlbae & RLBAE_IMP; - break; } /* end switch */ -return SCPE_OK; -} - -t_stat rl_wr (int32 data, int32 PA, int32 access) -{ -int32 curr, offs, newc, maxc; -UNIT *uptr; - -switch ((PA >> 1) & 07) { /* decode PA<2:1> */ -case 0: /* RLCS */ - rlcs = (rlcs & ~RLCS_MEX) | ((rlbae & RLCS_M_MEX) << RLCS_V_MEX); - if (rlcs & RLCS_ALLERR) rlcs = rlcs | RLCS_ERR; - uptr = rl_dev.units + GET_DRIVE (data); /* get new drive */ - if (sim_is_active (uptr)) rlcs = rlcs & ~RLCS_DRDY; - else rlcs = rlcs | RLCS_DRDY; /* see if ready */ - - if (access == WRITEB) data = (PA & 1)? - (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; } - - 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; - 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; - default: /* data transfer */ - 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 = data & RLBA_IMP; - break; -case 2: /* RLDA */ - if (access == WRITEB) data = (PA & 1)? - (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 = rlmp1 = rlmp2 = data; - break; -case 4: /* RLBAE */ - if (UNIBUS) return SCPE_NXM; /* not in RL11 */ - if (PA & 1) return SCPE_OK; - rlbae = data & RLBAE_IMP; - rlcs = (rlcs & ~RLCS_MEX) | ((rlbae & RLCS_M_MEX) << RLCS_V_MEX); - break; } /* end switch */ -return SCPE_OK; -} - -/* Service unit timeout - - If seek in progress, complete seek command - Else complete data transfer command - - The unit control block contains the function and cylinder for - the current command. -*/ - -t_stat rl_svc (UNIT *uptr) -{ -int32 err, wc, maxwc, t; -int32 i, func, da, awc; -uint32 ma; -uint16 comp; - -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); - if (uptr->flags & UNIT_RL02) rlmp = rlmp | RLDS_RL02; - if (uptr->flags & UNIT_WPRT) rlmp = rlmp | RLDS_WLK; - rlmp2 = rlmp1 = rlmp; - rl_set_done (0); /* done */ - return SCPE_OK; } - -if ((uptr->flags & UNIT_ATT) == 0) { /* attached? */ - rlcs = rlcs & ~RLCS_DRDY; /* clear drive ready */ - uptr->STAT = uptr->STAT | RLDS_SPE; /* spin error */ - rl_set_done (RLCS_ERR | RLCS_INCMP); /* flag error */ - return IORETURN (rl_stopioe, SCPE_UNATT); } - -if ((func == RLCS_WRITE) && (uptr->flags & UNIT_WPRT)) { - uptr->STAT = uptr->STAT | RLDS_WGE; /* write and locked */ - rl_set_done (RLCS_ERR | RLCS_DRE); - return SCPE_OK; } - -if (func == RLCS_SEEK) { /* seek? */ - rl_set_done (0); /* done */ - return SCPE_OK; } - -if (func == RLCS_RHDR) { /* read header? */ - rlmp = (uptr->TRK & RLDA_TRACK) | GET_SECT (rlda); - rlmp1 = rlmp2 = 0; - rl_set_done (0); /* done */ - return SCPE_OK; } - -if (((func != RLCS_RNOHDR) && ((uptr->TRK & RLDA_CYL) != (rlda & RLDA_CYL))) - || (GET_SECT (rlda) >= RL_NUMSC)) { /* bad cyl or sector? */ - rl_set_done (RLCS_ERR | RLCS_HDE | RLCS_INCMP); /* wrong cylinder? */ - return SCPE_OK; } - -ma = (rlbae << 16) | rlba; /* get mem addr */ -da = GET_DA (rlda) * RL_NUMWD; /* get disk addr */ -wc = 0200000 - rlmp; /* get true wc */ - -maxwc = (RL_NUMSC - GET_SECT (rlda)) * RL_NUMWD; /* max transfer */ -if (wc > maxwc) wc = maxwc; /* track overrun? */ -err = fseek (uptr->fileref, da * sizeof (int16), SEEK_SET); - -if ((func >= RLCS_READ) && (err == 0)) { /* read (no hdr)? */ - i = fxread (rlxb, sizeof (int16), wc, uptr->fileref); - 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 */ - } /* 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 */ - 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); } - } /* end write */ - -if ((func == RLCS_WCHK) && (err == 0)) { /* write check? */ - i = fxread (rlxb, sizeof (int16), wc, uptr->fileref); - err = ferror (uptr->fileref); - 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 */ - } /* end wcheck */ - -rlmp = (rlmp + wc) & 0177777; /* final word count */ -if (rlmp != 0) rlcs = rlcs | RLCS_ERR | RLCS_INCMP; /* completed? */ -ma = ma + (wc << 1); /* final byte addr */ -rlbae = (ma >> 16) & RLBAE_IMP; /* upper 6b */ -rlba = ma & RLBA_IMP; /* lower 16b */ -rlcs = (rlcs & ~RLCS_MEX) | ((rlbae & RLCS_M_MEX) << RLCS_V_MEX); -rlda = rlda + ((wc + (RL_NUMWD - 1)) / RL_NUMWD); -rl_set_done (0); - -if (err != 0) { /* error? */ - perror ("RL I/O error"); - clearerr (uptr->fileref); - return SCPE_IOERR; } -return SCPE_OK; -} - -/* Set done and possibly errors */ - -void rl_set_done (int32 status) -{ - rlcs = rlcs | status | CSR_DONE; /* set done */ - if (rlcs & CSR_IE) SET_INT (RL); - else CLR_INT (RL); - return; -} - -/* Device reset - - Note that the RL11 does NOT recalibrate its drives on RESET -*/ - -t_stat rl_reset (DEVICE *dptr) -{ -int32 i; -UNIT *uptr; - -rlcs = CSR_DONE; -rlda = rlba = rlbae = rlmp = rlmp1 = rlmp2 = 0; -CLR_INT (RL); -for (i = 0; i < RL_NUMDR; i++) { - uptr = rl_dev.units + i; - sim_cancel (uptr); - uptr->STAT = 0; } -if (rlxb == NULL) rlxb = calloc (RL_MAXFR, sizeof (unsigned int16)); -if (rlxb == NULL) return SCPE_MEM; -return SCPE_OK; -} - -/* Attach routine */ - -t_stat rl_attach (UNIT *uptr, char *cptr) -{ -uint32 p; -t_stat r; - -uptr->capac = (uptr->flags & UNIT_RL02)? RL02_SIZE: RL01_SIZE; -r = attach_unit (uptr, cptr); /* attach unit */ -if (r != SCPE_OK) return r; /* error? */ -uptr->TRK = 0; /* cylinder 0 */ -uptr->STAT = RLDS_VCK; /* new volume */ -if (fseek (uptr->fileref, 0, SEEK_END)) return SCPE_OK; /* seek to end */ -if ((p = ftell (uptr->fileref)) == 0) { /* new disk image? */ - if (uptr->flags & UNIT_RO) return SCPE_OK; /* if ro, done */ - return pdp11_bad_block (uptr, RL_NUMSC, RL_NUMWD); } -if ((uptr->flags & UNIT_AUTO) == 0) return SCPE_OK; /* autosize? */ -if (p > (RL01_SIZE * sizeof (int16))) { - uptr->flags = uptr->flags | UNIT_RL02; - uptr->capac = RL02_SIZE; } -else { uptr->flags = uptr->flags & ~UNIT_RL02; - uptr->capac = RL01_SIZE; } -return SCPE_OK; -} - -/* Set size routine */ - -t_stat rl_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -if (uptr->flags & UNIT_ATT) return SCPE_ALATT; -uptr->capac = (val & UNIT_RL02)? RL02_SIZE: RL01_SIZE; -return SCPE_OK; -} - -/* Set bad block routine */ - -t_stat rl_set_bad (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -return pdp11_bad_block (uptr, RL_NUMSC, RL_NUMWD); -} - -/* Device bootstrap */ - -#if defined (VM_PDP11) - -#define BOOT_START 02000 /* start */ -#define BOOT_ENTRY (BOOT_START + 002) /* entry */ -#define BOOT_UNIT (BOOT_START + 010) /* unit number */ -#define BOOT_CSR (BOOT_START + 020) /* CSR */ -#define BOOT_LEN (sizeof (boot_rom) / sizeof (int16)) - -static const uint16 boot_rom[] = { - 0042114, /* "LD" */ - 0012706, BOOT_START, /* MOV #boot_start, SP */ - 0012700, 0000000, /* MOV #unit, R0 */ - 0010003, /* MOV R0, R3 */ - 0000303, /* SWAB R3 */ - 0012701, 0174400, /* MOV #RLCS, R1 ; csr */ - 0012761, 0000013, 0000004, /* MOV #13, 4(R1) ; clr err */ - 0052703, 0000004, /* BIS #4, R3 ; unit+gstat */ - 0010311, /* MOV R3, (R1) ; issue cmd */ - 0105711, /* TSTB (R1) ; wait */ - 0100376, /* BPL .-2 */ - 0105003, /* CLRB R3 */ - 0052703, 0000010, /* BIS #10, R3 ; unit+rdhdr */ - 0010311, /* MOV R3, (R1) ; issue cmd */ - 0105711, /* TSTB (R1) ; wait */ - 0100376, /* BPL .-2 */ - 0016102, 0000006, /* MOV 6(R1), R2 ; get hdr */ - 0042702, 0000077, /* BIC #77, R2 ; clr sector */ - 0005202, /* INC R2 ; magic bit */ - 0010261, 0000004, /* MOV R2, 4(R1) ; seek to 0 */ - 0105003, /* CLRB R3 */ - 0052703, 0000006, /* BIS #6, R3 ; unit+seek */ - 0010311, /* MOV R3, (R1) ; issue cmd */ - 0105711, /* TSTB (R1) ; wait */ - 0100376, /* BPL .-2 */ - 0005061, 0000002, /* CLR 2(R1) ; clr ba */ - 0005061, 0000004, /* CLR 4(R1) ; clr da */ - 0012761, 0177000, 0000006, /* MOV #-512., 6(R1) ; set wc */ - 0105003, /* CLRB R3 */ - 0052703, 0000014, /* BIS #14, R3 ; unit+read */ - 0010311, /* MOV R3, (R1) ; issue cmd */ - 0105711, /* TSTB (R1) ; wait */ - 0100376, /* BPL .-2 */ - 0042711, 0000377, /* BIC #377, (R1) */ - 0005002, /* CLR R2 */ - 0005003, /* CLR R3 */ - 0012704, BOOT_START+020, /* MOV #START+20, R4 */ - 0005005, /* CLR R5 */ - 0005007 /* CLR PC */ -}; - -t_stat rl_boot (int32 unitno, DEVICE *dptr) -{ -int32 i; -extern int32 saved_PC; - -for (i = 0; i < BOOT_LEN; i++) M[(BOOT_START >> 1) + i] = boot_rom[i]; -M[BOOT_UNIT >> 1] = unitno & RLCS_M_DRIVE; -M[BOOT_CSR >> 1] = rl_dib.ba & DMASK; -saved_PC = BOOT_ENTRY; -return SCPE_OK; -} - -#else - -t_stat rl_boot (int32 unitno, DEVICE *dptr) -{ -return SCPE_NOFNC; -} -#endif diff --git a/PDP11/pdp11_rp.c b/PDP11/pdp11_rp.c deleted file mode 100644 index d8246211..00000000 --- a/PDP11/pdp11_rp.c +++ /dev/null @@ -1,1182 +0,0 @@ -/* pdp11_rp.c - RP04/05/06/07 RM02/03/05/80 "Massbus style" disk controller - - 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. - - rp RH/RP/RM moving head disks - - 19-May-03 RMS Revised for new conditional compilation scheme - 25-Apr-03 RMS Revised for extended file support - 29-Sep-02 RMS Added variable address support to bootstrap - Added vector change/display support - Revised mapping mnemonics - New data structures - 24-Apr-02 RMS Fixed SHOW RP ADDRESS - 26-Jan-02 RMS Revised bootstrap to conform to M9312 - 06-Jan-02 RMS Revised enable/disable support - 30-Nov-01 RMS Added read only unit, extended SET/SHOW support - 24-Nov-01 RMS Changed RPDS, RPER, FLG, CAPAC, RPFN to arrays - 09-Nov-01 RMS Added bus map, VAX support - 23-Oct-01 RMS Fixed bug in error interrupts - 15-Oct-01 RMS Added debug logging - 05-Oct-01 RMS Rewrote interrupt handling from schematics - 02-Oct-01 RMS Revised CS1 write code - 30-Sep-01 RMS Moved CS1<5:0> into drives - 28-Sep-01 RMS Fixed interrupt handling for SC/ATA - 07-Sep-01 RMS Revised device disable and interrupt mechanisms - 20-Aug-01 RMS Added bad block option in attach - 13-Jul-01 RMS Changed fread call to fxread (found by Peter Schorn) - 14-May-01 RMS Added check for unattached drive - 25-Apr-01 RMS Added device enable/disable support - 21-Apr-01 RMS Implemented UAI function - 02-Apr-01 RMS Fixed CS1.TRE error clear function, CS2.MXF/PE writes - 25-Mar-01 RMS Corrected block fill calculation, IE write processing - 15-Feb-01 RMS Corrected bootstrap string - 14-Apr-99 RMS Changed t_addr to unsigned - 05-Oct-98 RMS Fixed bug, failing to interrupt on go error - 04-Oct-98 RMS Changed names to allow coexistence with RH/TU77 - 12-Nov-97 RMS Added bad block table command - 10-Aug-97 RMS Fixed bugs in interrupt handling - - The "Massbus style" disks consisted of several different large - capacity drives interfaced through a reasonably common (but not - 100% compatible) family of interfaces into a 22b direct addressing - port. On the PDP-11/70, this was the Massbus; but on 22b Qbus - systems, this was through many different third party controllers - which emulated the Massbus interface. - - WARNING: The interupt logic of the RH11/RH70 is unusual and must be - simulated with great precision. The RH11 has an internal interrupt - request flop, CSTB INTR, which is controlled as follows: - - Writing IE and DONE simultaneously sets CSTB INTR - - Controller clear, INIT, and interrupt acknowledge clear CSTB INTR - (and also clear IE) - - A transition of DONE from 0 to 1 sets CSTB from INTR - The output of INTR is OR'd with the AND of RPCS1 to - create the interrupt request signal. Thus, - - The DONE interrupt is edge sensitive, but the SC interrupt is - level sensitive. - - The DONE interrupt, once set, is not disabled if IE is cleared, - but the SC interrupt is. - - The RP/RM functions in four environments: - - - PDP-11 Q22 systems - bus map is bypassed - - PDP-11 Unibus systems with native 22b controllers - see above - - PDP-11 Unibus without native 22b controllers - the RP/RM behaves - as an 18b Unibus peripheral and must go through the I/O map - - VAX Q22 systems - the RP/RM must go through the I/O map - - To distinguish the two Unibus cases, the PDP-11 version of the RP/RM - provides an internal mode flag for RH11 vs RH70 -*/ - -#if defined (VM_PDP10) /* PDP10 version */ -#error "PDP-10 uses pdp10_rp.c!" - -#elif defined (VM_VAX) /* VAX version */ -#include "vax_defs.h" -#define RP_WID 32 -#define DMASK 0xFFFF -#define RH11 0 /* always 22b */ -extern int32 int_req[IPL_HLVL]; -extern int32 int_vec[IPL_HLVL][32]; - -#else /* PDP-11 version */ -#include "pdp11_defs.h" -#define PT_DIS 0 -#define RP_WID 16 -#define RH (cpu_18b || (cpu_ubm && cpu_rh11)) -#define RH11 (RH) -extern uint16 *M; -extern int32 cpu_18b, cpu_ubm, cpu_rh11; -extern int32 int_req[IPL_HLVL]; -extern int32 int_vec[IPL_HLVL][32]; -#endif - -#include - -#define RP_NUMDR 8 /* #drives */ -#define RP_NUMWD 256 /* words/sector */ -#define RP_MAXFR (1 << 16) /* max transfer */ -#define GET_SECTOR(x,d) ((int) fmod (sim_gtime() / ((double) (x)), \ - ((double) drv_tab[d].sect))) - -/* Flags in the unit flags word */ - -#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */ -#define UNIT_V_DTYPE (UNIT_V_UF + 1) /* disk type */ -#define UNIT_M_DTYPE 7 -#define UNIT_V_AUTO (UNIT_V_UF + 4) /* autosize */ -#define UNIT_V_DUMMY (UNIT_V_UF + 5) /* dummy flag */ -#define UNIT_WLK (1 << UNIT_V_WLK) -#define UNIT_DTYPE (UNIT_M_DTYPE << UNIT_V_DTYPE) -#define UNIT_AUTO (1 << UNIT_V_AUTO) -#define UNIT_DUMMY (1 << UNIT_V_DUMMY) -#define GET_DTYPE(x) (((x) >> UNIT_V_DTYPE) & UNIT_M_DTYPE) -#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write prot */ - -/* Parameters in the unit descriptor */ - -#define CYL u3 /* current cylinder */ -#define FUNC u4 /* function */ - -/* RPCS1 - 176700 - control/status 1 */ - -#define CS1_GO CSR_GO /* go */ -#define CS1_V_FNC 1 /* function pos */ -#define CS1_M_FNC 037 /* function mask */ -#define CS1_FNC (CS1_M_FNC << CS1_V_FNC) -#define FNC_NOP 000 /* no operation */ -#define FNC_UNLOAD 001 /* unload */ -#define FNC_SEEK 002 /* seek */ -#define FNC_RECAL 003 /* recalibrate */ -#define FNC_DCLR 004 /* drive clear */ -#define FNC_RELEASE 005 /* port release */ -#define FNC_OFFSET 006 /* offset */ -#define FNC_RETURN 007 /* return to center */ -#define FNC_PRESET 010 /* read-in preset */ -#define FNC_PACK 011 /* pack acknowledge */ -#define FNC_SEARCH 014 /* search */ -#define FNC_XFER 024 /* >=? data xfr */ -#define FNC_WCHK 024 /* write check */ -#define FNC_WRITE 030 /* write */ -#define FNC_WRITEH 031 /* write w/ headers */ -#define FNC_READ 034 /* read */ -#define FNC_READH 035 /* read w/ headers */ -#define CS1_IE CSR_IE /* int enable */ -#define CS1_DONE CSR_DONE /* ready */ -#define CS1_V_UAE 8 /* Unibus addr ext */ -#define CS1_M_UAE 03 -#define CS1_UAE (CS1_M_UAE << CS1_V_UAE) -#define CS1_DVA 0004000 /* drive avail NI */ -#define CS1_MCPE 0020000 /* Mbus par err NI */ -#define CS1_TRE 0040000 /* transfer err */ -#define CS1_SC 0100000 /* special cond */ -#define CS1_MBZ 0012000 -#define CS1_DRV (CS1_FNC | CS1_GO) -#define GET_FNC(x) (((x) >> CS1_V_FNC) & CS1_M_FNC) - -/* RPWC - 176702 - word count */ - -/* RPBA - 176704 - base address */ - -#define BA_MBZ 0000001 /* must be zero */ - -/* RPDA - 176706 - sector/track */ - -#define DA_V_SC 0 /* sector pos */ -#define DA_M_SC 077 /* sector mask */ -#define DA_V_SF 8 /* track pos */ -#define DA_M_SF 077 /* track mask */ -#define DA_MBZ 0140300 -#define GET_SC(x) (((x) >> DA_V_SC) & DA_M_SC) -#define GET_SF(x) (((x) >> DA_V_SF) & DA_M_SF) - -/* RPCS2 - 176710 - control/status 2 */ - -#define CS2_V_UNIT 0 /* unit pos */ -#define CS2_M_UNIT 07 /* unit mask */ -#define CS2_UNIT (CS2_M_UNIT << CS2_V_UNIT) -#define CS2_UAI 0000010 /* addr inhibit */ -#define CS2_PAT 0000020 /* parity test NI */ -#define CS2_CLR 0000040 /* controller clear */ -#define CS2_IR 0000100 /* input ready */ -#define CS2_OR 0000200 /* output ready */ -#define CS2_MDPE 0000400 /* Mbus par err NI */ -#define CS2_MXF 0001000 /* missed xfer NI */ -#define CS2_PGE 0002000 /* program err */ -#define CS2_NEM 0004000 /* nx mem err */ -#define CS2_NED 0010000 /* nx drive err */ -#define CS2_PE 0020000 /* parity err NI */ -#define CS2_WCE 0040000 /* write check err */ -#define CS2_DLT 0100000 /* data late NI */ -#define CS2_MBZ (CS2_CLR) -#define CS2_RW (CS2_UNIT | CS2_UAI | CS2_PAT | CS2_MXF | CS2_PE) -#define CS2_ERR (CS2_MDPE | CS2_MXF | CS2_PGE | CS2_NEM | \ - CS2_NED | CS2_PE | CS2_WCE | CS2_DLT ) -#define GET_UNIT(x) (((x) >> CS2_V_UNIT) & CS2_M_UNIT) - -/* RPDS - 176712 - drive status */ - -#define DS_OF 0000001 /* offset mode */ -#define DS_VV 0000100 /* volume valid */ -#define DS_RDY 0000200 /* drive ready */ -#define DS_DPR 0000400 /* drive present */ -#define DS_PGM 0001000 /* programable NI */ -#define DS_LST 0002000 /* last sector */ -#define DS_WRL 0004000 /* write locked */ -#define DS_MOL 0010000 /* medium online */ -#define DS_PIP 0020000 /* pos in progress */ -#define DS_ERR 0040000 /* error */ -#define DS_ATA 0100000 /* attention active */ -#define DS_MBZ 0000076 - -/* RPER1 - 176714 - error status 1 */ - -#define ER1_ILF 0000001 /* illegal func */ -#define ER1_ILR 0000002 /* illegal register */ -#define ER1_RMR 0000004 /* reg mod refused */ -#define ER1_PAR 0000010 /* parity err */ -#define ER1_FER 0000020 /* format err NI */ -#define ER1_WCF 0000040 /* write clk fail NI */ -#define ER1_ECH 0000100 /* ECC hard err NI */ -#define ER1_HCE 0000200 /* hdr comp err NI */ -#define ER1_HCR 0000400 /* hdr CRC err NI */ -#define ER1_AOE 0001000 /* addr ovflo err */ -#define ER1_IAE 0002000 /* invalid addr err */ -#define ER1_WLE 0004000 /* write lock err */ -#define ER1_DTE 0010000 /* drive time err NI */ -#define ER1_OPI 0020000 /* op incomplete */ -#define ER1_UNS 0040000 /* drive unsafe */ -#define ER1_DCK 0100000 /* data check NI */ - -/* RPAS - 176716 - attention summary */ - -#define AS_U0 0000001 /* unit 0 flag */ - -/* RPLA - 176720 - look ahead register */ - -#define LA_V_SC 6 /* sector pos */ - -/* RPDB - 176722 - data buffer */ -/* RPMR - 176724 - maintenace register */ -/* RPDT - 176726 - drive type */ -/* RPSN - 176730 - serial number */ - -/* RPOF - 176732 - offset register */ - -#define OF_HCI 0002000 /* hdr cmp inh NI */ -#define OF_ECI 0004000 /* ECC inhibit NI */ -#define OF_F22 0010000 /* format NI */ -#define OF_MBZ 0161400 - -/* RPDC - 176734 - desired cylinder */ - -#define DC_V_CY 0 /* cylinder pos */ -#define DC_M_CY 01777 /* cylinder mask */ -#define DC_MBZ 0176000 -#define GET_CY(x) (((x) >> DC_V_CY) & DC_M_CY) -#define GET_DA(c,fs,d) ((((GET_CY (c) * drv_tab[d].surf) + \ - GET_SF (fs)) * drv_tab[d].sect) + GET_SC (fs)) - -/* RPCC - 176736 - current cylinder */ -/* RPER2 - 176740 - error status 2 - drive unsafe conditions - unimplemented */ -/* RPER3 - 176742 - error status 3 - more unsafe conditions - unimplemented */ -/* RPEC1 - 176744 - ECC status 1 - unimplemented */ -/* RPEC2 - 176746 - ECC status 2 - unimplemented */ - -/* RPBAE - 176750 - bus address extension */ - -#define AE_M_MAE 0 /* addr ext pos */ -#define AE_V_MAE 077 /* addr ext mask */ -#define AE_MBZ 0177700 - -/* RPCS3 - 176752 - control/status 3 - unused except for duplicate IE */ - -#define CS3_MBZ 0177660 - -/* This controller supports many different disk drive types: - - type #sectors/ #surfaces/ #cylinders/ - surface cylinder drive - - RM02/3 32 5 823 =67MB - RP04/5 22 19 411 =88MB - RM80 31 14 559 =124MB - RP06 22 19 815 =176MB - RM05 32 19 823 =256MB - RP07 50 32 630 =516MB - - 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. -*/ - -#define RM03_DTYPE 0 -#define RM03_SECT 32 -#define RM03_SURF 5 -#define RM03_CYL 823 -#define RM03_DEV 020024 -#define RM03_SIZE (RM03_SECT * RM03_SURF * RM03_CYL * RP_NUMWD) - -#define RP04_DTYPE 1 -#define RP04_SECT 22 -#define RP04_SURF 19 -#define RP04_CYL 411 -#define RP04_DEV 020020 -#define RP04_SIZE (RP04_SECT * RP04_SURF * RP04_CYL * RP_NUMWD) - -#define RM80_DTYPE 2 -#define RM80_SECT 31 -#define RM80_SURF 14 -#define RM80_CYL 559 -#define RM80_DEV 020026 -#define RM80_SIZE (RM80_SECT * RM80_SURF * RM80_CYL * RP_NUMWD) - -#define RP06_DTYPE 3 -#define RP06_SECT 22 -#define RP06_SURF 19 -#define RP06_CYL 815 -#define RP06_DEV 020022 -#define RP06_SIZE (RP06_SECT * RP06_SURF * RP06_CYL * RP_NUMWD) - -#define RM05_DTYPE 4 -#define RM05_SECT 32 -#define RM05_SURF 19 -#define RM05_CYL 823 -#define RM05_DEV 020027 -#define RM05_SIZE (RM05_SECT * RM05_SURF * RM05_CYL * RP_NUMWD) - -#define RP07_DTYPE 5 -#define RP07_SECT 50 -#define RP07_SURF 32 -#define RP07_CYL 630 -#define RP07_DEV 020042 -#define RP07_SIZE (RP07_SECT * RP07_SURF * RP07_CYL * RP_NUMWD) - -struct drvtyp { - int32 sect; /* sectors */ - int32 surf; /* surfaces */ - int32 cyl; /* cylinders */ - int32 size; /* #blocks */ - int32 devtype; /* device type */ -}; - -static struct drvtyp drv_tab[] = { - { RM03_SECT, RM03_SURF, RM03_CYL, RM03_SIZE, RM03_DEV }, - { RP04_SECT, RP04_SURF, RP04_CYL, RP04_SIZE, RP04_DEV }, - { RM80_SECT, RM80_SURF, RM80_CYL, RM80_SIZE, RM80_DEV }, - { RP06_SECT, RP06_SURF, RP06_CYL, RP06_SIZE, RP06_DEV }, - { RM05_SECT, RM05_SURF, RM05_CYL, RM05_SIZE, RM05_DEV }, - { RP07_SECT, RP07_SURF, RP07_CYL, RP07_SIZE, RP07_DEV }, - { 0 } }; - -extern int32 int_req[IPL_HLVL]; -extern int32 int_vec[IPL_HLVL][32]; -extern int32 cpu_log; -extern FILE *sim_log; - -uint16 *rpxb = NULL; /* xfer buffer */ -int32 rpcs1 = 0; /* control/status 1 */ -int32 rpwc = 0; /* word count */ -int32 rpba = 0; /* bus address */ -int32 rpda = 0; /* track/sector */ -int32 rpcs2 = 0; /* control/status 2 */ -int32 rpds[RP_NUMDR] = { 0 }; /* drive status */ -int32 rper1[RP_NUMDR] = { 0 }; /* error status 1 */ -int32 rpdb = 0; /* data buffer */ -int32 rpmr = 0; /* maint register */ -int32 rpof = 0; /* offset */ -int32 rpdc = 0; /* cylinder */ -int32 rper2 = 0; /* error status 2 */ -int32 rper3 = 0; /* error status 3 */ -int32 rpec1 = 0; /* ECC correction 1 */ -int32 rpec2 = 0; /* ECC correction 2 */ -int32 rpbae = 0; /* bus address ext */ -int32 rpcs3 = 0; /* control/status 3 */ -int32 rpiff = 0; /* INTR flip/flop */ -int32 rp_stopioe = 1; /* stop on error */ -int32 rp_swait = 10; /* seek time */ -int32 rp_rwait = 10; /* rotate time */ -static int32 reg_in_drive[32] = { - 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - -DEVICE rp_dev; -t_stat rp_rd (int32 *data, int32 PA, int32 access); -t_stat rp_wr (int32 data, int32 PA, int32 access); -int32 rp_inta (void); -t_stat rp_svc (UNIT *uptr); -t_stat rp_reset (DEVICE *dptr); -t_stat rp_boot (int32 unitno, DEVICE *dptr); -t_stat rp_attach (UNIT *uptr, char *cptr); -t_stat rp_detach (UNIT *uptr); -void update_rpcs (int32 flags, int32 drv); -void rp_go (int32 drv, int32 fnc); -t_stat rp_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat rp_set_bad (UNIT *uptr, int32 val, char *cptr, void *desc); -extern t_stat pdp11_bad_block (UNIT *uptr, int32 sec, int32 wds); - -/* RP data structures - - rp_dev RP device descriptor - rp_unit RP unit list - rp_reg RP register list - rp_mod RP modifier list -*/ - -DIB rp_dib = { IOBA_RP, IOLN_RP, &rp_rd, &rp_wr, - 1, IVCL (RP), VEC_RP, { &rp_inta } }; - -UNIT rp_unit[] = { - { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+ - UNIT_ROABLE+(RM03_DTYPE << UNIT_V_DTYPE), RM03_SIZE) }, - { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+ - UNIT_ROABLE+(RM03_DTYPE << UNIT_V_DTYPE), RM03_SIZE) }, - { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+ - UNIT_ROABLE+(RM03_DTYPE << UNIT_V_DTYPE), RM03_SIZE) }, - { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+ - UNIT_ROABLE+(RM03_DTYPE << UNIT_V_DTYPE), RM03_SIZE) }, - { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+ - UNIT_ROABLE+(RM03_DTYPE << UNIT_V_DTYPE), RM03_SIZE) }, - { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+ - UNIT_ROABLE+(RM03_DTYPE << UNIT_V_DTYPE), RM03_SIZE) }, - { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+ - UNIT_ROABLE+(RM03_DTYPE << UNIT_V_DTYPE), RM03_SIZE) }, - { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+ - UNIT_ROABLE+(RM03_DTYPE << UNIT_V_DTYPE), RM03_SIZE) } }; - -REG rp_reg[] = { - { GRDATA (RPCS1, rpcs1, DEV_RDX, 16, 0) }, - { GRDATA (RPWC, rpwc, DEV_RDX, 16, 0) }, - { GRDATA (RPBA, rpba, DEV_RDX, 16, 0) }, - { GRDATA (RPDA, rpda, DEV_RDX, 16, 0) }, - { GRDATA (RPCS2, rpcs2, DEV_RDX, 16, 0) }, - { BRDATA (RPDS, rpds, DEV_RDX, 16, RP_NUMDR) }, - { BRDATA (RPER1, rper1, DEV_RDX, 16, RP_NUMDR) }, - { GRDATA (RPOF, rpof, DEV_RDX, 16, 0) }, - { GRDATA (RPDC, rpdc, DEV_RDX, 16, 0) }, - { GRDATA (RPER2, rper2, DEV_RDX, 16, 0) }, - { GRDATA (RPER3, rper3, DEV_RDX, 16, 0) }, - { GRDATA (RPEC1, rpec1, DEV_RDX, 16, 0) }, - { GRDATA (RPEC2, rpec2, DEV_RDX, 16, 0) }, - { GRDATA (RPMR, rpmr, DEV_RDX, 16, 0) }, - { GRDATA (RPDB, rpdb, DEV_RDX, 16, 0) }, - { GRDATA (RPBAE, rpbae, DEV_RDX, 6, 0) }, - { GRDATA (RPCS3, rpcs3, DEV_RDX, 16, 0) }, - { FLDATA (IFF, rpiff, 0) }, - { FLDATA (INT, IREQ (RP), INT_V_RP) }, - { FLDATA (SC, rpcs1, CSR_V_ERR) }, - { FLDATA (DONE, rpcs1, CSR_V_DONE) }, - { FLDATA (IE, rpcs1, CSR_V_IE) }, - { DRDATA (STIME, rp_swait, 24), REG_NZ + PV_LEFT }, - { DRDATA (RTIME, rp_rwait, 24), REG_NZ + PV_LEFT }, - { URDATA (FNC, rp_unit[0].FUNC, DEV_RDX, 5, 0, - RP_NUMDR, REG_HRO) }, - { URDATA (CAPAC, rp_unit[0].capac, 10, T_ADDR_W, 0, - RP_NUMDR, PV_LEFT | REG_HRO) }, - { FLDATA (STOP_IOE, rp_stopioe, 0) }, - { GRDATA (DEVADDR, rp_dib.ba, DEV_RDX, 32, 0), REG_HRO }, - { GRDATA (DEVVEC, rp_dib.vec, DEV_RDX, 16, 0), REG_HRO }, - { NULL } }; - -MTAB rp_mod[] = { - { UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL }, - { UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL }, - { UNIT_DUMMY, 0, NULL, "BADBLOCK", &rp_set_bad }, - { (UNIT_DTYPE+UNIT_ATT), (RM03_DTYPE << UNIT_V_DTYPE) + UNIT_ATT, - "RM03", NULL, NULL }, - { (UNIT_DTYPE+UNIT_ATT), (RP04_DTYPE << UNIT_V_DTYPE) + UNIT_ATT, - "RP04", NULL, NULL }, - { (UNIT_DTYPE+UNIT_ATT), (RM80_DTYPE << UNIT_V_DTYPE) + UNIT_ATT, - "RM80", NULL, NULL }, - { (UNIT_DTYPE+UNIT_ATT), (RP06_DTYPE << UNIT_V_DTYPE) + UNIT_ATT, - "RP06", NULL, NULL }, - { (UNIT_DTYPE+UNIT_ATT), (RM05_DTYPE << UNIT_V_DTYPE) + UNIT_ATT, - "RM05", NULL, NULL }, - { (UNIT_DTYPE+UNIT_ATT), (RP07_DTYPE << UNIT_V_DTYPE) + UNIT_ATT, - "RP07", NULL, NULL }, - { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (RM03_DTYPE << UNIT_V_DTYPE), - "RM03", NULL, NULL }, - { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (RP04_DTYPE << UNIT_V_DTYPE), - "RP04", NULL, NULL }, - { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (RM80_DTYPE << UNIT_V_DTYPE), - "RM80", NULL, NULL }, - { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (RP06_DTYPE << UNIT_V_DTYPE), - "RP06", NULL, NULL }, - { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (RM05_DTYPE << UNIT_V_DTYPE), - "RM05", NULL, NULL }, - { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (RP07_DTYPE << UNIT_V_DTYPE), - "RP07", NULL, NULL }, - { (UNIT_AUTO+UNIT_ATT), UNIT_AUTO, "autosize", NULL, NULL }, - { UNIT_AUTO, UNIT_AUTO, NULL, "AUTOSIZE", NULL }, - { (UNIT_AUTO+UNIT_DTYPE), (RM03_DTYPE << UNIT_V_DTYPE), - NULL, "RM03", &rp_set_size }, - { (UNIT_AUTO+UNIT_DTYPE), (RP04_DTYPE << UNIT_V_DTYPE), - NULL, "RP04", &rp_set_size }, - { (UNIT_AUTO+UNIT_DTYPE), (RM80_DTYPE << UNIT_V_DTYPE), - NULL, "RM80", &rp_set_size }, - { (UNIT_AUTO+UNIT_DTYPE), (RP06_DTYPE << UNIT_V_DTYPE), - NULL, "RP06", &rp_set_size }, - { (UNIT_AUTO+UNIT_DTYPE), (RM05_DTYPE << UNIT_V_DTYPE), - NULL, "RM05", &rp_set_size }, - { (UNIT_AUTO+UNIT_DTYPE), (RP07_DTYPE << UNIT_V_DTYPE), - NULL, "RP07", &rp_set_size }, - { MTAB_XTD|MTAB_VDV, 0100, "ADDRESS", "ADDRESS", - &set_addr, &show_addr, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "VECTOR", "VECTOR", - &set_vec, &show_vec, NULL }, - { 0 } }; - -DEVICE rp_dev = { - "RP", rp_unit, rp_reg, rp_mod, - RP_NUMDR, DEV_RDX, 30, 1, DEV_RDX, RP_WID, - NULL, NULL, &rp_reset, - &rp_boot, &rp_attach, &rp_detach, - &rp_dib, DEV_DISABLE | DEV_UBUS | DEV_QBUS }; - -/* I/O dispatch routines, I/O addresses 17776700 - 17776776 */ - -t_stat rp_rd (int32 *data, int32 PA, int32 access) -{ -int32 drv, dtype, i, j; - -drv = GET_UNIT (rpcs2); /* get current unit */ -dtype = GET_DTYPE (rp_unit[drv].flags); /* get drive type */ -j = (PA >> 1) & 037; /* get reg offset */ -if (reg_in_drive[j] && (rp_unit[drv].flags & UNIT_DIS)) { /* nx disk */ - rpcs2 = rpcs2 | CS2_NED; /* set error flag */ - update_rpcs (CS1_SC, drv); /* request intr */ - *data = 0; - return SCPE_OK; } - -update_rpcs (0, drv); /* update status */ -switch (j) { /* decode PA<5:1> */ -case 000: /* RPCS1 */ - *data = rpcs1; - break; -case 001: /* RPWC */ - *data = rpwc; - break; -case 002: /* RPBA */ - *data = rpba = rpba & ~BA_MBZ; - break; -case 003: /* RPDA */ - *data = rpda = rpda & ~DA_MBZ; - break; -case 004: /* RPCS2 */ - *data = rpcs2 = (rpcs2 & ~CS2_MBZ) | CS2_IR | CS2_OR; - break; -case 005: /* RPDS */ - *data = rpds[drv]; - break; -case 006: /* RPER1 */ - *data = rper1[drv]; - break; -case 007: /* RPAS */ - *data = 0; - for (i = 0; i < RP_NUMDR; i++) - if (rpds[i] & DS_ATA) *data = *data | (AS_U0 << i); - break; -case 010: /* RPLA */ - *data = GET_SECTOR (rp_rwait, dtype) << LA_V_SC; - break; -case 011: /* RPDB */ - *data = rpdb; - break; -case 012: /* RPMR */ - *data = rpmr; - break; -case 013: /* RPDT */ - *data = drv_tab[dtype].devtype; - break; -case 014: /* RPSN */ - *data = 020 | (drv + 1); - break; -case 015: /* RPOF */ - *data = rpof = rpof & ~OF_MBZ; - break; -case 016: /* RPDC */ - *data = rpdc = rpdc & ~DC_MBZ; - break; -case 017: /* RPCC, RMHR */ - *data = rp_unit[drv].CYL; - break; -case 020: /* RPER2, RMMR2 */ - *data = rper2; - break; -case 021: /* RPER3, RMER2 */ - *data = rper3; - break; -case 022: /* RPEC1 */ - *data = rpec1; - break; -case 023: /* RPEC2 */ - *data = rpec2; - break; -case 024: /* RPBAE */ - if (RH11) return SCPE_NXM; /* not in RH11 */ - *data = rpbae = rpbae & ~AE_MBZ; - break; -case 025: /* RPCS3 */ - if (RH11) return SCPE_NXM; /* not in RH11 */ - *data = rpcs3 = (rpcs3 & ~(CS1_IE | CS3_MBZ)) | (rpcs1 & CS1_IE); - break; -default: /* all others */ - rper1[drv] = rper1[drv] | ER1_ILR; - update_rpcs (0, drv); - break; } -return SCPE_OK; -} - -t_stat rp_wr (int32 data, int32 PA, int32 access) -{ -int32 cs1f, drv, i, j; -UNIT *uptr; - -cs1f = 0; /* no int on cs1 upd */ -drv = GET_UNIT (rpcs2); /* get current unit */ -uptr = rp_dev.units + drv; /* get unit */ -j = (PA >> 1) & 037; /* get reg offset */ -if (reg_in_drive[j] && (rp_unit[drv].flags & UNIT_DIS)) { /* nx disk */ - rpcs2 = rpcs2 | CS2_NED; /* set error flag */ - update_rpcs (CS1_SC, drv); /* request intr */ - return SCPE_OK; } -if (reg_in_drive[j] && sim_is_active (&rp_unit[drv])) { /* unit busy? */ - rper1[drv] = rper1[drv] | ER1_RMR; /* won't write */ - update_rpcs (0, drv); - return SCPE_OK; } - -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> */ - if ((access == WRITE) || (PA & 1)) { /* hi byte write? */ - 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); } } - 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 = data; - break; -case 002: /* RPBA */ - if (access == WRITEB) data = (PA & 1)? - (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 = 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; } - drv = GET_UNIT (rpcs2); - break; -case 006: /* RPER1 */ - if (access == WRITEB) break; - rper1[drv] = rper1[drv] & data; - break; -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; - break; -case 011: /* RPDB */ - if (access == WRITEB) data = (PA & 1)? - (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 = data; - break; -case 015: /* RPOF */ - if (access == WRITEB) data = (PA & 1)? - (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 = data & ~DC_MBZ; - break; -case 024: /* RPBAE */ - if (RH11) return SCPE_NXM; /* not in RH11 */ - if ((access == WRITEB) && (PA & 1)) break; - rpbae = data & ~AE_MBZ; - rpcs1 = (rpcs1 & ~CS1_UAE) | ((rpbae << CS1_V_UAE) & CS1_UAE); - break; -case 025: /* RPCS3 */ - if (RH11) return SCPE_NXM; /* not in RH11 */ - if ((access == WRITEB) && (PA & 1)) break; - rpcs3 = data & ~CS3_MBZ; - rpcs1 = (rpcs1 & ~CS1_IE) | (rpcs3 & CS1_IE); - break; -case 005: /* RPDS */ -case 010: /* RPLA */ -case 013: /* RPDT */ -case 014: /* RPSN */ -case 017: /* RPDC, RMHR */ -case 020: /* RPER2, RMMN2 */ -case 021: /* RPER3, RMER2 */ -case 022: /* RPEC1 */ -case 023: /* RPEC2 */ - break; /* read only */ -default: /* all others */ - rper1[drv] = rper1[drv] | ER1_ILR; - break; } /* end switch */ -update_rpcs (cs1f, drv); /* update status */ -return SCPE_OK; -} - -/* Initiate operation - unit not busy, function set */ - -void rp_go (int32 drv, int32 fnc) -{ - -int32 dc, dtype, t; -UNIT *uptr; - -if (DBG_LOG (LOG_RP)) fprintf (sim_log, - ">>RP%d: fnc=%o, ds=%o, cyl=%o, da=%o, ba=%o, wc=%o\n", - drv, fnc, rpds[drv], rpdc, rpda, (rpbae << 16) | rpba, rpwc); -uptr = rp_dev.units + drv; /* get unit */ -if (uptr->flags & UNIT_DIS) { /* nx unit? */ - rpcs2 = rpcs2 | CS2_NED; /* set error flag */ - update_rpcs (CS1_SC, drv); /* request intr */ - return; } -if ((fnc != FNC_DCLR) && (rpds[drv] & DS_ERR)) { /* err & ~clear? */ - rper1[drv] = rper1[drv] | ER1_ILF; /* not allowed */ - rpds[drv] = rpds[drv] | DS_ATA; /* set attention */ - update_rpcs (CS1_SC, drv); /* request intr */ - return; } -dtype = GET_DTYPE (uptr->flags); /* get drive type */ -rpds[drv] = rpds[drv] & ~DS_ATA; /* clear attention */ -dc = rpdc; /* assume seek, sch */ - -switch (fnc) { /* case on function */ -case FNC_DCLR: /* drive clear */ - rpda = 0; /* clear disk addr */ - rper1[drv] = rper2 = rper3 = 0; /* clear errors */ -case FNC_NOP: /* no operation */ -case FNC_RELEASE: /* port release */ - return; - -case FNC_PRESET: /* read-in preset */ - rpdc = 0; /* clear disk addr */ - rpda = 0; - rpof = 0; /* clear offset */ -case FNC_PACK: /* pack acknowledge */ - rpds[drv] = rpds[drv] | DS_VV; /* set volume valid */ - return; - -case FNC_OFFSET: /* offset mode */ -case FNC_RETURN: - if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */ - 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; - -case FNC_UNLOAD: /* unload */ -case FNC_RECAL: /* recalibrate */ - dc = 0; /* seek to 0 */ -case FNC_SEEK: /* seek */ -case FNC_SEARCH: /* search */ - if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */ - 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; } - rpds[drv] = (rpds[drv] & ~DS_RDY) | DS_PIP; /* set positioning */ - t = abs (dc - uptr->CYL); /* cyl diff */ - if (t == 0) t = 1; /* min time */ - sim_activate (uptr, rp_swait * t); /* schedule */ - uptr->CYL = dc; /* save cylinder */ - return; - -case FNC_WRITEH: /* write headers */ -case FNC_WRITE: /* write */ -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; } - 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; } - 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 */ - return; - -default: /* all others */ - rper1[drv] = rper1[drv] | ER1_ILF; /* not supported */ - rpds[drv] = rpds[drv] | DS_ATA; /* set attention */ - break; } -rpds[drv] = rpds[drv] | DS_ATA; /* error, set attn */ -update_rpcs (CS1_SC, drv); /* req intr */ -return; -} - -/* Service unit timeout - - Complete movement or data transfer command - Unit must exist - can't remove an active unit - Unit must be attached - detach cancels in progress operations -*/ - -t_stat rp_svc (UNIT *uptr) -{ -int32 i, t, dtype, drv, err; -int32 wc, awc, da; -uint32 ba; -uint16 comp; - -dtype = GET_DTYPE (uptr->flags); /* get drive type */ -drv = uptr - rp_dev.units; /* get drv number */ -rpds[drv] = (rpds[drv] & ~DS_PIP) | DS_RDY; /* change drive status */ - -switch (uptr->FUNC) { /* case on function */ -case FNC_OFFSET: /* offset */ - rpds[drv] = rpds[drv] | DS_OF | DS_ATA; /* set offset, attention */ - update_rpcs (CS1_SC, drv); - break; -case FNC_RETURN: /* return to centerline */ - rpds[drv] = (rpds[drv] & ~DS_OF) | DS_ATA; /* clear offset, set attn */ - update_rpcs (CS1_SC, drv); - break; -case FNC_UNLOAD: /* unload */ - rp_detach (uptr); /* detach unit */ - break; -case FNC_RECAL: /* recalibrate */ -case FNC_SEARCH: /* search */ -case FNC_SEEK: /* seek */ - rpds[drv] = rpds[drv] | DS_ATA; /* set attention */ - update_rpcs (CS1_SC, drv); - break; - -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; } -case FNC_WCHK: /* write check */ -case FNC_READ: /* read */ -case FNC_READH: /* read headers */ - ba = (rpbae << 16) | rpba; /* get byte addr */ - da = GET_DA (rpdc, rpda, dtype) * RP_NUMWD; /* get disk addr */ - wc = 0200000 - rpwc; /* get true wc */ - - if ((da + wc) > drv_tab[dtype].size) { /* disk overrun? */ - rper1[drv] = rper1[drv] | ER1_AOE; /* set err */ - wc = drv_tab[dtype].size - da; /* trim xfer */ - if (da >= drv_tab[dtype].size) { /* none left? */ - update_rpcs (CS1_DONE | CS1_TRE, drv); /* set done, err */ - break; } } - - err = fseek (uptr->fileref, da * sizeof (int16), SEEK_SET); - if (uptr->FUNC == FNC_WRITE) { /* write? */ - if (rpcs2 & CS2_UAI) { /* no addr inc? */ - if (t = Map_ReadW (ba, 2, &comp, RH)) { /* get 1st wd */ - wc = 0; /* NXM, no xfr */ - rpcs2 = rpcs2 | CS2_NEM; } /* set nxm err */ - for (i = 0; i < wc; i++) rpxb[i] = comp; } - else { /* normal */ - if (t = Map_ReadW (ba, wc << 1, rpxb, RH)) { /* get buf */ - wc = wc - (t >> 1); /* NXM, adj wc */ - rpcs2 = rpcs2 | CS2_NEM; } /* set nxm err */ - ba = ba + (wc << 1); } /* adv ba */ - awc = (wc + (RP_NUMWD - 1)) & ~(RP_NUMWD - 1); - for (i = wc; i < awc; i++) rpxb[i] = 0; /* fill buf */ - if (wc && !err) { /* write buf */ - fxwrite (rpxb, sizeof (uint16), wc, uptr->fileref); - err = ferror (uptr->fileref); } - } /* end if wr */ - else if ((uptr->FUNC == FNC_READ) || /* read? */ - (uptr->FUNC == FNC_READH)) { - i = fxread (rpxb, sizeof (uint16), wc, uptr->fileref); - err = ferror (uptr->fileref); - for ( ; i < wc; i++) rpxb[i] = 0; /* fill buf */ - if (rpcs2 & CS2_UAI) { /* no addr inc? */ - if (t = Map_WriteW (ba, 2, &rpxb[wc - 1], RH)) { - wc = 0; /* NXM, no xfr */ - rpcs2 = rpcs2 | CS2_NEM; } } /* set nxm err */ - else { /* normal */ - if (t = Map_WriteW (ba, wc << 1, rpxb, RH)) { /* put buf */ - wc = wc - (t >> 1); /* NXM, adj wc */ - rpcs2 = rpcs2 | CS2_NEM; } /* set nxm err */ - ba = ba + (wc << 1); } /* adv ba */ - } /* end if read */ - else { /* wchk */ - i = fxread (rpxb, sizeof (uint16), wc, uptr->fileref); - err = ferror (uptr->fileref); - for ( ; i < wc; i++) rpxb[i] = 0; /* fill buf */ - 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; } - if (comp != rpxb[wc]) { /* compare wd */ - rpcs2 = rpcs2 | CS2_WCE; /* set error */ - break; } - if ((rpcs2 & CS2_UAI) == 0) ba = ba + 2; } - } /* end else wchk */ - - rpwc = (rpwc + wc) & 0177777; /* final word count */ - rpba = (ba & 0177777) & ~BA_MBZ; /* lower 16b */ - rpbae = (ba >> 16) & ~AE_MBZ; /* upper 6b */ - rpcs1 = (rpcs1 & ~ CS1_UAE) | ((rpbae << CS1_V_UAE) & CS1_UAE); - da = da + wc + (RP_NUMWD - 1); - if (da >= drv_tab[dtype].size) rpds[drv] = rpds[drv] | DS_LST; - da = da / RP_NUMWD; - rpda = da % drv_tab[dtype].sect; - da = da / drv_tab[dtype].sect; - rpda = rpda | ((da % drv_tab[dtype].surf) << DA_V_SF); - 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; } -case FNC_WRITEH: /* write headers stub */ - update_rpcs (CS1_DONE, drv); /* set done */ - break; } /* end case func */ -return SCPE_OK; -} - -/* Controller status update - - Check for done transition - Update drive status - Update RPCS1 - Update interrupt request -*/ - -void update_rpcs (int32 flag, int32 drv) -{ -int32 i; -UNIT *uptr; - -if ((flag & ~rpcs1) & CS1_DONE) /* DONE 0 to 1? */ - rpiff = (rpcs1 & CS1_IE)? 1: 0; /* CSTB INTR <- IE */ -uptr = rp_dev.units + drv; /* get unit */ -if (rp_unit[drv].flags & UNIT_DIS) rpds[drv] = rper1[drv] = 0; -else rpds[drv] = (rpds[drv] | DS_DPR) & ~DS_PGM; -if (rp_unit[drv].flags & UNIT_ATT) rpds[drv] = rpds[drv] | DS_MOL; -else rpds[drv] = rpds[drv] & ~(DS_MOL | DS_VV | DS_RDY); -if (rper1[drv] | rper2 | rper3) rpds[drv] = rpds[drv] | DS_ERR | DS_ATA; -else rpds[drv] = rpds[drv] & ~DS_ERR; - -rpcs1 = (rpcs1 & ~(CS1_SC | CS1_MCPE | CS1_MBZ | CS1_DRV)) | CS1_DVA | flag; -rpcs1 = rpcs1 | (uptr->FUNC << CS1_V_FNC); -if (sim_is_active (uptr)) rpcs1 = rpcs1 | CS1_GO; -if (rpcs2 & CS2_ERR) rpcs1 = rpcs1 | CS1_TRE | CS1_SC; -else if (rpcs1 & CS1_TRE) rpcs1 = rpcs1 | CS1_SC; -for (i = 0; i < RP_NUMDR; i++) - if (rpds[i] & DS_ATA) rpcs1 = rpcs1 | CS1_SC; -if (rpiff || ((rpcs1 & CS1_SC) && (rpcs1 & CS1_DONE) && (rpcs1 & CS1_IE))) - SET_INT (RP); -else CLR_INT (RP); -return; -} - -/* Interrupt acknowledge */ - -int32 rp_inta (void) -{ -rpcs1 = rpcs1 & ~CS1_IE; /* clear int enable */ -rpcs3 = rpcs3 & ~CS1_IE; /* in both registers */ -rpiff = 0; /* clear CSTB INTR */ -return rp_dib.vec; /* acknowledge */ -} - -/* Device reset */ - -t_stat rp_reset (DEVICE *dptr) -{ -int32 i; -UNIT *uptr; - -rpcs1 = CS1_DVA | CS1_DONE; -rpcs2 = CS2_IR | CS2_OR; -rpba = rpda = 0; -rpof = rpdc = 0; -rper2 = rper3 = 0; -rpec1 = rpec2 = 0; -rpbae = rpcs3 = 0; -rpiff = 0; /* clear CSTB INTR */ -CLR_INT (RP); /* clear intr req */ -for (i = 0; i < RP_NUMDR; i++) { - uptr = rp_dev.units + 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); - else if (uptr->flags & UNIT_DIS) rpds[i] = 0; - else rpds[i] = DS_DPR; - rper1[i] = 0; } -if (rpxb == NULL) rpxb = calloc (RP_MAXFR, sizeof (unsigned int16)); -if (rpxb == NULL) return SCPE_MEM; -return SCPE_OK; -} - -/* Device attach */ - -t_stat rp_attach (UNIT *uptr, char *cptr) -{ -int32 drv, i, p; -t_stat r; - -uptr->capac = drv_tab[GET_DTYPE (uptr->flags)].size; -r = attach_unit (uptr, cptr); /* attach unit */ -if (r != SCPE_OK) return r; /* error? */ -drv = uptr - rp_dev.units; /* get drv number */ -rpds[drv] = DS_ATA | DS_MOL | DS_RDY | DS_DPR | /* upd drv status */ - ((uptr->flags & UNIT_WPRT)? DS_WRL: 0); -rper1[drv] = 0; -update_rpcs (CS1_SC, drv); /* upd ctlr status */ - -if (fseek (uptr->fileref, 0, SEEK_END)) return SCPE_OK; /* seek to end */ -if ((p = ftell (uptr->fileref)) == 0) { /* new disk image? */ - if (uptr->flags & UNIT_RO) return SCPE_OK; - return pdp11_bad_block (uptr, - drv_tab[GET_DTYPE (uptr->flags)].sect, RP_NUMWD); } -if ((uptr->flags & UNIT_AUTO) == 0) return SCPE_OK; /* autosize? */ -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); - uptr->capac = drv_tab[i].size; - return SCPE_OK; } } -return SCPE_OK; -} - -/* Device detach */ - -t_stat rp_detach (UNIT *uptr) -{ -int32 drv; - -drv = uptr - rp_dev.units; /* get drv number */ -rpds[drv] = (rpds[drv] & ~(DS_MOL | DS_RDY | DS_WRL | DS_VV | DS_OF)) | - DS_ATA; -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 */ -update_rpcs (CS1_SC, drv); /* request intr */ -return detach_unit (uptr); -} - -/* Set size command validation routine */ - -t_stat rp_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; -} - -/* Set bad block routine */ - -t_stat rp_set_bad (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -return pdp11_bad_block (uptr, drv_tab[GET_DTYPE (uptr->flags)].sect, RP_NUMWD); -} - -/* Device bootstrap */ - -#if defined (VM_PDP11) - -#define BOOT_START 02000 /* start */ -#define BOOT_ENTRY (BOOT_START + 002) /* entry */ -#define BOOT_UNIT (BOOT_START + 010) /* unit number */ -#define BOOT_CSR (BOOT_START + 014) /* CSR */ -#define BOOT_LEN (sizeof (boot_rom) / sizeof (int16)) - -static const uint16 boot_rom[] = { - 0042102, /* "DB" */ - 0012706, BOOT_START, /* mov #boot_start, sp */ - 0012700, 0000000, /* mov #unit, r0 */ - 0012701, 0176700, /* mov #RPCS1, r1 */ - 0012761, 0000040, 0000010, /* mov #CS2_CLR, 10(r1) ; reset */ - 0010061, 0000010, /* mov r0, 10(r1) ; set unit */ - 0012711, 0000021, /* mov #RIP+GO, (r1) ; pack ack */ - 0012761, 0010000, 0000032, /* mov #FMT16B, 32(r1) ; 16b mode */ - 0012761, 0177000, 0000002, /* mov #-512., 2(r1) ; set wc */ - 0005061, 0000004, /* clr 4(r1) ; clr ba */ - 0005061, 0000006, /* clr 6(r1) ; clr da */ - 0005061, 0000034, /* clr 34(r1) ; clr cyl */ - 0012711, 0000071, /* mov #READ+GO, (r1) ; read */ - 0105711, /* tstb (r1) ; wait */ - 0100376, /* bpl .-2 */ - 0005002, /* clr R2 */ - 0005003, /* clr R3 */ - 0012704, BOOT_START+020, /* mov #start+020, r4 */ - 0005005, /* clr R5 */ - 0105011, /* clrb (r1) */ - 0005007 /* clr PC */ -}; - -t_stat rp_boot (int32 unitno, DEVICE *dptr) -{ -int32 i; -extern int32 saved_PC; - -for (i = 0; i < BOOT_LEN; i++) M[(BOOT_START >> 1) + i] = boot_rom[i]; -M[BOOT_UNIT >> 1] = unitno & CS2_M_UNIT; -M[BOOT_CSR >> 1] = rp_dib.ba & DMASK; -saved_PC = BOOT_ENTRY; -return SCPE_OK; -} - -#else - -t_stat rp_boot (int32 unitno, DEVICE *dptr) -{ -return SCPE_NOFNC; -} - -#endif diff --git a/PDP11/pdp11_rq.c b/PDP11/pdp11_rq.c deleted file mode 100644 index 0007e840..00000000 --- a/PDP11/pdp11_rq.c +++ /dev/null @@ -1,2316 +0,0 @@ -/* pdp11_rq.c: MSCP disk controller simulator - - Copyright (c) 2002-2003, Robert M Supnik - Derived from work by Stephen F. Shirron - - 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. - - rq RQDX3 disk controller - - 11-Jul-03 RMS Fixed bug in user disk size (found by Chaskiel M Grundman) - 19-May-03 RMS Revised for new conditional compilation scheme - 25-Apr-03 RMS Revised for extended file support - 14-Mar-03 RMS Fixed variable size interaction with save/restore - 27-Feb-03 RMS Added user-defined drive support - 26-Feb-03 RMS Fixed bug in vector calculation for VAXen - 22-Feb-03 RMS Fixed ordering bug in queue process - 12-Oct-02 RMS Added multicontroller support - 29-Sep-02 RMS Changed addressing to 18b in Unibus mode - Added variable address support to bootstrap - Added vector display support - Fixed status code in HBE error log - Consolidated MSCP/TMSCP header file - New data structures - 16-Aug-02 RMS Removed unused variables (found by David Hittner) - 04-May-02 RMS Fixed bug in polling loop for queued operations - 26-Mar-02 RMS Fixed bug, reset routine cleared UF_WPH - 09-Mar-02 RMS Adjusted delays for M+ timing bugs - 04-Mar-02 RMS Added delays to initialization for M+, RSTS/E - 16-Feb-02 RMS Fixed bugs in host timeout logic, boot - 26-Jan-02 RMS Revised bootstrap to conform to M9312 - 06-Jan-02 RMS Revised enable/disable support - 30-Dec-01 RMS Revised show routines - 19-Dec-01 RMS Added bigger drives - 17-Dec-01 RMS Added queue process -*/ - -#if defined (VM_PDP10) /* PDP10 version */ -#error "RQDX3 not supported on PDP-10!" - -#elif defined (VM_VAX) /* VAX version */ -#include "vax_defs.h" -#define RQ_AINC 4 -#define RQ_WID 32 -extern int32 int_req[IPL_HLVL]; -extern int32 int_vec[IPL_HLVL][32]; - -#else /* PDP-11 version */ -#include "pdp11_defs.h" -#define RQ_AINC 2 -#define RQ_WID 16 -extern int32 cpu_18b, cpu_ubm; -extern int32 int_req[IPL_HLVL]; -extern int32 int_vec[IPL_HLVL][32]; -#endif - -#if !defined (RQ_NUMCT) -#define RQ_NUMCT 4 -#elif (RQ_NUMCT > 4) -#error "Assertion failure: RQ_NUMCT exceeds 4" -#endif - -#include "pdp11_uqssp.h" -#include "pdp11_mscp.h" - -#define UF_MSK (UF_CMR|UF_CMW) /* settable flags */ - -#define RQ_SH_MAX 24 /* max display wds */ -#define RQ_SH_PPL 8 /* wds per line */ -#define RQ_SH_DPL 4 /* desc per line */ -#define RQ_SH_RI 001 /* show rings */ -#define RQ_SH_FR 002 /* show free q */ -#define RQ_SH_RS 004 /* show resp q */ -#define RQ_SH_UN 010 /* show unit q's */ - -#define RQ_CLASS 1 /* RQ class */ -#define RQ_UQPM 19 /* UQ port model */ -#define RQ_MODEL 19 /* MSCP ctrl model */ -#define RQ_HVER 1 /* hardware version */ -#define RQ_SVER 3 /* software version */ -#define RQ_DHTMO 60 /* def host timeout */ -#define RQ_DCTMO 120 /* def ctrl timeout */ -#define RQ_NUMDR 4 /* # drives */ -#define RQ_NUMBY 512 /* bytes per block */ -#define RQ_MAXFR (1 << 16) /* max xfer */ - -#define UNIT_V_ONL (UNIT_V_UF + 0) /* online */ -#define UNIT_V_WLK (UNIT_V_UF + 1) /* hwre write lock */ -#define UNIT_V_ATP (UNIT_V_UF + 2) /* attn pending */ -#define UNIT_V_DTYPE (UNIT_V_UF + 3) /* drive type */ -#define UNIT_M_DTYPE 0xF -#define UNIT_ONL (1 << UNIT_V_ONL) -#define UNIT_WLK (1 << UNIT_V_WLK) -#define UNIT_ATP (1 << UNIT_V_ATP) -#define UNIT_DTYPE (UNIT_M_DTYPE << UNIT_V_DTYPE) -#define GET_DTYPE(x) (((x) >> UNIT_V_DTYPE) & UNIT_M_DTYPE) -#define cpkt u3 /* current packet */ -#define pktq u4 /* packet queue */ -#define uf buf /* settable unit flags */ -#define cnum wait /* controller index */ -#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write prot */ -#define RQ_RMV(u) ((drv_tab[GET_DTYPE (u->flags)].flgs & RQDF_RMV)? \ - UF_RMV: 0) -#define RQ_WPH(u) (((drv_tab[GET_DTYPE (u->flags)].flgs & RQDF_RO) || \ - (u->flags & UNIT_WPRT))? UF_WPH: 0) - -#define CST_S1 0 /* init stage 1 */ -#define CST_S1_WR 1 /* stage 1 wrap */ -#define CST_S2 2 /* init stage 2 */ -#define CST_S3 3 /* init stage 3 */ -#define CST_S3_PPA 4 /* stage 3 sa wait */ -#define CST_S3_PPB 5 /* stage 3 ip wait */ -#define CST_S4 6 /* stage 4 */ -#define CST_UP 7 /* online */ -#define CST_DEAD 8 /* fatal error */ - -#define ERR 0 /* must be SCPE_OK! */ -#define OK 1 - -#define RQ_TIMER (RQ_NUMDR) -#define RQ_QUEUE (RQ_TIMER + 1) - -/* Internal packet management. The real RQDX3 manages its packets as true - linked lists. However, use of actual addresses in structures won't work - with save/restore. Accordingly, the packets are an arrayed structure, - and links are actually subscripts. To minimize complexity, packet[0] - is not used (0 = end of list), and the number of packets must be a power - of two. -*/ - -#define RQ_NPKTS 32 /* # packets (pwr of 2) */ -#define RQ_M_NPKTS (RQ_NPKTS - 1) /* mask */ -#define RQ_PKT_SIZE_W 32 /* payload size (wds) */ -#define RQ_PKT_SIZE (RQ_PKT_SIZE_W * sizeof (int16)) - -struct rqpkt { - int16 link; /* link to next */ - uint16 d[RQ_PKT_SIZE_W]; }; /* data */ - -/* Packet payload extraction and insertion; cp defines controller */ - -#define GETP(p,w,f) ((cp->pak[p].d[w] >> w##_V_##f) & w##_M_##f) -#define GETP32(p,w) (((uint32) cp->pak[p].d[w]) | \ - (((uint32) cp->pak[p].d[(w)+1]) << 16)) -#define PUTP32(p,w,x) cp->pak[p].d[w] = (x) & 0xFFFF; \ - cp->pak[p].d[(w)+1] = ((x) >> 16) & 0xFFFF - -/* Disk formats. An RQDX3 consists of the following regions: - - XBNs Extended blocks - contain information about disk format, - also holds track being reformatted during bad block repl. - Size = sectors/track + 1, replicated 3 times. - DBNs Diagnostic blocks - used by diagnostics. Sized to pad - out the XBNs to a cylinder boundary. - LBNs Logical blocks - contain user information. - RCT Replacement control table - first block contains status, - second contains data from block being replaced, remaining - contain information about replaced bad blocks. - Size = RBNs/128 + 3, replicated 4-8 times. - RBNs Replacement blocks - used to replace bad blocks. - - The simulator does not need to perform bad block replacement; the - information below is for simulating RCT reads, if required. - - Note that an RA drive has a different order: LBNs, RCT, XBN, DBN; - the RBNs are spare blocks at the end of every track. -*/ - -#define RCT_OVHD 2 /* #ovhd blks */ -#define RCT_ENTB 128 /* entries/blk */ -#define RCT_END 0x80000000 /* marks RCT end */ - -/* The RQDX3 supports multiple disk drive types: - - type sec surf cyl tpg gpc RCT LBNs - - RX50 10 1 80 5 16 - 800 - RX33 15 2 80 2 1 - 2400 - RD51 18 4 306 4 1 36*4 21600 - RD31 17 4 615 4 1 3*8 41560 - RD52 17 8 512 8 1 4*8 60480 - RD53 17 7 1024 7 1 5*8 138672 - RD54 17 15 1225 15 1 7*8 311200 - - The simulator also supports larger drives that only existed - on SDI controllers. XBN, DBN, RCTS and RCTC are not known - for the SDI drives and are not used by the simulator: - - RA82 57 15 1435 15 1 ?*8 1216665 - RA72 51 20 1921? 20 1 ?*8 1953300 - RA90 69 13 2656 13 1 ?*8 2376153 - RA92 73 13 3101 13 1 ?*8 2940951 - - Each drive can be a different type. The drive field in the - unit flags specified the drive type and thus, indirectly, - the drive size. -*/ - -#define RQDF_RMV 01 /* removable */ -#define RQDF_RO 02 /* read only */ -#define RQDF_SDI 04 /* SDI drive */ - -#define RX50_DTYPE 0 -#define RX50_SECT 10 -#define RX50_SURF 1 -#define RX50_CYL 80 -#define RX50_TPG 5 -#define RX50_GPC 16 -#define RX50_XBN 0 -#define RX50_DBN 0 -#define RX50_LBN 800 -#define RX50_RCTS 0 -#define RX50_RCTC 0 -#define RX50_RBN 0 -#define RX50_MOD 7 -#define RX50_MED 0x25658032 -#define RX50_FLGS RQDF_RMV - -#define RX33_DTYPE 1 -#define RX33_SECT 15 -#define RX33_SURF 2 -#define RX33_CYL 80 -#define RX33_TPG 2 -#define RX33_GPC 1 -#define RX33_XBN 0 -#define RX33_DBN 0 -#define RX33_LBN 2400 -#define RX33_RCTS 0 -#define RX33_RCTC 0 -#define RX33_RBN 0 -#define RX33_MOD 10 -#define RX33_MED 0x25658021 -#define RX33_FLGS RQDF_RMV - -#define RD51_DTYPE 2 -#define RD51_SECT 18 -#define RD51_SURF 4 -#define RD51_CYL 306 -#define RD51_TPG 4 -#define RD51_GPC 1 -#define RD51_XBN 57 -#define RD51_DBN 87 -#define RD51_LBN 21600 -#define RD51_RCTS 36 -#define RD51_RCTC 4 -#define RD51_RBN 144 -#define RD51_MOD 6 -#define RD51_MED 0x25644033 -#define RD51_FLGS 0 - -#define RD31_DTYPE 3 -#define RD31_SECT 17 -#define RD31_SURF 4 -#define RD31_CYL 615 /* last unused */ -#define RD31_TPG RD31_SURF -#define RD31_GPC 1 -#define RD31_XBN 54 -#define RD31_DBN 14 -#define RD31_LBN 41560 -#define RD31_RCTS 3 -#define RD31_RCTC 8 -#define RD31_RBN 100 -#define RD31_MOD 12 -#define RD31_MED 0x2564401F -#define RD31_FLGS 0 - -#define RD52_DTYPE 4 /* Quantum params */ -#define RD52_SECT 17 -#define RD52_SURF 8 -#define RD52_CYL 512 -#define RD52_TPG RD52_SURF -#define RD52_GPC 1 -#define RD52_XBN 54 -#define RD52_DBN 82 -#define RD52_LBN 60480 -#define RD52_RCTS 4 -#define RD52_RCTC 8 -#define RD52_RBN 168 -#define RD52_MOD 8 -#define RD52_MED 0x25644034 -#define RD52_FLGS 0 - -#define RD53_DTYPE 5 -#define RD53_SECT 17 -#define RD53_SURF 8 -#define RD53_CYL 1024 /* last unused */ -#define RD53_TPG RD53_SURF -#define RD53_GPC 1 -#define RD53_XBN 54 -#define RD53_DBN 82 -#define RD53_LBN 138672 -#define RD53_RCTS 5 -#define RD53_RCTC 8 -#define RD53_RBN 280 -#define RD53_MOD 9 -#define RD53_MED 0x25644035 -#define RD53_FLGS 0 - -#define RD54_DTYPE 6 -#define RD54_SECT 17 -#define RD54_SURF 15 -#define RD54_CYL 1225 /* last unused */ -#define RD54_TPG RD54_SURF -#define RD54_GPC 1 -#define RD54_XBN 54 -#define RD54_DBN 201 -#define RD54_LBN 311200 -#define RD54_RCTS 7 -#define RD54_RCTC 8 -#define RD54_RBN 609 -#define RD54_MOD 13 -#define RD54_MED 0x25644036 -#define RD54_FLGS 0 - -#define RA82_DTYPE 7 /* SDI drive */ -#define RA82_SECT 57 /* +1 spare/track */ -#define RA82_SURF 15 -#define RA82_CYL 1435 /* 0-1422 user */ -#define RA82_TPG RA82_SURF -#define RA82_GPC 1 -#define RA82_XBN 3420 /* cyl 1427-1430 */ -#define RA82_DBN 3420 /* cyl 1431-1434 */ -#define RA82_LBN 1216665 /* 57*15*1423 */ -#define RA82_RCTS 400 /* cyl 1423-1426 */ -#define RA82_RCTC 8 -#define RA82_RBN 21345 /* 1 *15*1423 */ -#define RA82_MOD 11 -#define RA82_MED 0x25641052 -#define RA82_FLGS RQDF_SDI - -#define RRD40_DTYPE 8 -#define RRD40_SECT 128 -#define RRD40_SURF 1 -#define RRD40_CYL 10400 -#define RRD40_TPG RRD40_SURF -#define RRD40_GPC 1 -#define RRD40_XBN 0 -#define RRD40_DBN 0 -#define RRD40_LBN 1331200 -#define RRD40_RCTS 0 -#define RRD40_RCTC 0 -#define RRD40_RBN 0 -#define RRD40_MOD 26 -#define RRD40_MED 0x25652228 -#define RRD40_FLGS (RQDF_RMV | RQDF_RO) - -#define RA72_DTYPE 9 /* SDI drive */ -#define RA72_SECT 51 /* +1 spare/trk */ -#define RA72_SURF 20 -#define RA72_CYL 1921 /* 0-1914 user */ -#define RA72_TPG RA72_SURF -#define RA72_GPC 1 -#define RA72_XBN 2040 /* cyl 1917-1918? */ -#define RA72_DBN 2040 /* cyl 1920-1921? */ -#define RA72_LBN 1953300 /* 51*20*1915 */ -#define RA72_RCTS 400 /* cyl 1915-1916? */ -#define RA72_RCTC 5 /* ? */ -#define RA72_RBN 38300 /* 1 *20*1915 */ -#define RA72_MOD 37 -#define RA72_MED 0x25641048 -#define RA72_FLGS RQDF_SDI - -#define RA90_DTYPE 10 /* SDI drive */ -#define RA90_SECT 69 /* +1 spare/trk */ -#define RA90_SURF 13 -#define RA90_CYL 2656 /* 0-2648 user */ -#define RA90_TPG RA90_SURF -#define RA90_GPC 1 -#define RA90_XBN 1794 /* cyl 2651-2652? */ -#define RA90_DBN 1794 /* cyl 2653-2654? */ -#define RA90_LBN 2376153 /* 69*13*2649 */ -#define RA90_RCTS 400 /* cyl 2649-2650? */ -#define RA90_RCTC 6 /* ? */ -#define RA90_RBN 34437 /* 1 *13*2649 */ -#define RA90_MOD 19 -#define RA90_MED 0x2564105A -#define RA90_FLGS RQDF_SDI - -#define RA92_DTYPE 11 /* SDI drive */ -#define RA92_SECT 73 /* +1 spare/trk */ -#define RA92_SURF 13 -#define RA92_CYL 3101 /* 0-3098 user */ -#define RA92_TPG RA92_SURF -#define RA92_GPC 1 -#define RA92_XBN 174 /* cyl 3100? */ -#define RA92_DBN 775 -#define RA92_LBN 2940951 /* 73*13*3099 */ -#define RA92_RCTS 316 /* cyl 3099? */ -#define RA92_RCTC 3 /* ? */ -#define RA92_RBN 40287 /* 1 *13*3099 */ -#define RA92_MOD 29 -#define RA92_MED 0x2564105C -#define RA92_FLGS RQDF_SDI - -#define RA8U_DTYPE 12 /* user defined */ -#define RA8U_SECT 57 /* +1 spare/track */ -#define RA8U_SURF 15 -#define RA8U_CYL 1435 /* 0-1422 user */ -#define RA8U_TPG RA8U_SURF -#define RA8U_GPC 1 -#define RA8U_XBN 3420 /* cyl 1427-1430 */ -#define RA8U_DBN 3420 /* cyl 1431-1434 */ -#define RA8U_LBN 1216665 /* 57*15*1423 */ -#define RA8U_RCTS 400 /* cyl 1423-1426 */ -#define RA8U_RCTC 8 -#define RA8U_RBN 21345 /* 1 *15*1423 */ -#define RA8U_MOD 11 /* RA82 */ -#define RA8U_MED 0x25641052 /* RA82 */ -#define RA8U_FLGS RQDF_SDI -#define RA8U_MINC 5 /* min cap MB */ -#define RA8U_MAXC 2000 /* max cap MB */ -#define RA8U_EMAXC 1000000 /* ext max cap */ - -struct drvtyp { - int32 sect; /* sectors */ - int32 surf; /* surfaces */ - int32 cyl; /* cylinders */ - int32 tpg; /* trk/grp */ - int32 gpc; /* grp/cyl */ - int32 xbn; /* XBN size */ - int32 dbn; /* DBN size */ - uint32 lbn; /* LBN size */ - int32 rcts; /* RCT size */ - int32 rctc; /* RCT copies */ - int32 rbn; /* RBNs */ - int32 mod; /* MSCP model */ - int32 med; /* MSCP media */ - int32 flgs; /* flags */ - char *name; /* name */ -}; - -#define RQ_DRV(d) \ - d##_SECT, d##_SURF, d##_CYL, d##_TPG, \ - d##_GPC, d##_XBN, d##_DBN, d##_LBN, \ - d##_RCTS, d##_RCTC, d##_RBN, d##_MOD, \ - d##_MED, d##_FLGS -#define RQ_SIZE(d) (d##_LBN * RQ_NUMBY) - -static struct drvtyp drv_tab[] = { - { RQ_DRV (RX50), "RX50" }, { RQ_DRV (RX33), "RX33" }, - { RQ_DRV (RD51), "RD51" }, { RQ_DRV (RD31), "RD31" }, - { RQ_DRV (RD52), "RD52" }, { RQ_DRV (RD53), "RD53" }, - { RQ_DRV (RD54), "RD54" }, { RQ_DRV (RA82), "RA82" }, - { RQ_DRV (RRD40), "RRD40" }, { RQ_DRV (RA72), "RA72" }, - { RQ_DRV (RA90), "RA90" }, { RQ_DRV (RA92), "RA92" }, - { RQ_DRV (RA8U), "RAUSER" }, { 0 } }; - -extern int32 int_req[IPL_HLVL]; -extern int32 tmr_poll, clk_tps; -extern int32 cpu_log; -extern UNIT cpu_unit; -extern FILE *sim_log; -extern uint32 sim_taddr_64; - -uint16 *rqxb = NULL; /* xfer buffer */ -int32 rq_itime = 200; /* init time, except */ -int32 rq_itime4 = 10; /* stage 4 */ -int32 rq_qtime = 200; /* queue time */ -int32 rq_xtime = 500; /* transfer time */ - -struct mscp_con { - uint32 cnum; /* ctrl number */ - uint32 ubase; /* unit base */ - uint32 sa; /* status, addr */ - uint32 saw; /* written data */ - uint32 s1dat; /* S1 data */ - uint32 comm; /* comm region */ - uint32 csta; /* ctrl state */ - uint32 perr; /* last error */ - uint32 cflgs; /* ctrl flags */ - uint32 irq; /* intr request */ - uint32 prgi; /* purge int */ - uint32 pip; /* poll in progress */ - int32 freq; /* free list */ - int32 rspq; /* resp list */ - uint32 pbsy; /* #busy pkts */ - uint32 credits; /* credits */ - uint32 hat; /* host timer */ - uint32 htmo; /* host timeout */ - struct uq_ring cq; /* cmd ring */ - struct uq_ring rq; /* rsp ring */ - struct rqpkt pak[RQ_NPKTS]; /* packet queue */ -}; - -#define MSC struct mscp_con /* MSCP ctrl context */ - -DEVICE rq_dev, rqb_dev, rqc_dev,rqd_dev; - -t_stat rq_rd (int32 *data, int32 PA, int32 access); -t_stat rq_wr (int32 data, int32 PA, int32 access); -t_stat rq_svc (UNIT *uptr); -t_stat rq_tmrsvc (UNIT *uptr); -t_stat rq_quesvc (UNIT *uptr); -t_stat rq_reset (DEVICE *dptr); -t_stat rq_attach (UNIT *uptr, char *cptr); -t_stat rq_detach (UNIT *uptr); -t_stat rq_boot (int32 unitno, DEVICE *dptr); -t_stat rq_set_wlk (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat rq_set_type (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat rq_show_type (FILE *st, UNIT *uptr, int32 val, void *desc); -t_stat rq_show_wlk (FILE *st, UNIT *uptr, int32 val, void *desc); -t_stat rq_show_ctrl (FILE *st, UNIT *uptr, int32 val, void *desc); -t_stat rq_show_unitq (FILE *st, UNIT *uptr, int32 val, void *desc); - -t_bool rq_step4 (MSC *cp); -t_bool rq_mscp (MSC *cp, int32 pkt, t_bool q); -t_bool rq_abo (MSC *cp, int32 pkt, t_bool q); -t_bool rq_avl (MSC *cp, int32 pkt, t_bool q); -t_bool rq_fmt (MSC *cp, int32 pkt, t_bool q); -t_bool rq_gcs (MSC *cp, int32 pkt, t_bool q); -t_bool rq_gus (MSC *cp, int32 pkt, t_bool q); -t_bool rq_onl (MSC *cp, int32 pkt, t_bool q); -t_bool rq_rw (MSC *cp, int32 pkt, t_bool q); -t_bool rq_scc (MSC *cp, int32 pkt, t_bool q); -t_bool rq_suc (MSC *cp, int32 pkt, t_bool q); -t_bool rq_plf (MSC *cp, uint32 err); -t_bool rq_dte (MSC *cp, UNIT *uptr, uint32 err); -t_bool rq_hbe (MSC *cp, UNIT *uptr); -t_bool rq_una (MSC *cp, int32 un); -t_bool rq_deqf (MSC *cp, int32 *pkt); -int32 rq_deqh (MSC *cp, int32 *lh); -void rq_enqh (MSC *cp, int32 *lh, int32 pkt); -void rq_enqt (MSC *cp, int32 *lh, int32 pkt); -t_bool rq_getpkt (MSC *cp, int32 *pkt); -t_bool rq_putpkt (MSC *cp, int32 pkt, t_bool qt); -t_bool rq_getdesc (MSC *cp, struct uq_ring *ring, uint32 *desc); -t_bool rq_putdesc (MSC *cp, struct uq_ring *ring, uint32 desc); -int32 rq_rw_valid (MSC *cp, int32 pkt, UNIT *uptr, uint32 cmd); -t_bool rq_rw_end (MSC *cp, UNIT *uptr, uint32 flg, uint32 sts); -void rq_putr (MSC *cp, int32 pkt, uint32 cmd, uint32 flg, - uint32 sts, uint32 lnt, uint32 typ); -void rq_putr_unit (MSC *cp, int32 pkt, UNIT *uptr, uint32 lu, t_bool all); -void rq_setf_unit (MSC *cp, int32 pkt, UNIT *uptr); -void rq_init_int (MSC *cp); -void rq_ring_int (MSC *cp, struct uq_ring *ring); -t_bool rq_fatal (MSC *cp, uint32 err); -UNIT *rq_getucb (MSC *cp, uint32 lu); -int32 rq_map_pa (uint32 pa); -void rq_setint (MSC *cp); -void rq_clrint (MSC *cp); -int32 rq_inta (void); - -/* RQ data structures - - rq_dev RQ device descriptor - rq_unit RQ unit list - rq_reg RQ register list - rq_mod RQ modifier list -*/ - -MSC rq_ctx = { 0 }; - -DIB rq_dib = { IOBA_RQ, IOLN_RQ, &rq_rd, &rq_wr, - 1, IVCL (RQ), 0, { &rq_inta } }; - -UNIT rq_unit[] = { - { UDATA (&rq_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE+ - (RD54_DTYPE << UNIT_V_DTYPE), RQ_SIZE (RD54)) }, - { UDATA (&rq_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE+ - (RD54_DTYPE << UNIT_V_DTYPE), RQ_SIZE (RD54)) }, - { UDATA (&rq_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE+ - (RD54_DTYPE << UNIT_V_DTYPE), RQ_SIZE (RD54)) }, - { UDATA (&rq_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE+ - (RX50_DTYPE << UNIT_V_DTYPE), RQ_SIZE (RX50)) }, - { UDATA (&rq_tmrsvc, UNIT_DIS, 0) }, - { UDATA (&rq_quesvc, UNIT_DIS, 0) } }; - -REG rq_reg[] = { - { GRDATA (SA, rq_ctx.sa, DEV_RDX, 16, 0) }, - { GRDATA (SAW, rq_ctx.saw, DEV_RDX, 16, 0) }, - { GRDATA (S1DAT, rq_ctx.s1dat, DEV_RDX, 16, 0) }, - { GRDATA (COMM, rq_ctx.comm, DEV_RDX, 22, 0) }, - { GRDATA (CQBA, rq_ctx.cq.ba, DEV_RDX, 22, 0) }, - { GRDATA (CQLNT, rq_ctx.cq.lnt, DEV_RDX, 8, 2), REG_NZ }, - { GRDATA (CQIDX, rq_ctx.cq.idx, DEV_RDX, 8, 2) }, - { GRDATA (RQBA, rq_ctx.rq.ba, DEV_RDX, 22, 0) }, - { GRDATA (RQLNT, rq_ctx.rq.lnt, DEV_RDX, 8, 2), REG_NZ }, - { GRDATA (RQIDX, rq_ctx.rq.idx, DEV_RDX, 8, 2) }, - { DRDATA (FREE, rq_ctx.freq, 5) }, - { DRDATA (RESP, rq_ctx.rspq, 5) }, - { DRDATA (PBSY, rq_ctx.pbsy, 5) }, - { GRDATA (CFLGS, rq_ctx.cflgs, DEV_RDX, 16, 0) }, - { GRDATA (CSTA, rq_ctx.csta, DEV_RDX, 4, 0) }, - { GRDATA (PERR, rq_ctx.perr, DEV_RDX, 9, 0) }, - { DRDATA (CRED, rq_ctx.credits, 5) }, - { DRDATA (HAT, rq_ctx.hat, 17) }, - { DRDATA (HTMO, rq_ctx.htmo, 17) }, - { FLDATA (PRGI, rq_ctx.prgi, 0), REG_HIDDEN }, - { FLDATA (PIP, rq_ctx.pip, 0), REG_HIDDEN }, - { FLDATA (INT, rq_ctx.irq, 0) }, - { DRDATA (ITIME, rq_itime, 24), PV_LEFT + REG_NZ }, - { DRDATA (I4TIME, rq_itime4, 24), PV_LEFT + REG_NZ }, - { DRDATA (QTIME, rq_qtime, 24), PV_LEFT + REG_NZ }, - { DRDATA (XTIME, rq_xtime, 24), PV_LEFT + REG_NZ }, - { BRDATA (PKTS, rq_ctx.pak, DEV_RDX, 16, RQ_NPKTS * (RQ_PKT_SIZE_W + 1)) }, - { URDATA (CPKT, rq_unit[0].cpkt, 10, 5, 0, RQ_NUMDR, 0) }, - { URDATA (PKTQ, rq_unit[0].pktq, 10, 5, 0, RQ_NUMDR, 0) }, - { URDATA (UFLG, rq_unit[0].uf, DEV_RDX, 16, 0, RQ_NUMDR, 0) }, - { URDATA (CAPAC, rq_unit[0].capac, 10, T_ADDR_W, 0, RQ_NUMDR, PV_LEFT | REG_HRO) }, - { GRDATA (DEVADDR, rq_dib.ba, DEV_RDX, 32, 0), REG_HRO }, - { GRDATA (DEVVEC, rq_dib.vec, DEV_RDX, 16, 0), REG_HRO }, - { DRDATA (DEVLBN, drv_tab[RA8U_DTYPE].lbn, 22), REG_HRO }, - { NULL } }; - -MTAB rq_mod[] = { - { UNIT_WLK, 0, NULL, "WRITEENABLED", &rq_set_wlk }, - { UNIT_WLK, UNIT_WLK, NULL, "LOCKED", &rq_set_wlk }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, RQ_SH_RI, "RINGS", NULL, - NULL, &rq_show_ctrl, 0 }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, RQ_SH_FR, "FREEQ", NULL, - NULL, &rq_show_ctrl, 0 }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, RQ_SH_RS, "RESPQ", NULL, - NULL, &rq_show_ctrl, 0 }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, RQ_SH_UN, "UNITQ", NULL, - NULL, &rq_show_ctrl, 0 }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, -1, "ALL", NULL, - NULL, &rq_show_ctrl, 0 }, - { MTAB_XTD | MTAB_VUN | MTAB_NMO, 0, "UNITQ", NULL, - NULL, &rq_show_unitq, 0 }, - { MTAB_XTD | MTAB_VUN, 0, "WRITE", NULL, - NULL, &rq_show_wlk, NULL }, - { MTAB_XTD | MTAB_VUN, RX50_DTYPE, NULL, "RX50", - &rq_set_type, NULL, NULL }, - { MTAB_XTD | MTAB_VUN, RX33_DTYPE, NULL, "RX33", - &rq_set_type, NULL, NULL }, - { MTAB_XTD | MTAB_VUN, RD31_DTYPE, NULL, "RD31", - &rq_set_type, NULL, NULL }, - { MTAB_XTD | MTAB_VUN, RD51_DTYPE, NULL, "RD51", - &rq_set_type, NULL, NULL }, - { MTAB_XTD | MTAB_VUN, RD52_DTYPE, NULL, "RD52", - &rq_set_type, NULL, NULL }, - { MTAB_XTD | MTAB_VUN, RD53_DTYPE, NULL, "RD53", - &rq_set_type, NULL, NULL }, - { MTAB_XTD | MTAB_VUN, RD54_DTYPE, NULL, "RD54", - &rq_set_type, NULL, NULL }, - { MTAB_XTD | MTAB_VUN, RA82_DTYPE, NULL, "RA82", - &rq_set_type, NULL, NULL }, - { MTAB_XTD | MTAB_VUN, RRD40_DTYPE, NULL, "RRD40", - &rq_set_type, NULL, NULL }, - { MTAB_XTD | MTAB_VUN, RRD40_DTYPE, NULL, "CDROM", - &rq_set_type, NULL, NULL }, - { MTAB_XTD | MTAB_VUN, RA72_DTYPE, NULL, "RA72", - &rq_set_type, NULL, NULL }, - { MTAB_XTD | MTAB_VUN, RA90_DTYPE, NULL, "RA90", - &rq_set_type, NULL, NULL }, - { MTAB_XTD | MTAB_VUN, RA92_DTYPE, NULL, "RA92", - &rq_set_type, NULL, NULL }, - { MTAB_XTD | MTAB_VUN, RA8U_DTYPE, NULL, "RAUSER", - &rq_set_type, NULL, NULL }, - { MTAB_XTD | MTAB_VUN, 0, "TYPE", NULL, - NULL, &rq_show_type, NULL }, -#if defined (VM_PDP11) - { MTAB_XTD|MTAB_VDV, 004, "ADDRESS", "ADDRESS", - &set_addr, &show_addr, NULL }, -#else - { MTAB_XTD|MTAB_VDV, 004, "ADDRESS", NULL, - NULL, &show_addr, NULL }, -#endif - { MTAB_XTD|MTAB_VDV, 0, "VECTOR", NULL, - NULL, &show_vec, NULL }, - { MTAB_XTD | MTAB_VDV, 0, NULL, "AUTOCONFIGURE", - &set_addr_flt, NULL, NULL }, - { 0 } }; - -DEVICE rq_dev = { - "RQ", rq_unit, rq_reg, rq_mod, - RQ_NUMDR + 2, DEV_RDX, 31, RQ_AINC, DEV_RDX, RQ_WID, - NULL, NULL, &rq_reset, - &rq_boot, &rq_attach, &rq_detach, - &rq_dib, DEV_FLTA | DEV_DISABLE | DEV_UBUS | DEV_QBUS }; - -/* RQB data structures - - rqb_dev RQB device descriptor - rqb_unit RQB unit list - rqb_reg RQB register list - rqb_mod RQB modifier list -*/ - -MSC rqb_ctx = { 1 }; - -DIB rqb_dib = { IOBA_RQB, IOLN_RQB, &rq_rd, &rq_wr, - 1, IVCL (RQ), 0, { &rq_inta } }; - -UNIT rqb_unit[] = { - { UDATA (&rq_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE+ - (RD54_DTYPE << UNIT_V_DTYPE), RQ_SIZE (RD54)) }, - { UDATA (&rq_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE+ - (RD54_DTYPE << UNIT_V_DTYPE), RQ_SIZE (RD54)) }, - { UDATA (&rq_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE+ - (RD54_DTYPE << UNIT_V_DTYPE), RQ_SIZE (RD54)) }, - { UDATA (&rq_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE+ - (RD54_DTYPE << UNIT_V_DTYPE), RQ_SIZE (RD54)) }, - { UDATA (&rq_tmrsvc, UNIT_DIS, 0) }, - { UDATA (&rq_quesvc, UNIT_DIS, 0) } }; - -REG rqb_reg[] = { - { GRDATA (SA, rqb_ctx.sa, DEV_RDX, 16, 0) }, - { GRDATA (SAW, rqb_ctx.saw, DEV_RDX, 16, 0) }, - { GRDATA (S1DAT, rqb_ctx.s1dat, DEV_RDX, 16, 0) }, - { GRDATA (COMM, rqb_ctx.comm, DEV_RDX, 22, 0) }, - { GRDATA (CQBA, rqb_ctx.cq.ba, DEV_RDX, 22, 0) }, - { GRDATA (CQLNT, rqb_ctx.cq.lnt, DEV_RDX, 8, 2), REG_NZ }, - { GRDATA (CQIDX, rqb_ctx.cq.idx, DEV_RDX, 8, 2) }, - { GRDATA (RQBA, rqb_ctx.rq.ba, DEV_RDX, 22, 0) }, - { GRDATA (RQLNT, rqb_ctx.rq.lnt, DEV_RDX, 8, 2), REG_NZ }, - { GRDATA (RQIDX, rqb_ctx.rq.idx, DEV_RDX, 8, 2) }, - { DRDATA (FREE, rqb_ctx.freq, 5) }, - { DRDATA (RESP, rqb_ctx.rspq, 5) }, - { DRDATA (PBSY, rqb_ctx.pbsy, 5) }, - { GRDATA (CFLGS, rqb_ctx.cflgs, DEV_RDX, 16, 0) }, - { GRDATA (CSTA, rqb_ctx.csta, DEV_RDX, 4, 0) }, - { GRDATA (PERR, rqb_ctx.perr, DEV_RDX, 9, 0) }, - { DRDATA (CRED, rqb_ctx.credits, 5) }, - { DRDATA (HAT, rqb_ctx.hat, 17) }, - { DRDATA (HTMO, rqb_ctx.htmo, 17) }, - { FLDATA (PRGI, rqb_ctx.prgi, 0), REG_HIDDEN }, - { FLDATA (PIP, rqb_ctx.pip, 0), REG_HIDDEN }, - { FLDATA (INT, rqb_ctx.irq, 0) }, - { BRDATA (PKTS, rqb_ctx.pak, DEV_RDX, 16, RQ_NPKTS * (RQ_PKT_SIZE_W + 1)) }, - { URDATA (CPKT, rqb_unit[0].cpkt, 10, 5, 0, RQ_NUMDR, 0) }, - { URDATA (PKTQ, rqb_unit[0].pktq, 10, 5, 0, RQ_NUMDR, 0) }, - { URDATA (UFLG, rqb_unit[0].uf, DEV_RDX, 16, 0, RQ_NUMDR, 0) }, - { URDATA (CAPAC, rqb_unit[0].capac, 10, 31, 0, RQ_NUMDR, PV_LEFT | REG_HRO) }, - { GRDATA (DEVADDR, rqb_dib.ba, DEV_RDX, 32, 0), REG_HRO }, - { GRDATA (DEVVEC, rqb_dib.vec, DEV_RDX, 16, 0), REG_HRO }, - { NULL } }; - -DEVICE rqb_dev = { - "RQB", rqb_unit, rqb_reg, rq_mod, - RQ_NUMDR + 2, DEV_RDX, 31, RQ_AINC, DEV_RDX, RQ_WID, - NULL, NULL, &rq_reset, - &rq_boot, &rq_attach, &rq_detach, - &rqb_dib, DEV_FLTA | DEV_DISABLE | DEV_DIS | DEV_UBUS | DEV_QBUS }; - -/* RQC data structures - - rqc_dev RQC device descriptor - rqc_unit RQC unit list - rqc_reg RQC register list - rqc_mod RQC modifier list -*/ - -MSC rqc_ctx = { 2 }; - -DIB rqc_dib = { IOBA_RQC, IOLN_RQC, &rq_rd, &rq_wr, - 1, IVCL (RQ), 0, { &rq_inta } }; - -UNIT rqc_unit[] = { - { UDATA (&rq_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE+ - (RD54_DTYPE << UNIT_V_DTYPE), RQ_SIZE (RD54)) }, - { UDATA (&rq_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE+ - (RD54_DTYPE << UNIT_V_DTYPE), RQ_SIZE (RD54)) }, - { UDATA (&rq_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE+ - (RD54_DTYPE << UNIT_V_DTYPE), RQ_SIZE (RD54)) }, - { UDATA (&rq_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE+ - (RD54_DTYPE << UNIT_V_DTYPE), RQ_SIZE (RD54)) }, - { UDATA (&rq_tmrsvc, UNIT_DIS, 0) }, - { UDATA (&rq_quesvc, UNIT_DIS, 0) } }; - -REG rqc_reg[] = { - { GRDATA (SA, rqc_ctx.sa, DEV_RDX, 16, 0) }, - { GRDATA (SAW, rqc_ctx.saw, DEV_RDX, 16, 0) }, - { GRDATA (S1DAT, rqc_ctx.s1dat, DEV_RDX, 16, 0) }, - { GRDATA (COMM, rqc_ctx.comm, DEV_RDX, 22, 0) }, - { GRDATA (CQBA, rqc_ctx.cq.ba, DEV_RDX, 22, 0) }, - { GRDATA (CQLNT, rqc_ctx.cq.lnt, DEV_RDX, 8, 2), REG_NZ }, - { GRDATA (CQIDX, rqc_ctx.cq.idx, DEV_RDX, 8, 2) }, - { GRDATA (RQBA, rqc_ctx.rq.ba, DEV_RDX, 22, 0) }, - { GRDATA (RQLNT, rqc_ctx.rq.lnt, DEV_RDX, 8, 2), REG_NZ }, - { GRDATA (RQIDX, rqc_ctx.rq.idx, DEV_RDX, 8, 2) }, - { DRDATA (FREE, rqc_ctx.freq, 5) }, - { DRDATA (RESP, rqc_ctx.rspq, 5) }, - { DRDATA (PBSY, rqc_ctx.pbsy, 5) }, - { GRDATA (CFLGS, rqc_ctx.cflgs, DEV_RDX, 16, 0) }, - { GRDATA (CSTA, rqc_ctx.csta, DEV_RDX, 4, 0) }, - { GRDATA (PERR, rqc_ctx.perr, DEV_RDX, 9, 0) }, - { DRDATA (CRED, rqc_ctx.credits, 5) }, - { DRDATA (HAT, rqc_ctx.hat, 17) }, - { DRDATA (HTMO, rqc_ctx.htmo, 17) }, - { FLDATA (PRGI, rqc_ctx.prgi, 0), REG_HIDDEN }, - { FLDATA (PIP, rqc_ctx.pip, 0), REG_HIDDEN }, - { FLDATA (INT, rqc_ctx.irq, 0) }, - { BRDATA (PKTS, rqc_ctx.pak, DEV_RDX, 16, RQ_NPKTS * (RQ_PKT_SIZE_W + 1)) }, - { URDATA (CPKT, rqc_unit[0].cpkt, 10, 5, 0, RQ_NUMDR, 0) }, - { URDATA (PKTQ, rqc_unit[0].pktq, 10, 5, 0, RQ_NUMDR, 0) }, - { URDATA (UFLG, rqc_unit[0].uf, DEV_RDX, 16, 0, RQ_NUMDR, 0) }, - { URDATA (CAPAC, rqc_unit[0].capac, 10, 31, 0, RQ_NUMDR, PV_LEFT | REG_HRO) }, - { GRDATA (DEVADDR, rqc_dib.ba, DEV_RDX, 32, 0), REG_HRO }, - { GRDATA (DEVVEC, rqc_dib.vec, DEV_RDX, 16, 0), REG_HRO }, - { NULL } }; - -DEVICE rqc_dev = { - "RQC", rqc_unit, rqc_reg, rq_mod, - RQ_NUMDR + 2, DEV_RDX, 31, RQ_AINC, DEV_RDX, RQ_WID, - NULL, NULL, &rq_reset, - &rq_boot, &rq_attach, &rq_detach, - &rqc_dib, DEV_FLTA | DEV_DISABLE | DEV_DIS | DEV_UBUS | DEV_QBUS }; - -/* RQD data structures - - rqd_dev RQ device descriptor - rqd_unit RQ unit list - rqd_reg RQ register list - rqd_mod RQ modifier list -*/ - -MSC rqd_ctx = { 3 }; - -DIB rqd_dib = { IOBA_RQD, IOLN_RQD, &rq_rd, &rq_wr, - 1, IVCL (RQ), 0, { &rq_inta } }; - -UNIT rqd_unit[] = { - { UDATA (&rq_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE+ - (RD54_DTYPE << UNIT_V_DTYPE), RQ_SIZE (RD54)) }, - { UDATA (&rq_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE+ - (RD54_DTYPE << UNIT_V_DTYPE), RQ_SIZE (RD54)) }, - { UDATA (&rq_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE+ - (RD54_DTYPE << UNIT_V_DTYPE), RQ_SIZE (RD54)) }, - { UDATA (&rq_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE+ - (RD54_DTYPE << UNIT_V_DTYPE), RQ_SIZE (RD54)) }, - { UDATA (&rq_tmrsvc, UNIT_DIS, 0) }, - { UDATA (&rq_quesvc, UNIT_DIS, 0) } }; - -REG rqd_reg[] = { - { GRDATA (SA, rqd_ctx.sa, DEV_RDX, 16, 0) }, - { GRDATA (SAW, rqd_ctx.saw, DEV_RDX, 16, 0) }, - { GRDATA (S1DAT, rqd_ctx.s1dat, DEV_RDX, 16, 0) }, - { GRDATA (COMM, rqd_ctx.comm, DEV_RDX, 22, 0) }, - { GRDATA (CQBA, rqd_ctx.cq.ba, DEV_RDX, 22, 0) }, - { GRDATA (CQLNT, rqd_ctx.cq.lnt, DEV_RDX, 8, 2), REG_NZ }, - { GRDATA (CQIDX, rqd_ctx.cq.idx, DEV_RDX, 8, 2) }, - { GRDATA (RQBA, rqd_ctx.rq.ba, DEV_RDX, 22, 0) }, - { GRDATA (RQLNT, rqd_ctx.rq.lnt, DEV_RDX, 8, 2), REG_NZ }, - { GRDATA (RQIDX, rqd_ctx.rq.idx, DEV_RDX, 8, 2) }, - { DRDATA (FREE, rqd_ctx.freq, 5) }, - { DRDATA (RESP, rqd_ctx.rspq, 5) }, - { DRDATA (PBSY, rqd_ctx.pbsy, 5) }, - { GRDATA (CFLGS, rqd_ctx.cflgs, DEV_RDX, 16, 0) }, - { GRDATA (CSTA, rqd_ctx.csta, DEV_RDX, 4, 0) }, - { GRDATA (PERR, rqd_ctx.perr, DEV_RDX, 9, 0) }, - { DRDATA (CRED, rqd_ctx.credits, 5) }, - { DRDATA (HAT, rqd_ctx.hat, 17) }, - { DRDATA (HTMO, rqd_ctx.htmo, 17) }, - { FLDATA (PRGI, rqd_ctx.prgi, 0), REG_HIDDEN }, - { FLDATA (PIP, rqd_ctx.pip, 0), REG_HIDDEN }, - { FLDATA (INT, rqd_ctx.irq, 0) }, - { BRDATA (PKTS, rqd_ctx.pak, DEV_RDX, 16, RQ_NPKTS * (RQ_PKT_SIZE_W + 1)) }, - { URDATA (CPKT, rqd_unit[0].cpkt, 10, 5, 0, RQ_NUMDR, 0) }, - { URDATA (PKTQ, rqd_unit[0].pktq, 10, 5, 0, RQ_NUMDR, 0) }, - { URDATA (UFLG, rqd_unit[0].uf, DEV_RDX, 16, 0, RQ_NUMDR, 0) }, - { URDATA (CAPAC, rqd_unit[0].capac, 10, 31, 0, RQ_NUMDR, PV_LEFT | REG_HRO) }, - { GRDATA (DEVADDR, rqd_dib.ba, DEV_RDX, 32, 0), REG_HRO }, - { GRDATA (DEVVEC, rqd_dib.vec, DEV_RDX, 16, 0), REG_HRO }, - { NULL } }; - -DEVICE rqd_dev = { - "RQD", rqd_unit, rqd_reg, rq_mod, - RQ_NUMDR + 2, DEV_RDX, 31, RQ_AINC, DEV_RDX, RQ_WID, - NULL, NULL, &rq_reset, - &rq_boot, &rq_attach, &rq_detach, - &rqd_dib, DEV_FLTA | DEV_DISABLE | DEV_DIS | DEV_UBUS | DEV_QBUS }; - -static DEVICE *rq_devmap[RQ_NUMCT] = { - &rq_dev, &rqb_dev, &rqc_dev, &rqd_dev }; - -static MSC *rq_ctxmap[RQ_NUMCT] = { - &rq_ctx, &rqb_ctx, &rqc_ctx, &rqd_ctx }; - -/* I/O dispatch routine, I/O addresses 17772150 - 17772152 - - base + 0 IP read/write - base + 2 SA read/write -*/ - -t_stat rq_rd (int32 *data, int32 PA, int32 access) -{ -int32 cidx = rq_map_pa ((uint32) PA); -MSC *cp = rq_ctxmap[cidx]; -DEVICE *dptr = rq_devmap[cidx]; - -if (cidx < 0) return SCPE_IERR; -switch ((PA >> 1) & 01) { /* decode PA<1> */ -case 0: /* IP */ - *data = 0; /* reads zero */ - if (cp->csta == CST_S3_PPB) rq_step4 (cp); /* waiting for poll? */ - else if (cp->csta == CST_UP) { /* if up */ - cp->pip = 1; /* poll host */ - sim_activate (dptr->units + RQ_QUEUE, rq_qtime); } - break; -case 1: /* SA */ - *data = cp->sa; - break; } -return SCPE_OK; -} - -t_stat rq_wr (int32 data, int32 PA, int32 access) -{ -int32 cidx = rq_map_pa ((uint32) PA); -MSC *cp = rq_ctxmap[cidx]; -DEVICE *dptr = rq_devmap[cidx]; - -if (cidx < 0) return SCPE_IERR; -switch ((PA >> 1) & 01) { /* decode PA<1> */ -case 0: /* IP */ - rq_reset (rq_devmap[cidx]); /* init device */ - if (DBG_LOG (LOG_RQ)) fprintf (sim_log, - ">>RQ%c: initialization started\n", 'A' + cp->cnum); - break; -case 1: /* SA */ - cp->saw = data; - if (cp->csta < CST_S4) /* stages 1-3 */ - sim_activate (dptr->units + RQ_QUEUE, rq_itime); - else if (cp->csta == CST_S4) /* stage 4 (fast) */ - sim_activate (dptr->units + RQ_QUEUE, rq_itime4); - break; } -return SCPE_OK; -} - -/* Map physical address to device context */ - -int32 rq_map_pa (uint32 pa) -{ -int32 i; -DEVICE *dptr; -DIB *dibp; - -for (i = 0; i < RQ_NUMCT; i++) { /* loop thru ctrls */ - dptr = rq_devmap[i]; /* get device */ - dibp = (DIB *) dptr->ctxt; /* get DIB */ - if ((pa >= dibp->ba) && /* in range? */ - (pa < (dibp->ba + dibp->lnt))) - return i; } /* return ctrl idx */ -return -1; -} - -/* Transition to step 4 - init communications region */ - -t_bool rq_step4 (MSC *cp) -{ -int32 i, lnt; -uint32 base; -uint16 zero[SA_COMM_MAX >> 1]; - -cp->rq.ioff = SA_COMM_RI; /* set intr offset */ -cp->rq.ba = cp->comm; /* set rsp q base */ -cp->rq.lnt = SA_S1H_RQ (cp->s1dat) << 2; /* get resp q len */ -cp->cq.ioff = SA_COMM_CI; /* set intr offset */ -cp->cq.ba = cp->comm + cp->rq.lnt; /* set cmd q base */ -cp->cq.lnt = SA_S1H_CQ (cp->s1dat) << 2; /* get cmd q len */ -cp->cq.idx = cp->rq.idx = 0; /* clear q idx's */ -if (cp->prgi) base = cp->comm + SA_COMM_QQ; -else base = cp->comm + SA_COMM_CI; -lnt = cp->comm + cp->cq.lnt + cp->rq.lnt - base; /* comm lnt */ -if (lnt > SA_COMM_MAX) lnt = SA_COMM_MAX; /* paranoia */ -for (i = 0; i < (lnt >> 1); i++) zero[i] = 0; /* clr buffer */ -if (Map_WriteW (base, lnt, zero, MAP)) /* zero comm area */ - return rq_fatal (cp, PE_QWE); /* error? */ -cp->sa = SA_S4 | (RQ_UQPM << SA_S4C_V_MOD) | /* send step 4 */ - (RQ_SVER << SA_S4C_V_VER); -cp->csta = CST_S4; /* set step 4 */ -rq_init_int (cp); /* poke host */ -return OK; -} - -/* Queue service - invoked when any of the queues (host queue, unit - queues, response queue) require servicing. Also invoked during - initialization to provide some delay to the next step. - - Process at most one item off each unit queue - If the unit queues were empty, process at most one item off the host queue - Process at most one item off the response queue - - If all queues are idle, terminate thread -*/ - -t_stat rq_quesvc (UNIT *uptr) -{ -int32 i, cnid; -int32 pkt = 0; -UNIT *nuptr; -MSC *cp = rq_ctxmap[uptr->cnum]; -DEVICE *dptr = rq_devmap[uptr->cnum]; -DIB *dibp = (DIB *) dptr->ctxt; - -if (cp->csta < CST_UP) { /* still init? */ - switch (cp->csta) { /* controller state? */ - case CST_S1: /* need S1 reply */ - if (cp->saw & SA_S1H_VL) { /* valid? */ - if (cp->saw & SA_S1H_WR) { /* wrap? */ - cp->sa = cp->saw; /* echo data */ - cp->csta = CST_S1_WR; } /* endless loop */ - else { - cp->s1dat = cp->saw; /* save data */ - dibp->vec = (cp->s1dat & SA_S1H_VEC) << 2; /* get vector */ - if (dibp->vec) dibp->vec = dibp->vec + VEC_Q; /* if nz, bias */ - cp->sa = SA_S2 | SA_S2C_PT | SA_S2C_EC (cp->s1dat); - cp->csta = CST_S2; /* now in step 2 */ - rq_init_int (cp); } /* intr if req */ - } /* end if valid */ - break; - case CST_S1_WR: /* wrap mode */ - cp->sa = cp->saw; /* echo data */ - break; - case CST_S2: /* need S2 reply */ - cp->comm = cp->saw & SA_S2H_CLO; /* get low addr */ - cp->prgi = cp->saw & SA_S2H_PI; /* get purge int */ - cp->sa = SA_S3 | SA_S3C_EC (cp->s1dat); - cp->csta = CST_S3; /* now in step 3 */ - rq_init_int (cp); /* intr if req */ - break; - case CST_S3: /* need S3 reply */ - cp->comm = ((cp->saw & SA_S3H_CHI) << 16) | cp->comm; - if (cp->saw & SA_S3H_PP) { /* purge/poll test? */ - cp->sa = 0; /* put 0 */ - cp->csta = CST_S3_PPA; } /* wait for 0 write */ - else rq_step4 (cp); /* send step 4 */ - break; - case CST_S3_PPA: /* need purge test */ - if (cp->saw) rq_fatal (cp, PE_PPF); /* data not zero? */ - else cp->csta = CST_S3_PPB; /* wait for poll */ - break; - case CST_S4: /* need S4 reply */ - if (cp->saw & SA_S4H_GO) { /* go set? */ - if (DBG_LOG (LOG_RQ)) fprintf (sim_log, - ">>RQ%c: initialization complete\n", 'A' + cp->cnum); - cp->csta = CST_UP; /* we're up */ - cp->sa = 0; /* clear SA */ - sim_activate (dptr->units + RQ_TIMER, tmr_poll * clk_tps); - if ((cp->saw & SA_S4H_LF) && cp->perr) rq_plf (cp, cp->perr); - cp->perr = 0; } - break; } /* end switch */ - return SCPE_OK; } /* end if */ - -for (i = 0; i < RQ_NUMDR; i++) { /* chk unit q's */ - nuptr = dptr->units + i; /* ptr to unit */ - if (nuptr->cpkt || (nuptr->pktq == 0)) continue; - pkt = rq_deqh (cp, &nuptr->pktq); /* get top of q */ - if (!rq_mscp (cp, pkt, FALSE)) return SCPE_OK; } /* process */ -if ((pkt == 0) && cp->pip) { /* polling? */ - if (!rq_getpkt (cp, &pkt)) return SCPE_OK; /* get host pkt */ - if (pkt) { /* got one? */ - if (DBG_LOG (LOG_RQ)) { - fprintf (sim_log, ">>RQ%c: cmd=%04X, mod=%04X, unit=%d, ", - 'A' + cp->cnum, cp->pak[pkt].d[CMD_OPC], - cp->pak[pkt].d[CMD_MOD], cp->pak[pkt].d[CMD_UN]); - fprintf (sim_log, "bc=%04X%04X, ma=%04X%04X, lbn=%04X%04X\n", - cp->pak[pkt].d[RW_BCH], cp->pak[pkt].d[RW_BCL], - cp->pak[pkt].d[RW_BAH], cp->pak[pkt].d[RW_BAL], - cp->pak[pkt].d[RW_LBNH], cp->pak[pkt].d[RW_LBNL]); } - if (GETP (pkt, UQ_HCTC, TYP) != UQ_TYP_SEQ) /* seq packet? */ - return rq_fatal (cp, PE_PIE); /* no, term thread */ - cnid = GETP (pkt, UQ_HCTC, CID); /* get conn ID */ - if (cnid == UQ_CID_MSCP) { /* MSCP packet? */ - if (!rq_mscp (cp, pkt, TRUE)) return SCPE_OK; } /* proc, q non-seq */ - else if (cnid == UQ_CID_DUP) { /* DUP packet? */ - rq_putr (cp, pkt, OP_END, 0, ST_CMD | I_OPCD, RSP_LNT, UQ_TYP_SEQ); - if (!rq_putpkt (cp, pkt, TRUE)) return SCPE_OK; } /* ill cmd */ - else return rq_fatal (cp, PE_ICI); /* no, term thread */ - } /* end if pkt */ - else cp->pip = 0; /* discontinue poll */ - } /* end if pip */ -if (cp->rspq) { /* resp q? */ - pkt = rq_deqh (cp, &cp->rspq); /* get top of q */ - if (!rq_putpkt (cp, pkt, FALSE)) return SCPE_OK; /* send to hst */ - } /* end if resp q */ -if (pkt) sim_activate (uptr, rq_qtime); /* more to do? */ -return SCPE_OK; /* done */ -} - -/* Clock service (roughly once per second) */ - -t_stat rq_tmrsvc (UNIT *uptr) -{ -int32 i; -UNIT *nuptr; -MSC *cp = rq_ctxmap[uptr->cnum]; -DEVICE *dptr = rq_devmap[uptr->cnum]; - -sim_activate (uptr, tmr_poll * clk_tps); /* reactivate */ -for (i = 0; i < RQ_NUMDR; i++) { /* poll */ - nuptr = dptr->units + i; - if ((nuptr->flags & UNIT_ATP) && /* ATN pending? */ - (nuptr->flags & UNIT_ATT) && /* still online? */ - (cp->cflgs & CF_ATN)) { /* wanted? */ - if (!rq_una (cp, i)) return SCPE_OK; } - nuptr->flags = nuptr->flags & ~UNIT_ATP; } -if ((cp->hat > 0) && (--cp->hat == 0)) /* host timeout? */ - rq_fatal (cp, PE_HAT); /* fatal err */ -return SCPE_OK; -} - -/* MSCP packet handling */ - -t_bool rq_mscp (MSC *cp, int32 pkt, t_bool q) -{ -uint32 sts, cmd = GETP (pkt, CMD_OPC, OPC); - -switch (cmd) { -case OP_ABO: /* abort */ - return rq_abo (cp, pkt, q); -case OP_AVL: /* avail */ - return rq_avl (cp, pkt, q); -case OP_FMT: /* format */ - return rq_fmt (cp, pkt, q); -case OP_GCS: /* get cmd status */ - return rq_gcs (cp, pkt, q); -case OP_GUS: /* get unit status */ - return rq_gus (cp, pkt, q); -case OP_ONL: /* online */ - return rq_onl (cp, pkt, q); -case OP_SCC: /* set ctrl char */ - return rq_scc (cp, pkt, q); -case OP_SUC: /* set unit char */ - return rq_suc (cp, pkt, q); -case OP_ACC: /* access */ -case OP_CMP: /* compare */ -case OP_ERS: /* erase */ -case OP_RD: /* read */ -case OP_WR: /* write */ - return rq_rw (cp, pkt, q); -case OP_CCD: /* nops */ -case OP_DAP: -case OP_FLU: - cmd = cmd | OP_END; /* set end flag */ - sts = ST_SUC; /* success */ - break; -default: - cmd = OP_END; /* set end op */ - sts = ST_CMD | I_OPCD; /* ill op */ - break; } -rq_putr (cp, pkt, cmd, 0, sts, RSP_LNT, UQ_TYP_SEQ); -return rq_putpkt (cp, pkt, TRUE); -} - -/* Abort a command - 1st parameter is ref # of cmd to abort */ - -t_bool rq_abo (MSC *cp, int32 pkt, t_bool q) -{ -uint32 lu = cp->pak[pkt].d[CMD_UN]; /* unit # */ -uint32 cmd = GETP (pkt, CMD_OPC, OPC); /* opcode */ -uint32 ref = GETP32 (pkt, ABO_REFL); /* cmd ref # */ -int32 tpkt, prv; -UNIT *uptr; -DEVICE *dptr = rq_devmap[cp->cnum]; - -tpkt = 0; /* set no mtch */ -if (uptr = rq_getucb (cp, lu)) { /* get unit */ - if (uptr->cpkt && /* curr pkt? */ - (GETP32 (uptr->cpkt, CMD_REFL) == ref)) { /* match ref? */ - tpkt = uptr->cpkt; /* save match */ - uptr->cpkt = 0; /* gonzo */ - sim_cancel (uptr); /* cancel unit */ - sim_activate (dptr->units + RQ_QUEUE, rq_qtime); } - else if (uptr->pktq && /* head of q? */ - (GETP32 (uptr->pktq, CMD_REFL) == ref)) { /* match ref? */ - tpkt = uptr->pktq; /* save match */ - uptr->pktq = cp->pak[tpkt].link; } /* unlink */ - else if (prv = uptr->pktq) { /* srch pkt q */ - while (tpkt = cp->pak[prv].link) { /* walk list */ - if (GETP32 (tpkt, RSP_REFL) == ref) { /* match? unlink */ - cp->pak[prv].link = cp->pak[tpkt].link; - break; } } } - if (tpkt) { /* found target? */ - uint32 tcmd = GETP (tpkt, CMD_OPC, OPC); /* get opcode */ - rq_putr (cp, tpkt, tcmd | OP_END, 0, ST_ABO, RSP_LNT, UQ_TYP_SEQ); - if (!rq_putpkt (cp, tpkt, TRUE)) return ERR; } - } /* end if unit */ -rq_putr (cp, pkt, cmd | OP_END, 0, ST_SUC, ABO_LNT, UQ_TYP_SEQ); -return rq_putpkt (cp, pkt, TRUE); -} - -/* Unit available - set unit status to available - defer if q'd cmds */ - -t_bool rq_avl (MSC *cp, int32 pkt, t_bool q) -{ -uint32 lu = cp->pak[pkt].d[CMD_UN]; /* unit # */ -uint32 cmd = GETP (pkt, CMD_OPC, OPC); /* opcode */ -uint32 sts; -UNIT *uptr; - -if (uptr = rq_getucb (cp, lu)) { /* unit exist? */ - if (q && uptr->cpkt) { /* need to queue? */ - rq_enqt (cp, &uptr->pktq, pkt); /* do later */ - return OK; } - uptr->flags = uptr->flags & ~UNIT_ONL; /* not online */ - uptr->uf = 0; /* clr flags */ - sts = ST_SUC; } /* success */ -else sts = ST_OFL; /* offline */ -rq_putr (cp, pkt, cmd | OP_END, 0, sts, AVL_LNT, UQ_TYP_SEQ); -return rq_putpkt (cp, pkt, TRUE); -} - -/* Get command status - only interested in active xfr cmd */ - -t_bool rq_gcs (MSC *cp, int32 pkt, t_bool q) -{ -uint32 lu = cp->pak[pkt].d[CMD_UN]; /* unit # */ -uint32 cmd = GETP (pkt, CMD_OPC, OPC); /* opcode */ -uint32 ref = GETP32 (pkt, GCS_REFL); /* ref # */ -int32 tpkt; -UNIT *uptr; - -if ((uptr = rq_getucb (cp, lu)) && /* valid lu? */ - (tpkt = uptr->cpkt) && /* queued pkt? */ - (GETP32 (tpkt, CMD_REFL) == ref) && /* match ref? */ - (GETP (tpkt, CMD_OPC, OPC) >= OP_ACC)) { /* rd/wr cmd? */ - cp->pak[pkt].d[GCS_STSL] = cp->pak[tpkt].d[RW_WBCL]; - cp->pak[pkt].d[GCS_STSH] = cp->pak[tpkt].d[RW_WBCH]; } -else { - cp->pak[pkt].d[GCS_STSL] = 0; /* return 0 */ - cp->pak[pkt].d[GCS_STSH] = 0; } -rq_putr (cp, pkt, cmd | OP_END, 0, ST_SUC, GCS_LNT, UQ_TYP_SEQ); -return rq_putpkt (cp, pkt, TRUE); -} - -/* Get unit status */ - -t_bool rq_gus (MSC *cp, int32 pkt, t_bool q) -{ -uint32 lu = cp->pak[pkt].d[CMD_UN]; /* unit # */ -uint32 cmd = GETP (pkt, CMD_OPC, OPC); /* opcode */ -uint32 dtyp, sts, rbpar; -UNIT *uptr; - -if (cp->pak[pkt].d[CMD_MOD] & MD_NXU) { /* next unit? */ - if (lu >= (cp->ubase + RQ_NUMDR)) { /* end of range? */ - lu = 0; /* reset to 0 */ - cp->pak[pkt].d[RSP_UN] = lu; } } -if (uptr = rq_getucb (cp, lu)) { /* unit exist? */ - if ((uptr->flags & UNIT_ATT) == 0) /* not attached? */ - sts = ST_OFL | SB_OFL_NV; /* offl no vol */ - else if (uptr->flags & UNIT_ONL) sts = ST_SUC; /* online */ - else sts = ST_AVL; /* avail */ - rq_putr_unit (cp, pkt, uptr, lu, FALSE); /* fill unit fields */ - dtyp = GET_DTYPE (uptr->flags); /* get drive type */ - if (drv_tab[dtyp].rcts) rbpar = 1; /* ctrl bad blk? */ - else rbpar = 0; /* fill geom, bblk */ - cp->pak[pkt].d[GUS_TRK] = drv_tab[dtyp].sect; - cp->pak[pkt].d[GUS_GRP] = drv_tab[dtyp].tpg; - cp->pak[pkt].d[GUS_CYL] = drv_tab[dtyp].gpc; - cp->pak[pkt].d[GUS_UVER] = 0; - cp->pak[pkt].d[GUS_RCTS] = drv_tab[dtyp].rcts; - cp->pak[pkt].d[GUS_RBSC] = - (rbpar << GUS_RB_V_RBNS) | (rbpar << GUS_RB_V_RCTC); } -else sts = ST_OFL; /* offline */ -cp->pak[pkt].d[GUS_SHUN] = lu; /* shadowing */ -cp->pak[pkt].d[GUS_SHST] = 0; -rq_putr (cp, pkt, cmd | OP_END, 0, sts, GUS_LNT_D, UQ_TYP_SEQ); -return rq_putpkt (cp, pkt, TRUE); -} - -/* Unit online - defer if q'd commands */ - -t_bool rq_onl (MSC *cp, int32 pkt, t_bool q) -{ -uint32 lu = cp->pak[pkt].d[CMD_UN]; /* unit # */ -uint32 cmd = GETP (pkt, CMD_OPC, OPC); /* opcode */ -uint32 sts; -UNIT *uptr; - -if (uptr = rq_getucb (cp, lu)) { /* unit exist? */ - if (q && uptr->cpkt) { /* need to queue? */ - rq_enqt (cp, &uptr->pktq, pkt); /* do later */ - return OK; } - if ((uptr->flags & UNIT_ATT) == 0) /* not attached? */ - sts = ST_OFL | SB_OFL_NV; /* offl no vol */ - else if (uptr->flags & UNIT_ONL) /* already online? */ - sts = ST_SUC | SB_SUC_ON; - else { /* mark online */ - sts = ST_SUC; - uptr->flags = uptr->flags | UNIT_ONL; - rq_setf_unit (cp, pkt, uptr); } /* hack flags */ - rq_putr_unit (cp, pkt, uptr, lu, TRUE); } /* set fields */ -else sts = ST_OFL; /* offline */ -cp->pak[pkt].d[ONL_SHUN] = lu; /* shadowing */ -cp->pak[pkt].d[ONL_SHST] = 0; -rq_putr (cp, pkt, cmd | OP_END, 0, sts, ONL_LNT, UQ_TYP_SEQ); -return rq_putpkt (cp, pkt, TRUE); -} - -/* Set controller characteristics */ - -t_bool rq_scc (MSC *cp, int32 pkt, t_bool q) -{ -int32 sts, cmd; - -if (cp->pak[pkt].d[SCC_MSV]) { /* MSCP ver = 0? */ - sts = ST_CMD | I_VRSN; /* no, lose */ - cmd = 0; } -else { sts = ST_SUC; /* success */ - cmd = GETP (pkt, CMD_OPC, OPC); /* get opcode */ - cp->cflgs = (cp->cflgs & CF_RPL) | /* hack ctrl flgs */ - cp->pak[pkt].d[SCC_CFL]; - if (cp->htmo = cp->pak[pkt].d[SCC_TMO]) /* set timeout */ - cp->htmo = cp->htmo + 2; /* if nz, round up */ - cp->pak[pkt].d[SCC_CFL] = cp->cflgs; /* return flags */ - cp->pak[pkt].d[SCC_TMO] = RQ_DCTMO; /* ctrl timeout */ - cp->pak[pkt].d[SCC_VER] = (RQ_HVER << SCC_VER_V_HVER) | - (RQ_SVER << SCC_VER_V_SVER); - cp->pak[pkt].d[SCC_CIDA] = 0; /* ctrl ID */ - cp->pak[pkt].d[SCC_CIDB] = 0; - cp->pak[pkt].d[SCC_CIDC] = 0; - cp->pak[pkt].d[SCC_CIDD] = (RQ_CLASS << SCC_CIDD_V_CLS) | - (RQ_MODEL << SCC_CIDD_V_MOD); - cp->pak[pkt].d[SCC_MBCL] = 0; /* max bc */ - cp->pak[pkt].d[SCC_MBCH] = 0; } -rq_putr (cp, pkt, cmd | OP_END, 0, sts, SCC_LNT, UQ_TYP_SEQ); -return rq_putpkt (cp, pkt, TRUE); -} - -/* Set unit characteristics - defer if q'd commands */ - -t_bool rq_suc (MSC *cp, int32 pkt, t_bool q) -{ -uint32 lu = cp->pak[pkt].d[CMD_UN]; /* unit # */ -uint32 cmd = GETP (pkt, CMD_OPC, OPC); /* opcode */ -uint32 sts; -UNIT *uptr; - -if (uptr = rq_getucb (cp, lu)) { /* unit exist? */ - if (q && uptr->cpkt) { /* need to queue? */ - rq_enqt (cp, &uptr->pktq, pkt); /* do later */ - return OK; } - if ((uptr->flags & UNIT_ATT) == 0) /* not attached? */ - sts = ST_OFL | SB_OFL_NV; /* offl no vol */ - else { /* avail or onl */ - sts = ST_SUC; - rq_setf_unit (cp, pkt, uptr); } /* hack flags */ - rq_putr_unit (cp, pkt, uptr, lu, TRUE); } /* set fields */ -else sts = ST_OFL; /* offline */ -cp->pak[pkt].d[ONL_SHUN] = lu; /* shadowing */ -cp->pak[pkt].d[ONL_SHST] = 0; -rq_putr (cp, pkt, cmd | OP_END, 0, sts, SUC_LNT, UQ_TYP_SEQ); -return rq_putpkt (cp, pkt, TRUE); -} - -/* Format command - floppies only */ - -t_bool rq_fmt (MSC *cp, int32 pkt, t_bool q) -{ -uint32 lu = cp->pak[pkt].d[CMD_UN]; /* unit # */ -uint32 cmd = GETP (pkt, CMD_OPC, OPC); /* opcode */ -uint32 sts; -UNIT *uptr; - -if (uptr = rq_getucb (cp, lu)) { /* unit exist? */ - if (q && uptr->cpkt) { /* need to queue? */ - rq_enqt (cp, &uptr->pktq, pkt); /* do later */ - return OK; } - if (GET_DTYPE (uptr->flags) != RX33_DTYPE) /* RX33? */ - sts = ST_CMD | I_OPCD; /* no, err */ - else if ((cp->pak[pkt].d[FMT_IH] & 0100000) == 0) /* magic bit set? */ - sts = ST_CMD | I_FMTI; /* no, err */ - else if ((uptr->flags & UNIT_ATT) == 0) /* offline? */ - sts = ST_OFL | SB_OFL_NV; /* no vol */ - else if (uptr->flags & UNIT_ONL) { /* online? */ - uptr->flags = uptr->flags & ~UNIT_ONL; - uptr->uf = 0; /* clear flags */ - sts = ST_AVL | SB_AVL_INU; } /* avail, in use */ - else if (RQ_WPH (uptr)) /* write prot? */ - sts = ST_WPR | SB_WPR_HW; /* can't fmt */ - else sts = ST_SUC; /*** for now ***/ - } -else sts = ST_OFL; /* offline */ -rq_putr (cp, pkt, cmd | OP_END, 0, sts, FMT_LNT, UQ_TYP_SEQ); -return rq_putpkt (cp, pkt, TRUE); -} - -/* Data transfer commands */ - -t_bool rq_rw (MSC *cp, int32 pkt, t_bool q) -{ -uint32 lu = cp->pak[pkt].d[CMD_UN]; /* unit # */ -uint32 cmd = GETP (pkt, CMD_OPC, OPC); /* opcode */ -uint32 sts; -UNIT *uptr; - -if (uptr = rq_getucb (cp, lu)) { /* unit exist? */ - if (q && uptr->cpkt) { /* need to queue? */ - rq_enqt (cp, &uptr->pktq, pkt); /* do later */ - return OK; } - sts = rq_rw_valid (cp, pkt, uptr, cmd); /* validity checks */ - if (sts == 0) { /* ok? */ - uptr->cpkt = pkt; /* op in progress */ - cp->pak[pkt].d[RW_WBAL] = cp->pak[pkt].d[RW_BAL]; - cp->pak[pkt].d[RW_WBAH] = cp->pak[pkt].d[RW_BAH]; - cp->pak[pkt].d[RW_WBCL] = cp->pak[pkt].d[RW_BCL]; - cp->pak[pkt].d[RW_WBCH] = cp->pak[pkt].d[RW_BCH]; - cp->pak[pkt].d[RW_WBLL] = cp->pak[pkt].d[RW_LBNL]; - cp->pak[pkt].d[RW_WBLH] = cp->pak[pkt].d[RW_LBNH]; - sim_activate (uptr, rq_xtime); /* activate */ - 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_D, UQ_TYP_SEQ); -return rq_putpkt (cp, pkt, TRUE); -} - -/* Validity checks */ - -int32 rq_rw_valid (MSC *cp, int32 pkt, UNIT *uptr, uint32 cmd) -{ -uint32 dtyp = GET_DTYPE (uptr->flags); /* get drive type */ -uint32 lbn = GETP32 (pkt, RW_LBNL); /* get lbn */ -uint32 bc = GETP32 (pkt, RW_BCL); /* get byte cnt */ -uint32 maxlbn = drv_tab[dtyp].lbn; /* get max lbn */ - -if ((uptr->flags & UNIT_ATT) == 0) /* not attached? */ - return (ST_OFL | SB_OFL_NV); /* offl no vol */ -if ((uptr->flags & UNIT_ONL) == 0) /* not online? */ - return ST_AVL; /* only avail */ -if ((cmd != OP_ACC) && (cmd != OP_ERS) && /* 'real' xfer */ - (cp->pak[pkt].d[RW_BAL] & 1)) /* odd address? */ - return (ST_HST | SB_HST_OA); /* host buf odd */ -if (bc & 1) return (ST_HST | SB_HST_OC); /* odd byte cnt? */ -if (bc & 0xF0000000) return (ST_CMD | I_BCNT); /* 'reasonable' bc? */ -/* if (lbn & 0xF0000000) return (ST_CMD | I_LBN); /* 'reasonable' lbn? */ -if (lbn >= maxlbn) { /* accessing RCT? */ - if (lbn >= (maxlbn + drv_tab[dtyp].rcts)) /* beyond copy 1? */ - return (ST_CMD | I_LBN); /* lbn err */ - if (bc != RQ_NUMBY) return (ST_CMD | I_BCNT); }/* bc must be 512 */ -else if ((lbn + ((bc + (RQ_NUMBY - 1)) / RQ_NUMBY)) > maxlbn) - return (ST_CMD | I_BCNT); /* spiral to RCT */ -if ((cmd == OP_WR) || (cmd == OP_ERS)) { /* write op? */ - if (lbn >= maxlbn) /* accessing RCT? */ - return (ST_CMD | I_LBN); /* lbn err */ - if (uptr->uf & UF_WPS) /* swre wlk? */ - return (ST_WPR | SB_WPR_SW); - if (RQ_WPH (uptr)) /* hwre wlk? */ - return (ST_WPR | SB_WPR_HW); } -return 0; /* success! */ -} - -/* Unit service for data transfer commands */ - -t_stat rq_svc (UNIT *uptr) -{ -MSC *cp = rq_ctxmap[uptr->cnum]; - -uint32 i, t, err, tbc, abc, wwc; -int32 pkt = uptr->cpkt; /* get packet */ -uint32 cmd = GETP (pkt, CMD_OPC, OPC); /* get cmd */ -uint32 ba = GETP32 (pkt, RW_WBAL); /* buf addr */ -uint32 bc = GETP32 (pkt, RW_WBCL); /* byte count */ -uint32 bl = GETP32 (pkt, RW_WBLL); /* block addr */ -t_addr da = ((t_addr) bl) * RQ_NUMBY; /* disk addr */ - -if ((cp == NULL) || (pkt == 0)) return STOP_RQ; /* what??? */ -tbc = (bc > RQ_MAXFR)? RQ_MAXFR: bc; /* trim cnt to max */ - -if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */ - rq_rw_end (cp, uptr, 0, ST_OFL | SB_OFL_NV); /* offl no vol */ - return SCPE_OK; } -if (bc == 0) { /* no xfer? */ - rq_rw_end (cp, uptr, 0, ST_SUC); /* ok by me... */ - return SCPE_OK; } - -if ((cmd == OP_ERS) || (cmd == OP_WR)) { /* write op? */ - if (RQ_WPH (uptr)) { - rq_rw_end (cp, uptr, 0, ST_WPR | SB_WPR_HW); - return SCPE_OK; } - if (uptr->uf & UF_WPS) { - rq_rw_end (cp, uptr, 0, ST_WPR | SB_WPR_SW); - return SCPE_OK; } } - -if (cmd == OP_ERS) { /* erase? */ - wwc = ((tbc + (RQ_NUMBY - 1)) & ~(RQ_NUMBY - 1)) >> 1; - for (i = 0; i < wwc; i++) rqxb[i] = 0; /* clr buf */ - err = fseek_ext (uptr->fileref, da, SEEK_SET); /* set pos */ - if (!err) fxwrite (rqxb, sizeof (int16), wwc, uptr->fileref); - err = ferror (uptr->fileref); } /* end if erase */ - -else if (cmd == OP_WR) { /* write? */ - t = Map_ReadW (ba, tbc, rqxb, MAP); /* fetch buffer */ - if (abc = tbc - t) { /* any xfer? */ - wwc = ((abc + (RQ_NUMBY - 1)) & ~(RQ_NUMBY - 1)) >> 1; - for (i = (abc >> 1); i < wwc; i++) rqxb[i] = 0; - err = fseek_ext (uptr->fileref, da, SEEK_SET); - if (!err) fxwrite (rqxb, sizeof (int16), wwc, uptr->fileref); - err = ferror (uptr->fileref); } - if (t) { /* nxm? */ - PUTP32 (pkt, RW_WBCL, bc - abc); /* adj bc */ - PUTP32 (pkt, RW_WBAL, ba + abc); /* adj ba */ - if (rq_hbe (cp, uptr)) /* post err log */ - rq_rw_end (cp, uptr, EF_LOG, ST_HST | SB_HST_NXM); - return SCPE_OK; } } /* end else wr */ - -else { err = fseek_ext (uptr->fileref, da, SEEK_SET); /* set pos */ - if (!err) { - i = fxread (rqxb, sizeof (int16), tbc >> 1, uptr->fileref); - for ( ; i < (tbc >> 1); i++) rqxb[i] = 0; /* fill */ - err = ferror (uptr->fileref); } - if ((cmd == OP_RD) && !err) { /* read? */ - if (t = Map_WriteW (ba, tbc, rqxb, MAP)) { /* store, nxm? */ - PUTP32 (pkt, RW_WBCL, bc - (tbc - t)); /* adj bc */ - PUTP32 (pkt, RW_WBAL, ba + (tbc - t)); /* adj ba */ - if (rq_hbe (cp, uptr)) /* post err log */ - rq_rw_end (cp, uptr, EF_LOG, ST_HST | SB_HST_NXM); - return SCPE_OK; } - } - else if ((cmd == OP_CMP) && !err) { /* compare? */ - uint8 dby, mby; - for (i = 0; i < tbc; i++) { /* loop */ - if (Map_ReadB (ba + i, 1, &mby, MAP)) { /* fetch, nxm? */ - PUTP32 (pkt, RW_WBCL, bc - i); /* adj bc */ - PUTP32 (pkt, RW_WBAL, bc - i); /* adj ba */ - if (rq_hbe (cp, uptr)) /* post err log */ - rq_rw_end (cp, uptr, EF_LOG, ST_HST | SB_HST_NXM); - return SCPE_OK; } - dby = (rqxb[i >> 1] >> ((i & 1)? 8: 0)) & 0xFF; - if (mby != dby) { /* cmp err? */ - PUTP32 (pkt, RW_WBCL, bc - i); /* adj bc */ - rq_rw_end (cp, uptr, 0, ST_CMP); /* done */ - return SCPE_OK; } /* exit */ - } /* end for */ - } /* end else if */ - } /* end else read */ -if (err != 0) { /* error? */ - if (rq_dte (cp, uptr, ST_DRV)) /* post err log */ - rq_rw_end (cp, uptr, EF_LOG, ST_DRV); /* if ok, report err */ - perror ("RQ I/O error"); - clearerr (uptr->fileref); - return SCPE_IOERR; } -ba = ba + tbc; /* incr bus addr */ -bc = bc - tbc; /* decr byte cnt */ -bl = bl + ((tbc + (RQ_NUMBY - 1)) / RQ_NUMBY); /* incr blk # */ -PUTP32 (pkt, RW_WBAL, ba); /* update pkt */ -PUTP32 (pkt, RW_WBCL, bc); -PUTP32 (pkt, RW_WBLL, bl); -if (bc) sim_activate (uptr, rq_xtime); /* more? resched */ -else rq_rw_end (cp, uptr, 0, ST_SUC); /* done! */ -return SCPE_OK; -} - -/* Transfer command complete */ - -t_bool rq_rw_end (MSC *cp, UNIT *uptr, uint32 flg, uint32 sts) -{ -int32 pkt = uptr->cpkt; /* packet */ -uint32 cmd = GETP (pkt, CMD_OPC, OPC); /* get cmd */ -uint32 bc = GETP32 (pkt, RW_BCL); /* init bc */ -uint32 wbc = GETP32 (pkt, RW_WBCL); /* work bc */ -DEVICE *dptr = rq_devmap[uptr->cnum]; - -uptr->cpkt = 0; /* done */ -PUTP32 (pkt, RW_BCL, bc - wbc); /* bytes processed */ -cp->pak[pkt].d[RW_WBAL] = 0; /* clear temps */ -cp->pak[pkt].d[RW_WBAH] = 0; -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_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 */ -return OK; -} - -/* Data transfer error log packet */ - -t_bool rq_dte (MSC *cp, UNIT *uptr, uint32 err) -{ -int32 pkt, tpkt; -uint32 lu, dtyp, lbn, ccyl, csurf, csect, t; - -if ((cp->cflgs & CF_THS) == 0) return OK; /* logging? */ -if (!rq_deqf (cp, &pkt)) return ERR; /* get log pkt */ -tpkt = uptr->cpkt; /* rw pkt */ -lu = cp->pak[tpkt].d[CMD_UN]; /* unit # */ -lbn = GETP32 (tpkt, RW_WBLL); /* recent LBN */ -dtyp = GET_DTYPE (uptr->flags); /* drv type */ -if (drv_tab[dtyp].flgs & RQDF_SDI) t = 0; /* SDI? ovhd @ end */ -else t = (drv_tab[dtyp].xbn + drv_tab[dtyp].dbn) / /* ovhd cylinders */ - (drv_tab[dtyp].sect * drv_tab[dtyp].surf); -ccyl = t + (lbn / drv_tab[dtyp].cyl); /* curr real cyl */ -t = lbn % drv_tab[dtyp].cyl; /* trk relative blk */ -csurf = t / drv_tab[dtyp].surf; /* curr surf */ -csect = t % drv_tab[dtyp].surf; /* curr sect */ - -cp->pak[pkt].d[ELP_REFL] = cp->pak[tpkt].d[CMD_REFL]; /* copy cmd ref */ -cp->pak[pkt].d[ELP_REFH] = cp->pak[tpkt].d[CMD_REFH]; -cp->pak[pkt].d[ELP_UN] = lu; /* copy unit */ -cp->pak[pkt].d[ELP_SEQ] = 0; /* clr seq # */ -cp->pak[pkt].d[DTE_CIDA] = 0; /* ctrl ID */ -cp->pak[pkt].d[DTE_CIDB] = 0; -cp->pak[pkt].d[DTE_CIDC] = 0; -cp->pak[pkt].d[DTE_CIDD] = (RQ_CLASS << DTE_CIDD_V_CLS) | - (RQ_MODEL << DTE_CIDD_V_MOD); -cp->pak[pkt].d[DTE_VER] = (RQ_HVER << DTE_VER_V_HVER) | - (RQ_SVER << DTE_VER_V_SVER); -cp->pak[pkt].d[DTE_MLUN] = lu; /* MLUN */ -cp->pak[pkt].d[DTE_UIDA] = lu; /* unit ID */ -cp->pak[pkt].d[DTE_UIDB] = 0; -cp->pak[pkt].d[DTE_UIDC] = 0; -cp->pak[pkt].d[DTE_UIDD] = (UID_DISK << DTE_UIDD_V_CLS) | - (drv_tab[dtyp].mod << DTE_UIDD_V_MOD); -cp->pak[pkt].d[DTE_UVER] = 0; /* unit versn */ -cp->pak[pkt].d[DTE_SCYL] = ccyl; /* cylinder */ -cp->pak[pkt].d[DTE_VSNL] = 01234 + lu; /* vol ser # */ -cp->pak[pkt].d[DTE_VSNH] = 0; -cp->pak[pkt].d[DTE_D1] = 0; -cp->pak[pkt].d[DTE_D2] = csect << DTE_D2_V_SECT; /* geometry */ -cp->pak[pkt].d[DTE_D3] = (ccyl << DTE_D3_V_CYL) | - (csurf << DTE_D3_V_SURF); -rq_putr (cp, pkt, FM_SDE, LF_SNR, err, DTE_LNT, UQ_TYP_DAT); -return rq_putpkt (cp, pkt, TRUE); -} - -/* Host bus error log packet */ - -t_bool rq_hbe (MSC *cp, UNIT *uptr) -{ -int32 pkt, tpkt; - -if ((cp->cflgs & CF_THS) == 0) return OK; /* logging? */ -if (!rq_deqf (cp, &pkt)) return ERR; /* get log pkt */ -tpkt = uptr->cpkt; /* rw pkt */ -cp->pak[pkt].d[ELP_REFL] = cp->pak[tpkt].d[CMD_REFL]; /* copy cmd ref */ -cp->pak[pkt].d[ELP_REFH] = cp->pak[tpkt].d[CMD_REFH]; -cp->pak[pkt].d[ELP_UN] = cp->pak[tpkt].d[CMD_UN]; /* copy unit */ -cp->pak[pkt].d[ELP_SEQ] = 0; /* clr seq # */ -cp->pak[pkt].d[HBE_CIDA] = 0; /* ctrl ID */ -cp->pak[pkt].d[HBE_CIDB] = 0; -cp->pak[pkt].d[HBE_CIDC] = 0; -cp->pak[pkt].d[HBE_CIDD] = (RQ_CLASS << DTE_CIDD_V_CLS) | - (RQ_MODEL << DTE_CIDD_V_MOD); -cp->pak[pkt].d[HBE_VER] = (RQ_HVER << HBE_VER_V_HVER) | /* versions */ - (RQ_SVER << HBE_VER_V_SVER); -cp->pak[pkt].d[HBE_RSV] = 0; -cp->pak[pkt].d[HBE_BADL] = cp->pak[tpkt].d[RW_WBAL]; /* bad addr */ -cp->pak[pkt].d[HBE_BADH] = cp->pak[tpkt].d[RW_WBAH]; -rq_putr (cp, pkt, FM_BAD, LF_SNR, ST_HST | SB_HST_NXM, HBE_LNT, UQ_TYP_DAT); -return rq_putpkt (cp, pkt, TRUE); -} - -/* Port last failure error log packet */ - -t_bool rq_plf (MSC *cp, uint32 err) -{ -int32 pkt; - -if (!rq_deqf (cp, &pkt)) return ERR; /* get log pkt */ -cp->pak[pkt].d[ELP_REFL] = 0; /* ref = 0 */ -cp->pak[pkt].d[ELP_REFH] = 0; -cp->pak[pkt].d[ELP_UN] = 0; /* no unit */ -cp->pak[pkt].d[ELP_SEQ] = 0; /* no seq */ -cp->pak[pkt].d[PLF_CIDA] = 0; /* cntl ID */ -cp->pak[pkt].d[PLF_CIDB] = 0; -cp->pak[pkt].d[PLF_CIDC] = 0; -cp->pak[pkt].d[PLF_CIDD] = (RQ_CLASS << PLF_CIDD_V_CLS) | - (RQ_MODEL << PLF_CIDD_V_MOD); -cp->pak[pkt].d[PLF_VER] = (RQ_SVER << PLF_VER_V_SVER) | - (RQ_HVER << PLF_VER_V_HVER); -cp->pak[pkt].d[PLF_ERR] = err; -rq_putr (cp, pkt, FM_CNT, LF_SNR, ST_CNT, PLF_LNT, UQ_TYP_DAT); -cp->pak[pkt].d[UQ_HCTC] |= (UQ_CID_DIAG << UQ_HCTC_V_CID); -return rq_putpkt (cp, pkt, TRUE); -} - -/* Unit now available attention packet */ - -int32 rq_una (MSC *cp, int32 un) -{ -int32 pkt; -uint32 lu = cp->ubase + un; -UNIT *uptr = rq_getucb (cp, lu); - -if (uptr == NULL) return OK; /* huh? */ -if (!rq_deqf (cp, &pkt)) return ERR; /* get log pkt */ -cp->pak[pkt].d[RSP_REFL] = 0; /* ref = 0 */ -cp->pak[pkt].d[RSP_REFH] = 0; -cp->pak[pkt].d[RSP_UN] = lu; -cp->pak[pkt].d[RSP_RSV] = 0; -rq_putr_unit (cp, pkt, uptr, lu, FALSE); /* fill unit fields */ -rq_putr (cp, pkt, OP_AVA, 0, 0, UNA_LNT, UQ_TYP_SEQ); /* fill std fields */ -return rq_putpkt (cp, pkt, TRUE); -} - -/* List handling - - rq_deqf - dequeue head of free list (fatal err if none) - rq_deqh - dequeue head of list - rq_enqh - enqueue at head of list - rq_enqt - enqueue at tail of list -*/ - -t_bool rq_deqf (MSC *cp, int32 *pkt) -{ -if (cp->freq == 0) return rq_fatal (cp, PE_NSR); /* no free pkts?? */ -cp->pbsy = cp->pbsy + 1; /* cnt busy pkts */ -*pkt = cp->freq; /* head of list */ -cp->freq = cp->pak[cp->freq].link; /* next */ -return OK; -} - -int32 rq_deqh (MSC *cp, int32 *lh) -{ -int32 ptr = *lh; /* head of list */ - -if (ptr) *lh = cp->pak[ptr].link; /* next */ -return ptr; -} - -void rq_enqh (MSC *cp, int32 *lh, int32 pkt) -{ -if (pkt == 0) return; /* any pkt? */ -cp->pak[pkt].link = *lh; /* link is old lh */ -*lh = pkt; /* pkt is new lh */ -return; -} - -void rq_enqt (MSC *cp, int32 *lh, int32 pkt) -{ -if (pkt == 0) return; /* any pkt? */ -cp->pak[pkt].link = 0; /* it will be tail */ -if (*lh == 0) *lh = pkt; /* if empty, enqh */ -else { uint32 ptr = *lh; /* chase to end */ - while (cp->pak[ptr].link) ptr = cp->pak[ptr].link; - cp->pak[ptr].link = pkt; } /* enq at tail */ -return; -} - -/* Packet and descriptor handling */ - -/* Get packet from command ring */ - -t_bool rq_getpkt (MSC *cp, int32 *pkt) -{ -uint32 addr, desc; - -if (!rq_getdesc (cp, &cp->cq, &desc)) return ERR; /* get cmd desc */ -if ((desc & UQ_DESC_OWN) == 0) { /* none */ - *pkt = 0; /* pkt = 0 */ - return OK; } /* no error */ -if (!rq_deqf (cp, pkt)) return ERR; /* get cmd pkt */ -cp->hat = 0; /* dsbl hst timer */ -addr = desc & UQ_ADDR; /* get Q22 addr */ -if (Map_ReadW (addr + UQ_HDR_OFF, RQ_PKT_SIZE, cp->pak[*pkt].d, MAP)) - return rq_fatal (cp, PE_PRE); /* read pkt */ -return rq_putdesc (cp, &cp->cq, desc); /* release desc */ -} - -/* Put packet to response ring - note the clever hack about credits. - The controller sends all its credits to the host. Thereafter, it - supplies one credit for every response packet sent over. Simple! -*/ - -t_bool rq_putpkt (MSC *cp, int32 pkt, t_bool qt) -{ -uint32 addr, desc, lnt, cr; -DEVICE *dptr = rq_devmap[cp->cnum]; - -if (pkt == 0) return OK; /* any packet? */ -if (DBG_LOG (LOG_RQ)) fprintf (sim_log, - ">>RQ%c: rsp=%04X, sts=%04X\n", 'A' + cp->cnum, - cp->pak[pkt].d[RSP_OPF], cp->pak[pkt].d[RSP_STS]); -if (!rq_getdesc (cp, &cp->rq, &desc)) return ERR; /* get rsp desc */ -if ((desc & UQ_DESC_OWN) == 0) { /* not valid? */ - if (qt) rq_enqt (cp, &cp->rspq, pkt); /* normal? q tail */ - else rq_enqh (cp, &cp->rspq, pkt); /* resp q call */ - sim_activate (dptr->units + RQ_QUEUE, rq_qtime); /* activate q thrd */ - return OK; } -addr = desc & UQ_ADDR; /* get Q22 addr */ -lnt = cp->pak[pkt].d[UQ_HLNT] - UQ_HDR_OFF; /* size, with hdr */ -if ((GETP (pkt, UQ_HCTC, TYP) == UQ_TYP_SEQ) && /* seq packet? */ - (GETP (pkt, CMD_OPC, OPC) & OP_END)) { /* end packet? */ - cr = (cp->credits >= 14)? 14: cp->credits; /* max 14 credits */ - cp->credits = cp->credits - cr; /* decr credits */ - cp->pak[pkt].d[UQ_HCTC] |= ((cr + 1) << UQ_HCTC_V_CR); } -if (Map_WriteW (addr + UQ_HDR_OFF, lnt, cp->pak[pkt].d, MAP)) - return rq_fatal (cp, PE_PWE); /* write pkt */ -rq_enqh (cp, &cp->freq, pkt); /* pkt is free */ -cp->pbsy = cp->pbsy - 1; /* decr busy cnt */ -if (cp->pbsy == 0) cp->hat = cp->htmo; /* idle? strt hst tmr */ -return rq_putdesc (cp, &cp->rq, desc); /* release desc */ -} - -/* Get a descriptor from the host */ - -t_bool rq_getdesc (MSC *cp, struct uq_ring *ring, uint32 *desc) -{ -uint32 addr = ring->ba + ring->idx; -uint16 d[2]; - -if (Map_ReadW (addr, 4, d, MAP)) /* fetch desc */ - return rq_fatal (cp, PE_QRE); /* err? dead */ -*desc = ((uint32) d[0]) | (((uint32) d[1]) << 16); -return OK; -} - -/* Return a descriptor to the host, clearing owner bit - If rings transitions from "empty" to "not empty" or "full" to - "not full", and interrupt bit was set, interrupt the host. - Actually, test whether previous ring entry was owned by host. -*/ - -t_bool rq_putdesc (MSC *cp, struct uq_ring *ring, uint32 desc) -{ -uint32 prvd, newd = (desc & ~UQ_DESC_OWN) | UQ_DESC_F; -uint32 prva, addr = ring->ba + ring->idx; -uint16 d[2]; - -d[0] = newd & 0xFFFF; /* 32b to 16b */ -d[1] = (newd >> 16) & 0xFFFF; -if (Map_WriteW (addr, 4, d, MAP)) /* store desc */ - return rq_fatal (cp, PE_QWE); /* err? dead */ -if (desc & UQ_DESC_F) { /* was F set? */ - if (ring->lnt <= 4) rq_ring_int (cp, ring); /* lnt = 1? intr */ - else { /* prv desc */ - prva = ring->ba + ((ring->idx - 4) & (ring->lnt - 1)); - if (Map_ReadW (prva, 4, d, MAP)) /* read prv */ - return rq_fatal (cp, PE_QRE); - prvd = ((uint32) d[0]) | (((uint32) d[1]) << 16); - if (prvd & UQ_DESC_OWN) rq_ring_int (cp, ring); } } -ring->idx = (ring->idx + 4) & (ring->lnt - 1); -return OK; -} - -/* Get unit descriptor for logical unit */ - -UNIT *rq_getucb (MSC *cp, uint32 lu) -{ -DEVICE *dptr = rq_devmap[cp->cnum]; -UNIT *uptr; - -if ((lu < cp->ubase) || (lu >= (cp->ubase + RQ_NUMDR))) - return NULL; -uptr = dptr->units + (lu % RQ_NUMDR); -if (uptr->flags & UNIT_DIS) return NULL; -return uptr; -} - -/* Hack unit flags */ - -void rq_setf_unit (MSC *cp, int32 pkt, UNIT *uptr) -{ -uptr->uf = cp->pak[pkt].d[ONL_UFL] & UF_MSK; /* settable flags */ -if ((cp->pak[pkt].d[CMD_MOD] & MD_SWP) && /* swre wrp enb? */ - (cp->pak[pkt].d[ONL_UFL] & UF_WPS)) /* swre wrp on? */ - uptr->uf = uptr->uf | UF_WPS; /* simon says... */ -return; -} - -/* Unit response fields */ - -void rq_putr_unit (MSC *cp, int32 pkt, UNIT *uptr, uint32 lu, t_bool all) -{ -uint32 dtyp = GET_DTYPE (uptr->flags); /* get drive type */ - -cp->pak[pkt].d[ONL_MLUN] = lu; /* unit */ -cp->pak[pkt].d[ONL_UFL] = uptr->uf | UF_RPL | RQ_WPH (uptr) | RQ_RMV (uptr); -cp->pak[pkt].d[ONL_RSVL] = 0; /* reserved */ -cp->pak[pkt].d[ONL_RSVH] = 0; -cp->pak[pkt].d[ONL_UIDA] = lu; /* UID low */ -cp->pak[pkt].d[ONL_UIDB] = 0; -cp->pak[pkt].d[ONL_UIDC] = 0; -cp->pak[pkt].d[ONL_UIDD] = (UID_DISK << ONL_UIDD_V_CLS) | - (drv_tab[dtyp].mod << ONL_UIDD_V_MOD); /* UID hi */ -PUTP32 (pkt, ONL_MEDL, drv_tab[dtyp].med); /* media type */ -if (all) { /* if long form */ - PUTP32 (pkt, ONL_SIZL, drv_tab[dtyp].lbn); /* user LBNs */ - cp->pak[pkt].d[ONL_VSNL] = 01234 + lu; /* vol serial # */ - cp->pak[pkt].d[ONL_VSNH] = 0; } -return; -} - -/* UQ_HDR and RSP_OP fields */ - -void rq_putr (MSC *cp, int32 pkt, uint32 cmd, uint32 flg, - uint32 sts, uint32 lnt, uint32 typ) -{ -cp->pak[pkt].d[RSP_OPF] = (cmd << RSP_OPF_V_OPC) | /* set cmd, flg */ - (flg << RSP_OPF_V_FLG); -cp->pak[pkt].d[RSP_STS] = sts; -cp->pak[pkt].d[UQ_HLNT] = lnt; /* length */ -cp->pak[pkt].d[UQ_HCTC] = (typ << UQ_HCTC_V_TYP) | /* type, cid */ - (UQ_CID_MSCP << UQ_HCTC_V_CID); /* clr credits */ -return; -} - -/* Post interrupt during init */ - -void rq_init_int (MSC *cp) -{ -if (cp->s1dat & (SA_S1H_IE | SA_S1H_VEC)) rq_setint (cp); -return; -} - -/* Post interrupt during putpkt - note that NXMs are ignored! */ - -void rq_ring_int (MSC *cp, struct uq_ring *ring) -{ -uint32 iadr = cp->comm + ring->ioff; /* addr intr wd */ -uint16 flag = 1; - -Map_WriteW (iadr, 2, &flag, MAP); /* write flag */ -if (cp->s1dat & SA_S1H_VEC) rq_setint (cp); /* if enb, intr */ -return; -} - -/* Set RQ interrupt */ - -void rq_setint (MSC *cp) -{ -cp->irq = 1; /* set ctrl int */ -SET_INT (RQ); /* set master int */ -return; -} - -/* Clear RQ interrupt */ - -void rq_clrint (MSC *cp) -{ -int32 i; -MSC *ncp; - -cp->irq = 0; /* clr ctrl int */ -for (i = 0; i < RQ_NUMCT; i++) { /* loop thru ctrls */ - ncp = rq_ctxmap[i]; /* get context */ - if (ncp->irq) { /* other interrupt? */ - SET_INT (RQ); /* yes, set master */ - return; } } -CLR_INT (RQ); /* no, clr master */ -return; -} - -/* Return interrupt vector */ - -int32 rq_inta (void) -{ -int32 i; -MSC *ncp; -DEVICE *dptr; -DIB *dibp; - -for (i = 0; i < RQ_NUMCT; i++) { /* loop thru ctrl */ - ncp = rq_ctxmap[i]; /* get context */ - if (ncp->irq) { /* ctrl int set? */ - dptr = rq_devmap[i]; /* get device */ - dibp = (DIB *) dptr->ctxt; /* get DIB */ - rq_clrint (ncp); /* clear int req */ - return dibp->vec; } } /* return vector */ -return 0; /* no intr req */ -} - -/* Fatal error */ - -t_bool rq_fatal (MSC *cp, uint32 err) -{ -if (DBG_LOG (LOG_RQ)) - fprintf (sim_log, ">>RQ%c: fatal err=%X\n", 'A' + cp->cnum, err); -rq_reset (rq_devmap[cp->cnum]); /* reset device */ -cp->sa = SA_ER | err; /* SA = dead code */ -cp->csta = CST_DEAD; /* state = dead */ -cp->perr = err; /* save error */ -return ERR; -} - -/* Set/clear hardware write lock */ - -t_stat rq_set_wlk (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -uint32 dtyp = GET_DTYPE (uptr->flags); /* get drive type */ - -if (drv_tab[dtyp].flgs & RQDF_RO) return SCPE_NOFNC; /* not on read only */ -return SCPE_OK; -} - -/* Show write lock status */ - -t_stat rq_show_wlk (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -uint32 dtyp = GET_DTYPE (uptr->flags); /* get drive type */ - -if (drv_tab[dtyp].flgs & RQDF_RO) fprintf (st, "read only"); -else if (uptr->flags & UNIT_WPRT) fprintf (st, "write locked"); -else fprintf (st, "write enabled"); -return SCPE_OK; -} - -/* Set unit type (and capacity if user defined) */ - -t_stat rq_set_type (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -uint32 cap; -uint32 max = sim_taddr_64? RA8U_EMAXC: RA8U_MAXC; -t_stat r; - -if ((val < 0) || (val > RA8U_DTYPE) || ((val != RA8U_DTYPE) && cptr)) - return SCPE_ARG; -if (uptr->flags & UNIT_ATT) return SCPE_ALATT; -if (cptr) { - cap = (int32) get_uint (cptr, 10, max, &r); - if ((r != SCPE_OK) || (cap < RA8U_MINC)) return SCPE_ARG; - drv_tab[val].lbn = cap << (20 - 9); } -uptr->flags = (uptr->flags & ~UNIT_DTYPE) | (val << UNIT_V_DTYPE); -uptr->capac = ((t_addr) drv_tab[val].lbn) * RQ_NUMBY; -return SCPE_OK; -} - -/* Show unit type (and capacity if user defined) */ - -t_stat rq_show_type (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -fprintf (st, "%s", drv_tab[GET_DTYPE (uptr->flags)].name); -return SCPE_OK; -} - -/* Device attach */ - -t_stat rq_attach (UNIT *uptr, char *cptr) -{ -int32 dtyp = GET_DTYPE (uptr->flags); -MSC *cp = rq_ctxmap[uptr->cnum]; -t_stat r; - -uptr->capac = drv_tab[dtyp].lbn * RQ_NUMBY; -r = attach_unit (uptr, cptr); -if (r != SCPE_OK) return r; -if (cp->csta == CST_UP) uptr->flags = uptr->flags | UNIT_ATP; -return SCPE_OK; -} - -/* Device detach */ - -t_stat rq_detach (UNIT *uptr) -{ -t_stat r; - -r = detach_unit (uptr); /* detach unit */ -if (r != SCPE_OK) return r; -uptr->flags = uptr->flags & ~(UNIT_ONL | UNIT_ATP); /* clr onl, atn pend */ -uptr->uf = 0; /* clr unit flgs */ -return SCPE_OK; -} - -/* Device reset */ - -t_stat rq_reset (DEVICE *dptr) -{ -int32 i, j, cidx; -UNIT *uptr; -MSC *cp; -DIB *dibp = (DIB *) dptr->ctxt; - -for (i = 0, cidx = -1; i < RQ_NUMCT; i++) { /* find ctrl num */ - if (rq_devmap[i] == dptr) cidx = i; } -if (cidx < 0) return SCPE_IERR; /* not found??? */ -cp = rq_ctxmap[cidx]; /* get context */ -cp->cnum = cidx; /* init index */ -cp->ubase = cidx * RQ_NUMDR; /* init unit base */ -cp->csta = CST_S1; /* init stage 1 */ -cp->s1dat = 0; /* no S1 data */ -dibp->vec = 0; /* no vector */ -cp->comm = 0; /* no comm region */ -cp->sa = SA_S1 | SA_S1C_Q22 | SA_S1C_DI | SA_S1C_MP; /* init SA val */ -cp->cflgs = CF_RPL; /* ctrl flgs off */ -cp->htmo = RQ_DHTMO; /* default timeout */ -cp->hat = cp->htmo; /* default timer */ -cp->cq.ba = cp->cq.lnt = cp->cq.idx = 0; /* clr cmd ring */ -cp->rq.ba = cp->rq.lnt = cp->rq.idx = 0; /* clr rsp ring */ -cp->credits = (RQ_NPKTS / 2) - 1; /* init credits */ -cp->freq = 1; /* init free list */ -for (i = 0; i < RQ_NPKTS; i++) { /* all pkts free */ - if (i) cp->pak[i].link = (i + 1) & RQ_M_NPKTS; - else cp->pak[i].link = 0; - for (j = 0; j < RQ_PKT_SIZE_W; j++) cp->pak[i].d[j] = 0; } -cp->rspq = 0; /* no q'd rsp pkts */ -cp->pbsy = 0; /* all pkts free */ -cp->pip = 0; /* not polling */ -rq_clrint (cp); /* clr intr req */ -for (i = 0; i < (RQ_NUMDR + 2); i++) { /* init units */ - uptr = dptr->units + i; - sim_cancel (uptr); /* clr activity */ - uptr->cnum = cidx; /* set ctrl index */ - uptr->flags = uptr->flags & ~(UNIT_ONL | UNIT_ATP); - uptr->uf = 0; /* clr unit flags */ - uptr->cpkt = uptr->pktq = 0; } /* clr pkt q's */ -if (rqxb == NULL) rqxb = calloc (RQ_MAXFR >> 1, sizeof (unsigned int16)); -if (rqxb == NULL) return SCPE_MEM; -return auto_config (0, 0); /* run autoconfig */ -} - -/* Device bootstrap */ - -#if defined (VM_PDP11) - -#define BOOT_START 016000 /* start */ -#define BOOT_ENTRY (BOOT_START + 002) /* entry */ -#define BOOT_UNIT (BOOT_START + 010) /* unit number */ -#define BOOT_CSR (BOOT_START + 014) /* CSR */ -#define BOOT_LEN (sizeof (boot_rom) / sizeof (int16)) - -static const uint16 boot_rom[] = { - - 0042125, /* st: "UD" */ - - /* Four step init process */ - - 0012706, 0016000, /* mov #st,sp */ - 0012700, 0000000, /* mov #unit,r0 */ - 0012701, 0172150, /* mov #172150, r1 ; ip addr */ - 0012704, 0016162, /* mov #it, r4 */ - 0012705, 0004000, /* mov #4000,r5 ; s1 mask */ - 0010102, /* mov r1,r2 */ - 0005022, /* clr (r2)+ ; init */ - 0005712, /* 10$: tst (r2) ; err? */ - 0100001, /* bpl 20$ */ - 0000000, /* halt */ - 0030512, /* 20$: bit r5,(r2) ; step set? */ - 0001773, /* beq 10$ ; wait */ - 0012412, /* mov (r4)+,(r2) ; send next */ - 0006305, /* asl r5 ; next mask */ - 0100370, /* bpl 10$ ; s4 done? */ - - /* Send ONL, READ commands */ - - 0105714, /* 30$: tstb (r4) ; end tbl? */ - 0001434, /* beq done ; 0 = yes */ - 0012702, 0007000, /* mov #rpkt-4,r2 ; clr pkts */ - 0005022, /* 40$: clr (r2)+ */ - 0020227, 0007204, /* cmp r2,#comm */ - 0103774, /* blo 40$ */ - 0112437, 0007100, /* movb (r4)+,cpkt-4 ; set lnt */ - 0110037, 0007110, /* movb r0,cpkt+4 ; set unit */ - 0112437, 0007114, /* movb (r4)+,cpkt+10 ; set op */ - 0112437, 0007121, /* movb (r4)+,cpkt+15 ; set param */ - 0012722, 0007004, /* mov #rpkt,(r2)+ ; rq desc */ - 0010522, /* mov r5,(r2)+ ; rq own */ - 0012722, 0007104, /* mov #ckpt,(r2)+ ; cq desc */ - 0010512, /* mov r5,(r2) ; cq own */ - 0024242, /* cmp -(r2),-(r2) ; back up */ - 0005711, /* tst (r1) ; wake ctrl */ - 0005712, /* 50$: tst (r2) ; rq own clr? */ - 0100776, /* bmi 50$ ; wait */ - 0005737, 0007016, /* tst rpkt+12 ; stat ok? */ - 0001743, /* beq 30$ ; next cmd */ - 0000000, /* halt */ - - /* Boot block read in, jump to 0 */ - - 0005011, /* done: clr (r1) ; for M+ */ - 0005003, /* clr r3 */ - 0012704, BOOT_START+020, /* mov #st+020,r4 */ - 0005005, /* clr r5 */ - 0005007, /* clr pc */ - - /* Data */ - - 0100000, /* it: no ints, ring sz = 1 */ - 0007204, /* .word comm */ - 0000000, /* .word 0 */ - 0000001, /* .word 1 */ - 0004420, /* .byte 20,11 */ - 0020000, /* .byte 0,40 */ - 0001041, /* .byte 41,2 */ - 0000000 -}; - -t_stat rq_boot (int32 unitno, DEVICE *dptr) -{ -int32 i; -extern int32 saved_PC; -extern uint16 *M; -DIB *dibp = (DIB *) dptr->ctxt; - -for (i = 0; i < BOOT_LEN; i++) M[(BOOT_START >> 1) + i] = boot_rom[i]; -M[BOOT_UNIT >> 1] = unitno & 3; -M[BOOT_CSR >> 1] = dibp->ba & DMASK; -saved_PC = BOOT_ENTRY; -return SCPE_OK; -} - -#else - -t_stat rq_boot (int32 unitno, DEVICE *dptr) -{ -return SCPE_NOFNC; -} -#endif - -/* Special show commands */ - -void rq_show_ring (FILE *st, struct uq_ring *rp) -{ -uint32 i, desc; -uint16 d[2]; - -#if defined (VM_PDP11) -fprintf (st, "ring, base = %o, index = %d, length = %d\n", - rp->ba, rp->idx >> 2, rp->lnt >> 2); -#else -fprintf (st, "ring, base = %x, index = %d, length = %d\n", - rp->ba, rp->idx >> 2, rp->lnt >> 2); -#endif -for (i = 0; i < (rp->lnt >> 2); i++) { - if (Map_ReadW (rp->ba + (i << 2), 4, d, MAP)) { - fprintf (st, " %3d: non-existent memory\n", i); - break; } - desc = ((uint32) d[0]) | (((uint32) d[1]) << 16); -#if defined (VM_PDP11) - fprintf (st, " %3d: %011o\n", i, desc); -#else - fprintf (st, " %3d: %08x\n", i, desc); -#endif - } -return; -} - -void rq_show_pkt (FILE *st, MSC *cp, int32 pkt) -{ -int32 i, j; -uint32 cr = GETP (pkt, UQ_HCTC, CR); -uint32 typ = GETP (pkt, UQ_HCTC, TYP); -uint32 cid = GETP (pkt, UQ_HCTC, CID); - -fprintf (st, "packet %d, credits = %d, type = %d, cid = %d\n", - pkt, cr, typ, cid); -for (i = 0; i < RQ_SH_MAX; i = i + RQ_SH_PPL) { - fprintf (st, " %2d:", i); - for (j = i; j < (i + RQ_SH_PPL); j++) -#if defined (VM_PDP11) - fprintf (st, " %06o", cp->pak[pkt].d[j]); -#else - fprintf (st, " %04x", cp->pak[pkt].d[j]); -#endif - fprintf (st, "\n"); - } -return; -} - -t_stat rq_show_unitq (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -MSC *cp = rq_ctxmap[uptr->cnum]; -DEVICE *dptr = rq_devmap[uptr->cnum]; -int32 pkt, u; - -u = uptr - dptr->units; -if (cp->csta != CST_UP) { - fprintf (st, "Controller is not initialized\n"); - return SCPE_OK; } -if ((uptr->flags & UNIT_ONL) == 0) { - if (uptr->flags & UNIT_ATT) - fprintf (st, "Unit %d is available\n", u); - else fprintf (st, "Unit %d is offline\n", u); - return SCPE_OK; } -if (uptr->cpkt) { - fprintf (st, "Unit %d current ", u); - rq_show_pkt (st, cp, uptr->cpkt); - if (pkt = uptr->pktq) { - do { fprintf (st, "Unit %d queued ", u); - rq_show_pkt (st, cp, pkt); } - while (pkt = cp->pak[pkt].link); } } -else fprintf (st, "Unit %d queues are empty\n", u); -return SCPE_OK; -} - -t_stat rq_show_ctrl (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -MSC *cp = rq_ctxmap[uptr->cnum]; -DEVICE *dptr = rq_devmap[uptr->cnum]; -int32 i, pkt; - -if (cp->csta != CST_UP) { - fprintf (st, "Controller is not initialized\n"); - return SCPE_OK; } -if (val & RQ_SH_RI) { - if (cp->pip) fprintf (st, "Polling in progress, host timer = %d\n", cp->hat); - else fprintf (st, "Host timer = %d\n", cp->hat); - fprintf (st, "Command "); - rq_show_ring (st, &cp->cq); - fprintf (st, "Response "); - rq_show_ring (st, &cp->rq); - } -if (val & RQ_SH_FR) { - if (pkt = cp->freq) { - for (i = 0; pkt != 0; i++, pkt = cp->pak[pkt].link) { - if (i == 0) fprintf (st, "Free queue = %d", pkt); - else if ((i % 16) == 0) fprintf (st, ",\n %d", pkt); - else fprintf (st, ", %d", pkt); } - fprintf (st, "\n"); } - else fprintf (st, "Free queue is empty\n"); - } -if (val & RQ_SH_RS) { - if (pkt = cp->rspq) { - do { fprintf (st, "Response "); - rq_show_pkt (st, cp, pkt); } - while (pkt = cp->pak[pkt].link); } - else fprintf (st, "Response queue is empty\n"); - } -if (val & RQ_SH_UN) { - for (i = 0; i < RQ_NUMDR; i++) - rq_show_unitq (st, dptr->units + i, 0, desc); - } -return SCPE_OK; -} diff --git a/PDP11/pdp11_rx.c b/PDP11/pdp11_rx.c deleted file mode 100644 index ea10d132..00000000 --- a/PDP11/pdp11_rx.c +++ /dev/null @@ -1,483 +0,0 @@ -/* pdp11_rx.c: RX11/RX01 floppy disk simulator - - 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. - - rx RX11/RX01 floppy disk - - 12-Oct-02 RMS Added autoconfigure support - 08-Oct-02 RMS Added variable address support to bootstrap - Added vector change/display support - Revised state machine based on RX211 - New data structures - Fixed reset of disabled device - 26-Jan-02 RMS Revised bootstrap to conform to M9312 - 06-Jan-02 RMS Revised enable/disable support - 30-Nov-01 RMS Added read only unit, extended SET/SHOW support - 24-Nov-01 RMS Converted FLG to array - 07-Sep-01 RMS Revised device disable and interrupt mechanisms - 17-Jul-01 RMS Fixed warning from VC++ 6.0 - 26-Apr-01 RMS Added device enable/disable support - 13-Apr-01 RMS Revised for register arrays - 15-Feb-01 RMS Corrected bootstrap string - 14-Apr-99 RMS Changed t_addr to unsigned - - An RX01 diskette consists of 77 tracks, each with 26 sectors of 128B. - Tracks are numbered 0-76, sectors 1-26. -*/ - -#include "pdp11_defs.h" - -#define RX_NUMTR 77 /* tracks/disk */ -#define RX_M_TRACK 0377 -#define RX_NUMSC 26 /* sectors/track */ -#define RX_M_SECTOR 0177 -#define RX_NUMBY 128 /* bytes/sector */ -#define RX_SIZE (RX_NUMTR * RX_NUMSC * RX_NUMBY) /* bytes/disk */ -#define RX_NUMDR 2 /* drives/controller */ -#define RX_M_NUMDR 01 -#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 IDLE 0 /* idle state */ -#define RWDS 1 /* rw, sect next */ -#define RWDT 2 /* rw, track next */ -#define RWXFR 3 /* rw, transfer */ -#define FILL 4 /* fill buffer */ -#define EMPTY 5 /* empty buffer */ -#define CMD_COMPLETE 6 /* set done next */ -#define INIT_COMPLETE 7 /* init compl next */ - -#define RXCS_V_FUNC 1 /* function */ -#define RXCS_M_FUNC 7 -#define RXCS_FILL 0 /* fill buffer */ -#define RXCS_EMPTY 1 /* empty buffer */ -#define RXCS_WRITE 2 /* write sector */ -#define RXCS_READ 3 /* read sector */ -#define RXCS_RXES 5 /* read status */ -#define RXCS_WRDEL 6 /* write del data */ -#define RXCS_ECODE 7 /* read error code */ -#define RXCS_V_DRV 4 /* drive select */ -#define RXCS_V_DONE 5 /* done */ -#define RXCS_V_IE 6 /* intr enable */ -#define RXCS_V_TR 7 /* xfer request */ -#define RXCS_V_INIT 14 /* init */ -#define RXCS_V_ERR 15 /* error */ -#define RXCS_FUNC (RXCS_M_FUNC << RXCS_V_FUNC) -#define RXCS_DRV (1u << RXCS_V_DRV) -#define RXCS_DONE (1u << RXCS_V_DONE) -#define RXCS_IE (1u << RXCS_V_IE) -#define RXCS_TR (1u << RXCS_V_TR) -#define RXCS_INIT (1u << RXCS_V_INIT) -#define RXCS_ERR (1u << RXCS_V_ERR) -#define RXCS_ROUT (RXCS_ERR+RXCS_TR+RXCS_IE+RXCS_DONE) -#define RXCS_IMP (RXCS_ROUT+RXCS_DRV+RXCS_FUNC) -#define RXCS_RW (RXCS_IE) /* read/write */ -#define RXCS_GETFNC(x) (((x) >> RXCS_V_FUNC) & RXCS_M_FUNC) - -#define RXES_CRC 0001 /* CRC error */ -#define RXES_PAR 0002 /* parity error */ -#define RXES_ID 0004 /* init done */ -#define RXES_WLK 0010 /* write protect */ -#define RXES_DD 0100 /* deleted data */ -#define RXES_DRDY 0200 /* drive ready */ - -#define TRACK u3 /* current track */ -#define CALC_DA(t,s) (((t) * RX_NUMSC) + ((s) - 1)) * RX_NUMBY - -extern int32 int_req[IPL_HLVL]; -extern int32 int_vec[IPL_HLVL][32]; - -int32 rx_csr = 0; /* control/status */ -int32 rx_dbr = 0; /* data buffer */ -int32 rx_esr = 0; /* error status */ -int32 rx_ecode = 0; /* error code */ -int32 rx_track = 0; /* desired track */ -int32 rx_sector = 0; /* desired sector */ -int32 rx_state = IDLE; /* controller state */ -int32 rx_stopioe = 1; /* stop on error */ -int32 rx_cwait = 100; /* command time */ -int32 rx_swait = 10; /* seek, per track */ -int32 rx_xwait = 1; /* tr set time */ -uint8 rx_buf[RX_NUMBY] = { 0 }; /* sector buffer */ -static int32 bptr = 0; /* buffer pointer */ -int32 rx_enb = 1; /* device enable */ - -DEVICE rx_dev; -t_stat rx_rd (int32 *data, int32 PA, int32 access); -t_stat rx_wr (int32 data, int32 PA, int32 access); -t_stat rx_svc (UNIT *uptr); -t_stat rx_reset (DEVICE *dptr); -t_stat rx_boot (int32 unitno, DEVICE *dptr); -void rx_done (int esr_flags, int new_ecode); - -/* RX11 data structures - - rx_dev RX device descriptor - rx_unit RX unit list - rx_reg RX register list - rx_mod RX modifier list -*/ - -DIB rx_dib = { IOBA_RX, IOLN_RX, &rx_rd, &rx_wr, - 1, IVCL (RX), VEC_RX, { NULL } }; - -UNIT rx_unit[] = { - { UDATA (&rx_svc, - UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+UNIT_MUSTBUF, RX_SIZE) }, - { UDATA (&rx_svc, - UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+UNIT_MUSTBUF, RX_SIZE) } }; - -REG rx_reg[] = { - { ORDATA (RXCS, rx_csr, 16) }, - { ORDATA (RXDB, rx_dbr, 8) }, - { ORDATA (RXES, rx_esr, 8) }, - { ORDATA (RXERR, rx_ecode, 8) }, - { ORDATA (RXTA, rx_track, 8) }, - { ORDATA (RXSA, rx_sector, 8) }, - { DRDATA (STAPTR, rx_state, 3), REG_RO }, - { DRDATA (BUFPTR, bptr, 7) }, - { FLDATA (INT, IREQ (RX), INT_V_RX) }, - { FLDATA (ERR, rx_csr, RXCS_V_ERR) }, - { FLDATA (TR, rx_csr, RXCS_V_TR) }, - { FLDATA (IE, rx_csr, RXCS_V_IE) }, - { FLDATA (DONE, rx_csr, RXCS_V_DONE) }, - { DRDATA (CTIME, rx_cwait, 24), PV_LEFT }, - { DRDATA (STIME, rx_swait, 24), PV_LEFT }, - { DRDATA (XTIME, rx_xwait, 24), PV_LEFT }, - { FLDATA (STOP_IOE, rx_stopioe, 0) }, - { BRDATA (SBUF, rx_buf, 8, 8, RX_NUMBY) }, - { ORDATA (DEVADDR, rx_dib.ba, 32), REG_HRO }, - { ORDATA (DEVVEC, rx_dib.vec, 16), REG_HRO }, - { NULL } }; - -MTAB rx_mod[] = { - { UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL }, - { UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL }, - { MTAB_XTD|MTAB_VDV, 004, "ADDRESS", "ADDRESS", - &set_addr, &show_addr, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "VECTOR", "VECTOR", - &set_vec, &show_vec, NULL }, - { MTAB_XTD | MTAB_VDV, 0, NULL, "AUTOCONFIGURE", - &set_addr_flt, NULL, NULL }, - { 0 } }; - -DEVICE rx_dev = { - "RX", rx_unit, rx_reg, rx_mod, - RX_NUMDR, 8, 20, 1, 8, 8, - NULL, NULL, &rx_reset, - &rx_boot, NULL, NULL, - &rx_dib, DEV_FLTA | DEV_DISABLE | DEV_UBUS | DEV_QBUS }; - -/* I/O dispatch routine, I/O addresses 17777170 - 17777172 - - 17777170 floppy CSR - 17777172 floppy data register -*/ - -t_stat rx_rd (int32 *data, int32 PA, int32 access) -{ -switch ((PA >> 1) & 1) { /* decode PA<1> */ -case 0: /* RXCS */ - rx_csr = rx_csr & RXCS_IMP; /* clear junk */ - *data = rx_csr & RXCS_ROUT; - 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 */ - *data = rx_dbr; /* return data */ - break; } /* end switch PA */ -return SCPE_OK; -} - -t_stat rx_wr (int32 data, int32 PA, int32 access) -{ -int32 drv; - -switch ((PA >> 1) & 1) { /* decode PA<1> */ - -/* Writing RXCS, three cases: - 1. Writing INIT, reset device - 2. Idle and writing new function - - clear error, done, transfer ready, int req - - save int enable, function, drive - - start new function - 3. Otherwise, write IE and update interrupts -*/ - -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; - if (data & RXCS_INIT) { /* initialize? */ - 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 */ - if ((data & RXCS_IE) == 0) CLR_INT (RX); - else if ((rx_csr & (RXCS_DONE + RXCS_IE)) == RXCS_DONE) - SET_INT (RX); - rx_csr = (rx_csr & ~RXCS_RW) | (data & RXCS_RW); - break; /* end case RXCS */ - -/* Accessing RXDB, two cases: - 1. Write idle, write - 2. Write not idle and TR set, state dependent -*/ - -case 1: /* RXDB */ - if ((PA & 1) || ((rx_state != IDLE) && ((rx_csr & RXCS_TR) == 0))) - 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 */ - break; /* end case RXDB */ - } /* end switch PA */ -return SCPE_OK; -} - -/* Unit service; the action to be taken depends on the transfer state: - - IDLE Should never get here - RWDS Save sector, set TR, set RWDT - RWDT Save track, set RWXFR - RWXFR Read/write buffer - FILL copy ir to rx_buf[bptr], advance ptr - if bptr > max, finish command, else set tr - EMPTY if bptr > max, finish command, else - copy rx_buf[bptr] to ir, advance ptr, set tr - CMD_COMPLETE copy requested data to ir, finish command - INIT_COMPLETE read drive 0, track 1, sector 1 to buffer, finish command - - For RWDT and CMD_COMPLETE, the input argument is the selected drive; - otherwise, it is drive 0. -*/ - -t_stat rx_svc (UNIT *uptr) -{ -int32 i, func; -uint32 da; - -func = RXCS_GETFNC (rx_csr); /* get function */ -switch (rx_state) { /* case on state */ - -case IDLE: /* idle */ - return SCPE_IERR; /* done */ - -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 */ - break; - -case FILL: /* fill buffer */ - rx_buf[bptr] = rx_dbr; /* write next */ - bptr = bptr + 1; - if (bptr < RX_NUMBY) rx_csr = rx_csr | RXCS_TR; /* if more, set xfer */ - else rx_done (0, 0); /* else done */ - break; - -case RWDS: /* wait for sector */ - rx_sector = rx_dbr & RX_M_SECTOR; /* save sector */ - rx_csr = rx_csr | RXCS_TR; /* set xfer */ - rx_state = RWDT; /* advance state */ - return SCPE_OK; -case RWDT: /* wait for track */ - rx_track = rx_dbr & RX_M_TRACK; /* save track */ - rx_state = RWXFR; - sim_activate (uptr, /* sched done */ - rx_swait * abs (rx_track - uptr->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); } - if (rx_track >= RX_NUMTR) { /* bad track? */ - 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; } - 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; } - 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 */ - else rx_done (0, 0); - break; - -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; } - 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_done (RXES_ID, 0); /* set done */ - if ((rx_unit[1].flags & UNIT_ATT) == 0) rx_ecode = 0020; - break; } /* end case state */ -return SCPE_OK; -} - -/* Command complete. Set done and put final value in interface register, - request interrupt if needed, return to IDLE state. -*/ - -void rx_done (int32 esr_flags, int32 new_ecode) -{ -int32 drv = (rx_csr & RXCS_DRV)? 1: 0; - -rx_state = IDLE; /* now idle */ -rx_csr = rx_csr | RXCS_DONE; /* set done */ -if (rx_csr & RXCS_IE) SET_INT (RX); /* if ie, intr */ -rx_esr = (rx_esr | esr_flags) & ~RXES_DRDY; -if (rx_unit[drv].flags & UNIT_ATT) - rx_esr = rx_esr | RXES_DRDY; -if (new_ecode > 0) rx_csr = rx_csr | RXCS_ERR; /* test for error */ -if (new_ecode < 0) return; /* don't update? */ -rx_ecode = new_ecode; /* update ecode */ -rx_dbr = rx_esr; /* update RXDB */ -return; -} - -/* Device initialization. The RX is one of the few devices that schedules - an I/O transfer as part of its initialization. -*/ - -t_stat rx_reset (DEVICE *dptr) -{ -rx_csr = rx_dbr = 0; /* clear regs */ -rx_esr = rx_ecode = 0; /* clear error */ -rx_track = rx_sector = 0; /* clear addr */ -rx_state = IDLE; /* ctrl idle */ -CLR_INT (RX); /* clear int req */ -sim_cancel (&rx_unit[1]); /* cancel drive 1 */ -if (dptr->flags & DEV_DIS) sim_cancel (&rx_unit[0]); /* disabled? */ -else if (rx_unit[0].flags & UNIT_BUF) { /* attached? */ - rx_state = INIT_COMPLETE; /* yes, sched init */ - sim_activate (&rx_unit[0], rx_swait * abs (1 - rx_unit[0].TRACK)); } -else rx_done (0, 0010); /* no, error */ -return auto_config (0, 0); /* run autoconfig */ -} - -/* Device bootstrap */ - -#define BOOT_START 02000 /* start */ -#define BOOT_ENTRY (BOOT_START + 002) /* entry */ -#define BOOT_UNIT (BOOT_START + 010) /* unit number */ -#define BOOT_CSR (BOOT_START + 026) /* CSR */ -#define BOOT_LEN (sizeof (boot_rom) / sizeof (int16)) - -static const uint16 boot_rom[] = { - 042130, /* "XD" */ - 0012706, BOOT_START, /* MOV #boot_start, SP */ - 0012700, 0000000, /* MOV #unit, R0 ; unit number */ - 0010003, /* MOV R0, R3 */ - 0006303, /* ASL R3 */ - 0006303, /* ASL R3 */ - 0006303, /* ASL R3 */ - 0006303, /* ASL R3 */ - 0012701, 0177170, /* MOV #RXCS, R1 ; csr */ - 0032711, 0000040, /* BITB #40, (R1) ; ready? */ - 0001775, /* BEQ .-4 */ - 0052703, 0000007, /* BIS #READ+GO, R3 */ - 0010311, /* MOV R3, (R1) ; read & go */ - 0105711, /* TSTB (R1) ; xfr ready? */ - 0100376, /* BPL .-2 */ - 0012761, 0000001, 0000002, /* MOV #1, 2(R1) ; sector */ - 0105711, /* TSTB (R1) ; xfr ready? */ - 0100376, /* BPL .-2 */ - 0012761, 0000001, 0000002, /* MOV #1, 2(R1) ; track */ - 0005003, /* CLR R3 */ - 0032711, 0000040, /* BITB #40, (R1) ; ready? */ - 0001775, /* BEQ .-4 */ - 0012711, 0000003, /* MOV #EMPTY+GO, (R1) ; empty & go */ - 0105711, /* TSTB (R1) ; xfr, done? */ - 0001776, /* BEQ .-2 */ - 0100003, /* BPL .+010 */ - 0116123, 0000002, /* MOVB 2(R1), (R3)+ ; move byte */ - 0000772, /* BR .-012 */ - 0005002, /* CLR R2 */ - 0005003, /* CLR R3 */ - 0012704, BOOT_START+020, /* MOV #START+20, R4 */ - 0005005, /* CLR R5 */ - 0005007 /* CLR R7 */ -}; - -t_stat rx_boot (int32 unitno, DEVICE *dptr) -{ -int32 i; -extern int32 saved_PC; -extern uint16 *M; - -for (i = 0; i < BOOT_LEN; i++) M[(BOOT_START >> 1) + i] = boot_rom[i]; -M[BOOT_UNIT >> 1] = unitno & RX_M_NUMDR; -M[BOOT_CSR >> 1] = rx_dib.ba & DMASK; -saved_PC = BOOT_ENTRY; -return SCPE_OK; -} diff --git a/PDP11/pdp11_ry.c b/PDP11/pdp11_ry.c deleted file mode 100644 index 1a17cd9b..00000000 --- a/PDP11/pdp11_ry.c +++ /dev/null @@ -1,632 +0,0 @@ -/* pdp11_ry.c: RY11/RX02 floppy disk simulator - - 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. - - ry RY11/RX02 floppy disk - - 19-May-03 RMS Revised for new conditional compilation scheme - 25-Apr-03 RMS Revised for extended file support - 14-Mar-03 RMS Fixed variable size interaction with save/restore - 03-Mar-03 RMS Fixed autosizing - 12-Oct-02 RMS Added autoconfigure support - - An RX02 diskette consists of 77 tracks, each with 26 sectors of 256B. - Tracks are numbered 0-76, sectors 1-26. -*/ - -#if defined (VM_PDP10) /* PDP10 version */ -#include "pdp10_defs.h" -extern int32 int_req; -extern int32 int_vec[32]; - -#elif defined (VM_VAX) /* VAX version */ -#error "RX211 not supported on VAX!" - -#else /* PDP-11 version */ -#include "pdp11_defs.h" -extern int32 int_req[IPL_HLVL]; -extern int32 int_vec[IPL_HLVL][32]; -#endif - -#define RX_NUMTR 77 /* tracks/disk */ -#define RX_M_TRACK 0377 -#define RX_NUMSC 26 /* sectors/track */ -#define RX_M_SECTOR 0177 -#define RX_NUMBY 128 -#define RX_SIZE (RX_NUMTR * RX_NUMSC * RX_NUMBY) -#define RY_NUMBY 256 /* bytes/sector */ -#define RY_SIZE (RX_NUMTR * RX_NUMSC * RY_NUMBY) -#define RX_NUMDR 2 /* drives/controller */ -#define RX_M_NUMDR 01 -#define UNIT_V_WLK (UNIT_V_UF) /* write locked */ -#define UNIT_V_DEN (UNIT_V_UF + 1) /* double density */ -#define UNIT_V_AUTO (UNIT_V_UF + 2) /* autosize */ -#define UNIT_WLK (1u << UNIT_V_WLK) -#define UNIT_DEN (1u << UNIT_V_DEN) -#define UNIT_AUTO (1u << UNIT_V_AUTO) -#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */ - -#define IDLE 0 /* idle state */ -#define RWDS 1 /* rw, sect next */ -#define RWDT 2 /* rw, track next */ -#define RWXFR 3 /* rw, transfer */ -#define FEWC 4 /* fill empty, wc next */ -#define FEBA 5 /* fill empty, ba next */ -#define FEXFR 6 /* fill empty, transfer */ -#define SDCNF 7 /* set dens, conf next */ -#define SDXFR 8 /* set dens, transfer */ -#define ESBA 9 /* ext sta, ba next */ -#define ESXFR 10 /* ext sta, transfer */ -#define CMD_COMPLETE 11 /* set done next */ -#define INIT_COMPLETE 12 /* init compl next */ - -#define RYCS_V_FUNC 1 /* function */ -#define RYCS_M_FUNC 7 -#define RYCS_FILL 0 /* fill buffer */ -#define RYCS_EMPTY 1 /* empty buffer */ -#define RYCS_WRITE 2 /* write sector */ -#define RYCS_READ 3 /* read sector */ -#define RYCS_SDEN 4 /* set density */ -#define RYCS_RYES 5 /* read status */ -#define RYCS_WRDEL 6 /* write del data */ -#define RYCS_ESTAT 7 /* read ext status */ -#define RYCS_V_DRV 4 /* drive select */ -#define RYCS_V_DONE 5 /* done */ -#define RYCS_V_IE 6 /* int enable */ -#define RYCS_V_TR 7 /* xfer request */ -#define RYCS_V_DEN 8 /* density select */ -#define RYCS_V_RY 11 /* RX02 flag */ -#define RYCS_V_UAE 12 /* addr ext */ -#define RYCS_M_UAE 03 -#define RYCS_V_INIT 14 /* init */ -#define RYCS_V_ERR 15 /* error */ -#define RYCS_FUNC (RYCS_M_FUNC << RYCS_V_FUNC) -#define RYCS_DRV (1u << RYCS_V_DRV) -#define RYCS_DONE (1u << RYCS_V_DONE) -#define RYCS_IE (1u << RYCS_V_IE) -#define RYCS_TR (1u << RYCS_V_TR) -#define RYCS_DEN (1u << RYCS_V_DEN) -#define RYCS_RY (1u << RYCS_V_RY) -#define RYCS_UAE (RYCS_M_UAE << RYCS_V_UAE) -#define RYCS_INIT (1u << RYCS_V_INIT) -#define RYCS_ERR (1u << RYCS_V_ERR) -#define RYCS_IMP (RYCS_ERR+RYCS_UAE+RYCS_DEN+RYCS_TR+RYCS_IE+\ - RYCS_DONE+RYCS_DRV+RYCS_FUNC) -#define RYCS_RW (RYCS_UAE+RYCS_DEN+RYCS_IE+RYCS_DRV+RYCS_FUNC) -#define RYCS_GETFNC(x) (((x) >> RYCS_V_FUNC) & RYCS_M_FUNC) -#define RYCS_GETUAE(x) (((x) >> RYCS_V_UAE) & RYCS_M_UAE) - -#define RYES_CRC 00001 /* CRC error NI */ -#define RYES_ID 00004 /* init done */ -#define RYES_ACLO 00010 /* ACLO NI */ -#define RYES_DERR 00020 /* density err */ -#define RYES_DDEN 00040 /* drive density */ -#define RYES_DD 00100 /* deleted data */ -#define RYES_DRDY 00200 /* drive ready */ -#define RYES_USEL 00400 /* unit selected */ -#define RYES_WCO 02000 /* wc overflow */ -#define RYES_NXM 04000 /* nxm */ -#define RYES_ERR (RYES_NXM|RYES_WCO|RYES_DERR|RYES_ACLO|RYES_CRC) - -#define TRACK u3 /* current track */ -#define CALC_DA(t,s,b) (((t) * RX_NUMSC) + ((s) - 1)) * b - -int32 ry_csr = 0; /* control/status */ -int32 ry_dbr = 0; /* data buffer */ -int32 ry_esr = 0; /* error status */ -int32 ry_ecode = 0; /* error code */ -int32 ry_track = 0; /* desired track */ -int32 ry_sector = 0; /* desired sector */ -int32 ry_ba = 0; /* bus addr */ -int32 ry_wc = 0; /* word count */ -int32 ry_state = IDLE; /* controller state */ -int32 ry_stopioe = 1; /* stop on error */ -int32 ry_cwait = 100; /* command time */ -int32 ry_swait = 10; /* seek, per track */ -int32 ry_xwait = 1; /* tr set time */ -uint8 rx2xb[RY_NUMBY] = { 0 }; /* sector buffer */ -int32 ry_enb = 0; /* device enable */ - -DEVICE ry_dev; -t_stat ry_rd (int32 *data, int32 PA, int32 access); -t_stat ry_wr (int32 data, int32 PA, int32 access); -t_stat ry_svc (UNIT *uptr); -t_stat ry_reset (DEVICE *dptr); -t_stat ry_boot (int32 unitno, DEVICE *dptr); -void ry_done (int esr_flags, int new_ecode); -t_stat ry_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat ry_attach (UNIT *uptr, char *cptr); - -/* RY11 data structures - - ry_dev RY device descriptor - ry_unit RY unit list - ry_reg RY register list - ry_mod RY modifier list -*/ - -DIB ry_dib = { IOBA_RY, IOLN_RY, &ry_rd, &ry_wr, - 1, IVCL (RY), VEC_RY, { NULL } }; - -UNIT ry_unit[] = { - { UDATA (&ry_svc, UNIT_DEN+ - UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+UNIT_MUSTBUF, RY_SIZE) }, - { UDATA (&ry_svc, UNIT_DEN+ - UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+UNIT_MUSTBUF, RY_SIZE) } }; - -REG ry_reg[] = { - { ORDATA (RYCS, ry_csr, 16) }, - { ORDATA (RYBA, ry_ba, 16) }, - { ORDATA (RYWC, ry_wc, 8) }, - { ORDATA (RYDB, ry_dbr, 16) }, - { ORDATA (RYES, ry_esr, 12) }, - { ORDATA (RYERR, ry_ecode, 8) }, - { ORDATA (RYTA, ry_track, 8) }, - { ORDATA (RYSA, ry_sector, 8) }, - { DRDATA (STAPTR, ry_state, 4), REG_RO }, - { FLDATA (INT, IREQ (RY), INT_V_RY) }, - { FLDATA (ERR, ry_csr, RYCS_V_ERR) }, - { FLDATA (TR, ry_csr, RYCS_V_TR) }, - { FLDATA (IE, ry_csr, RYCS_V_IE) }, - { FLDATA (DONE, ry_csr, RYCS_V_DONE) }, - { DRDATA (CTIME, ry_cwait, 24), PV_LEFT }, - { DRDATA (STIME, ry_swait, 24), PV_LEFT }, - { DRDATA (XTIME, ry_xwait, 24), PV_LEFT }, - { BRDATA (SBUF, rx2xb, 8, 8, RY_NUMBY) }, - { FLDATA (STOP_IOE, ry_stopioe, 0) }, - { URDATA (CAPAC, ry_unit[0].capac, 10, T_ADDR_W, 0, - RX_NUMDR, REG_HRO | PV_LEFT) }, - { ORDATA (DEVADDR, ry_dib.ba, 32), REG_HRO }, - { ORDATA (DEVVEC, ry_dib.vec, 16), REG_HRO }, - { NULL } }; - -MTAB ry_mod[] = { - { UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL }, - { UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL }, - { (UNIT_DEN+UNIT_ATT), UNIT_ATT, "single density", NULL, NULL }, - { (UNIT_DEN+UNIT_ATT), (UNIT_DEN+UNIT_ATT), "double density", NULL, NULL }, - { (UNIT_AUTO+UNIT_DEN+UNIT_ATT), 0, "single density", NULL, NULL }, - { (UNIT_AUTO+UNIT_DEN+UNIT_ATT), UNIT_DEN, "double density", NULL, NULL }, - { (UNIT_AUTO+UNIT_ATT), UNIT_AUTO, "autosize", NULL, NULL }, - { UNIT_AUTO, UNIT_AUTO, NULL, "AUTOSIZE", NULL }, - { (UNIT_AUTO+UNIT_DEN), 0, NULL, "SINGLE", &ry_set_size }, - { (UNIT_AUTO+UNIT_DEN), UNIT_DEN, NULL, "DOUBLE", &ry_set_size }, - { MTAB_XTD|MTAB_VDV, 004, "ADDRESS", "ADDRESS", - &set_addr, &show_addr, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "VECTOR", "VECTOR", - &set_vec, &show_vec, NULL }, -#if defined (VM_PDP11) - { MTAB_XTD | MTAB_VDV, 0, NULL, "AUTOCONFIGURE", - &set_addr_flt, NULL, NULL }, -#endif - { 0 } }; - -DEVICE ry_dev = { - "RY", ry_unit, ry_reg, ry_mod, - RX_NUMDR, 8, 20, 1, 8, 8, - NULL, NULL, &ry_reset, - &ry_boot, &ry_attach, NULL, - &ry_dib, DEV_FLTA | DEV_DISABLE | DEV_DIS | DEV_UBUS }; - -/* I/O dispatch routine, I/O addresses 17777170 - 17777172 - - 17777170 floppy CSR - 17777172 floppy data register -*/ - -t_stat ry_rd (int32 *data, int32 PA, int32 access) -{ -switch ((PA >> 1) & 1) { /* decode PA<1> */ -case 0: /* RYCS */ - ry_csr = (ry_csr & RYCS_IMP) | RYCS_RY; /* clear junk */ - *data = ry_csr; - break; -case 1: /* RYDB */ - *data = ry_dbr; /* return data */ - break; } /* end switch PA */ -return SCPE_OK; -} - -t_stat ry_wr (int32 data, int32 PA, int32 access) -{ -int32 drv; - -switch ((PA >> 1) & 1) { /* decode PA<1> */ - -/* Writing RYCS, three cases: - 1. Writing INIT, reset device - 2. Idle and writing new function - - clear error, done, transfer ready, int req - - save int enable, function, drive - - start new function - 3. Otherwise, write IE and update interrupts -*/ - -case 0: /* RYCS */ - ry_csr = (ry_csr & RYCS_IMP) | RYCS_RY; /* clear junk */ - if (access == WRITEB) data = (PA & 1)? /* write byte? */ - (ry_csr & 0377) | (data << 8): (ry_csr & ~0377) | data; - if (data & RYCS_INIT) { /* initialize? */ - ry_reset (&ry_dev); /* reset device */ - return SCPE_OK; } /* end if init */ - if ((data & CSR_GO) && (ry_state == IDLE)) { /* new function? */ - ry_csr = (data & RYCS_RW) | RYCS_RY; - drv = ((ry_csr & RYCS_DRV)? 1: 0); /* reselect drv */ - switch (RYCS_GETFNC (data)) { - case RYCS_FILL: case RYCS_EMPTY: - ry_state = FEWC; /* state = get wc */ - ry_csr = ry_csr | RYCS_TR; /* xfer is ready */ - break; - case RYCS_SDEN: - ry_state = SDCNF; /* state = get conf */ - ry_csr = ry_csr | RYCS_TR; /* xfer is ready */ - break; - case RYCS_ESTAT: - ry_state = ESBA; /* state = get ba */ - ry_csr = ry_csr | RYCS_TR; /* xfer is ready */ - break; - case RYCS_READ: case RYCS_WRITE: case RYCS_WRDEL: - ry_state = RWDS; /* state = get sector */ - ry_csr = ry_csr | RYCS_TR; /* xfer is ready */ - ry_esr = ry_esr & RYES_ID; /* clear errors */ - ry_ecode = 0; - break; - default: - ry_state = CMD_COMPLETE; /* state = cmd compl */ - sim_activate (&ry_unit[drv], ry_cwait); - break; } /* end switch func */ - return SCPE_OK; } /* end if GO */ - if ((data & RYCS_IE) == 0) CLR_INT (RY); - else if ((ry_csr & (RYCS_DONE + RYCS_IE)) == RYCS_DONE) - SET_INT (RY); - ry_csr = (ry_csr & ~RYCS_RW) | (data & RYCS_RW); - break; /* end case RYCS */ - -/* Accessing RYDB, two cases: - 1. Write idle, write - 2. Write not idle and TR set, state dependent -*/ - -case 1: /* RYDB */ - if ((PA & 1) || ((ry_state != IDLE) && ((ry_csr & RYCS_TR) == 0))) - return SCPE_OK; /* if ~IDLE, need tr */ - ry_dbr = data; /* save data */ - if (ry_state != IDLE) { - drv = ((ry_csr & RYCS_DRV)? 1: 0); /* select drv */ - sim_activate (&ry_unit[drv], ry_xwait); /* sched event */ - ry_csr = ry_csr & ~RYCS_TR; } /* clear xfer */ - break; /* end case RYDB */ - } /* end switch PA */ -return SCPE_OK; -} - -/* Unit service; the action to be taken depends on the transfer state: - - IDLE Should never get here - FEWC Save word count, set TR, set FEBA - FEBA Save bus address, set FEXFR - FEXFR Fill/empty buffer - RWDS Save sector, set TR, set RWDT - RWDT Save track, set RWXFR - RWXFR Read/write buffer - SDCNF Check confirmation, set SDXFR - SDXFR Erase disk - CMD_COMPLETE copy requested data to ir, finish command - INIT_COMPLETE read drive 0, track 1, sector 1 to buffer, finish command -*/ - -t_stat ry_svc (UNIT *uptr) -{ -int32 i, t, func, bps; -static uint8 estat[8]; -uint32 ba, da; - -func = RYCS_GETFNC (ry_csr); /* get function */ -bps = (ry_csr & RYCS_DEN)? RY_NUMBY: RX_NUMBY; /* get sector size */ -ba = (RYCS_GETUAE (ry_csr) << 16) | ry_ba; /* get mem addr */ -switch (ry_state) { /* case on state */ - -case IDLE: /* idle */ - return SCPE_IERR; -case FEWC: /* word count */ - ry_wc = ry_dbr & 0377; /* save WC */ - ry_csr = ry_csr | RYCS_TR; /* set TR */ - ry_state = FEBA; /* next state */ - return SCPE_OK; -case FEBA: /* buffer address */ - ry_ba = ry_dbr; /* save buf addr */ - ry_state = FEXFR; /* next state */ - sim_activate (uptr, ry_cwait); /* schedule xfer */ - return SCPE_OK; -case FEXFR: /* transfer */ - if ((ry_wc << 1) > bps) { /* wc too big? */ - ry_done (RYES_WCO, 0230); /* error */ - break; } - if (func == RYCS_FILL) { /* fill? read */ - for (i = 0; i < RY_NUMBY; i++) rx2xb[i] = 0; - t = Map_ReadB (ba, ry_wc << 1, rx2xb, MAP); } - else t = Map_WriteB (ba, ry_wc << 1, rx2xb, MAP); - ry_wc = t >> 1; /* adjust wc */ - ry_done (t? RYES_NXM: 0, 0); /* done */ - break; - -case RWDS: /* wait for sector */ - ry_sector = ry_dbr & RX_M_SECTOR; /* save sector */ - ry_csr = ry_csr | RYCS_TR; /* set xfer */ - ry_state = RWDT; /* advance state */ - return SCPE_OK; -case RWDT: /* wait for track */ - ry_track = ry_dbr & RX_M_TRACK; /* save track */ - ry_state = RWXFR; /* next state */ - sim_activate (uptr, /* sched xfer */ - ry_swait * abs (ry_track - uptr->TRACK)); - return SCPE_OK; -case RWXFR: /* read/write */ - if ((uptr->flags & UNIT_BUF) == 0) { /* not buffered? */ - ry_done (0, 0110); /* done, error */ - return IORETURN (ry_stopioe, SCPE_UNATT); } - if (ry_track >= RX_NUMTR) { /* bad track? */ - ry_done (0, 0040); /* done, error */ - break; } - uptr->TRACK = ry_track; /* now on track */ - if ((ry_sector == 0) || (ry_sector > RX_NUMSC)) { /* bad sect? */ - ry_done (0, 0070); /* done, error */ - break; } - if (((uptr->flags & UNIT_DEN) != 0) ^ - ((ry_csr & RYCS_DEN) != 0)) { /* densities agree? */ - ry_done (RYES_DERR, 0240); /* no, error */ - break; } - da = CALC_DA (ry_track, ry_sector, bps); /* get disk address */ - if (func == RYCS_WRDEL) ry_esr = ry_esr | RYES_DD; /* del data? */ - if (func == RYCS_READ) { /* read? */ - for (i = 0; i < bps; i++) - rx2xb[i] = *(((int8 *) uptr->filebuf) + da + i); } - else { if (uptr->flags & UNIT_WPRT) { /* write and locked? */ - ry_done (0, 0100); /* done, error */ - break; } - for (i = 0; i < bps; i++) /* write */ - *(((int8 *) uptr->filebuf) + da + i) = rx2xb[i]; - da = da + bps; - if (da > uptr->hwmark) uptr->hwmark = da; } - ry_done (0, 0); /* done */ - break; - -case SDCNF: /* confirm set density */ - if ((ry_dbr & 0377) != 0111) { /* confirmed? */ - ry_done (0, 0250); /* no, error */ - break; } - ry_state = SDXFR; /* next state */ - sim_activate (uptr, ry_cwait * 100); /* schedule operation */ - break; -case SDXFR: /* erase disk */ - for (i = 0; i < (int32) uptr->capac; i++) - *(((int8 *) uptr->filebuf) + i) = 0; - uptr->hwmark = uptr->capac; - if (ry_csr & RYCS_DEN) uptr->flags = uptr->flags | UNIT_DEN; - else uptr->flags = uptr->flags & ~UNIT_DEN; - ry_done (0, 0); - break; - -case ESBA: - ry_ba = ry_dbr; /* save WC */ - ry_state = ESXFR; /* next state */ - sim_activate (uptr, ry_cwait); /* schedule xfer */ - return SCPE_OK; -case ESXFR: - estat[0] = ry_ecode; /* fill 8B status */ - estat[1] = ry_wc; - estat[2] = ry_unit[0].TRACK; - estat[3] = ry_unit[1].TRACK; - estat[4] = ry_track; - estat[5] = ry_sector; - estat[6] = ((ry_csr & RYCS_DRV)? 0200: 0) | - ((ry_unit[1].flags & UNIT_DEN)? 0100: 0) | - ((uptr->flags & UNIT_ATT)? 0040: 0) | - ((ry_unit[0].flags & UNIT_DEN)? 0020: 0) | - ((ry_csr & RYCS_DEN)? 0001: 0); - estat[7] = uptr->TRACK; - t = Map_WriteB (ba, 8, estat, MAP); /* DMA to memory */ - ry_done (t? RYES_NXM: 0, 0); /* done */ - break; - -case CMD_COMPLETE: /* command complete */ - ry_done (0, 0); - break; - -case INIT_COMPLETE: /* init complete */ - ry_unit[0].TRACK = 1; /* drive 0 to trk 1 */ - ry_unit[1].TRACK = 0; /* drive 1 to trk 0 */ - if ((uptr->flags & UNIT_BUF) == 0) { /* not buffered? */ - ry_done (RYES_ID, 0010); /* init done, error */ - break; } - da = CALC_DA (1, 1, bps); /* track 1, sector 1 */ - for (i = 0; i < bps; i++) /* read sector */ - rx2xb[i] = *(((int8 *) uptr->filebuf) + da + i); - ry_done (RYES_ID, 0); /* set done */ - if ((ry_unit[1].flags & UNIT_ATT) == 0) ry_ecode = 0020; - break; } /* end case state */ - -return SCPE_OK; -} - -/* Command complete. Set done and put final value in interface register, - request interrupt if needed, return to IDLE state. -*/ - -void ry_done (int32 esr_flags, int32 new_ecode) -{ -int32 drv = (ry_csr & RYCS_DRV)? 1: 0; - -ry_state = IDLE; /* now idle */ -ry_csr = ry_csr | RYCS_DONE; /* set done */ -if (ry_csr & CSR_IE) SET_INT (RY); /* if ie, intr */ -ry_esr = (ry_esr | esr_flags) & ~(RYES_USEL|RYES_DDEN|RYES_DRDY); -if (drv) ry_esr = ry_esr | RYES_USEL; /* updates RYES */ -if (ry_unit[drv].flags & UNIT_ATT) { - ry_esr = ry_esr | RYES_DRDY; - if (ry_unit[drv].flags & UNIT_DEN) - ry_esr = ry_esr | RYES_DDEN; } -if ((new_ecode > 0) || (ry_esr & RYES_ERR)) /* test for error */ - ry_csr = ry_csr | RYCS_ERR; -ry_ecode = new_ecode; /* update ecode */ -ry_dbr = ry_esr; /* update RYDB */ -return; -} - -/* Device initialization. The RY is one of the few devices that schedules - an I/O transfer as part of its initialization. -*/ - -t_stat ry_reset (DEVICE *dptr) -{ -ry_csr = ry_dbr = 0; /* clear registers */ -ry_esr = ry_ecode = 0; /* clear error */ -ry_ba = ry_wc = 0; /* clear wc, ba */ -ry_track = ry_sector = 0; /* clear trk, sector */ -ry_state = IDLE; /* ctrl idle */ -CLR_INT (RY); /* clear int req */ -sim_cancel (&ry_unit[1]); /* cancel drive 1 */ -if (dptr->flags & UNIT_DIS) sim_cancel (&ry_unit[0]); /* disabled? */ -else if (ry_unit[0].flags & UNIT_BUF) { /* attached? */ - ry_state = INIT_COMPLETE; /* yes, sched init */ - sim_activate (&ry_unit[0], ry_swait * abs (1 - ry_unit[0].TRACK)); } -else ry_done (RYES_ID, 0010); /* no, error */ -return auto_config (0, 0); /* run autoconfig */ -} - -/* Attach routine */ - -t_stat ry_attach (UNIT *uptr, char *cptr) -{ -uint32 sz; - -if ((uptr->flags & UNIT_AUTO) && (sz = sim_fsize (cptr))) { - if (sz > RX_SIZE) uptr->flags = uptr->flags | UNIT_DEN; - else uptr->flags = uptr->flags & ~UNIT_DEN; } -uptr->capac = (uptr->flags & UNIT_DEN)? RY_SIZE: RX_SIZE; -return attach_unit (uptr, cptr); -} - -/* Set size routine */ - -t_stat ry_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -if (uptr->flags & UNIT_ATT) return SCPE_ALATT; -uptr->capac = val? RY_SIZE: RX_SIZE; -return SCPE_OK; -} - -/* Device bootstrap */ - -#if defined (VM_PDP11) - -#define BOOT_START 02000 /* start */ -#define BOOT_ENTRY (BOOT_START + 002) /* entry */ -#define BOOT_UNIT (BOOT_START + 010) /* unit number */ -#define BOOT_CSR (BOOT_START + 026) /* CSR */ -#define BOOT_LEN (sizeof (boot_rom) / sizeof (int16)) - -static const uint16 boot_rom[] = { - 042131, /* "YD" */ - 0012706, BOOT_START, /* MOV #boot_start, SP */ - 0012700, 0000000, /* MOV #unit, R0 ; unit number */ - 0010003, /* MOV R0, R3 */ - 0006303, /* ASL R3 */ - 0006303, /* ASL R3 */ - 0006303, /* ASL R3 */ - 0006303, /* ASL R3 */ - 0012701, 0177170, /* MOV #RYCS, R1 ; csr */ - 0005002, /* CLR R2 ; ba */ - 0005004, /* CLR R4 ; density */ - 0012705, 0000001, /* MOV #1, R5 ; sector */ - 0005104, /* DN: COM R4 ; compl dens */ - 0042704, 0177377, /* BIC #177377, R4 ; clr rest */ - 0032711, 0000040, /* RD: BIT #40, (R1) ; ready? */ - 0001775, /* BEQ .-4 */ - 0012746, 0000007, /* MOV #READ+GO, -(SP) */ - 0050416, /* BIS R4, (SP) ; or density */ - 0012611, /* MOV (SP)+, (R1) ; read & go */ - 0105711, /* TSTB (R1) ; xfr ready? */ - 0100376, /* BPL .-2 */ - 0010561, 0000002, /* MOV R5, 2(R1) ; sector */ - 0105711, /* TSTB (R1) ; xfr ready? */ - 0100376, /* BPL .-2 */ - 0012761, 0000001, 0000002, /* MOV #1, 2(R1) ; track */ - 0032711, 0000040, /* BIT #40, (R1) ; ready? */ - 0001775, /* BEQ .-4 */ - 0005711, /* TST (R1) ; error? */ - 0100003, /* BEQ OK */ - 0005704, /* TST R4 ; single? */ - 0001346, /* BNE DN ; no, try again */ - 0000000, /* HALT ; dead */ - 0012746, 0000003, /* OK: MOV #EMPTY+GO, -(SP); empty & go */ - 0050416, /* BIS R4, (SP) ; or density */ - 0012611, /* MOV (SP)+, (R1) ; read & go */ - 0105711, /* TSTB (R1) ; xfr, done? */ - 0001776, /* BPL .-2 */ - 0012746, 0000100, /* MOV #100, -(SP) ; assume sd */ - 0005704, /* TST R4 ; test dd */ - 0001401, /* BEQ .+4 */ - 0006316, /* ASL (SP) ; dd, double */ - 0011661, 0000002, /* MOV (SP), 2(R1) ; wc */ - 0105711, /* TSTB (R1) ; xfr, done? */ - 0001776, /* BPL .-2 */ - 0010261, 0000002, /* MOV R2, 2(R1) ; ba */ - 0032711, 0000040, /* BIT #40, (R1) ; ready? */ - 0001775, /* BEQ .-4 */ - 0061602, /* ADD (SP), R2 ; cvt wd to byte */ - 0062602, /* ADD (SP)+, R2 ; adv buf addr */ - 0122525, /* CMPB (R5)+, (R5)+ ; sect += 2 */ - 0020527, 0000007, /* CMP R5, #7 ; end? */ - 0101716, /* BLOS RD ; read next */ - 0005002, /* CLR R2 */ - 0005003, /* CLR R3 */ - 0012704, BOOT_START+020, /* MOV #START+20, R4 */ - 0005005, /* CLR R5 */ - 0005007 /* CLR R7 */ -}; - -t_stat ry_boot (int32 unitno, DEVICE *dptr) -{ -int32 i; -extern int32 saved_PC; -extern uint16 *M; - -if ((ry_unit[unitno & RX_M_NUMDR].flags & UNIT_DEN) == 0) - return SCPE_NOFNC; -for (i = 0; i < BOOT_LEN; i++) M[(BOOT_START >> 1) + i] = boot_rom[i]; -M[BOOT_UNIT >> 1] = unitno & RX_M_NUMDR; -M[BOOT_CSR >> 1] = ry_dib.ba & DMASK; -saved_PC = BOOT_ENTRY; -return SCPE_OK; -} - -#else - -t_stat ry_boot (int32 unitno, DEVICE *dptr) -{ -return SCPE_NOFNC; -} - -#endif diff --git a/PDP11/pdp11_stddev.c b/PDP11/pdp11_stddev.c deleted file mode 100644 index f9c4b24d..00000000 --- a/PDP11/pdp11_stddev.c +++ /dev/null @@ -1,409 +0,0 @@ -/* pdp11_stddev.c: PDP-11 standard I/O devices simulator - - 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. - - tti,tto DL11 terminal input/output - clk KW11L line frequency clock - - 25-Apr-03 RMS Revised for extended file support - 01-Mar-03 RMS Added SET/SHOW CLOCK FREQ, SET TTI CTRL-C - 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 - Split DL11 dibs - 30-May-02 RMS Widened POS to 32b - 26-Jan-02 RMS Revised for multiple timers - 09-Jan-02 RMS Fixed bugs in KW11L (found by John Dundas) - 06-Jan-02 RMS Split I/O address routines, revised enable/disable support - 29-Nov-01 RMS Added read only unit support - 09-Nov-01 RMS Added RQDX3 support - 07-Oct-01 RMS Upgraded clock to full KW11L for RSTS/E autoconfigure - 07-Sep-01 RMS Moved function prototypes, revised interrupt mechanism - 17-Jul-01 RMS Moved function prototype - 04-Jul-01 RMS Added DZ11 support - 05-Mar-01 RMS Added clock calibration support - 30-Oct-00 RMS Standardized register order - 25-Jun-98 RMS Fixed bugs in paper tape error handling -*/ - -#include "pdp11_defs.h" - -#define TTICSR_IMP (CSR_DONE + CSR_IE) /* terminal input */ -#define TTICSR_RW (CSR_IE) -#define TTOCSR_IMP (CSR_DONE + CSR_IE) /* terminal output */ -#define TTOCSR_RW (CSR_IE) -#define CLKCSR_IMP (CSR_DONE + CSR_IE) /* real-time clock */ -#define CLKCSR_RW (CSR_IE) -#define CLK_DELAY 8000 - -#define UNIT_V_8B (UNIT_V_UF + 0) /* 8B */ -#define UNIT_8B (1 << UNIT_V_8B) - -extern int32 int_req[IPL_HLVL]; -extern int32 int_vec[IPL_HLVL][32]; - -int32 tti_csr = 0; /* control/status */ -int32 tto_csr = 0; /* control/status */ -int32 clk_csr = 0; /* control/status */ -int32 clk_tps = 60; /* ticks/second */ -int32 tmxr_poll = CLK_DELAY; /* term mux poll */ -int32 tmr_poll = CLK_DELAY; /* timer poll */ - -t_stat tti_rd (int32 *data, int32 PA, int32 access); -t_stat tti_wr (int32 data, int32 PA, int32 access); -t_stat tti_svc (UNIT *uptr); -t_stat tti_reset (DEVICE *dptr); -t_stat tto_rd (int32 *data, int32 PA, int32 access); -t_stat tto_wr (int32 data, int32 PA, int32 access); -t_stat tto_svc (UNIT *uptr); -t_stat tto_reset (DEVICE *dptr); -t_stat tti_set_ctrlc (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat tty_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat clk_rd (int32 *data, int32 PA, int32 access); -t_stat clk_wr (int32 data, int32 PA, int32 access); -t_stat clk_svc (UNIT *uptr); -t_stat clk_reset (DEVICE *dptr); -t_stat clk_set_freq (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat clk_show_freq (FILE *st, UNIT *uptr, int32 val, void *desc); - -/* TTI data structures - - tti_dev TTI device descriptor - tti_unit TTI unit descriptor - tti_reg TTI register list -*/ - -DIB tti_dib = { IOBA_TTI, IOLN_TTI, &tti_rd, &tti_wr, - 1, IVCL (TTI), VEC_TTI, { NULL } }; - -UNIT tti_unit = { UDATA (&tti_svc, 0, 0), KBD_POLL_WAIT }; - -REG tti_reg[] = { - { ORDATA (BUF, tti_unit.buf, 8) }, - { ORDATA (CSR, tti_csr, 16) }, - { FLDATA (INT, IREQ (TTI), INT_V_TTI) }, - { FLDATA (ERR, tti_csr, CSR_V_ERR) }, - { FLDATA (DONE, tti_csr, CSR_V_DONE) }, - { FLDATA (IE, tti_csr, CSR_V_IE) }, - { DRDATA (POS, tti_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, tti_unit.wait, 24), REG_NZ + PV_LEFT }, - { NULL } }; - -MTAB tti_mod[] = { - { UNIT_8B, 0 , "7b" , "7B" , &tty_set_mode }, - { UNIT_8B, UNIT_8B , "8b" , "8B" , &tty_set_mode }, - { MTAB_XTD|MTAB_VDV|MTAB_VUN, 0, NULL, "CTRL-C", - &tti_set_ctrlc, NULL, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "ADDRESS", NULL, - NULL, &show_addr, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "VECTOR", NULL, - NULL, &show_vec, NULL }, - { 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, DEV_UBUS | DEV_QBUS }; - -/* TTO data structures - - tto_dev TTO device descriptor - tto_unit TTO unit descriptor - tto_reg TTO register list -*/ - -DIB tto_dib = { IOBA_TTO, IOLN_TTO, &tto_rd, &tto_wr, - 1, IVCL (TTO), VEC_TTO, { NULL } }; - -UNIT tto_unit = { UDATA (&tto_svc, 0, 0), SERIAL_OUT_WAIT }; - -REG tto_reg[] = { - { ORDATA (BUF, tto_unit.buf, 8) }, - { ORDATA (CSR, tto_csr, 16) }, - { FLDATA (INT, IREQ (TTO), INT_V_TTO) }, - { FLDATA (ERR, tto_csr, CSR_V_ERR) }, - { FLDATA (DONE, tto_csr, CSR_V_DONE) }, - { FLDATA (IE, tto_csr, CSR_V_IE) }, - { DRDATA (POS, tto_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, tto_unit.wait, 24), PV_LEFT }, - { NULL } }; - -MTAB tto_mod[] = { - { UNIT_8B, 0 , "7b" , "7B" , &tty_set_mode }, - { UNIT_8B, UNIT_8B , "8b" , "8B" , &tty_set_mode }, - { MTAB_XTD|MTAB_VDV, 0, "ADDRESS", NULL, - NULL, &show_addr, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "VECTOR", NULL, - NULL, &show_vec, NULL }, - { 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, DEV_UBUS | DEV_QBUS }; - -/* CLK data structures - - clk_dev CLK device descriptor - clk_unit CLK unit descriptor - clk_reg CLK register list -*/ - -DIB clk_dib = { IOBA_CLK, IOLN_CLK, &clk_rd, &clk_wr, - 1, IVCL (CLK), VEC_CLK, { NULL } }; - -UNIT clk_unit = { UDATA (&clk_svc, 0, 0), 8000 }; - -REG clk_reg[] = { - { ORDATA (CSR, clk_csr, 16) }, - { FLDATA (INT, IREQ (CLK), INT_V_CLK) }, - { FLDATA (DONE, clk_csr, CSR_V_DONE) }, - { FLDATA (IE, clk_csr, CSR_V_IE) }, - { DRDATA (TIME, clk_unit.wait, 24), REG_NZ + PV_LEFT }, - { DRDATA (TPS, clk_tps, 8), PV_LEFT + REG_HRO }, - { NULL } }; - -MTAB clk_mod[] = { - { MTAB_XTD|MTAB_VDV, 50, NULL, "50HZ", - &clk_set_freq, NULL, NULL }, - { MTAB_XTD|MTAB_VDV, 60, NULL, "60HZ", - &clk_set_freq, NULL, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "FREQUENCY", NULL, - NULL, &clk_show_freq, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "ADDRESS", NULL, - NULL, &show_addr, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "VECTOR", NULL, - NULL, &show_vec, NULL }, - { 0 } }; - -DEVICE clk_dev = { - "CLK", &clk_unit, clk_reg, clk_mod, - 1, 0, 0, 0, 0, 0, - NULL, NULL, &clk_reset, - NULL, NULL, NULL, - &clk_dib, DEV_UBUS | DEV_QBUS }; - -/* Terminal input address routines */ - -t_stat tti_rd (int32 *data, int32 PA, int32 access) -{ -switch ((PA >> 1) & 01) { /* decode PA<1> */ -case 00: /* tti csr */ - *data = tti_csr & TTICSR_IMP; - return SCPE_OK; -case 01: /* tti buf */ - tti_csr = tti_csr & ~CSR_DONE; - CLR_INT (TTI); - *data = tti_unit.buf & 0377; - return SCPE_OK; } /* end switch PA */ -return SCPE_NXM; -} - -t_stat tti_wr (int32 data, int32 PA, int32 access) -{ -switch ((PA >> 1) & 01) { /* decode PA<1> */ -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); - tti_csr = (tti_csr & ~TTICSR_RW) | (data & TTICSR_RW); - return SCPE_OK; -case 01: /* tti buf */ - return SCPE_OK; } /* end switch PA */ -return SCPE_NXM; -} - -/* Terminal input service */ - -t_stat tti_svc (UNIT *uptr) -{ -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 (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); -return SCPE_OK; -} - -/* Terminal input reset */ - -t_stat tti_reset (DEVICE *dptr) -{ -tti_unit.buf = 0; -tti_csr = 0; -CLR_INT (TTI); -sim_activate (&tti_unit, tti_unit.wait); /* activate unit */ -return SCPE_OK; -} - -/* Set control-C */ - -t_stat tti_set_ctrlc (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -if (cptr) return SCPE_ARG; -uptr->buf = 003; -uptr->pos = uptr->pos + 1; -tti_csr = tti_csr | CSR_DONE; -if (tti_csr & CSR_IE) SET_INT (TTI); -return SCPE_OK; -} - -/* Terminal output address routines */ - -t_stat tto_rd (int32 *data, int32 PA, int32 access) -{ -switch ((PA >> 1) & 01) { /* decode PA<1> */ -case 00: /* tto csr */ - *data = tto_csr & TTOCSR_IMP; - return SCPE_OK; -case 01: /* tto buf */ - *data = tto_unit.buf; - return SCPE_OK; } /* end switch PA */ -return SCPE_NXM; -} - -t_stat tto_wr (int32 data, int32 PA, int32 access) -{ -switch ((PA >> 1) & 01) { /* decode PA<1> */ -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); - tto_csr = (tto_csr & ~TTOCSR_RW) | (data & TTOCSR_RW); - return SCPE_OK; -case 01: /* tto buf */ - if ((PA & 1) == 0) tto_unit.buf = data & 0377; - tto_csr = tto_csr & ~CSR_DONE; - CLR_INT (TTO); - sim_activate (&tto_unit, tto_unit.wait); - return SCPE_OK; } /* end switch PA */ -return SCPE_NXM; -} - -/* Terminal output service */ - -t_stat tto_svc (UNIT *uptr) -{ -int32 c; -t_stat r; - -tto_csr = tto_csr | CSR_DONE; -if (tto_csr & CSR_IE) SET_INT (TTO); -c = tto_unit.buf & ((tto_unit.flags & UNIT_8B)? 0377: 0177); -if ((r = sim_putchar (c)) != SCPE_OK) return r; -tto_unit.pos = tto_unit.pos + 1; -return SCPE_OK; -} - -/* Terminal output reset */ - -t_stat tto_reset (DEVICE *dptr) -{ -tto_unit.buf = 0; -tto_csr = CSR_DONE; -CLR_INT (TTO); -sim_cancel (&tto_unit); /* deactivate unit */ -return SCPE_OK; -} - -t_stat tty_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -tti_unit.flags = (tti_unit.flags & ~UNIT_8B) | val; -tto_unit.flags = (tto_unit.flags & ~UNIT_8B) | val; -return SCPE_OK; -} - -/* Clock I/O address routines */ - -t_stat clk_rd (int32 *data, int32 PA, int32 access) -{ -*data = clk_csr & CLKCSR_IMP; -return SCPE_OK; -} - -t_stat clk_wr (int32 data, int32 PA, int32 access) -{ -if (PA & 1) return SCPE_OK; -clk_csr = (clk_csr & ~CLKCSR_RW) | (data & CLKCSR_RW); -if ((data & CSR_DONE) == 0) clk_csr = clk_csr & ~CSR_DONE; -if (((clk_csr & CSR_IE) == 0) || /* unless IE+DONE */ - ((clk_csr & CSR_DONE) == 0)) CLR_INT (CLK); /* clr intr */ -return SCPE_OK; -} - -/* Clock service */ - -t_stat clk_svc (UNIT *uptr) -{ -int32 t; - -clk_csr = clk_csr | CSR_DONE; /* set done */ -if (clk_csr & CSR_IE) SET_INT (CLK); -t = sim_rtcn_calb (clk_tps, TMR_CLK); /* calibrate clock */ -sim_activate (&clk_unit, t); /* reactivate unit */ -tmr_poll = t; /* set timer poll */ -tmxr_poll = t; /* set mux poll */ -return SCPE_OK; -} - -/* Clock reset */ - -t_stat clk_reset (DEVICE *dptr) -{ -clk_csr = CSR_DONE; /* set done */ -CLR_INT (CLK); -sim_activate (&clk_unit, clk_unit.wait); /* activate unit */ -tmr_poll = clk_unit.wait; /* set timer poll */ -tmxr_poll = clk_unit.wait; /* set mux poll */ -return SCPE_OK; -} - -/* Set frequency */ - -t_stat clk_set_freq (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -if (cptr) return SCPE_ARG; -if ((val != 50) && (val != 60)) return SCPE_IERR; -clk_tps = val; -return SCPE_OK; -} - -/* Show frequency */ - -t_stat clk_show_freq (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -fprintf (st, (clk_tps == 50)? "50Hz": "60Hz"); -return SCPE_OK; -} diff --git a/PDP11/pdp11_sys.c b/PDP11/pdp11_sys.c deleted file mode 100644 index 2a140b75..00000000 --- a/PDP11/pdp11_sys.c +++ /dev/null @@ -1,902 +0,0 @@ -/* pdp11_sys.c: PDP-11 simulator interface - - 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. - - 06-May-03 RMS Added support for second DEQNA/DELQA - 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 - 29-Nov-01 RMS Added read only unit support - 17-Sep-01 RMS Removed multiconsole support - 26-Aug-01 RMS Added DZ11 - 20-Aug-01 RMS Updated bad block inquiry - 17-Jul-01 RMS Fixed warning from VC++ 6.0 - 27-May-01 RMS Added multiconsole support - 05-Apr-01 RMS Added support for TS11/TSV05 - 14-Mar-01 RMS Revised load/dump interface (again) - 11-Feb-01 RMS Added DECtape support - 30-Oct-00 RMS Added support for examine to file - 14-Apr-99 RMS Changed t_addr to unsigned - 09-Nov-98 RMS Fixed assignments of ROR/ROL (John Wilson) - 27-Oct-98 RMS V2.4 load interface - 08-Oct-98 RMS Fixed bug in bad block routine - 30-Mar-98 RMS Fixed bug in floating point display - 12-Nov-97 RMS Added bad block table routine -*/ - -#include "pdp11_defs.h" -#include - -extern DEVICE cpu_dev; -extern DEVICE ptr_dev, ptp_dev; -extern DEVICE tti_dev, tto_dev; -extern DEVICE lpt_dev; -extern DEVICE clk_dev, pclk_dev; -extern DEVICE dz_dev; -extern DEVICE rk_dev, rl_dev; -extern DEVICE hk_dev; -extern DEVICE rx_dev, ry_dev; -extern DEVICE rp_dev; -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, xqb_dev; -extern DEVICE xu_dev; -extern UNIT cpu_unit; -extern REG cpu_reg[]; -extern uint16 *M; -extern int32 saved_PC; - -/* 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-11"; - -REG *sim_PC = &cpu_reg[0]; - -int32 sim_emax = 4; - -DEVICE *sim_devices[] = { - &cpu_dev, - &ptr_dev, - &ptp_dev, - &tti_dev, - &tto_dev, - &lpt_dev, - &clk_dev, - &pclk_dev, - &dz_dev, - &rk_dev, - &rl_dev, - &hk_dev, - &rx_dev, - &ry_dev, - &rp_dev, - &rq_dev, - &rqb_dev, - &rqc_dev, - &rqd_dev, - &dt_dev, - &tm_dev, - &ts_dev, - &tq_dev, - &xq_dev, - &xqb_dev, - &xu_dev, - NULL }; - -const char *sim_stop_messages[] = { - "Unknown error", - "Red stack trap", - "Odd address trap", - "Memory management trap", - "Non-existent memory trap", - "Parity error trap", - "Privilege trap", - "Illegal instruction trap", - "BPT trap", - "IOT trap", - "EMT trap", - "TRAP trap", - "Trace trap", - "Yellow stack trap", - "Powerfail trap", - "Floating point exception", - "HALT instruction", - "Breakpoint", - "Wait state", - "Trap vector fetch abort", - "Trap stack push abort", - "RQDX3 consistency error", - "Sanity timer expired" }; - -/* Binary loader. - - Loader format consists of blocks, optionally preceded, separated, and - followed by zeroes. Each block consists of: - - 001 --- - xxx | - lo_count | - hi_count | - lo_origin > count bytes - hi_origin | - data byte | - : | - data byte --- - checksum - - If the byte count is exactly six, the block is the last on the tape, and - there is no checksum. If the origin is not 000001, then the origin is - the PC at which to start the program. -*/ - -t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag) -{ -int32 csum, count, state, i; -uint32 origin; - -if ((*cptr != 0) || (flag != 0)) return SCPE_ARG; -state = csum = 0; -while ((i = getc (fileref)) != EOF) { - csum = csum + i; /* add into chksum */ - switch (state) { - case 0: /* leader */ - if (i == 1) state = 1; - else csum = 0; - break; - case 1: /* ignore after 001 */ - state = 2; - break; - case 2: /* low count */ - count = i; - state = 3; - break; - case 3: /* high count */ - count = (i << 8) | count; - state = 4; - break; - case 4: /* low origin */ - origin = i; - state = 5; - break; - case 5: /* high origin */ - origin = (i << 8) | origin; - if (count == 6) { - if (origin != 1) saved_PC = origin & 0177776; - return SCPE_OK; } - count = count - 6; - state = 6; - break; - case 6: /* data */ - if (origin >= MEMSIZE) return SCPE_NXM; - M[origin >> 1] = (origin & 1)? - (M[origin >> 1] & 0377) | (i << 8): - (M[origin >> 1] & 0177400) | i; - origin = origin + 1; - count = count - 1; - state = state + (count == 0); - break; - case 7: /* checksum */ - if (csum & 0377) return SCPE_CSUM; - csum = state = 0; - break; } /* end switch */ - } /* end while */ -return SCPE_FMT; /* unexpected eof */ -} - -/* Factory bad block table creation routine - - This routine writes a DEC standard 044 compliant bad block table on the - last track of the specified unit. The bad block table consists of 10 - repetitions of the same table, formatted as follows: - - words 0-1 pack id number - words 2-3 cylinder/sector/surface specifications - : - words n-n+1 end of table (-1,-1) - - Inputs: - uptr = pointer to unit - sec = number of sectors per surface - wds = number of words per sector - Outputs: - sta = status code -*/ - -t_stat pdp11_bad_block (UNIT *uptr, int32 sec, int32 wds) -{ -int32 i, da; -int16 *buf; - -if ((sec < 2) || (wds < 16)) return SCPE_ARG; -if ((uptr->flags & UNIT_ATT) == 0) return SCPE_UNATT; -if (uptr->flags & UNIT_RO) return SCPE_RO; -if (!get_yn ("Create bad block table on last track? [N]", FALSE)) return SCPE_OK; -da = (uptr->capac - (sec * wds)) * sizeof (int16); -if (fseek (uptr->fileref, da, SEEK_SET)) return SCPE_IOERR; -if ((buf = malloc (wds * sizeof (int16))) == NULL) return SCPE_MEM; -buf[0] = buf[1] = 012345u; -buf[2] = buf[3] = 0; -for (i = 4; i < wds; i++) buf[i] = 0177777u; -for (i = 0; (i < sec) && (i < 10); i++) - fxwrite (buf, sizeof (int16), wds, uptr->fileref); -free (buf); -if (ferror (uptr->fileref)) return SCPE_IOERR; -return SCPE_OK; -} - -/* Symbol tables */ - -#define I_V_L 16 /* long mode */ -#define I_V_D 17 /* double mode */ -#define I_L (1 << I_V_L) -#define I_D (1 << I_V_D) - -/* Warning: for literals, the class number MUST equal the field width!! */ - -#define I_V_CL 18 /* class bits */ -#define I_M_CL 017 /* class mask */ -#define I_V_NPN 0 /* no operands */ -#define I_V_REG 1 /* reg */ -#define I_V_SOP 2 /* operand */ -#define I_V_3B 3 /* 3b literal */ -#define I_V_FOP 4 /* flt operand */ -#define I_V_AFOP 5 /* fac, flt operand */ -#define I_V_6B 6 /* 6b literal */ -#define I_V_BR 7 /* cond branch */ -#define I_V_8B 8 /* 8b literal */ -#define I_V_SOB 9 /* reg, disp */ -#define I_V_RSOP 10 /* reg, operand */ -#define I_V_ASOP 11 /* fac, operand */ -#define I_V_ASMD 12 /* fac, moded int op */ -#define I_V_DOP 13 /* double operand */ -#define I_V_CCC 14 /* CC clear */ -#define I_V_CCS 15 /* CC set */ -#define I_NPN (I_V_NPN << I_V_CL) -#define I_REG (I_V_REG << I_V_CL) -#define I_3B (I_V_3B << I_V_CL) -#define I_SOP (I_V_SOP << I_V_CL) -#define I_FOP (I_V_FOP << I_V_CL) -#define I_6B (I_V_6B << I_V_CL) -#define I_BR (I_V_BR << I_V_CL) -#define I_8B (I_V_8B << I_V_CL) -#define I_AFOP (I_V_AFOP << I_V_CL) -#define I_ASOP (I_V_ASOP << I_V_CL) -#define I_RSOP (I_V_RSOP << I_V_CL) -#define I_SOB (I_V_SOB << I_V_CL) -#define I_ASMD (I_V_ASMD << I_V_CL) -#define I_DOP (I_V_DOP << I_V_CL) -#define I_CCC (I_V_CCC << I_V_CL) -#define I_CCS (I_V_CCS << I_V_CL) - -static const int32 masks[] = { -0177777, 0177770, 0177700, 0177770, -0177700+I_D, 0177400+I_D, 0177700, 0177400, -0177400, 0177000, 0177000, 0177400, -0177400+I_D+I_L, 0170000, 0177777, 0177777 }; - -static const char *opcode[] = { -"HALT","WAIT","RTI","BPT", -"IOT","RESET","RTT","MFPT", -"JMP","RTS","SPL", -"NOP","CLC","CLV","CLV CLC", -"CLZ","CLZ CLC","CLZ CLV","CLZ CLV CLC", -"CLN","CLN CLC","CLN CLV","CLN CLV CLC", -"CLN CLZ","CLN CLZ CLC","CLN CLZ CLC","CCC", -"NOP","SEC","SEV","SEV SEC", -"SEZ","SEZ SEC","SEZ SEV","SEZ SEV SEC", -"SEN","SEN SEC","SEN SEV","SEN SEV SEC", -"SEN SEZ","SEN SEZ SEC","SEN SEZ SEC","SCC", -"SWAB","BR","BNE","BEQ", -"BGE","BLT","BGT","BLE", -"JSR", -"CLR","COM","INC","DEC", -"NEG","ADC","SBC","TST", -"ROR","ROL","ASR","ASL", -"MARK","MFPI","MTPI","SXT", -"CSM", "TSTSET","WRTLCK", -"MOV","CMP","BIT","BIC", -"BIS","ADD", -"MUL","DIV","ASH","ASHC", -"XOR", -"FADD","FSUB","FMUL","FDIV", -"L2DR", -"MOVC","MOVRC","MOVTC", -"LOCC","SKPC","SCANC","SPANC", -"CMPC","MATC", -"ADDN","SUBN","CMPN","CVTNL", -"CVTPN","CVTNP","ASHN","CVTLN", -"L3DR", -"ADDP","SUBP","CMPP","CVTPL", -"MULP","DIVP","ASHP","CVTLP", -"MOVCI","MOVRCI","MOVTCI", -"LOCCI","SKPCI","SCANCI","SPANCI", -"CMPCI","MATCI", -"ADDNI","SUBNI","CMPNI","CVTNLI", -"CVTPNI","CVTNPI","ASHNI","CVTLNI", -"ADDPI","SUBPI","CMPPI","CVTPLI", -"MULPI","DIVPI","ASHPI","CVTLPI", -"SOB", -"BPL","BMI","BHI","BLOS", -"BVC","BVS","BCC","BCS", -"BHIS","BLO", /* encode only */ -"EMT","TRAP", -"CLRB","COMB","INCB","DECB", -"NEGB","ADCB","SBCB","TSTB", -"RORB","ROLB","ASRB","ASLB", -"MTPS","MFPD","MTPD","MFPS", -"MOVB","CMPB","BITB","BICB", -"BISB","SUB", -"CFCC","SETF","SETI","SETD","SETL", -"LDFPS","STFPS","STST", -"CLRF","CLRD","TSTF","TSTD", -"ABSF","ABSD","NEGF","NEGD", -"MULF","MULD","MODF","MODD", -"ADDF","ADDD","LDF","LDD", -"SUBF","SUBD","CMPF","CMPD", -"STF","STD","DIVF","DIVD", -"STEXP", -"STCFI","STCDI","STCFL","STCDL", -"STCFD","STCDF", -"LDEXP", -"LDCIF","LDCID","LDCLF","LDCLD", -"LDCFD","LDCDF", -NULL }; - -static const int32 opc_val[] = { -0000000+I_NPN, 0000001+I_NPN, 0000002+I_NPN, 0000003+I_NPN, -0000004+I_NPN, 0000005+I_NPN, 0000006+I_NPN, 0000007+I_NPN, -0000100+I_SOP, 0000200+I_REG, 0000230+I_3B, -0000240+I_CCC, 0000241+I_CCC, 0000242+I_CCC, 0000243+I_NPN, -0000244+I_CCC, 0000245+I_NPN, 0000246+I_NPN, 0000247+I_NPN, -0000250+I_CCC, 0000251+I_NPN, 0000252+I_NPN, 0000253+I_NPN, -0000254+I_NPN, 0000255+I_NPN, 0000256+I_NPN, 0000257+I_CCC, -0000260+I_CCS, 0000261+I_CCS, 0000262+I_CCS, 0000263+I_NPN, -0000264+I_CCS, 0000265+I_NPN, 0000266+I_NPN, 0000267+I_NPN, -0000270+I_CCS, 0000271+I_NPN, 0000272+I_NPN, 0000273+I_NPN, -0000274+I_NPN, 0000275+I_NPN, 0000276+I_NPN, 0000277+I_CCS, -0000300+I_SOP, 0000400+I_BR, 0001000+I_BR, 0001400+I_BR, -0002000+I_BR, 0002400+I_BR, 0003000+I_BR, 0003400+I_BR, -0004000+I_RSOP, -0005000+I_SOP, 0005100+I_SOP, 0005200+I_SOP, 0005300+I_SOP, -0005400+I_SOP, 0005500+I_SOP, 0005600+I_SOP, 0005700+I_SOP, -0006000+I_SOP, 0006100+I_SOP, 0006200+I_SOP, 0006300+I_SOP, -0006400+I_6B, 0006500+I_SOP, 0006600+I_SOP, 0006700+I_SOP, -0007000+I_SOP, 0007200+I_SOP, 0007300+I_SOP, -0010000+I_DOP, 0020000+I_DOP, 0030000+I_DOP, 0040000+I_DOP, -0050000+I_DOP, 0060000+I_DOP, -0070000+I_RSOP, 0071000+I_RSOP, 0072000+I_RSOP, 0073000+I_RSOP, -0074000+I_RSOP, -0075000+I_REG, 0075010+I_REG, 0075020+I_REG, 0075030+I_REG, -0076020+I_REG, -0076030+I_NPN, 0076031+I_NPN, 0076032+I_NPN, -0076040+I_NPN, 0076041+I_NPN, 0076042+I_NPN, 0076043+I_NPN, -0076044+I_NPN, 0076045+I_NPN, -0076050+I_NPN, 0076051+I_NPN, 0076052+I_NPN, 0076053+I_NPN, -0076054+I_NPN, 0076055+I_NPN, 0076056+I_NPN, 0076057+I_NPN, -0076060+I_REG, -0076070+I_NPN, 0076071+I_NPN, 0076072+I_NPN, 0076073+I_NPN, -0076074+I_NPN, 0076075+I_NPN, 0076076+I_NPN, 0076077+I_NPN, -0076130+I_NPN, 0076131+I_NPN, 0076132+I_NPN, -0076140+I_NPN, 0076141+I_NPN, 0076142+I_NPN, 0076143+I_NPN, -0076144+I_NPN, 0076145+I_NPN, -0076150+I_NPN, 0076151+I_NPN, 0076152+I_NPN, 0076153+I_NPN, -0076154+I_NPN, 0076155+I_NPN, 0076156+I_NPN, 0076157+I_NPN, -0076170+I_NPN, 0076171+I_NPN, 0076172+I_NPN, 0076173+I_NPN, -0076174+I_NPN, 0076175+I_NPN, 0076176+I_NPN, 0076177+I_NPN, -0077000+I_SOB, -0100000+I_BR, 0100400+I_BR, 0101000+I_BR, 0101400+I_BR, -0102000+I_BR, 0102400+I_BR, 0103000+I_BR, 0103400+I_BR, -0103000+I_BR, 0103400+I_BR, -0104000+I_8B, 0104400+I_8B, -0105000+I_SOP, 0105100+I_SOP, 0105200+I_SOP, 0105300+I_SOP, -0105400+I_SOP, 0105500+I_SOP, 0105600+I_SOP, 0105700+I_SOP, -0106000+I_SOP, 0106100+I_SOP, 0106200+I_SOP, 0106300+I_SOP, -0106400+I_SOP, 0106500+I_SOP, 0106600+I_SOP, 0106700+I_SOP, -0110000+I_DOP, 0120000+I_DOP, 0130000+I_DOP, 0140000+I_DOP, -0150000+I_DOP, 0160000+I_DOP, -0170000+I_NPN, 0170001+I_NPN, 0170002+I_NPN, 0170011+I_NPN, 0170012+I_NPN, -0170100+I_SOP, 0170200+I_SOP, 0170300+I_SOP, -0170400+I_FOP, 0170400+I_FOP+I_D, 0170500+I_FOP, 0170500+I_FOP+I_D, -0170600+I_FOP, 0170600+I_FOP+I_D, 0170700+I_FOP, 0170700+I_FOP+I_D, -0171000+I_AFOP, 0171000+I_AFOP+I_D, 0171400+I_AFOP, 0171400+I_AFOP+I_D, -0172000+I_AFOP, 0172000+I_AFOP+I_D, 0172400+I_AFOP, 0172400+I_AFOP+I_D, -0173000+I_AFOP, 0173000+I_AFOP+I_D, 0173400+I_AFOP, 0173400+I_AFOP+I_D, -0174000+I_AFOP, 0174000+I_AFOP+I_D, 0174400+I_AFOP, 0174400+I_AFOP+I_D, -0175000+I_ASOP, -0175400+I_ASMD, 0175400+I_ASMD+I_D, 0175400+I_ASMD+I_L, 0175400+I_ASMD+I_D+I_L, -0176000+I_AFOP, 0176000+I_AFOP+I_D, -0176400+I_ASOP, -0177000+I_ASMD, 0177000+I_ASMD+I_D, 0177000+I_ASMD+I_L, 0177000+I_ASMD+I_D+I_L, -0177400+I_AFOP, 0177400+I_AFOP+I_D, --1 }; - -static const char *rname [] = -{ "R0", "R1", "R2", "R3", "R4", "R5", "SP", "PC" }; - -static const char *fname [] = -{ "F0", "F1", "F2", "F3", "F4", "F5", "?6", "?7" }; - -static const char r50_to_asc[] = " ABCDEFGHIJKLMNOPQRSTUVWXYZ$._0123456789"; - -/* Specifier decode - - Inputs: - *of = output stream - addr = current PC - spec = specifier - nval = next word - flag = TRUE if decoding for CPU - iflag = TRUE if decoding integer instruction - Outputs: - count = -number of extra words retired -*/ - -int32 fprint_spec (FILE *of, t_addr addr, int32 spec, t_value nval, - int32 flag, int32 iflag) -{ -int32 reg, mode; -static const int32 rgwd[8] = { 0, 0, 0, 0, 0, 0, -1, -1 }; -static const int32 pcwd[8] = { 0, 0, -1, -1, 0, 0, -1, -1 }; - -reg = spec & 07; -mode = ((spec >> 3) & 07); -switch (mode) { -case 0: - if (iflag) fprintf (of, "%s", rname[reg]); - else fprintf (of, "%s", fname[reg]); - break; -case 1: - fprintf (of, "(%s)", rname[reg]); - break; -case 2: - if (reg != 7) fprintf (of, "(%s)+", rname[reg]); - else fprintf (of, "#%-o", nval); - break; -case 3: - if (reg != 7) fprintf (of, "@(%s)+", rname[reg]); - else fprintf (of, "@#%-o", nval); - break; -case 4: - fprintf (of, "-(%s)", rname[reg]); - break; -case 5: - fprintf (of, "@-(%s)", rname[reg]); - break; -case 6: - if ((reg != 7) || !flag) fprintf (of, "%-o(%s)", nval, rname[reg]); - else fprintf (of, "%-o", (nval + addr + 4) & 0177777); - break; -case 7: - if ((reg != 7) || !flag) fprintf (of, "@%-o(%s)", nval, rname[reg]); - else fprintf (of, "@%-o", (nval + addr + 4) & 0177777); - break; } /* end case */ -return ((reg == 07)? pcwd[mode]: rgwd[mode]); -} - -/* 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 words retired -*/ - -t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, - UNIT *uptr, int32 sw) -{ -int32 cflag, i, j, c1, c2, c3, inst, fac, srcm, srcr, dstm, dstr; -int32 l8b, brdisp, wd1, wd2; -extern int32 FPS; - -cflag = (uptr == NULL) || (uptr == &cpu_unit); -c1 = val[0] & 0177; -c2 = (val[0] >> 8) & 0177; -if (sw & SWMASK ('A')) { /* ASCII? */ - fprintf (of, (c1 < 040)? "<%03o>": "%c", c1); - return SCPE_OK; } -if (sw & SWMASK ('C')) { /* character? */ - fprintf (of, (c1 < 040)? "<%03o>": "%c", c1); - fprintf (of, (c2 < 040)? "<%03o>": "%c", c2); - return SCPE_OK; } -if (sw & SWMASK ('R')) { /* radix 50? */ - if (val[0] > 0174777) return SCPE_ARG; /* max value */ - c3 = val[0] % 050; - c2 = (val[0] / 050) % 050; - c1 = val[0] / (050 * 050); - fprintf (of, "%c%c%c", r50_to_asc[c1], - r50_to_asc[c2], r50_to_asc[c3]); - return SCPE_OK; } -if (!(sw & SWMASK ('M'))) return SCPE_ARG; - -inst = val[0] | ((FPS << (I_V_L - FPS_V_L)) & I_L) | - ((FPS << (I_V_D - FPS_V_D)) & I_D); /* inst + fp mode */ -for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */ - j = (opc_val[i] >> I_V_CL) & I_M_CL; /* get class */ - if ((opc_val[i] & 0777777) == (inst & masks[j])) { /* match? */ - srcm = (inst >> 6) & 077; /* opr fields */ - srcr = srcm & 07; - fac = srcm & 03; - dstm = inst & 077; - dstr = dstm & 07; - l8b = inst & 0377; - -/* Instruction decode */ - - switch (j) { /* case on class */ - case I_V_NPN: case I_V_CCC: case I_V_CCS: /* no operands */ - fprintf (of, "%s", opcode[i]); - return SCPE_OK; - case I_V_REG: /* reg */ - fprintf (of, "%s %-s", opcode[i], rname[dstr]); - return SCPE_OK; - case I_V_SOP: /* sop */ - fprintf (of, "%s ", opcode[i]); - return fprint_spec (of, addr, dstm, val[1], cflag, TRUE); - case I_V_3B: /* 3b */ - fprintf (of, "%s %-o", opcode[i], dstr); - return SCPE_OK; - case I_V_FOP: /* fop */ - fprintf (of, "%s ", opcode[i]); - return fprint_spec (of, addr, dstm, val[1], cflag, FALSE); - case I_V_AFOP: /* afop */ - fprintf (of, "%s %s,", opcode[i], fname[fac]); - return fprint_spec (of, addr, dstm, val[1], cflag, FALSE); - case I_V_6B: /* 6b */ - fprintf (of, "%s %-o", opcode[i], dstm); - return SCPE_OK; - case I_V_BR: /* cond branch */ - fprintf (of, "%s ", opcode[i]); - brdisp = (l8b + l8b + ((l8b & 0200)? 0177002: 2)) & 0177777; - if (cflag) fprintf (of, "%-o", (addr + brdisp) & 0177777); - else if (brdisp < 01000) fprintf (of, ".+%-o", brdisp); - else fprintf (of, ".-%-o", 0200000 - brdisp); - return SCPE_OK; - case I_V_8B: /* 8b */ - fprintf (of, "%s %-o", opcode[i], l8b); - return SCPE_OK; - case I_V_SOB: /* sob */ - fprintf (of, "%s %s,", opcode[i], rname[srcr]); - brdisp = (dstm * 2) - 2; - if (cflag) fprintf (of, "%-o", (addr - brdisp) & 0177777); - else if (brdisp <= 0) fprintf (of, ".+%-o", -brdisp); - else fprintf (of, ".-%-o", brdisp); - return SCPE_OK; - case I_V_RSOP: /* rsop */ - fprintf (of, "%s %s,", opcode[i], rname[srcr]); - return fprint_spec (of, addr, dstm, val[1], cflag, TRUE); - case I_V_ASOP: case I_V_ASMD: /* asop, asmd */ - fprintf (of, "%s %s,", opcode[i], fname[fac]); - return fprint_spec (of, addr, dstm, val[1], cflag, TRUE); - case I_V_DOP: /* dop */ - fprintf (of, "%s ", opcode[i]); - wd1 = fprint_spec (of, addr, srcm, val[1], cflag, TRUE); - fprintf (of, ","); - wd2 = fprint_spec (of, addr - wd1 - wd1, dstm, - val[1 - wd1], cflag, TRUE); - return wd1 + wd2; } /* end case */ - } /* end if */ - } /* end for */ -return SCPE_ARG; /* no match */ -} - -#define A_PND 100 /* # seen */ -#define A_MIN 040 /* -( seen */ -#define A_PAR 020 /* (Rn) seen */ -#define A_REG 010 /* Rn seen */ -#define A_PLS 004 /* + seen */ -#define A_NUM 002 /* number seen */ -#define A_REL 001 /* relative addr seen */ - -/* Register number - - Inputs: - *cptr = pointer to input string - *strings = pointer to register names - mchar = character to match after register name - Outputs: - rnum = 0..7 if a legitimate register - < 0 if error -*/ - -int32 get_reg (char *cptr, const char *strings[], char mchar) -{ -int32 i; - -if (*(cptr + 2) != mchar) return -1; -for (i = 0; i < 8; i++) { - if (strncmp (cptr, strings[i], 2) == 0) return i; } -return -1; -} - -/* Number or memory address - - Inputs: - *cptr = pointer to input string - *dptr = pointer to output displacement - *pflag = pointer to accumulating flags - Outputs: - cptr = pointer to next character in input string - NULL if parsing error - - Flags: 0 (no result), A_NUM (number), A_REL (relative) -*/ - -char *get_addr (char *cptr, int32 *dptr, int32 *pflag) -{ -int32 val, minus; -char *tptr; - -minus = 0; - -if (*cptr == '.') { /* relative? */ - *pflag = *pflag | A_REL; - cptr++; } -if (*cptr == '+') { /* +? */ - *pflag = *pflag | A_NUM; - cptr++; } -if (*cptr == '-') { /* -? */ - *pflag = *pflag | A_NUM; - minus = 1; - cptr++; } -errno = 0; -val = strtoul (cptr, &tptr, 8); -if (cptr == tptr) { /* no number? */ - if (*pflag == (A_REL + A_NUM)) return NULL; /* .+, .-? */ - *dptr = 0; - return cptr; } -if (errno || (*pflag == A_REL)) return NULL; /* .n? */ -*dptr = (minus? -val: val) & 0177777; -*pflag = *pflag | A_NUM; -return tptr; -} - -/* Specifier decode - - Inputs: - *cptr = pointer to input string - addr = current PC - n1 = 0 if no extra word used - -1 if extra word used in prior decode - *sptr = pointer to output specifier - *dptr = pointer to output displacement - cflag = true if parsing for the CPU - iflag = true if integer specifier - Outputs: - status = = -1 extra word decoded - = 0 ok - = +1 error -*/ - -t_stat get_spec (char *cptr, t_addr addr, int32 n1, int32 *sptr, t_value *dptr, - int32 cflag, int32 iflag) -{ -int32 reg, indir, pflag, disp; - -indir = 0; /* no indirect */ -pflag = 0; - -if (*cptr == '@') { /* indirect? */ - indir = 010; - cptr++; } -if (*cptr == '#') { /* literal? */ - pflag = pflag | A_PND; - cptr++; } -if (strncmp (cptr, "-(", 2) == 0) { /* autodecrement? */ - pflag = pflag | A_MIN; - cptr++; } -else if ((cptr = get_addr (cptr, &disp, &pflag)) == NULL) return 1; -if (*cptr == '(') { /* register index? */ - pflag = pflag | A_PAR; - if ((reg = get_reg (cptr + 1, rname, ')')) < 0) return 1; - cptr = cptr + 4; - if (*cptr == '+') { /* autoincrement? */ - pflag = pflag | A_PLS; - cptr++; } } -else if ((reg = get_reg (cptr, iflag? rname: fname, 0)) >= 0) { - pflag = pflag | A_REG; - cptr = cptr + 2; } -if (*cptr != 0) return 1; /* all done? */ - -/* Specifier decode, continued */ - -switch (pflag) { /* case on syntax */ -case A_REG: /* Rn, @Rn */ - *sptr = indir + reg; - return 0; -case A_PAR: /* (Rn), @(Rn) */ - if (indir) { /* @(Rn) = @0(Rn) */ - *sptr = 070 + reg; - *dptr = 0; - return -1; } - else *sptr = 010 + reg; - return 0; -case A_PAR+A_PLS: /* (Rn)+, @(Rn)+ */ - *sptr = 020 + indir + reg; - return 0; -case A_MIN+A_PAR: /* -(Rn), @-(Rn) */ - *sptr = 040 + indir + reg; - return 0; -case A_NUM+A_PAR: /* d(Rn), @d(Rn) */ - *sptr = 060 + indir + reg; - *dptr = disp; - return -1; -case A_PND+A_REL: case A_PND+A_REL+A_NUM: /* #.+n, @#.+n */ - if (!cflag) return 1; - disp = (disp + addr) & 0177777; /* fall through */ -case A_PND+A_NUM: /* #n, @#n */ - *sptr = 027 + indir; - *dptr = disp; - return -1; -case A_REL: case A_REL+A_NUM: /* .+n, @.+n */ - *sptr = 067 + indir; - *dptr = (disp - 4 + (2 * n1)) & 0177777; - return -1; -case A_NUM: /* n, @n */ - if (cflag) { /* CPU - use rel */ - *sptr = 067 + indir; - *dptr = (disp - addr - 4 + (2 * n1)) & 0177777; } - else { if (indir) return 1; /* other - use abs */ - *sptr = 037; - *dptr = disp; } - return -1; -default: - return 1; } /* end case */ -} - -/* Symbolic input - - Inputs: - *cptr = pointer to input string - addr = current PC - *uptr = pointer to unit - *val = pointer to output values - sw = switches - Outputs: - status = > 0 error code - <= 0 -number of extra words -*/ - -t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw) -{ -int32 cflag, d, i, j, reg, spec, n1, n2, disp, pflag; -t_stat r; -char *tptr, gbuf[CBUFSIZE]; - -cflag = (uptr == NULL) || (uptr == &cpu_unit); -while (isspace (*cptr)) cptr++; /* absorb spaces */ -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++)) { /* ASCII string? */ - if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */ - val[0] = ((t_value) cptr[1] << 8) + (t_value) cptr[0]; - return SCPE_OK; } -if (sw & SWMASK ('R')) return SCPE_ARG; /* radix 50 */ - -cptr = get_glyph (cptr, gbuf, 0); /* get opcode */ -n1 = n2 = pflag = 0; -for (i = 0; (opcode[i] != NULL) && (strcmp (opcode[i], gbuf) != 0) ; i++) ; -if (opcode[i] == NULL) return SCPE_ARG; -val[0] = opc_val[i] & 0177777; /* get value */ -j = (opc_val[i] >> I_V_CL) & I_M_CL; /* get class */ - -switch (j) { /* case on class */ -case I_V_NPN: /* no operand */ - break; -case I_V_REG: /* register */ - cptr = get_glyph (cptr, gbuf, 0); /* get glyph */ - if ((reg = get_reg (gbuf, rname, 0)) < 0) return SCPE_ARG; - val[0] = val[0] | reg; - break; -case I_V_3B: case I_V_6B: case I_V_8B: /* xb literal */ - cptr = get_glyph (cptr, gbuf, 0); /* get literal */ - d = get_uint (gbuf, 8, (1 << j) - 1, &r); - if (r != SCPE_OK) return SCPE_ARG; - val[0] = val[0] | d; /* put in place */ - break; -case I_V_BR: /* cond br */ - cptr = get_glyph (cptr, gbuf, 0); /* get address */ - tptr = get_addr (gbuf, &disp, &pflag); /* parse */ - if ((tptr == NULL) || (*tptr != 0)) return SCPE_ARG; - if ((pflag & A_REL) == 0) { - if (cflag) disp = (disp - addr) & 0177777; - else return SCPE_ARG; } - if ((disp & 1) || (disp > 0400) && (disp < 0177402)) return SCPE_ARG; - val[0] = val[0] | (((disp - 2) >> 1) & 0377); - break; -case I_V_SOB: /* sob */ - cptr = get_glyph (cptr, gbuf, ','); /* get glyph */ - if ((reg = get_reg (gbuf, rname, 0)) < 0) return SCPE_ARG; - val[0] = val[0] | (reg << 6); - cptr = get_glyph (cptr, gbuf, 0); /* get address */ - tptr = get_addr (gbuf, &disp, &pflag); /* parse */ - if ((tptr == NULL) || (*tptr != 0)) return SCPE_ARG; - if ((pflag & A_REL) == 0) { - if (cflag) disp = (disp - addr) & 0177777; - else return SCPE_ARG; } - if ((disp & 1) || ((disp > 2) && (disp < 0177604))) return SCPE_ARG; - val[0] = val[0] | (((2 - disp) >> 1) & 077); - break; -case I_V_RSOP: /* reg, sop */ - cptr = get_glyph (cptr, gbuf, ','); /* get glyph */ - if ((reg = get_reg (gbuf, rname, 0)) < 0) return SCPE_ARG; - val[0] = val[0] | (reg << 6); /* fall through */ -case I_V_SOP: /* sop */ - cptr = get_glyph (cptr, gbuf, 0); /* get glyph */ - if ((n1 = get_spec (gbuf, addr, 0, &spec, &val[1], cflag, TRUE)) > 0) - return SCPE_ARG; - val[0] = val[0] | spec; - break; -case I_V_AFOP: case I_V_ASOP: case I_V_ASMD: /* fac, (s)fop */ - cptr = get_glyph (cptr, gbuf, ','); /* get glyph */ - if ((reg = get_reg (gbuf, fname, 0)) < 0) return SCPE_ARG; - if (reg > 3) return SCPE_ARG; - val[0] = val[0] | (reg << 6); /* fall through */ -case I_V_FOP: /* fop */ - cptr = get_glyph (cptr, gbuf, 0); /* get glyph */ - if ((n1 = get_spec (gbuf, addr, 0, &spec, &val[1], cflag, - (j == I_V_ASOP) || (j == I_V_ASMD))) > 0) return SCPE_ARG; - val[0] = val[0] | spec; - break; -case I_V_DOP: /* double op */ - cptr = get_glyph (cptr, gbuf, ','); /* get glyph */ - if ((n1 = get_spec (gbuf, addr, 0, &spec, &val[1], cflag, TRUE)) > 0) - return SCPE_ARG; - val[0] = val[0] | (spec << 6); - cptr = get_glyph (cptr, gbuf, 0); /* get glyph */ - if ((n2 = get_spec (gbuf, addr, n1, &spec, &val[1 - n1], - cflag, TRUE)) > 0) return SCPE_ARG; - val[0] = val[0] | spec; - break; -case I_V_CCC: case I_V_CCS: /* cond code oper */ - 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 ((((opc_val[i] >> I_V_CL) & I_M_CL) != j) || - (opcode[i] == NULL)) return SCPE_ARG; - val[0] = val[0] | (opc_val[i] & 0177777); } - break; -default: - return SCPE_ARG; } -if (*cptr != 0) return SCPE_ARG; /* junk at end? */ -return n1 + n2; -} diff --git a/PDP11/pdp11_tc.c b/PDP11/pdp11_tc.c deleted file mode 100644 index 414dee28..00000000 --- a/PDP11/pdp11_tc.c +++ /dev/null @@ -1,1182 +0,0 @@ -/* pdp11_tc.c: PDP-11 DECtape simulator - - 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. - - tc TC11/TU56 DECtape - - 25-Apr-03 RMS Revised for extended file support - 14-Mar-03 RMS Fixed variable size interaction with save/restore - 29-Sep-02 RMS Added variable address support to bootstrap - Added vector change/display support - Added 16b format support - New data structures - 30-May-02 RMS Widened POS to 32b - 26-Jan-02 RMS Revised bootstrap to conform to M9312 - 06-Jan-02 RMS Revised enable/disable support - 30-Nov-01 RMS Added read only unit, extended SET/SHOW support - 24-Nov-01 RMS Converted POS, STATT, LASTT to arrays - 09-Nov-01 RMS Added bus map support - 15-Sep-01 RMS Integrated debug logging - 27-Sep-01 RMS Fixed interrupt after stop for RSTS/E - 07-Sep-01 RMS Revised device disable and interrupt mechanisms - 29-Aug-01 RMS Added casts to PDP-8 unpack routine - 17-Jul-01 RMS Moved function prototype - 11-May-01 RMS Fixed bug in reset - 26-Apr-01 RMS Added device enable/disable support - 18-Apr-01 RMS Changed to rewind tape before boot - 16-Mar-01 RMS Fixed bug in interrupt after stop - 15-Mar-01 RMS Added 129th word to PDP-8 format - - PDP-11 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). - - 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. -*/ - -#include "pdp11_defs.h" - -#define DT_NUMDR 8 /* #drives */ -#define DT_M_NUMDR (DT_NUMDR - 1) -#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 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 D16_FILSIZ (D18_TSIZE * D18_BSIZE * 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)) - -/* TCST - 177340 - status register */ - -#define STA_END 0100000 /* end zone */ -#define STA_PAR 0040000 /* parity err */ -#define STA_MRK 0020000 /* mark trk err */ -#define STA_ILO 0010000 /* illegal op */ -#define STA_SEL 0004000 /* select err */ -#define STA_BLKM 0002000 /* block miss err */ -#define STA_DATM 0001000 /* data miss err */ -#define STA_NXM 0000400 /* nx mem err */ -#define STA_UPS 0000200 /* up to speed */ -#define STA_V_XD 0 /* extended data */ -#define STA_M_XD 03 -#define STA_ALLERR (STA_END | STA_PAR | STA_MRK | STA_ILO | \ - STA_SEL | STA_BLKM | STA_DATM | STA_NXM ) -#define STA_RWERR (STA_END | STA_PAR | STA_MRK | \ - STA_BLKM | STA_DATM | STA_NXM ) -#define STA_RW 0000003 -#define STA_GETXD(x) (((x) >> STA_V_XD) & STA_M_XD) - -/* TCCM - 177342 - command register */ - -/* #define CSR_ERR 0100000 */ -#define CSR_MNT 0020000 /* maint (unimpl) */ -#define CSR_INH 0010000 /* delay inhibit */ -#define CSR_DIR 0004000 /* reverse */ -#define CSR_V_UNIT 8 /* unit select */ -#define CSR_M_UNIT 07 -#define CSR_UNIT (CSR_M_UNIT << CSR_V_UNIT) -/* #define CSR_DONE 0000200 */ -/* #define CSR_IE 0000100 */ -#define CSR_V_MEX 4 /* mem extension */ -#define CSR_M_MEX 03 -#define CSR_MEX (CSR_M_MEX << CSR_V_MEX) -#define CSR_V_FNC 1 /* function */ -#define CSR_M_FNC 07 -#define FNC_STOP 00 /* stop all */ -#define FNC_SRCH 01 /* search */ -#define FNC_READ 02 /* read */ -#define FNC_RALL 03 /* read all */ -#define FNC_SSEL 04 /* stop selected */ -#define FNC_WMRK 05 /* write */ -#define FNC_WRIT 06 /* write all */ -#define FNC_WALL 07 /* write timing */ -/* define CSR_GO 0000001 */ -#define CSR_RW 0117576 /* read/write */ - -#define CSR_GETUNIT(x) (((x) >> CSR_V_UNIT) & CSR_M_UNIT) -#define CSR_GETMEX(x) (((x) >> CSR_V_MEX) & CSR_M_MEX) -#define CSR_GETFNC(x) (((x) >> CSR_V_FNC) & CSR_M_FNC) -#define CSR_INCMEX(x) (((x) & ~CSR_MEX) | (((x) + (1 << CSR_V_MEX)) & CSR_MEX)) - -/* TCWC - 177344 - word count */ - -/* TCBA - 177346 - bus address */ - -/* TCDT - 177350 - data */ - -/* 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 FNC_WMRK /* "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) - -/* 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 DT_SETDONE tccm = tccm | CSR_DONE; \ - if (tccm & CSR_IE) SET_INT (DTA) -#define DT_CLRDONE tccm = tccm & ~CSR_DONE; \ - CLR_INT (DTA) -#define ABS(x) (((x) < 0)? (-(x)): (x)) - -extern uint16 *M; /* memory */ -extern int32 int_req[IPL_HLVL]; -extern int32 int_vec[IPL_HLVL][32]; -extern UNIT cpu_unit; -extern int32 sim_switches; -extern int32 cpu_log; -extern FILE *sim_log; - -int32 tcst = 0; /* status */ -int32 tccm = 0; /* command */ -int32 tcwc = 0; /* word count */ -int32 tcba = 0; /* bus address */ -int32 tcdt = 0; /* data */ -int32 dt_ctime = 100; /* fast cmd time */ -int32 dt_ltime = 12; /* interline time */ -int32 dt_actime = 54000; /* accel time */ -int32 dt_dctime = 72000; /* decel time */ -int32 dt_substate = 0; -int32 dt_logblk = 0; - -DEVICE dt_dev; -t_stat dt_rd (int32 *data, int32 PA, int32 access); -t_stat dt_wr (int32 data, int32 PA, int32 access); -t_stat dt_svc (UNIT *uptr); -t_stat dt_svcdone (UNIT *uptr); -t_stat dt_reset (DEVICE *dptr); -t_stat dt_attach (UNIT *uptr, char *cptr); -t_stat dt_detach (UNIT *uptr); -t_stat dt_boot (int32 unitno, DEVICE *dptr); -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); -void dt_stopunit (UNIT *uptr); -int32 dt_comobv (int32 val); -int32 dt_csum (UNIT *uptr, int32 blk); -int32 dt_gethdr (UNIT *uptr, int32 blk, int32 relpos); -extern int32 sim_is_running; - -/* DT data structures - - dt_dev DT device descriptor - dt_unit DT unit list - dt_reg DT register list - dt_mod DT modifier list -*/ - -DIB dt_dib = { IOBA_TC, IOLN_TC, &dt_rd, &dt_wr, - 1, IVCL (DTA), VEC_DTA, { NULL } }; - -UNIT dt_unit[] = { - { UDATA (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+UNIT_11FMT, DT_CAPAC) }, - { UDATA (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+UNIT_11FMT, DT_CAPAC) }, - { UDATA (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+UNIT_11FMT, DT_CAPAC) }, - { UDATA (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+UNIT_11FMT, DT_CAPAC) }, - { UDATA (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+UNIT_11FMT, DT_CAPAC) }, - { UDATA (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+UNIT_11FMT, DT_CAPAC) }, - { UDATA (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+UNIT_11FMT, DT_CAPAC) }, - { UDATA (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+UNIT_11FMT, DT_CAPAC) }, - { UDATA (&dt_svcdone, UNIT_DIS, 0) } }; - -#define DT_TIMER (DT_NUMDR) - -REG dt_reg[] = { - { ORDATA (TCST, tcst, 16) }, - { ORDATA (TCCM, tccm, 16) }, - { ORDATA (TCWC, tcwc, 16) }, - { ORDATA (TCBA, tcba, 16) }, - { ORDATA (TCDT, tcdt, 16) }, - { FLDATA (INT, IREQ (DTA), INT_V_DTA) }, - { FLDATA (ERR, tccm, CSR_V_ERR) }, - { FLDATA (DONE, tccm, CSR_V_DONE) }, - { FLDATA (IE, tccm, CSR_V_DONE) }, - { DRDATA (CTIME, dt_ctime, 31), REG_NZ }, - { 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, 1) }, - { DRDATA (LBLK, dt_logblk, 12), REG_HIDDEN }, - { URDATA (POS, dt_unit[0].pos, 10, T_ADDR_W, 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) }, - { ORDATA (DEVADDR, dt_dib.ba, 32), REG_HRO }, - { ORDATA (DEVVEC, dt_dib.vec, 16), 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 }, - { MTAB_XTD|MTAB_VDV, 004, "ADDRESS", "ADDRESS", - &set_addr, &show_addr, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "VECTOR", "VECTOR", - &set_vec, &show_vec, NULL }, - { 0 } }; - -DEVICE dt_dev = { - "TC", dt_unit, dt_reg, dt_mod, - DT_NUMDR + 1, 8, 24, 1, 8, 18, - NULL, NULL, &dt_reset, - &dt_boot, &dt_attach, &dt_detach, - &dt_dib, DEV_DISABLE | DEV_UBUS }; - -/* IO dispatch routines, I/O addresses 17777340 - 17777350 */ - -t_stat dt_rd (int32 *data, int32 PA, int32 access) -{ -int32 j, unum, mot, fnc; - -j = (PA >> 1) & 017; /* get reg offset */ -unum = CSR_GETUNIT (tccm); /* get drive */ -switch (j) { -case 000: /* TCST */ - mot = DTS_GETMOT (dt_unit[unum].STATE); /* get motion */ - if (mot >= DTS_ATSF) tcst = tcst | STA_UPS; /* set/clr speed */ - else tcst = tcst & ~STA_UPS; - *data = tcst; - break; -case 001: /* TCCM */ - if (tcst & STA_ALLERR) tccm = tccm | CSR_ERR; /* set/clr error */ - else tccm = tccm & ~CSR_ERR; - *data = tccm; - break; -case 002: /* TCWC */ - *data = tcwc; - break; -case 003: /* TCBA */ - *data = tcba; - break; -case 004: /* TCDT */ - fnc = DTS_GETFNC (dt_unit[unum].STATE); /* get function */ - if (fnc == FNC_RALL) { /* read all? */ - DT_CLRDONE; } /* clear done */ - *data = tcdt; - break; } -return SCPE_OK; -} - -t_stat dt_wr (int32 data, int32 PA, int32 access) -{ -int32 i, j, unum, old_tccm, fnc; -UNIT *uptr; - -j = (PA >> 1) & 017; /* get reg offset */ -switch (j) { -case 000: /* TCST */ - if ((access == WRITEB) && (PA & 1)) break; - tcst = (tcst & ~STA_RW) | (data & STA_RW); - break; -case 001: /* TCCM */ - old_tccm = tccm; /* save prior */ - if (access == WRITEB) data = (PA & 1)? - (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); - 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); } - else if ((tccm & CSR_ERR) == 0) { /* clear err? */ - tcst = tcst & ~STA_RWERR; - if (tcst & STA_ALLERR) tccm = tccm | CSR_ERR; } - break; -case 002: /* TCWC */ - tcwc = data; /* word write only! */ - break; -case 003: /* TCBA */ - tcba = data; /* word write only! */ - break; -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 */ - tcdt = data; /* word write only! */ - break; } -return SCPE_OK; -} - -/* Unit deselect */ - -void dt_deselect (int32 oldf) -{ -int32 old_unit = CSR_GETUNIT (oldf); -UNIT *uptr = dt_dev.units + old_unit; -int32 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; } - -/* New operation - - 1. If function = stop - - if not already stopped or decelerating, schedule deceleration - - schedule command completion - 2. If change in direction, - - if not decelerating, schedule deceleration - - set accelerating (other dir) as next state - - set function as next next state - 3. If not accelerating or at speed, - - schedule acceleration - - set function as next state - 4. If not yet at speed, - - set function as next state - 5. If at speed, - - set function as current state, schedule function -*/ - -void dt_newsa (int32 newf) -{ -int32 new_unit, prev_mot, new_fnc; -int32 prev_dir, new_dir; -UNIT *uptr; - -new_unit = CSR_GETUNIT (newf); /* new, old units */ -uptr = dt_dev.units + new_unit; -if ((uptr->flags & UNIT_ATT) == 0) { /* new unit attached? */ - dt_seterr (uptr, STA_SEL); /* no, error */ - return; } -prev_mot = DTS_GETMOT (uptr->STATE); /* previous motion */ -prev_dir = prev_mot & DTS_DIR; /* previous dir */ -new_fnc = CSR_GETFNC (newf); /* new function */ -new_dir = (newf & CSR_DIR) != 0; /* new di? */ - -if (new_fnc == FNC_SSEL) { /* stop unit? */ - sim_activate (&dt_dev.units[DT_TIMER], dt_ctime); /* sched done */ - dt_stopunit (uptr); /* stop unit */ - return; } - -if (prev_mot == DTS_STOP) { /* 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_dir ^ new_dir) { /* dir chg? */ - dt_stopunit (uptr); /* stop unit */ - 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, relpos, 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) - 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, STA_END); /* set ez flag, stop */ - return; } -dt_substate = 0; /* substate = normal */ -sim_cancel (uptr); /* cancel cur op */ -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_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 (DBG_LOG (LOG_TC_MS)) fprintf (sim_log, ">>DT%d: searching %s\n", - 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; } - 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; } - if (dir) newpos = DT_BLK2LN (((relpos >= (DTU_LPERB (uptr) - DT_HTLIN))? - blk + 1: blk), uptr) - DT_HTLIN - DT_WSIZE; - else newpos = DT_BLK2LN (((relpos < DT_HTLIN)? - 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")); - 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 (fnc == FNC_WALL) sim_activate /* write all? */ - (&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")); - break; -default: - dt_seterr (uptr, STA_SEL); /* bad state */ - return; } -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 == CSR_GETUNIT (tccm)) && (CSR_GETFNC (tccm) != FNC_STOP)) - dt_seterr (uptr, STA_SEL); /* error */ - return TRUE; } -return FALSE; -} - -/* Command timer service after stop - set done */ - -t_stat dt_svcdone (UNIT *uptr) -{ -DT_SETDONE; -return SCPE_OK; -} - -/* 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 blk, wrd, relpos, dat; -uint32 ba, ma, mma; - -/* 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, STA_SEL); /* state error */ - return SCPE_OK; } - -/* Functional cases - - 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, STA_END); /* end zone error */ - return SCPE_OK; } -blk = DT_LIN2BL (uptr->pos, uptr); /* get block # */ - -switch (fnc) { /* at speed, check fnc */ -case FNC_SRCH: /* search */ - tcdt = blk; /* set block # */ - dt_schedez (uptr, dir); /* sched end zone */ - DT_SETDONE; /* set done */ - break; -case DTS_OFR: /* off reel */ - detach_unit (uptr); /* must be deselected */ - uptr->STATE = uptr->pos = 0; /* no visible action */ - break; - -/* Read - - If wc ovf has not occurred, inc ma, wc and copy word from tape to memory - If wc ovf, set flag - If not end of block, schedule next word - If end of block and not wc ovf, schedule next block - If end of block and wc ovf, set done, schedule end zone -*/ - -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; } - if (wrd != (dir? 0: DTU_BSIZE (uptr) - 1)) /* not end blk? */ - sim_activate (uptr, DT_WSIZE * dt_ltime); - else if (dt_substate) { /* wc ovf? */ - dt_schedez (uptr, dir); /* sched end zone */ - DT_SETDONE; } /* set done */ - else sim_activate (uptr, ((2 * DT_HTLIN) + DT_WSIZE) * dt_ltime); - break; - -/* Write - - If wc ovf has not occurred, inc ma, wc - Copy word from memory (or 0, to fill block) to tape - If wc ovf, set flag - If not end of block, schedule next word - If end of block and not wc ovf, schedule next block - If end of block and wc ovf, set done, schedule end zone -*/ - -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); } - 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); - else if (dt_substate) { /* wc ovf? */ - dt_schedez (uptr, dir); /* sched end zone */ - DT_SETDONE; } - else sim_activate (uptr, ((2 * DT_HTLIN) + DT_WSIZE) * dt_ltime); - break; - -/* Read all - read current header or data word */ - -case FNC_RALL: - if (tccm & CSR_DONE) { /* done set? */ - 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 */ - else dat = dt_gethdr (uptr, blk, relpos); /* get hdr */ - if (dir) dat = dt_comobv (dat); /* rev? comp obv */ - tcdt = dat & DMASK; /* low 16b */ - tcst = (tcst & ~STA_M_XD) | ((dat >> 16) & STA_M_XD); - sim_activate (uptr, DT_WSIZE * dt_ltime); - DT_SETDONE; /* set done */ - break; - -/* Write all - write current header or data word */ - -case FNC_WALL: - if (tccm & CSR_DONE) { /* done set? */ - 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; } -/* else /* ignore hdr */ - sim_activate (uptr, DT_WSIZE * dt_ltime); - DT_SETDONE; /* set done */ - break; -default: - dt_seterr (uptr, STA_SEL); /* impossible state */ - break; } -return SCPE_OK; -} - -/* Utility routines */ - -/* Set error flag */ - -void dt_seterr (UNIT *uptr, int32 e) -{ -int32 mot = DTS_GETMOT (uptr->STATE); - -tcst = tcst | e; /* set error flag */ -tccm = tccm | CSR_ERR; -if (!(tccm & CSR_DONE)) { /* not done? */ - DT_SETDONE; } -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 */ -return; -} - -/* Stop unit */ - -void dt_stopunit (UNIT *uptr) -{ -int32 mot = DTS_GETMOT (uptr->STATE); -int32 dir = mot & DTS_DIR; - -if (mot == DTS_STOP) return; /* already stopped? */ -if ((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 | dir, 0); /* state = decel */ -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 (18b) */ - -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 = 077; /* init csum */ -for (i = 0; i < DTU_BSIZE (uptr); i++) { /* loop thru buf */ - wrd = bptr[ba + i] ^ 0777777; /* get ~word */ - csum = csum ^ (wrd >> 12) ^ (wrd >> 6) ^ wrd; } -return (csum & 077); -} - -/* Get header word (18b) */ - -int32 dt_gethdr (UNIT *uptr, int32 blk, int32 relpos) -{ -int32 wrd = relpos / DT_WSIZE; - -if (wrd == DT_BLKWD) return blk; /* fwd blknum */ -if (wrd == (2 * DT_HTWRD + DTU_BSIZE (uptr) - DT_CSMWD - 1)) /* fwd csum */ - return (dt_csum (uptr, blk) << 12); -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 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 (); } } -tcst = tcwc = tcba = tcdt = 0; /* clear reg */ -tccm = CSR_DONE; -CLR_INT (DTA); /* clear int req */ -return SCPE_OK; -} - -/* Device bootstrap */ - -#define BOOT_START 02000 /* start */ -#define BOOT_ENTRY (BOOT_START + 002) /* entry */ -#define BOOT_UNIT (BOOT_START + 010) /* unit number */ -#define BOOT_CSR (BOOT_START + 020) /* CSR */ -#define BOOT_LEN (sizeof (boot_rom) / sizeof (int16)) - -static const uint16 boot_rom[] = { - 0042124, /* "TD" */ - 0012706, BOOT_START, /* MOV #boot_start, SP */ - 0012700, 0000000, /* MOV #unit, R0 ; unit number */ - 0010003, /* MOV R0, R3 */ - 0000303, /* SWAB R3 */ - 0012701, 0177342, /* MOV #TCCM, R1 ; csr */ - 0012702, 0004003, /* RW: MOV #4003, R2 ; rev+rnum+go */ - 0050302, /* BIS R3, R2 */ - 0010211, /* MOV R2, (R1) ; load csr */ - 0032711, 0100200, /* BIT #100200, (R1) ; wait */ - 0001775, /* BEQ .-4 */ - 0100370, /* BPL RW ; no err, cont */ - 0005761, 0177776, /* TST -2(R1) ; end zone? */ - 0100036, /* BPL ER ; no, err */ - 0012702, 0000003, /* MOV #3, R2 ; rnum+go */ - 0050302, /* BIS R3, R2 */ - 0010211, /* MOV R2, (R1) ; load csr */ - 0032711, 0100200, /* BIT #100200, (R1) ; wait */ - 0001775, /* BEQ .-4 */ - 0100426, /* BMI ER ; err, die */ - 0005761, 0000006, /* TST 6(R1) ; blk 0? */ - 0001023, /* BNE ER ; no, die */ - 0012761, 0177000, 0000002, /* MOV #-256.*2, 2(R1) ; load wc */ - 0005061, 0000004, /* CLR 4(R1) ; clear ba */ - 0012702, 0000005, /* MOV #READ+GO, R2 ; read & go */ - 0050302, /* BIS R3, R2 */ - 0010211, /* MOV R2, (R1) ; load csr */ - 0005002, /* CLR R2 */ - 0005003, /* CLR R3 */ - 0012704, BOOT_START+020, /* MOV #START+20, R4 */ - 0005005, /* CLR R5 */ - 0032711, 0100200, /* BIT #100200, (R1) ; wait */ - 0001775, /* BEQ .-4 */ - 0100401, /* BMI ER ; err, die */ - 0005007, /* CLR PC */ - 0012711, 0000001, /* ER: MOV #1, (R1) ; stop all */ - 0000000 /* HALT */ -}; - -t_stat dt_boot (int32 unitno, DEVICE *dptr) -{ -int32 i; -extern int32 saved_PC; - -dt_unit[unitno].pos = DT_EZLIN; -for (i = 0; i < BOOT_LEN; i++) M[(BOOT_START >> 1) + i] = boot_rom[i]; -M[BOOT_UNIT >> 1] = unitno & DT_M_NUMDR; -M[BOOT_CSR >> 1] = (dt_dib.ba & DMASK) + 02; -saved_PC = BOOT_ENTRY; -return SCPE_OK; -} - -/* 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 ba, sz, k, *bptr; -int32 u = uptr - dt_dev.units; -t_stat r; - -r = attach_unit (uptr, cptr); /* attach */ -if (r != SCPE_OK) return r; /* fail? */ -if ((sim_switches & SIM_SW_REST) == 0) { /* not from rest? */ - uptr->flags = (uptr->flags | UNIT_11FMT) & ~UNIT_8FMT; /* default 16b */ - if (sim_switches & SWMASK ('R')) /* att 12b? */ - uptr->flags = (uptr->flags | UNIT_8FMT) & ~UNIT_11FMT; - else if (sim_switches & SWMASK ('T')) /* att 18b? */ - uptr->flags = uptr->flags & ~(UNIT_8FMT | UNIT_11FMT); - else if (!(sim_switches & SWMASK ('S')) && /* autosize? */ - ((sz = sim_fsize (cptr)) > D16_FILSIZ)) { - if (sz <= D8_FILSIZ) - 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)); -if (uptr->filebuf == NULL) { /* can't alloc? */ - detach_unit (uptr); - return SCPE_MEM; } -bptr = uptr->filebuf; /* file buffer */ -printf ("%s%d: ", sim_dname (&dt_dev), u); -if (uptr->flags & UNIT_8FMT) printf ("12b format"); -else if (uptr->flags & UNIT_11FMT) printf ("16b format"); -else printf ("18b/36b format"); -printf (", buffering file in memory\n"); -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] = ((pdp8b[k + 1] & 077) << 12) | - ((uint32) (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 ba, k, *bptr; -int32 u = uptr - dt_dev.units; - -if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; -if (sim_is_active (uptr)) { /* active? cancel op */ - sim_cancel (uptr); - if ((u == CSR_GETUNIT (tccm)) && ((tccm & CSR_DONE) == 0)) { - tcst = tcst | STA_SEL; - tccm = tccm | CSR_ERR | CSR_DONE; - if (tccm & CSR_IE) SET_INT (DTA); } - uptr->STATE = uptr->pos = 0; } -bptr = uptr->filebuf; /* file buffer */ -if (uptr->hwmark && ((uptr->flags & UNIT_RO) == 0)) { /* any data? */ - printf ("%s%d: writing buffer to file\n", sim_dname (&dt_dev), u); - 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++] & DMASK; - 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_11FMT) & ~UNIT_8FMT; /* default fmt */ -uptr->capac = DT_CAPAC; /* default size */ -return detach_unit (uptr); -} diff --git a/PDP11/pdp11_tm.c b/PDP11/pdp11_tm.c deleted file mode 100644 index e6872b36..00000000 --- a/PDP11/pdp11_tm.c +++ /dev/null @@ -1,656 +0,0 @@ -/* pdp11_tm.c: PDP-11 magnetic tape simulator - - 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. - - tm TM11/TU10 magtape - - 25-Apr-03 RMS Revised for extended file support - 28-Mar-03 RMS Added multiformat support - 28-Feb-03 RMS Revised for magtape library, added logging - 30-Oct-02 RMS Revised BOT handling, added error record handling - 30-Sep-02 RMS Added variable address support to bootstrap - Added vector change/display support - Changed mapping mnemonics - New data structures - Updated error handling - 28-Aug-02 RMS Added end of medium support - 30-May-02 RMS Widened POS to 32b - 22-Apr-02 RMS Fixed max record length, first block bootstrap - (found by Jonathan Engdahl) - 26-Jan-02 RMS Revised bootstrap to conform to M9312 - 06-Jan-02 RMS Revised enable/disable support - 30-Nov-01 RMS Added read only unit, extended SET/SHOW support - 24-Nov-01 RMS Converted UST, POS, FLG to arrays - 09-Nov-01 RMS Added bus map support - 18-Oct-01 RMS Added stub diagnostic register (found by Thord Nilson) - 07-Sep-01 RMS Revised device disable and interrupt mechanisms - 26-Apr-01 RMS Added device enable/disable support - 18-Apr-01 RMS Changed to rewind tape before boot - 14-Apr-99 RMS Changed t_addr to unsigned - 04-Oct-98 RMS V2.4 magtape format - 10-May-98 RMS Fixed bug with non-zero unit operation (from Steven Schultz) - 09-May-98 RMS Fixed problems in bootstrap (from Steven Schultz) - 10-Apr-98 RMS Added 2nd block bootstrap (from John Holden, - University of Sydney) - 31-Jul-97 RMS Added bootstrap (from Ethan Dicks, Ohio State) - 22-Jan-97 RMS V2.3 magtape format - 18-Jan-97 RMS Fixed double interrupt, error flag bugs - 29-Jun-96 RMS Added unit disable support - - 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 "pdp11_defs.h" -#include "sim_tape.h" - -#define TM_NUMDR 8 /* #drives */ -#define USTAT u3 /* unit status */ - -/* Command - tm_cmd */ - -#define MTC_ERR (1 << CSR_V_ERR) /* error */ -#define MTC_V_DEN 13 /* density */ -#define MTC_M_DEN 03 -#define MTC_DEN (MTC_M_DEN << MTC_V_DEN) -#define MTC_INIT 0010000 /* init */ -#define MTC_LPAR 0004000 /* parity select */ -#define MTC_V_UNIT 8 /* unit */ -#define MTC_M_UNIT 07 -#define MTC_UNIT (MTC_M_UNIT << MTC_V_UNIT) -#define MTC_DONE (1 << CSR_V_DONE) /* done */ -#define MTC_IE (1 << CSR_V_IE) /* interrupt enable */ -#define MTC_V_EMA 4 /* ext mem address */ -#define MTC_M_EMA 03 -#define MTC_EMA (MTC_M_EMA << MTC_V_EMA) -#define MTC_V_FNC 1 /* function */ -#define MTC_M_FNC 07 -#define MTC_UNLOAD 00 -#define MTC_READ 01 -#define MTC_WRITE 02 -#define MTC_WREOF 03 -#define MTC_SPACEF 04 -#define MTC_SPACER 05 -#define MTC_WREXT 06 -#define MTC_REWIND 07 -#define MTC_FNC (MTC_M_FNC << MTC_V_FNC) -#define MTC_GO (1 << CSR_V_GO) /* go */ -#define MTC_RW (MTC_DEN | MTC_LPAR | MTC_UNIT | MTC_IE | \ - MTC_EMA | MTC_FNC) -#define GET_EMA(x) (((x) & MTC_EMA) << (16 - MTC_V_EMA)) -#define GET_UNIT(x) (((x) >> MTC_V_UNIT) & MTC_M_UNIT) -#define GET_FNC(x) (((x) >> MTC_V_FNC) & MTC_M_FNC) - -/* Status - stored in tm_sta or (*) uptr->USTAT or (+) calculated */ - -#define STA_ILL 0100000 /* illegal */ -#define STA_EOF 0040000 /* *end of file */ -#define STA_CRC 0020000 /* CRC error */ -#define STA_PAR 0010000 /* parity error */ -#define STA_DLT 0004000 /* data late */ -#define STA_EOT 0002000 /* *end of tape */ -#define STA_RLE 0001000 /* rec lnt error */ -#define STA_BAD 0000400 /* bad tape error */ -#define STA_NXM 0000200 /* non-existent mem */ -#define STA_ONL 0000100 /* *online */ -#define STA_BOT 0000040 /* *start of tape */ -#define STA_7TK 0000020 /* 7 track */ -#define STA_SDN 0000010 /* settle down */ -#define STA_WLK 0000004 /* *write locked */ -#define STA_REW 0000002 /* *rewinding */ -#define STA_TUR 0000001 /* +unit ready */ - -#define STA_CLR (STA_7TK | STA_SDN) /* always clear */ -#define STA_DYN (STA_EOF | STA_EOT | STA_ONL | STA_BOT | \ - STA_WLK | STA_REW | STA_TUR) /* kept in USTAT */ -#define STA_EFLGS (STA_ILL | STA_EOF | STA_CRC | STA_PAR | \ - STA_DLT | STA_EOT | STA_RLE | STA_BAD | STA_NXM) - /* set error */ - -/* Read lines - tm_rdl */ - -#define RDL_CLK 0100000 /* 10 Khz clock */ - -extern uint16 *M; /* memory */ -extern int32 int_req[IPL_HLVL]; -extern int32 int_vec[IPL_HLVL][32]; -extern int32 cpu_log; -extern FILE *sim_log; - -uint8 *tmxb = NULL; /* xfer buffer */ -int32 tm_sta = 0; /* status register */ -int32 tm_cmd = 0; /* command register */ -int32 tm_ca = 0; /* current address */ -int32 tm_bc = 0; /* byte count */ -int32 tm_db = 0; /* data buffer */ -int32 tm_rdl = 0; /* read lines */ -int32 tm_time = 10; /* record latency */ -int32 tm_stopioe = 1; /* stop on error */ - -DEVICE tm_dev; -t_stat tm_rd (int32 *data, int32 PA, int32 access); -t_stat tm_wr (int32 data, int32 PA, int32 access); -t_stat tm_svc (UNIT *uptr); -t_stat tm_reset (DEVICE *dptr); -t_stat tm_attach (UNIT *uptr, char *cptr); -t_stat tm_detach (UNIT *uptr); -t_stat tm_boot (int32 unitno, DEVICE *dptr); -void tm_go (UNIT *uptr); -int32 tm_updcsta (UNIT *uptr); -void tm_set_done (void); -t_stat tm_map_err (UNIT *uptr, t_stat st); -t_stat tm_vlock (UNIT *uptr, int32 val, char *cptr, void *desc); - -/* MT data structures - - tm_dev MT device descriptor - tm_unit MT unit list - tm_reg MT register list - tm_mod MT modifier list -*/ - -DIB tm_dib = { IOBA_TM, IOLN_TM, &tm_rd, &tm_wr, - 1, IVCL (TM), VEC_TM, { NULL } }; - -UNIT tm_unit[] = { - { UDATA (&tm_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) }, - { UDATA (&tm_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) }, - { UDATA (&tm_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) }, - { UDATA (&tm_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) }, - { UDATA (&tm_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) }, - { UDATA (&tm_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) }, - { UDATA (&tm_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) }, - { UDATA (&tm_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) } }; - -REG tm_reg[] = { - { ORDATA (MTS, tm_sta, 16) }, - { ORDATA (MTC, tm_cmd, 16) }, - { ORDATA (MTBRC, tm_bc, 16) }, - { ORDATA (MTCMA, tm_ca, 16) }, - { ORDATA (MTD, tm_db, 8) }, - { ORDATA (MTRD, tm_rdl, 16) }, - { FLDATA (INT, IREQ (TM), INT_V_TM) }, - { FLDATA (ERR, tm_cmd, CSR_V_ERR) }, - { FLDATA (DONE, tm_cmd, CSR_V_DONE) }, - { FLDATA (IE, tm_cmd, CSR_V_IE) }, - { FLDATA (STOP_IOE, tm_stopioe, 0) }, - { DRDATA (TIME, tm_time, 24), PV_LEFT }, - { URDATA (UST, tm_unit[0].USTAT, 8, 16, 0, TM_NUMDR, 0) }, - { URDATA (POS, tm_unit[0].pos, 10, T_ADDR_W, 0, - TM_NUMDR, PV_LEFT | REG_RO) }, - { ORDATA (DEVADDR, tm_dib.ba, 32), REG_HRO }, - { ORDATA (DEVVEC, tm_dib.vec, 16), REG_HRO }, - { NULL } }; - -MTAB tm_mod[] = { - { MTUF_WLK, 0, "write enabled", "WRITEENABLED", &tm_vlock }, - { MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", &tm_vlock }, - { MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT", - &sim_tape_set_fmt, &sim_tape_show_fmt, NULL }, - { MTAB_XTD|MTAB_VDV, 020, "ADDRESS", "ADDRESS", - &set_addr, &show_addr, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "VECTOR", "VECTOR", - &set_vec, &show_vec, NULL }, - { 0 } }; - -DEVICE tm_dev = { - "TM", tm_unit, tm_reg, tm_mod, - TM_NUMDR, 10, 31, 1, 8, 8, - NULL, NULL, &tm_reset, - &tm_boot, &tm_attach, &tm_detach, - &tm_dib, DEV_DISABLE | DEV_UBUS }; - -/* I/O dispatch routine, I/O addresses 17772520 - 17772532 - - 17772520 MTS read only, constructed from tm_sta - plus current drive status flags - 17772522 MTC read/write - 17772524 MTBRC read/write - 17772526 MTCMA read/write - 17772530 MTD read/write - 17772532 MTRD read only -*/ - -t_stat tm_rd (int32 *data, int32 PA, int32 access) -{ -UNIT *uptr; - -uptr = tm_dev.units + GET_UNIT (tm_cmd); /* get unit */ -switch ((PA >> 1) & 07) { /* decode PA<3:1> */ -case 0: /* MTS */ - *data = tm_updcsta (uptr); /* update status */ - break; -case 1: /* MTC */ - tm_updcsta (uptr); /* update status */ - *data = tm_cmd; /* return command */ - break; -case 2: /* MTBRC */ - *data = tm_bc; /* return byte count */ - break; -case 3: /* MTCMA */ - *data = tm_ca; /* return mem addr */ - break; -case 4: /* MTD */ - *data = tm_db; /* return data buffer */ - break; -case 5: /* MTRD */ - tm_rdl = tm_rdl ^ RDL_CLK; /* "clock" ticks */ - *data = tm_rdl; - break; -default: /* unimplemented */ - *data = 0; - break; } -return SCPE_OK; -} - -t_stat tm_wr (int32 data, int32 PA, int32 access) -{ -UNIT *uptr; - -switch ((PA >> 1) & 07) { /* decode PA<3:1> */ -case 0: /* MTS: read only */ - break; -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? */ - 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 = data; - break; -case 3: /* MTCMA */ - if (access == WRITEB) data = (PA & 1)? - (tm_ca & 0377) | (data << 8): (tm_ca & ~0377) | data; - tm_ca = data; - break; -case 4: /* MTD */ - if ((access == WRITEB) && (PA & 1)) return SCPE_OK; - tm_db = data & 0377; - break; } /* end switch */ -return SCPE_OK; -} - -/* New magtape command */ - -void tm_go (UNIT *uptr) -{ -int32 f; - -f = GET_FNC (tm_cmd); /* get function */ -if (((uptr->flags & UNIT_ATT) == 0) || /* not attached? */ - sim_is_active (uptr) || /* busy? */ - (((f == MTC_WRITE) || (f == MTC_WREOF) || (f == MTC_WREXT)) && - sim_tape_wrp (uptr))) { /* write locked? */ - tm_sta = tm_sta | STA_ILL; /* illegal */ - tm_set_done (); /* set done */ - return; } -uptr->USTAT = uptr->USTAT & (STA_WLK | STA_ONL); /* clear status */ -tm_sta = 0; /* clear errors */ -if (f == MTC_UNLOAD) { /* unload? */ - uptr->USTAT = (uptr->USTAT | STA_REW) & ~STA_ONL; - detach_unit (uptr); } /* set offline */ -else if (f == MTC_REWIND) /* rewind */ - uptr->USTAT = uptr->USTAT | STA_REW; /* rewinding */ -/* else /* uncomment this else if rewind/unload don't set done */ -tm_cmd = tm_cmd & ~MTC_DONE; /* clear done */ -CLR_INT (TM); /* clear int */ -sim_activate (uptr, tm_time); /* start io */ -return; -} - -/* Unit service - - If rewind done, reposition to start of tape, set status - else, do operation, set done, interrupt -*/ - -t_stat tm_svc (UNIT *uptr) -{ -int32 f, t, u; -uint32 xma; -t_mtrlnt tbc, cbc; -t_stat st, r = SCPE_OK; - -u = uptr - tm_dev.units; /* get unit number */ -f = GET_FNC (tm_cmd); /* get command */ -xma = GET_EMA (tm_cmd) | tm_ca; /* get mem addr */ -cbc = 0200000 - tm_bc; /* get bc */ - -if (uptr->USTAT & STA_REW) { /* rewind? */ - sim_tape_rewind (uptr); /* update position */ - if (uptr->flags & UNIT_ATT) /* still on line? */ - uptr->USTAT = STA_ONL | STA_BOT | - (sim_tape_wrp (uptr)? STA_WLK: 0); - else uptr->USTAT = 0; - if (u == GET_UNIT (tm_cmd)) { /* selected? */ - tm_set_done (); /* set done */ - tm_updcsta (uptr); } /* update status */ - return SCPE_OK; } - -if ((uptr->flags & UNIT_ATT) == 0) { /* if not attached */ - uptr->USTAT = 0; /* unit off line */ - tm_sta = tm_sta | STA_ILL; /* illegal operation */ - tm_set_done (); /* set done */ - tm_updcsta (uptr); /* update status */ - return IORETURN (tm_stopioe, SCPE_UNATT); } - -if (DBG_LOG (LOG_TM)) fprintf (sim_log, - ">>TM: op=%o, ma=%o, bc=%o, pos=%d\n", f, xma, cbc, uptr->pos); -switch (f) { /* case on function */ - -/* Unit service, continued */ - -case MTC_READ: /* read */ - st = sim_tape_rdrecf (uptr, tmxb, &tbc, MT_MAXFR); /* read rec */ - if (st == MTSE_RECE) tm_sta = tm_sta | STA_PAR; /* rec in error? */ - else if (st != MTSE_OK) { /* other error? */ - r = tm_map_err (uptr, st); /* map error */ - break; } - if (tbc > cbc) tm_sta = tm_sta | STA_RLE; /* wrong size? */ - if (tbc < cbc) cbc = tbc; /* use smaller */ - 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 */ - xma = (xma + cbc) & 0777777; /* inc bus addr */ - tm_bc = (tm_bc + cbc) & 0177777; /* inc byte cnt */ - 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 */ - if (st = sim_tape_wrrecf (uptr, tmxb, cbc)) /* write rec, err? */ - r = tm_map_err (uptr, st); /* map error */ - else { - xma = (xma + cbc) & 0777777; /* inc bus addr */ - tm_bc = (tm_bc + cbc) & 0177777; } /* inc byte cnt */ - break; - -/* Unit service, continued */ - -case MTC_WREOF: /* write eof */ - if (st = sim_tape_wrtmk (uptr)) /* write tmk, err? */ - r = tm_map_err (uptr, st); /* map error */ - break; - -case MTC_SPACEF: /* space forward */ - do { - tm_bc = (tm_bc + 1) & 0177777; /* incr wc */ - if (st = sim_tape_sprecf (uptr, &tbc)) { /* spc rec fwd, err? */ - r = tm_map_err (uptr, st); /* map error */ - break; } - } - while (tm_bc != 0); - break; - -case MTC_SPACER: /* space reverse */ - do { - tm_bc = (tm_bc + 1) & 0177777; /* incr wc */ - if (st = sim_tape_sprecr (uptr, &tbc)) { /* spc rec rev, err? */ - r = tm_map_err (uptr, st); /* map error */ - break; } - } - while (tm_bc != 0); - break; } /* end case */ - -tm_cmd = (tm_cmd & ~MTC_EMA) | ((xma >> (16 - MTC_V_EMA)) & MTC_EMA); -tm_ca = xma & 0177777; /* update mem addr */ -tm_set_done (); /* set done */ -tm_updcsta (uptr); /* update status */ -if (DBG_LOG (LOG_TM)) fprintf (sim_log, - ">>TM: sta=%o, ma=%o, wc=%o, pos=%d\n", - tm_sta, tm_ca, tm_bc, uptr->pos); -return r; -} - -/* Update controller status */ - -int32 tm_updcsta (UNIT *uptr) -{ -tm_sta = (tm_sta & ~(STA_DYN | STA_CLR)) | (uptr->USTAT & STA_DYN); -if (sim_is_active (uptr)) tm_sta = tm_sta & ~STA_TUR; -else tm_sta = tm_sta | STA_TUR; -if (tm_sta & STA_EFLGS) tm_cmd = tm_cmd | MTC_ERR; -else tm_cmd = tm_cmd & ~MTC_ERR; -if ((tm_cmd & MTC_IE) == 0) CLR_INT (TM); -return tm_sta; -} - -/* Set done */ - -void tm_set_done (void) -{ -tm_cmd = tm_cmd | MTC_DONE; -if (tm_cmd & MTC_IE) SET_INT (TM); -return; -} - -/* Map tape error status */ - -t_stat tm_map_err (UNIT *uptr, t_stat st) -{ -switch (st) { -case MTSE_FMT: /* illegal fmt */ -case MTSE_UNATT: /* not attached */ - tm_sta = tm_sta | STA_ILL; -case MTSE_OK: /* no error */ - return SCPE_IERR; -case MTSE_TMK: /* tape mark */ - uptr->USTAT = uptr->USTAT | STA_EOF; /* end of file */ - break; -case MTSE_IOERR: /* IO error */ - tm_sta = tm_sta | STA_PAR; /* parity error */ - if (tm_stopioe) return SCPE_IOERR; - break; -case MTSE_INVRL: /* invalid rec lnt */ - tm_sta = tm_sta | STA_PAR; /* parity error */ - return SCPE_MTRLNT; -case MTSE_RECE: /* record in error */ - tm_sta = tm_sta | STA_PAR; /* parity error */ - break; -case MTSE_EOM: /* end of medium */ - tm_sta = tm_sta | STA_BAD; /* bad tape */ - break; -case MTSE_BOT: /* reverse into BOT */ - uptr->USTAT = uptr->USTAT | STA_BOT; /* set status */ - break; -case MTSE_WRP: /* write protect */ - tm_sta = tm_sta | STA_ILL; /* illegal operation */ - break; } -return SCPE_OK; -} - -/* Reset routine */ - -t_stat tm_reset (DEVICE *dptr) -{ -int32 u; -UNIT *uptr; - -tm_cmd = MTC_DONE; /* set done */ -tm_bc = tm_ca = tm_db = tm_sta = tm_rdl = 0; -CLR_INT (TM); /* clear interrupt */ -for (u = 0; u < TM_NUMDR; u++) { /* loop thru units */ - uptr = tm_dev.units + u; - sim_tape_reset (uptr); /* reset tape */ - sim_cancel (uptr); /* cancel activity */ - if (uptr->flags & UNIT_ATT) uptr->USTAT = STA_ONL | - (sim_tape_bot (uptr)? STA_BOT: 0) | - (sim_tape_wrp (uptr)? STA_WLK: 0); - else uptr->USTAT = 0; } -if (tmxb == NULL) tmxb = calloc (MT_MAXFR, sizeof (unsigned int8)); -if (tmxb == NULL) return SCPE_MEM; -return SCPE_OK; -} - -/* Attach routine */ - -t_stat tm_attach (UNIT *uptr, char *cptr) -{ -t_stat r; -int32 u = uptr - tm_dev.units; - -r = sim_tape_attach (uptr, cptr); -if (r != SCPE_OK) return r; -uptr->USTAT = STA_ONL | STA_BOT | (sim_tape_wrp (uptr)? STA_WLK: 0); -if (u == GET_UNIT (tm_cmd)) tm_updcsta (uptr); -return r; -} - -/* Detach routine */ - -t_stat tm_detach (UNIT* uptr) -{ -int32 u = uptr - tm_dev.units; - -if (!sim_is_active (uptr)) uptr->USTAT = 0; -if (u == GET_UNIT (tm_cmd)) tm_updcsta (uptr); -return sim_tape_detach (uptr); -} - -/* Write lock/enable routine */ - -t_stat tm_vlock (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -int32 u = uptr - tm_dev.units; - -if ((uptr->flags & UNIT_ATT) && - (val || sim_tape_wrp (uptr))) - uptr->USTAT = uptr->USTAT | STA_WLK; -else uptr->USTAT = uptr->USTAT & ~STA_WLK; -if (u == GET_UNIT (tm_cmd)) tm_updcsta (uptr); -return SCPE_OK; -} - -/* Device bootstrap - - Magtape boot format changed over time. Originally, a boot tape - contained a boot loader in the first block. Eventually, the first - block was reserved for a tape label, and the second block was - expected to contain a boot loader. BSD and DEC operating systems - use the second block scheme, so it is the default. - - To boot from the first block, use boot -o (old). -*/ - -#define BOOT_START 016000 -#define BOOT_ENTRY (BOOT_START + 2) -#define BOOT_UNIT (BOOT_START + 010) -#define BOOT_CSR (BOOT_START + 014) -#define BOOT1_LEN (sizeof (boot1_rom) / sizeof (int16)) -#define BOOT2_LEN (sizeof (boot2_rom) / sizeof (int16)) - -static const uint16 boot1_rom[] = { - 0046524, /* boot_start: "TM" */ - 0012706, BOOT_START, /* mov #boot_start, sp */ - 0012700, 0000000, /* mov #unit_num, r0 */ - 0012701, 0172526, /* mov #172526, r1 ; mtcma */ - 0005011, /* clr (r1) */ - 0010141, /* mov r1, -(r1) ; mtbrc */ - 0010002, /* mov r0,r2 */ - 0000302, /* swab r2 */ - 0062702, 0060003, /* add #60003, r2 */ - 0010241, /* mov r2, -(r1) ; read + go */ - 0105711, /* tstb (r1) ; mtc */ - 0100376, /* bpl .-2 */ - 0005002, /* clr r2 */ - 0005003, /* clr r3 */ - 0012704, BOOT_START+020, /* mov #boot_start+20, r4 */ - 0005005, /* clr r5 */ - 0005007 /* clr r7 */ -}; - -static const uint16 boot2_rom[] = { - 0046524, /* boot_start: "TM" */ - 0012706, BOOT_START, /* mov #boot_start, sp */ - 0012700, 0000000, /* mov #unit_num, r0 */ - 0012701, 0172526, /* mov #172526, r1 ; mtcma */ - 0005011, /* clr (r1) */ - 0012741, 0177777, /* mov #-1, -(r1) ; mtbrc */ - 0010002, /* mov r0,r2 */ - 0000302, /* swab r2 */ - 0062702, 0060011, /* add #60011, r2 */ - 0010241, /* mov r2, -(r1) ; space + go */ - 0105711, /* tstb (r1) ; mtc */ - 0100376, /* bpl .-2 */ - 0010002, /* mov r0,r2 */ - 0000302, /* swab r2 */ - 0062702, 0060003, /* add #60003, r2 */ - 0010211, /* mov r2, (r1) ; read + go */ - 0105711, /* tstb (r1) ; mtc */ - 0100376, /* bpl .-2 */ - 0005002, /* clr r2 */ - 0005003, /* clr r3 */ - 0012704, BOOT_START+020, /* mov #boot_start+20, r4 */ - 0005005, /* clr r5 */ - 0005007 /* clr r7 */ -}; - -t_stat tm_boot (int32 unitno, DEVICE *dptr) -{ -int32 i; -extern int32 saved_PC; -extern int32 sim_switches; - -sim_tape_rewind (&tm_unit[unitno]); -if (sim_switches & SWMASK ('O')) { - for (i = 0; i < BOOT1_LEN; i++) - M[(BOOT_START >> 1) + i] = boot1_rom[i]; } -else { for (i = 0; i < BOOT2_LEN; i++) - M[(BOOT_START >> 1) + i] = boot2_rom[i]; } -M[BOOT_UNIT >> 1] = unitno; -M[BOOT_CSR >> 1] = (tm_dib.ba & DMASK) + 06; -saved_PC = BOOT_ENTRY; -return SCPE_OK; -} diff --git a/PDP11/pdp11_tq.c b/PDP11/pdp11_tq.c deleted file mode 100644 index d310372b..00000000 --- a/PDP11/pdp11_tq.c +++ /dev/null @@ -1,2010 +0,0 @@ -/* pdp11_tq.c: TMSCP tape controller simulator - - 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"), - 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. - - tq TQK50 tape controller - - 19-May-03 RMS Revised for new conditional compilation scheme - 25-Apr-03 RMS Revised for extended file support - 28-Mar-03 RMS Added multiformat support - 28-Feb-03 RMS Added variable controller, user-defined drive support - 26-Feb-03 RMS Fixed bug in vector calculation for VAXen - 22-Feb-03 RMS Fixed ordering bug in queue process - Fixed flags table to allow MD_CSE everywhere - 09-Jan-03 RMS Fixed bug in transfer end packet status - 17-Oct-02 RMS Fixed bug in read reverse (found by Hans Pufal) -*/ - -#if defined (VM_PDP10) /* PDP10 version */ -#error "TQK50 not supported on PDP-10!" - -#elif defined (VM_VAX) /* VAX version */ -#include "vax_defs.h" -extern int32 int_req[IPL_HLVL]; -extern int32 int_vec[IPL_HLVL][32]; - -#else /* PDP-11 version */ -#include "pdp11_defs.h" -extern int32 int_req[IPL_HLVL]; -extern int32 int_vec[IPL_HLVL][32]; -extern int32 cpu_18b, cpu_ubm; -#endif - -#include "pdp11_uqssp.h" -#include "pdp11_mscp.h" -#include "sim_tape.h" - -#define UF_MSK (UF_SCH|UF_VSS|UF_CMR|UF_CMW) /* settable flags */ - -#define TQ_SH_MAX 24 /* max display wds */ -#define TQ_SH_PPL 8 /* wds per line */ -#define TQ_SH_DPL 4 /* desc per line */ -#define TQ_SH_RI 001 /* show rings */ -#define TQ_SH_FR 002 /* show free q */ -#define TQ_SH_RS 004 /* show resp q */ -#define TQ_SH_UN 010 /* show unit q's */ - -#define TQ_CLASS 1 /* TQK50 class */ -#define TQ_DHTMO 0 /* def host timeout */ -#define TQ_DCTMO 120 /* def ctrl timeout */ -#define TQ_NUMDR 4 /* # drives */ -#define TQ_MAXFR (1 << 16) /* max xfer */ - -#define UNIT_V_ONL (MTUF_V_UF + 0) /* online */ -#define UNIT_V_ATP (MTUF_V_UF + 1) /* attn pending */ -#define UNIT_V_SXC (MTUF_V_UF + 2) /* serious exc */ -#define UNIT_V_POL (MTUF_V_UF + 3) /* position lost */ -#define UNIT_V_TMK (MTUF_V_UF + 4) /* tape mark seen */ -#define UNIT_ONL (1 << UNIT_V_ONL) -#define UNIT_ATP (1 << UNIT_V_ATP) -#define UNIT_SXC (1 << UNIT_V_SXC) -#define UNIT_POL (1 << UNIT_V_POL) -#define UNIT_TMK (1 << UNIT_V_TMK) -#define cpkt u3 /* current packet */ -#define pktq u4 /* packet queue */ -#define uf buf /* settable unit flags */ -#define objp wait /* object position */ -#define TQ_WPH(u) (sim_tape_wrp (u)) - -#define CST_S1 0 /* init stage 1 */ -#define CST_S1_WR 1 /* stage 1 wrap */ -#define CST_S2 2 /* init stage 2 */ -#define CST_S3 3 /* init stage 3 */ -#define CST_S3_PPA 4 /* stage 3 sa wait */ -#define CST_S3_PPB 5 /* stage 3 ip wait */ -#define CST_S4 6 /* stage 4 */ -#define CST_UP 7 /* online */ -#define CST_DEAD 8 /* fatal error */ - -#define tq_comm tq_rq.ba - -#define ERR 0 /* must be SCPE_OK! */ -#define OK 1 - -#define CMF_IMM 0x10000 /* immediate */ -#define CMF_SEQ 0x20000 /* sequential */ -#define CMF_WR 0x40000 /* write */ -#define CMF_RW 0x80000 /* resp to GCS */ - -/* Internal packet management */ - -#define TQ_NPKTS 32 /* # packets (pwr of 2) */ -#define TQ_M_NPKTS (TQ_NPKTS - 1) /* mask */ -#define TQ_PKT_SIZE_W 32 /* payload size (wds) */ -#define TQ_PKT_SIZE (TQ_PKT_SIZE_W * sizeof (int16)) - -struct tqpkt { - int16 link; /* link to next */ - uint16 d[TQ_PKT_SIZE_W]; }; /* data */ - -/* Packet payload extraction and insertion */ - -#define GETP(p,w,f) ((tq_pkt[p].d[w] >> w##_V_##f) & w##_M_##f) -#define GETP32(p,w) (((uint32) tq_pkt[p].d[w]) | \ - (((uint32) tq_pkt[p].d[(w)+1]) << 16)) -#define PUTP32(p,w,x) tq_pkt[p].d[w] = (x) & 0xFFFF; \ - tq_pkt[p].d[(w)+1] = ((x) >> 16) & 0xFFFF - -/* Controller and device types - TQK50 must be swre rev 5 or later */ - -#define TQ5_TYPE 0 /* TK50 */ -#define TQ5_UQPM 3 /* UQ port ID */ -#define TQ5_CMOD 9 /* ctrl ID */ -#define TQ5_UMOD 3 /* unit ID */ -#define TQ5_MED 0x6D68B032 /* media ID */ -#define TQ5_CREV ((1 << 8) | 5) /* ctrl revs */ -#define TQ5_FREV 0 /* formatter revs */ -#define TQ5_UREV 0 /* unit revs */ -#define TQ5_CAP (94 * (1 << 20)) /* capacity */ -#define TQ5_FMT (TF_CTP|TF_CTP_LO) /* menu */ - -#define TQ7_TYPE 1 /* TK70 */ -#define TQ7_UQPM 14 /* UQ port ID */ -#define TQ7_CMOD 14 /* ctrl ID */ -#define TQ7_UMOD 11 /* unit ID */ -#define TQ7_MED 0x6A68B046 /* media ID */ -#define TQ7_CREV ((1 << 8) | 5) /* ctrl revs */ -#define TQ7_FREV 0 /* formatter revs */ -#define TQ7_UREV 0 /* unit revs */ -#define TQ7_CAP (300 * (1 << 20)) /* capacity */ -#define TQ7_FMT (TF_CTP|TF_CTP_LO) /* menu */ - -#define TQ8_TYPE 2 /* TU81 */ -#define TQ8_UQPM 5 /* UQ port ID */ -#define TQ8_CMOD 5 /* ctrl ID */ -#define TQ8_UMOD 2 /* unit ID */ -#define TQ8_MED 0x6D695051 /* media ID */ -#define TQ8_CREV ((1 << 8) | 5) /* ctrl revs */ -#define TQ8_FREV 0 /* formatter revs */ -#define TQ8_UREV 0 /* unit revs */ -#define TQ8_CAP (180 * (1 << 20)) /* capacity */ -#define TQ8_FMT (TF_9TK|TF_9TK_GRP) /* menu */ - -#define TQU_TYPE 3 /* TKuser defined */ -#define TQU_UQPM 3 /* UQ port ID */ -#define TQU_CMOD 9 /* ctrl ID */ -#define TQU_UMOD 3 /* unit ID */ -#define TQU_MED 0x6D68B032 /* media ID */ -#define TQU_CREV ((1 << 8) | 5) /* ctrl revs */ -#define TQU_FREV 0 /* formatter revs */ -#define TQU_UREV 0 /* unit revs */ -#define TQU_CAP (94 * (1 << 20)) /* capacity */ -#define TQU_FMT (TF_CTP|TF_CTP_LO) /* menu */ -#define TQU_MINC 30 /* min cap MB */ -#define TQU_MAXC 2000 /* max cap MB */ -#define TQU_EMAXC 2000000000 /* ext max cap MB */ - -#define TQ_DRV(d) \ - d##_UQPM, \ - d##_CMOD, d##_MED, d##_FMT, d##_CAP, \ - d##_UMOD, d##_CREV, d##_FREV, d##_UREV - -#define TEST_EOT(u) (sim_tape_eot (u, drv_tab[tq_typ].cap)) - -struct drvtyp { - uint32 uqpm; /* UQ port model */ - uint32 cmod; /* ctrl model */ - uint32 med; /* MSCP media */ - uint32 fmt; /* flags */ - t_addr cap; /* capacity */ - uint32 umod; /* unit model */ - uint32 cver; - uint32 fver; - uint32 uver; - char *name; -}; - -static struct drvtyp drv_tab[] = { - { TQ_DRV (TQ5), "TK50" }, - { TQ_DRV (TQ7), "TK70" }, - { TQ_DRV (TQ8), "TU81" }, - { TQ_DRV (TQU), "TKUSER" }, -}; - -/* Data */ - -extern int32 int_req[IPL_HLVL]; -extern int32 tmr_poll, clk_tps; -extern int32 cpu_log; -extern UNIT cpu_unit; -extern FILE *sim_log; -extern uint32 sim_taddr_64; - -uint8 *tqxb = NULL; /* xfer buffer */ -uint32 tq_sa = 0; /* status, addr */ -uint32 tq_saw = 0; /* written data */ -uint32 tq_s1dat = 0; /* S1 data */ -uint32 tq_csta = 0; /* ctrl state */ -uint32 tq_perr = 0; /* last error */ -uint32 tq_cflgs = 0; /* ctrl flags */ -uint32 tq_prgi = 0; /* purge int */ -uint32 tq_pip = 0; /* poll in progress */ -struct uq_ring tq_cq = { 0 }; /* cmd ring */ -struct uq_ring tq_rq = { 0 }; /* rsp ring */ -struct tqpkt tq_pkt[TQ_NPKTS]; /* packet queue */ -int32 tq_freq = 0; /* free list */ -int32 tq_rspq = 0; /* resp list */ -uint32 tq_pbsy = 0; /* #busy pkts */ -uint32 tq_credits = 0; /* credits */ -uint32 tq_hat = 0; /* host timer */ -uint32 tq_htmo = TQ_DHTMO; /* host timeout */ -int32 tq_itime = 200; /* init time, except */ -int32 tq_itime4 = 10; /* stage 4 */ -int32 tq_qtime = 200; /* queue time */ -int32 tq_xtime = 500; /* transfer time */ -int32 tq_typ = TQ5_TYPE; /* device type */ - -/* Command table - legal modifiers (low 16b) and flags (high 16b) */ - -static uint32 tq_cmf[64] = { - 0, /* 0 */ - CMF_IMM, /* abort */ - CMF_IMM|MD_CSE, /* get cmd status */ - CMF_IMM|MD_CSE|MD_NXU, /* get unit status */ - CMF_IMM|MD_CSE, /* set ctrl char */ - 0, 0, 0, /* 5-7 */ - CMF_SEQ|MD_ACL|MD_CDL|MD_CSE|MD_EXA|MD_UNL, /* available */ - CMF_SEQ|MD_CDL|MD_CSE|MD_SWP|MD_EXA, /* online */ - CMF_SEQ|MD_CDL|MD_CSE|MD_SWP|MD_EXA, /* set unit char */ - CMF_IMM, /* define acc paths */ - 0, 0, 0, 0, /* 12-15 */ - CMF_SEQ|CMF_RW|MD_CDL|MD_CSE|MD_REV| /* access */ - MD_SCH|MD_SEC|MD_SER, - 0, /* 17 */ - CMF_SEQ|CMF_WR|MD_CDL|MD_CSE|MD_IMM, /* erase */ - CMF_SEQ|CMF_WR|MD_CDL|MD_CSE, /* flush */ - 0, 0, /* 20-21 */ - CMF_SEQ|CMF_WR|MD_CDL|MD_CSE|MD_IMM, /* erase gap */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 22-31 */ - CMF_SEQ|CMF_RW|MD_CDL|MD_CSE|MD_REV| /* compare */ - MD_SCH|MD_SEC|MD_SER, - CMF_SEQ|CMF_RW|MD_CDL|MD_CSE|MD_REV|MD_CMP| /* read */ - MD_SCH|MD_SEC|MD_SER, - CMF_SEQ|CMF_RW|CMF_WR|MD_CDL|MD_CSE|MD_IMM| /* write */ - MD_CMP|MD_ERW|MD_SEC|MD_SER, - 0, /* 35 */ - CMF_SEQ|MD_CDL|MD_CSE|MD_IMM, /* wr tape mark */ - CMF_SEQ|MD_CDL|MD_CSE|MD_IMM|MD_OBC| /* reposition */ - MD_REV|MD_RWD|MD_DLE| - MD_SCH|MD_SEC|MD_SER, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 38-47 */ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0 }; - -/* Forward references */ - -DEVICE tq_dev; - -t_stat tq_rd (int32 *data, int32 PA, int32 access); -t_stat tq_wr (int32 data, int32 PA, int32 access); -t_stat tq_inta (void); -t_stat tq_svc (UNIT *uptr); -t_stat tq_tmrsvc (UNIT *uptr); -t_stat tq_quesvc (UNIT *uptr); -t_stat tq_reset (DEVICE *dptr); -t_stat tq_attach (UNIT *uptr, char *cptr); -t_stat tq_detach (UNIT *uptr); -t_stat tq_boot (int32 unitno, DEVICE *dptr); -t_stat tq_set_wlk (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat tq_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat tq_show_ctrl (FILE *st, UNIT *uptr, int32 val, void *desc); -t_stat tq_show_unitq (FILE *st, UNIT *uptr, int32 val, void *desc); -t_stat tq_set_type (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat tq_show_type (FILE *st, UNIT *uptr, int32 val, void *desc); - -t_bool tq_step4 (void); -t_bool tq_mscp (int32 pkt, t_bool q); -t_bool tq_abo (int32 pkt); -t_bool tq_avl (int32 pkt); -t_bool tq_erase (int32 pkt); -t_bool tq_flu (int32 pkt); -t_bool tq_gcs (int32 pkt); -t_bool tq_gus (int32 pkt); -t_bool tq_onl (int32 pkt); -t_bool tq_pos (int32 pkt); -t_bool tq_rw (int32 pkt); -t_bool tq_scc (int32 pkt); -t_bool tq_suc (int32 pkt); -t_bool tq_wtm (int32 pkt); -t_bool tq_plf (uint32 err); -t_bool tq_dte (UNIT *uptr, uint32 err); -t_bool tq_hbe (UNIT *uptr, uint32 ba); -t_bool tq_una (UNIT *uptr); -uint32 tq_map_status (UNIT *uptr, t_stat st); -uint32 tq_spacef (UNIT *uptr, uint32 cnt, uint32 *skipped, t_bool qrec); -uint32 tq_skipff (UNIT *uptr, uint32 cnt, uint32 *skipped); -uint32 tq_rdbuff (UNIT *uptr, t_mtrlnt *tbc); -uint32 tq_spacer (UNIT *uptr, uint32 cnt, uint32 *skipped, t_bool qrec); -uint32 tq_skipfr (UNIT *uptr, uint32 cnt, uint32 *skipped); -uint32 tq_rdbufr (UNIT *uptr, t_mtrlnt *tbc); -t_bool tq_deqf (int32 *pkt); -int32 tq_deqh (int32 *lh); -void tq_enqh (int32 *lh, int32 pkt); -void tq_enqt (int32 *lh, int32 pkt); -t_bool tq_getpkt (int32 *pkt); -t_bool tq_putpkt (int32 pkt, t_bool qt); -t_bool tq_getdesc (struct uq_ring *ring, uint32 *desc); -t_bool tq_putdesc (struct uq_ring *ring, uint32 desc); -int32 tq_mot_valid (UNIT *uptr, uint32 cmd); -t_stat tq_mot_err (UNIT *uptr, uint32 rsiz); -t_bool tq_mot_end (UNIT *uptr, uint32 flg, uint32 sts, uint32 rsiz); -void tq_putr (int32 pkt, uint32 cmd, uint32 flg, uint32 sts, uint32 lnt, uint32 typ); -void tq_putr_unit (int32 pkt, UNIT *uptr, uint32 lu, t_bool all); -void tq_setf_unit (int32 pkt, UNIT *uptr); -uint32 tq_efl (UNIT *uptr); -void tq_init_int (void); -void tq_ring_int (struct uq_ring *ring); -t_bool tq_fatal (uint32 err); -UNIT *tq_getucb (uint32 lu); - -/* TQ data structures - - tq_dev TQ device descriptor - tq_unit TQ unit list - tq_reg TQ register list - tq_mod TQ modifier list -*/ - -DIB tq_dib = { IOBA_TQ, IOLN_TQ, &tq_rd, &tq_wr, - 1, IVCL (TQ), 0, { &tq_inta } }; - -UNIT tq_unit[] = { - { UDATA (&tq_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0), 0 }, - { UDATA (&tq_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0), 0 }, - { UDATA (&tq_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0), 0 }, - { UDATA (&tq_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0), 0 }, - { UDATA (&tq_tmrsvc, UNIT_DIS, 0) }, - { UDATA (&tq_quesvc, UNIT_DIS, 0) } }; - -#define TQ_TIMER (TQ_NUMDR) -#define TQ_QUEUE (TQ_TIMER + 1) - -REG tq_reg[] = { - { GRDATA (SA, tq_sa, DEV_RDX, 16, 0) }, - { GRDATA (SAW, tq_saw, DEV_RDX, 16, 0) }, - { GRDATA (S1DAT, tq_s1dat, DEV_RDX, 16, 0) }, - { GRDATA (CQBA, tq_cq.ba, DEV_RDX, 22, 0) }, - { GRDATA (CQLNT, tq_cq.lnt, DEV_RDX, 8, 2), REG_NZ }, - { GRDATA (CQIDX, tq_cq.idx, DEV_RDX, 8, 2) }, - { GRDATA (TQBA, tq_rq.ba, DEV_RDX, 22, 0) }, - { GRDATA (TQLNT, tq_rq.lnt, DEV_RDX, 8, 2), REG_NZ }, - { GRDATA (TQIDX, tq_rq.idx, DEV_RDX, 8, 2) }, - { DRDATA (FREE, tq_freq, 5) }, - { DRDATA (RESP, tq_rspq, 5) }, - { DRDATA (PBSY, tq_pbsy, 5) }, - { GRDATA (CFLGS, tq_cflgs, DEV_RDX, 16, 0) }, - { GRDATA (CSTA, tq_csta, DEV_RDX, 4, 0) }, - { GRDATA (PERR, tq_perr, DEV_RDX, 9, 0) }, - { DRDATA (CRED, tq_credits, 5) }, - { DRDATA (HAT, tq_hat, 17) }, - { DRDATA (HTMO, tq_htmo, 17) }, - { URDATA (CPKT, tq_unit[0].cpkt, 10, 5, 0, TQ_NUMDR, 0) }, - { URDATA (PKTQ, tq_unit[0].pktq, 10, 5, 0, TQ_NUMDR, 0) }, - { URDATA (UFLG, tq_unit[0].uf, DEV_RDX, 16, 0, TQ_NUMDR, 0) }, - { URDATA (POS, tq_unit[0].pos, 10, T_ADDR_W, 0, TQ_NUMDR, 0) }, - { URDATA (OBJP, tq_unit[0].objp, 10, 32, 0, TQ_NUMDR, 0) }, - { FLDATA (PRGI, tq_prgi, 0), REG_HIDDEN }, - { FLDATA (PIP, tq_pip, 0), REG_HIDDEN }, - { FLDATA (INT, IREQ (TQ), INT_V_TQ) }, - { DRDATA (ITIME, tq_itime, 24), PV_LEFT + REG_NZ }, - { DRDATA (I4TIME, tq_itime4, 24), PV_LEFT + REG_NZ }, - { DRDATA (QTIME, tq_qtime, 24), PV_LEFT + REG_NZ }, - { DRDATA (XTIME, tq_xtime, 24), PV_LEFT + REG_NZ }, - { BRDATA (PKTS, tq_pkt, DEV_RDX, 16, TQ_NPKTS * (TQ_PKT_SIZE_W + 1)) }, - { DRDATA (DEVTYPE, tq_typ, 2), REG_HRO }, - { DRDATA (DEVCAP, drv_tab[TQU_TYPE].cap, T_ADDR_W), PV_LEFT | REG_HRO }, - { GRDATA (DEVADDR, tq_dib.ba, DEV_RDX, 32, 0), REG_HRO }, - { GRDATA (DEVVEC, tq_dib.vec, DEV_RDX, 16, 0), REG_HRO }, - { NULL } }; - -MTAB tq_mod[] = { - { MTUF_WLK, 0, "write enabled", "WRITEENABLED", NULL }, - { MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL }, - { MTAB_XTD | MTAB_VDV, TQ5_TYPE, NULL, "TK50", - &tq_set_type, NULL, NULL }, - { MTAB_XTD | MTAB_VDV, TQ7_TYPE, NULL, "TK70", - &tq_set_type, NULL, NULL }, - { MTAB_XTD | MTAB_VDV, TQ8_TYPE, NULL, "TU81", - &tq_set_type, NULL, NULL }, - { MTAB_XTD | MTAB_VDV, TQU_TYPE, NULL, "TKUSER", - &tq_set_type, NULL, NULL }, - { MTAB_XTD | MTAB_VDV, 0, "TYPE", NULL, - NULL, &tq_show_type, NULL }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, TQ_SH_RI, "RINGS", NULL, - NULL, &tq_show_ctrl, NULL }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, TQ_SH_FR, "FREEQ", NULL, - NULL, &tq_show_ctrl, NULL }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, TQ_SH_RS, "RESPQ", NULL, - NULL, &tq_show_ctrl, NULL }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, TQ_SH_UN, "UNITQ", NULL, - NULL, &tq_show_ctrl, NULL }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, -1, "ALL", NULL, - NULL, &tq_show_ctrl, NULL }, - { MTAB_XTD | MTAB_VUN | MTAB_NMO, 0, "UNITQ", NULL, - NULL, &tq_show_unitq, NULL }, - { MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT", - &sim_tape_set_fmt, &sim_tape_show_fmt, NULL }, -#if defined (VM_PDP11) - { MTAB_XTD|MTAB_VDV, 004, "ADDRESS", "ADDRESS", - &set_addr, &show_addr, NULL }, -#else - { MTAB_XTD|MTAB_VDV, 004, "ADDRESS", NULL, - NULL, &show_addr, NULL }, -#endif - { MTAB_XTD|MTAB_VDV, 0, "VECTOR", NULL, - NULL, &show_vec, NULL }, - { 0 } }; - -DEVICE tq_dev = { - "TQ", tq_unit, tq_reg, tq_mod, - TQ_NUMDR + 2, 10, 31, 1, DEV_RDX, 8, - NULL, NULL, &tq_reset, - &tq_boot, &tq_attach, &tq_detach, - &tq_dib, DEV_DISABLE | DEV_UBUS | DEV_QBUS }; - -/* I/O dispatch routine, I/O addresses 17772150 - 17772152 - - 17772150 IP read/write - 17772152 SA read/write -*/ - -t_stat tq_rd (int32 *data, int32 PA, int32 access) -{ -switch ((PA >> 1) & 01) { /* decode PA<1> */ -case 0: /* IP */ - *data = 0; /* reads zero */ - if (tq_csta == CST_S3_PPB) tq_step4 (); /* waiting for poll? */ - else if (tq_csta == CST_UP) { /* if up */ - tq_pip = 1; /* poll host */ - sim_activate (&tq_unit[TQ_QUEUE], tq_qtime); } - break; -case 1: /* SA */ - *data = tq_sa; - break; } -return SCPE_OK; -} - -t_stat tq_wr (int32 data, int32 PA, int32 access) -{ -switch ((PA >> 1) & 01) { /* decode PA<1> */ -case 0: /* IP */ - tq_reset (&tq_dev); /* init device */ - if (DBG_LOG (LOG_TQ)) fprintf (sim_log, - ">>TQ: initialization started, time=%.0f\n", sim_gtime ()); - break; -case 1: /* SA */ - tq_saw = data; - if (tq_csta < CST_S4) /* stages 1-3 */ - sim_activate (&tq_unit[TQ_QUEUE], tq_itime); - else if (tq_csta == CST_S4) /* stage 4 (fast) */ - sim_activate (&tq_unit[TQ_QUEUE], tq_itime4); - break; } -return SCPE_OK; -} - -/* Transition to step 4 - init communications region */ - -t_bool tq_step4 (void) -{ -int32 i, lnt; -uint32 base; -uint16 zero[SA_COMM_MAX >> 1]; - -tq_rq.ioff = SA_COMM_RI; /* set intr offset */ -tq_rq.ba = tq_comm; /* set rsp q base */ -tq_rq.lnt = SA_S1H_RQ (tq_s1dat) << 2; /* get resp q len */ -tq_cq.ioff = SA_COMM_CI; /* set intr offset */ -tq_cq.ba = tq_comm + tq_rq.lnt; /* set cmd q base */ -tq_cq.lnt = SA_S1H_CQ (tq_s1dat) << 2; /* get cmd q len */ -tq_cq.idx = tq_rq.idx = 0; /* clear q idx's */ -if (tq_prgi) base = tq_comm + SA_COMM_QQ; -else base = tq_comm + SA_COMM_CI; -lnt = tq_comm + tq_cq.lnt + tq_rq.lnt - base; /* comm lnt */ -if (lnt > SA_COMM_MAX) lnt = SA_COMM_MAX; /* paranoia */ -for (i = 0; i < (lnt >> 1); i++) zero[i] = 0; /* clr buffer */ -if (Map_WriteW (base, lnt, zero, MAP)) /* zero comm area */ - return tq_fatal (PE_QWE); /* error? */ -tq_sa = SA_S4 | (drv_tab[tq_typ].uqpm << SA_S4C_V_MOD) |/* send step 4 */ - ((drv_tab[tq_typ].cver & 0xFF) << SA_S4C_V_VER); -tq_csta = CST_S4; /* set step 4 */ -tq_init_int (); /* poke host */ -return OK; -} - -/* Queue service - invoked when any of the queues (host queue, unit - queues, response queue) require servicing. Also invoked during - initialization to provide some delay to the next step. - - Process at most one item off each unit queue - If the unit queues were empty, process at most one item off the host queue - Process at most one item off the response queue - - If all queues are idle, terminate thread -*/ - -t_stat tq_quesvc (UNIT *uptr) -{ -int32 i, cnid; -int32 pkt = 0; -UNIT *nuptr; - -if (tq_csta < CST_UP) { /* still init? */ - switch (tq_csta) { /* controller state? */ - case CST_S1: /* need S1 reply */ - if (tq_saw & SA_S1H_VL) { /* valid? */ - if (tq_saw & SA_S1H_WR) { /* wrap? */ - tq_sa = tq_saw; /* echo data */ - tq_csta = CST_S1_WR; } /* endless loop */ - else { - tq_s1dat = tq_saw; /* save data */ - tq_dib.vec = (tq_s1dat & SA_S1H_VEC) << 2; /* get vector */ - if (tq_dib.vec) tq_dib.vec = tq_dib.vec + VEC_Q; /* if nz, bias */ - tq_sa = SA_S2 | SA_S2C_PT | SA_S2C_EC (tq_s1dat); - tq_csta = CST_S2; /* now in step 2 */ - tq_init_int (); } /* intr if req */ - } /* end if valid */ - break; - case CST_S1_WR: /* wrap mode */ - tq_sa = tq_saw; /* echo data */ - break; - case CST_S2: /* need S2 reply */ - tq_comm = tq_saw & SA_S2H_CLO; /* get low addr */ - tq_prgi = tq_saw & SA_S2H_PI; /* get purge int */ - tq_sa = SA_S3 | SA_S3C_EC (tq_s1dat); - tq_csta = CST_S3; /* now in step 3 */ - tq_init_int (); /* intr if req */ - break; - case CST_S3: /* need S3 reply */ - tq_comm = ((tq_saw & SA_S3H_CHI) << 16) | tq_comm; - if (tq_saw & SA_S3H_PP) { /* purge/poll test? */ - tq_sa = 0; /* put 0 */ - tq_csta = CST_S3_PPA; } /* wait for 0 write */ - else tq_step4 (); /* send step 4 */ - break; - case CST_S3_PPA: /* need purge test */ - if (tq_saw) tq_fatal (PE_PPF); /* data not zero? */ - else tq_csta = CST_S3_PPB; /* wait for poll */ - break; - case CST_S4: /* need S4 reply */ - if (tq_saw & SA_S4H_GO) { /* go set? */ - if (DBG_LOG (LOG_TQ)) fprintf (sim_log, - ">>TQ: initialization complete\n"); - tq_csta = CST_UP; /* we're up */ - tq_sa = 0; /* clear SA */ - sim_activate (&tq_unit[TQ_TIMER], tmr_poll * clk_tps); - if ((tq_saw & SA_S4H_LF) && tq_perr) tq_plf (tq_perr); - tq_perr = 0; } - break; } /* end switch */ - return SCPE_OK; } /* end if */ - -for (i = 0; i < TQ_NUMDR; i++) { /* chk unit q's */ - nuptr = tq_dev.units + i; /* ptr to unit */ - if (nuptr->cpkt || (nuptr->pktq == 0)) continue; - pkt = tq_deqh (&nuptr->pktq); /* get top of q */ - if (!tq_mscp (pkt, FALSE)) return SCPE_OK; } /* process */ -if ((pkt == 0) && tq_pip) { /* polling? */ - if (!tq_getpkt (&pkt)) return SCPE_OK; /* get host pkt */ - if (pkt) { /* got one? */ - if (DBG_LOG (LOG_TQ)) { - UNIT *up = tq_getucb (tq_pkt[pkt].d[CMD_UN]); - fprintf (sim_log, ">>TQ: cmd=%04X, mod=%04X, unit=%d, ", - tq_pkt[pkt].d[CMD_OPC], tq_pkt[pkt].d[CMD_MOD], tq_pkt[pkt].d[CMD_UN]); - fprintf (sim_log, "bc=%04X%04X, ma=%04X%04X", - 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"); - 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 */ - if (cnid == UQ_CID_TMSCP) { /* TMSCP packet? */ - if (!tq_mscp (pkt, TRUE)) return SCPE_OK; } /* proc, q non-seq */ - else if (cnid == UQ_CID_DUP) { /* DUP packet? */ - tq_putr (pkt, OP_END, 0, ST_CMD | I_OPCD, RSP_LNT, UQ_TYP_SEQ); - if (!tq_putpkt (pkt, TRUE)) return SCPE_OK; } /* ill cmd */ - else return tq_fatal (PE_ICI); /* no, term thread */ - } /* end if pkt */ - else tq_pip = 0; /* discontinue poll */ - } /* end if pip */ -if (tq_rspq) { /* resp q? */ - pkt = tq_deqh (&tq_rspq); /* get top of q */ - if (!tq_putpkt (pkt, FALSE)) return SCPE_OK; /* send to hst */ - } /* end if resp q */ -if (pkt) sim_activate (&tq_unit[TQ_QUEUE], tq_qtime); /* more to do? */ -return SCPE_OK; /* done */ -} - -/* Clock service (roughly once per second) */ - -t_stat tq_tmrsvc (UNIT *uptr) -{ -int32 i; -UNIT *nuptr; - -sim_activate (uptr, tmr_poll * clk_tps); /* reactivate */ -for (i = 0; i < TQ_NUMDR; i++) { /* poll */ - nuptr = tq_dev.units + i; - if ((nuptr->flags & UNIT_ATP) && /* ATN pending? */ - (nuptr->flags & UNIT_ATT) && /* still online? */ - (tq_cflgs & CF_ATN)) { /* wanted? */ - if (!tq_una (nuptr)) return SCPE_OK; } - nuptr->flags = nuptr->flags & ~UNIT_ATP; } -if ((tq_hat > 0) && (--tq_hat == 0)) /* host timeout? */ - tq_fatal (PE_HAT); /* fatal err */ -return SCPE_OK; -} - -/* MSCP packet handling */ - -t_bool tq_mscp (int32 pkt, t_bool q) -{ -uint32 sts; -uint32 cmd = GETP (pkt, CMD_OPC, OPC); /* command */ -uint32 flg = GETP (pkt, CMD_OPC, FLG); /* flags */ -uint32 mdf = tq_pkt[pkt].d[CMD_MOD]; /* modifier */ -uint32 lu = tq_pkt[pkt].d[CMD_UN]; /* unit # */ -UNIT *uptr; - -if ((cmd >= 64) || (tq_cmf[cmd] == 0)) { /* invalid cmd? */ - cmd = OP_END; /* set end op */ - sts = ST_CMD | I_OPCD; } /* ill op */ -else if (flg) { /* flags? */ - cmd = cmd | OP_END; /* set end flag */ - sts = ST_CMD | I_FLAG; } /* ill flags */ -else if (mdf & ~tq_cmf[cmd]) { /* invalid mod? */ - cmd = cmd | OP_END; /* set end flag */ - sts = ST_CMD | I_MODF; } /* ill mods */ -else { /* valid cmd */ - if (uptr = tq_getucb (lu)) { /* valid unit? */ - if (q && (tq_cmf[cmd] & CMF_SEQ) && /* queueing, seq, */ - (uptr->cpkt || uptr->pktq)) { /* and active? */ - tq_enqt (&uptr->pktq, pkt); /* do later */ - return OK; } -/* if (tq_cmf[cmd] & MD_CDL) /* clr cch lost? */ -/* uptr->flags = uptr->flags & ~UNIT_CDL; */ - if (tq_cmf[cmd] & MD_CSE) /* clr ser exc? */ - uptr->flags = uptr->flags & ~UNIT_SXC; } - switch (cmd) { - case OP_ABO: /* abort */ - return tq_abo (pkt); - case OP_AVL: /* avail */ - return tq_avl (pkt); - case OP_GCS: /* get cmd status */ - return tq_gcs (pkt); - case OP_GUS: /* get unit status */ - return tq_gus (pkt); - case OP_ONL: /* online */ - return tq_onl (pkt); - case OP_SCC: /* set ctrl char */ - return tq_scc (pkt); - case OP_SUC: /* set unit char */ - return tq_suc (pkt); - case OP_ERS: /* erase */ - case OP_ERG: /* erase gap */ - return tq_erase (pkt); - case OP_FLU: /* flush */ - return tq_flu (pkt); - case OP_POS: /* position */ - return tq_pos (pkt); - case OP_WTM: /* write tape mark */ - return tq_wtm (pkt); - case OP_ACC: /* access */ - case OP_CMP: /* compare */ - case OP_RD: /* read */ - case OP_WR: /* write */ - return tq_rw (pkt); - case OP_DAP: - cmd = cmd | OP_END; /* set end flag */ - sts = ST_SUC; /* success */ - break; - default: - cmd = OP_END; /* set end op */ - sts = ST_CMD | I_OPCD; /* ill op */ - break; - } /* end switch */ - } /* end else */ -tq_putr (pkt, cmd, 0, sts, RSP_LNT, UQ_TYP_SEQ); -return tq_putpkt (pkt, TRUE); -} - -/* Abort a command - 1st parameter is ref # of cmd to abort */ - -t_bool tq_abo (int32 pkt) -{ -uint32 lu = tq_pkt[pkt].d[CMD_UN]; /* unit # */ -uint32 ref = GETP32 (pkt, ABO_REFL); /* cmd ref # */ -int32 tpkt, prv; -UNIT *uptr; - -tpkt = 0; /* set no mtch */ -if (uptr = tq_getucb (lu)) { /* get unit */ - if (uptr->cpkt && /* curr pkt? */ - (GETP32 (uptr->cpkt, CMD_REFL) == ref)) { /* match ref? */ - tpkt = uptr->cpkt; /* save match */ - uptr->cpkt = 0; /* gonzo */ - sim_cancel (uptr); /* cancel unit */ - sim_activate (&tq_unit[TQ_QUEUE], tq_qtime); } - else if (uptr->pktq && /* head of q? */ - (GETP32 (uptr->pktq, CMD_REFL) == ref)) { /* match ref? */ - tpkt = uptr->pktq; /* save match */ - uptr->pktq = tq_pkt[tpkt].link; } /* unlink */ - else if (prv = uptr->pktq) { /* srch pkt q */ - while (tpkt = tq_pkt[prv].link) { /* walk list */ - if (GETP32 (tpkt, RSP_REFL) == ref) { /* match ref? */ - tq_pkt[prv].link = tq_pkt[tpkt].link; /* unlink */ - break; } } } - if (tpkt) { /* found target? */ - uint32 tcmd = GETP (tpkt, CMD_OPC, OPC); /* get opcode */ - tq_putr (tpkt, tcmd | OP_END, 0, ST_ABO, RSP_LNT, UQ_TYP_SEQ); - if (!tq_putpkt (tpkt, TRUE)) return ERR; } - } /* end if unit */ -tq_putr (pkt, OP_ABO | OP_END, 0, ST_SUC, ABO_LNT, UQ_TYP_SEQ); -return tq_putpkt (pkt, TRUE); -} - -/* Unit available - set unit status to available - Deferred if q'd cmds, bypassed if ser exc */ - -t_bool tq_avl (int32 pkt) -{ -uint32 lu = tq_pkt[pkt].d[CMD_UN]; /* unit # */ -uint32 mdf = tq_pkt[pkt].d[CMD_MOD]; /* modifiers */ -uint32 sts; -UNIT *uptr; - -if (uptr = tq_getucb (lu)) { /* unit exist? */ - if (uptr->flags & UNIT_SXC) sts = ST_SXC; /* ser exc pending? */ - else { - uptr->flags = uptr->flags & ~(UNIT_ONL | UNIT_TMK | UNIT_POL); - sim_tape_rewind (uptr); /* rewind */ - uptr->uf = uptr->objp = 0; /* clr flags */ - if (uptr->flags & UNIT_ATT) { /* attached? */ - sts = ST_SUC; /* success */ - if (mdf & MD_UNL) tq_detach (uptr); } /* unload? */ - else sts = ST_OFL | SB_OFL_NV; } } /* no, offline */ -else sts = ST_OFL; /* offline */ -tq_putr (pkt, OP_AVL | OP_END, tq_efl (uptr), sts, AVL_LNT, UQ_TYP_SEQ); -return tq_putpkt (pkt, TRUE); -} - -/* Get command status - only interested in active xfr cmd */ - -t_bool tq_gcs (int32 pkt) -{ -uint32 lu = tq_pkt[pkt].d[CMD_UN]; /* unit # */ -uint32 ref = GETP32 (pkt, GCS_REFL); /* ref # */ -int32 tpkt; -UNIT *uptr; - -if ((uptr = tq_getucb (lu)) && /* valid lu? */ - (tpkt = uptr->cpkt) && /* queued pkt? */ - (GETP32 (tpkt, CMD_REFL) == ref) && /* match ref? */ - (tq_cmf[GETP (tpkt, CMD_OPC, OPC)] & CMF_RW)) { /* rd/wr cmd? */ - tq_pkt[pkt].d[GCS_STSL] = tq_pkt[tpkt].d[RW_BCL]; - tq_pkt[pkt].d[GCS_STSH] = tq_pkt[tpkt].d[RW_BCH]; } -else tq_pkt[pkt].d[GCS_STSL] = tq_pkt[pkt].d[GCS_STSH] = 0; -tq_putr (pkt, OP_GCS | OP_END, 0, ST_SUC, GCS_LNT, UQ_TYP_SEQ); -return tq_putpkt (pkt, TRUE); -} - -/* Get unit status */ - -t_bool tq_gus (int32 pkt) -{ -uint32 lu = tq_pkt[pkt].d[CMD_UN]; /* unit # */ -uint32 sts; -UNIT *uptr; - -if (tq_pkt[pkt].d[CMD_MOD] & MD_NXU) { /* next unit? */ - if (lu >= TQ_NUMDR) { /* end of range? */ - lu = 0; /* reset to 0 */ - tq_pkt[pkt].d[RSP_UN] = lu; } } -if (uptr = tq_getucb (lu)) { /* unit exist? */ - if ((uptr->flags & UNIT_ATT) == 0) /* not attached? */ - sts = ST_OFL | SB_OFL_NV; /* offl no vol */ - else if (uptr->flags & UNIT_ONL) sts = ST_SUC; /* online */ - else sts = ST_AVL; /* avail */ - tq_putr_unit (pkt, uptr, lu, FALSE); /* fill unit fields */ - tq_pkt[pkt].d[GUS_MENU] = drv_tab[tq_typ].fmt; /* format menu */ - tq_pkt[pkt].d[GUS_CAP] = 0; /* free capacity */ - tq_pkt[pkt].d[GUS_FVER] = drv_tab[tq_typ].fver; /* formatter version */ - tq_pkt[pkt].d[GUS_UVER] = drv_tab[tq_typ].uver; /* unit version */ - } -else sts = ST_OFL; /* offline */ -tq_putr (pkt, OP_GUS | OP_END, tq_efl (uptr), sts, GUS_LNT_T, UQ_TYP_SEQ); -return tq_putpkt (pkt, TRUE); -} - -/* Unit online - deferred if q'd commands */ - -t_bool tq_onl (int32 pkt) -{ -uint32 lu = tq_pkt[pkt].d[CMD_UN]; /* unit # */ -uint32 sts; -UNIT *uptr; - -if (uptr = tq_getucb (lu)) { /* unit exist? */ - if ((uptr->flags & UNIT_ATT) == 0) /* not attached? */ - sts = ST_OFL | SB_OFL_NV; /* offl no vol */ - else if (uptr->flags & UNIT_ONL) /* already online? */ - sts = ST_SUC | SB_SUC_ON; - else { sts = ST_SUC; /* mark online */ - sim_tape_rewind (uptr); /* rewind */ - uptr->objp = 0; /* clear flags */ - uptr->flags = (uptr->flags | UNIT_ONL) & - ~(UNIT_TMK | UNIT_POL); /* onl, pos ok */ - tq_setf_unit (pkt, uptr); } /* hack flags */ - tq_putr_unit (pkt, uptr, lu, TRUE); } /* set fields */ -else sts = ST_OFL; /* offline */ -tq_putr (pkt, OP_ONL | OP_END, tq_efl (uptr), sts, ONL_LNT, UQ_TYP_SEQ); -return tq_putpkt (pkt, TRUE); -} - -/* Set controller characteristics */ - -t_bool tq_scc (int32 pkt) -{ -if (tq_pkt[pkt].d[SCC_MSV]) /* MSCP ver = 0? */ - tq_putr (pkt, 0, 0, ST_CMD | I_VRSN, SCC_LNT, UQ_TYP_SEQ); -else { tq_cflgs = (tq_cflgs & CF_RPL) | /* hack ctrl flgs */ - tq_pkt[pkt].d[SCC_CFL]; - if (tq_htmo = tq_pkt[pkt].d[SCC_TMO]) /* set timeout */ - tq_htmo = tq_htmo + 2; /* if nz, round up */ - tq_pkt[pkt].d[SCC_CFL] = tq_cflgs; /* return flags */ - tq_pkt[pkt].d[SCC_TMO] = TQ_DCTMO; /* ctrl timeout */ - tq_pkt[pkt].d[SCC_VER] = drv_tab[tq_typ].cver; /* ctrl version */ - tq_pkt[pkt].d[SCC_CIDA] = 0; /* ctrl ID */ - tq_pkt[pkt].d[SCC_CIDB] = 0; - tq_pkt[pkt].d[SCC_CIDC] = 0; - tq_pkt[pkt].d[SCC_CIDD] = (TQ_CLASS << SCC_CIDD_V_CLS) | - (drv_tab[tq_typ].cmod << SCC_CIDD_V_MOD); - PUTP32 (pkt, SCC_MBCL, TQ_MAXFR); /* max bc */ - tq_putr (pkt, OP_SCC | OP_END, 0, ST_SUC, SCC_LNT, UQ_TYP_SEQ); - } -return tq_putpkt (pkt, TRUE); -} - -/* Set unit characteristics - defer if q'd commands */ - -t_bool tq_suc (int32 pkt) -{ -uint32 lu = tq_pkt[pkt].d[CMD_UN]; /* unit # */ -uint32 sts; -UNIT *uptr; - -if (uptr = tq_getucb (lu)) { /* unit exist? */ - if ((uptr->flags & UNIT_ATT) == 0) /* not attached? */ - sts = ST_OFL | SB_OFL_NV; /* offl no vol */ - else { sts = ST_SUC; /* avail or onl */ - tq_setf_unit (pkt, uptr); } /* hack flags */ - tq_putr_unit (pkt, uptr, lu, TRUE); } /* set fields */ -else sts = ST_OFL; /* offline */ -tq_putr (pkt, OP_SUC | OP_END, 0, sts, SUC_LNT, UQ_TYP_SEQ); -return tq_putpkt (pkt, TRUE); -} - -/* Flush - sequential nop - deferred if q'd cmds, bypassed if ser exc */ - -t_bool tq_flu (int32 pkt) -{ -uint32 lu = tq_pkt[pkt].d[CMD_UN]; /* unit # */ -uint32 sts; -UNIT *uptr; - -if (uptr = tq_getucb (lu)) { /* unit exist? */ - sts = tq_mot_valid (uptr, OP_FLU); } /* validate req */ -else sts = ST_OFL; /* offline */ -tq_putr (pkt, OP_FLU | OP_END, tq_efl (uptr), sts, FLU_LNT, UQ_TYP_SEQ); -return tq_putpkt (pkt, TRUE); -} - -/* Erase, erase gap - deferred if q'd cmds, bypassed if ser exc */ - -t_bool tq_erase (int32 pkt) -{ -uint32 lu = tq_pkt[pkt].d[CMD_UN]; /* unit # */ -uint32 cmd = GETP (pkt, CMD_OPC, OPC); /* opcode */ -uint32 sts; -UNIT *uptr; - -if (uptr = tq_getucb (lu)) { /* unit exist? */ - sts = tq_mot_valid (uptr, cmd); /* validity checks */ - if (sts == ST_SUC) { /* ok? */ - uptr->cpkt = pkt; /* op in progress */ - sim_activate (uptr, tq_xtime); /* activate */ - return OK; } } /* done */ -else sts = ST_OFL; /* offline */ -tq_putr (pkt, cmd | OP_END, tq_efl (uptr), sts, ERS_LNT, UQ_TYP_SEQ); -return tq_putpkt (pkt, TRUE); -} - -/* Write tape mark - deferred if q'd cmds, bypassed if ser exc */ - -t_bool tq_wtm (int32 pkt) -{ -uint32 lu = tq_pkt[pkt].d[CMD_UN]; /* unit # */ -uint32 sts, objp = 0; -UNIT *uptr; - -if (uptr = tq_getucb (lu)) { /* unit exist? */ - objp = uptr->objp; /* position op */ - sts = tq_mot_valid (uptr, OP_WTM); /* validity checks */ - if (sts == ST_SUC) { /* ok? */ - uptr->cpkt = pkt; /* op in progress */ - sim_activate (uptr, tq_xtime); /* activate */ - return OK; } } /* done */ -else sts = ST_OFL; /* offline */ -PUTP32 (pkt, WTM_POSL, objp); /* set obj pos */ -tq_putr (pkt, OP_WTM | OP_END, tq_efl (uptr), sts, WTM_LNT, UQ_TYP_SEQ); -return tq_putpkt (pkt, TRUE); -} - -/* Position - deferred if q'd cmds, bypassed if ser exc */ - -t_bool tq_pos (int32 pkt) -{ -uint32 lu = tq_pkt[pkt].d[CMD_UN]; /* unit # */ -uint32 sts, objp = 0; -UNIT *uptr; - -if (uptr = tq_getucb (lu)) { /* unit exist? */ - objp = uptr->objp; /* position op */ - sts = tq_mot_valid (uptr, OP_POS); /* validity checks */ - if (sts == ST_SUC) { /* ok? */ - uptr->cpkt = pkt; /* op in progress */ - sim_activate (uptr, tq_xtime); /* activate */ - return OK; } } /* done */ -else sts = ST_OFL; /* offline */ -PUTP32 (pkt, POS_RCL, 0); /* clear #skipped */ -PUTP32 (pkt, POS_TMCL, 0); -PUTP32 (pkt, POS_POSL, objp); /* set obj pos */ -tq_putr (pkt, OP_POS | OP_END, tq_efl (uptr), sts, POS_LNT, UQ_TYP_SEQ); -return tq_putpkt (pkt, TRUE); -} - -/* Data transfer commands - deferred if q'd commands, bypassed if ser exc */ - -t_bool tq_rw (int32 pkt) -{ -uint32 lu = tq_pkt[pkt].d[CMD_UN]; /* unit # */ -uint32 cmd = GETP (pkt, CMD_OPC, OPC); /* opcode */ -uint32 bc = GETP32 (pkt, RW_BCL); /* byte count */ -uint32 sts, objp = 0; -UNIT *uptr; - -if (uptr = tq_getucb (lu)) { /* unit exist? */ - objp = uptr->objp; /* position op */ - sts = tq_mot_valid (uptr, cmd); /* validity checks */ - if (sts == ST_SUC) { /* ok? */ - if ((bc == 0) || (bc > TQ_MAXFR)) { /* invalid? */ - uptr->flags = uptr->flags | UNIT_SXC; /* set ser exc */ - sts = ST_CMD | I_BCNT; } - else { - uptr->cpkt = pkt; /* op in progress */ - sim_activate (uptr, tq_xtime); /* activate */ - return OK; } } } /* done */ -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_T, UQ_TYP_SEQ); -return tq_putpkt (pkt, TRUE); -} - -/* Validity checks */ - -int32 tq_mot_valid (UNIT *uptr, uint32 cmd) -{ -if (uptr->flags & UNIT_SXC) return ST_SXC; /* ser exc pend? */ -if ((uptr->flags & UNIT_ATT) == 0) /* not attached? */ - return (ST_OFL | SB_OFL_NV); /* offl no vol */ -if ((uptr->flags & UNIT_ONL) == 0) /* not online? */ - return ST_AVL; /* only avail */ -if (tq_cmf[cmd] & CMF_WR) { /* write op? */ - if (uptr->uf & UF_WPS) { /* swre wlk? */ - uptr->flags = uptr->flags | UNIT_SXC; /* set ser exc */ - return (ST_WPR | SB_WPR_SW); } - if (TQ_WPH (uptr)) { /* hwre wlk? */ - uptr->flags = uptr->flags | UNIT_SXC; /* set ser exc */ - return (ST_WPR | SB_WPR_HW); } } -return ST_SUC; /* success! */ -} - -/* Unit service for motion commands */ - -t_stat tq_svc (UNIT *uptr) -{ -uint32 t, sts, sktmk, skrec; -t_mtrlnt i, tbc, wbc; -int32 pkt = uptr->cpkt; /* get packet */ -uint32 cmd = GETP (pkt, CMD_OPC, OPC); /* get cmd */ -uint32 mdf = tq_pkt[pkt].d[CMD_MOD]; /* modifier */ -uint32 ba = GETP32 (pkt, RW_BAL); /* buf addr */ -t_mtrlnt bc = GETP32 (pkt, RW_BCL); /* byte count */ -uint32 nrec = GETP32 (pkt, POS_RCL); /* #rec to skip */ -uint32 ntmk = GETP32 (pkt, POS_TMCL); /* #tmk to skp */ - -if (pkt == 0) return SCPE_IERR; /* what??? */ -if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */ - tq_mot_end (uptr, 0, ST_OFL | SB_OFL_NV, 0); /* offl no vol */ - return SCPE_OK; } - -if (tq_cmf[cmd] & CMF_WR) { /* write op? */ - if (TQ_WPH (uptr)) { /* hwre write prot? */ - uptr->flags = uptr->flags | UNIT_SXC; /* set ser exc */ - tq_mot_end (uptr, 0, ST_WPR | SB_WPR_HW, 0); - return SCPE_OK; } - if (uptr->uf & UF_WPS) { /* swre write prot? */ - uptr->flags = uptr->flags | UNIT_SXC; /* set ser exc */ - tq_mot_end (uptr, 0, ST_WPR | SB_WPR_SW, 0); - return SCPE_OK; } } -sts = ST_SUC; /* assume success */ -tbc = 0; /* assume zero rec */ -switch (cmd) { /* case on command */ - -case OP_RD:case OP_ACC:case OP_CMP: /* read-like op */ - if (mdf & MD_REV) sts = tq_rdbufr (uptr, &tbc); /* read record */ - else sts = tq_rdbuff (uptr, &tbc); - if (sts == ST_DRV) { /* read error? */ - PUTP32 (pkt, RW_BCL, 0); /* no bytes processed */ - return tq_mot_err (uptr, tbc); } /* log, done */ - if ((sts != ST_SUC) || (cmd == OP_ACC)) { /* error or access? */ - PUTP32 (pkt, RW_BCL, 0); /* no bytes processed */ - break; } - if (tbc > bc) { /* tape rec > buf? */ - uptr->flags = uptr->flags | UNIT_SXC; /* serious exc */ - sts = ST_RDT; /* data truncated */ - wbc = bc; } /* set working bc */ - else wbc = tbc; - if (cmd == OP_RD) { /* read? */ - if (t = Map_WriteB (ba, wbc, tqxb, MAP)) { /* store, nxm? */ - PUTP32 (pkt, RW_BCL, wbc - t); /* adj bc */ - if (tq_hbe (uptr, ba + wbc - t)) /* post err log */ - tq_mot_end (uptr, EF_LOG, ST_HST | SB_HST_NXM, tbc); - return SCPE_OK; } /* end if nxm */ - } /* end if read */ - else { /* compare */ - uint8 mby, dby; - uint32 mba; - for (i = 0; i < wbc; i++) { /* loop */ - if (mdf & MD_REV) { /* reverse? */ - mba = ba + bc - 1 - i; /* mem addr */ - dby = tqxb[tbc - 1 - i]; } /* byte */ - else { - mba = ba + i; - dby = tqxb[i]; } - if (Map_ReadB (mba, 1, &mby, MAP)) { /* fetch, nxm? */ - PUTP32 (pkt, RW_BCL, i); /* adj bc */ - if (tq_hbe (uptr, mba)) /* post err log */ - tq_mot_end (uptr, EF_LOG, ST_HST | SB_HST_NXM, tbc); - return SCPE_OK; } - if (mby != dby) { /* cmp err? */ - uptr->flags = uptr->flags | UNIT_SXC; /* ser exc */ - PUTP32 (pkt, RW_BCL, i); /* adj bc */ - tq_mot_end (uptr, 0, ST_CMP, tbc); - return SCPE_OK; } /* exit */ - } /* end for */ - } /* end if compare */ - PUTP32 (pkt, RW_BCL, wbc); /* bytes read/cmp'd */ - break; - -case OP_WR: /* write */ - if (t = Map_ReadB (ba, bc, tqxb, MAP)) { /* fetch buf, nxm? */ - PUTP32 (pkt, RW_BCL, 0); /* no bytes xfer'd */ - if (tq_hbe (uptr, ba + bc - t)) /* post err log */ - tq_mot_end (uptr, EF_LOG, ST_HST | SB_HST_NXM, bc); - return SCPE_OK; } /* end else wr */ - if (sim_tape_wrrecf (uptr, tqxb, bc)) /* write rec fwd, err? */ - return tq_mot_err (uptr, bc); /* log, end */ - uptr->objp = uptr->objp + 1; /* upd obj pos */ - if (TEST_EOT (uptr)) /* EOT on write? */ - uptr->flags = uptr->flags | UNIT_SXC; - uptr->flags = uptr->flags & ~UNIT_TMK; /* disable LEOT */ - tbc = bc; /* RW_BC is ok */ - break; - -case OP_WTM: /* write tape mark */ - if (sim_tape_wrtmk (uptr)) /* write tmk, err? */ - return tq_mot_err (uptr, 0); /* log, end */ - uptr->objp = uptr->objp + 1; /* incr obj cnt */ -case OP_ERG: /* erase gap */ - if (TEST_EOT (uptr)) /* EOT on write? */ - uptr->flags = uptr->flags | UNIT_SXC; - uptr->flags = uptr->flags & ~UNIT_TMK; /* disable LEOT */ - break; - -case OP_ERS: /* erase */ - if (sim_tape_wreom (uptr)) /* write eom, err? */ - return tq_mot_err (uptr, 0); /* log, end */ - sim_tape_rewind (uptr); /* rewind */ - uptr->objp = 0; - uptr->flags = uptr->flags & ~(UNIT_TMK | UNIT_POL); - break; - -case OP_POS: /* position */ - sktmk = skrec = 0; /* clr skipped */ - if (mdf & MD_RWD) { /* rewind? */ - sim_tape_rewind (uptr); - uptr->objp = 0; /* clr flags */ - uptr->flags = uptr->flags & ~(UNIT_TMK | UNIT_POL); } - if (mdf & MD_OBC) { /* skip obj? */ - if (mdf & MD_REV) /* reverse? */ - sts = tq_spacer (uptr, nrec, &skrec, FALSE); - else sts = tq_spacef (uptr, nrec, &skrec, FALSE); - } - else { /* skip tmk, rec */ - if (mdf & MD_REV) sts = tq_skipfr (uptr, ntmk, &sktmk); - else sts = tq_skipff (uptr, ntmk, &sktmk); - if (sts == ST_SUC) { /* tmk succeed? */ - if (mdf & MD_REV) /* reverse? */ - sts = tq_spacer (uptr, nrec, &skrec, TRUE); - else sts = tq_spacef (uptr, nrec, &skrec, TRUE); - if (sts == ST_TMK) sktmk = sktmk + 1; } - } - PUTP32 (pkt, POS_RCL, skrec); /* #rec skipped */ - PUTP32 (pkt, POS_TMCL, sktmk); /* #tmk skipped */ - break; - -default: - return SCPE_IERR; } -tq_mot_end (uptr, 0, sts, tbc); /* done */ -return SCPE_OK; -} - -/* Motion command drive error */ - -t_stat tq_mot_err (UNIT *uptr, uint32 rsiz) -{ -uptr->flags = (uptr->flags | UNIT_SXC) & ~UNIT_TMK; /* serious exception */ -if (tq_dte (uptr, ST_DRV)) /* post err log */ - tq_mot_end (uptr, EF_LOG, ST_DRV, rsiz); /* if ok, report err */ -perror ("TQ I/O error"); -clearerr (uptr->fileref); -return SCPE_IOERR; -} - -/* Motion command complete */ - -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_T; /* assume rw */ - -if (cmd == OP_ERG) lnt = ERG_LNT; /* set pkt lnt */ -else if (cmd == OP_ERS) lnt = ERS_LNT; -else if (cmd == OP_WTM) lnt = WTM_LNT; -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 */ - 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 */ -if (uptr->pktq) /* more to do? */ - sim_activate (&tq_unit[TQ_QUEUE], tq_qtime); /* activate thread */ -return OK; -} - -/* Tape motion routines */ - -uint32 tq_map_status (UNIT *uptr, t_stat st) -{ -switch (st) -{ -case MTSE_OK: - break; -case MTSE_UNATT: - uptr->flags = uptr->flags | UNIT_SXC; - return (ST_OFL | SB_OFL_NV); -case MTSE_FMT: - uptr->flags = uptr->flags | UNIT_SXC; - return ST_MFE; -case MTSE_TMK: - uptr->flags = uptr->flags | UNIT_SXC; - return ST_TMK; -case MTSE_INVRL: - uptr->flags = uptr->flags | UNIT_SXC | UNIT_POL; - return ST_FMT; -case MTSE_RECE: -case MTSE_IOERR: - uptr->flags = uptr->flags | UNIT_SXC | UNIT_POL; - return ST_DRV; -case MTSE_EOM: - uptr->flags = uptr->flags | UNIT_SXC | UNIT_POL; - return ST_DAT; -case MTSE_BOT: - uptr->flags = (uptr->flags | UNIT_SXC) & ~UNIT_POL; - return ST_BOT; -case MTSE_WRP: - uptr->flags = uptr->flags | UNIT_SXC; - return ST_WPR; } -return ST_SUC; -} - -uint32 tq_spacef (UNIT *uptr, uint32 cnt, uint32 *skipped, t_bool qrec) -{ -t_stat st; -t_mtrlnt tbc; - -*skipped = 0; -while (*skipped < cnt) { /* loop */ - st = sim_tape_sprecf (uptr, &tbc); /* space rec fwd */ - if ((st != MTSE_OK) && (st != MTSE_TMK)) /* real error? */ - return tq_map_status (uptr, st); /* map status */ - uptr->objp = uptr->objp + 1; /* upd obj cnt */ - if (st == MTSE_TMK) { /* tape mark? */ - int32 pkt = uptr->cpkt; /* get pkt */ - if ((tq_pkt[pkt].d[CMD_MOD] & MD_DLE) && /* LEOT? */ - (uptr->flags & UNIT_TMK)) { - sim_tape_sprecr (uptr, &tbc); /* rev over tmk */ - uptr->flags = uptr->flags | UNIT_SXC; /* serious exc */ - return ST_LED; } - uptr->flags = uptr->flags | UNIT_TMK; /* set TM seen */ - if (qrec) return ST_TMK; } /* rec spc? stop */ - else uptr->flags = uptr->flags & ~UNIT_TMK; /* clr TM seen */ - *skipped = *skipped + 1; } /* # obj skipped */ -return ST_SUC; -} - -uint32 tq_skipff (UNIT *uptr, uint32 cnt, uint32 *skipped) -{ -uint32 st, skrec; - -*skipped = 0; -while (*skipped < cnt) { /* loop */ - st = tq_spacef (uptr, 0x7FFFFFFF, &skrec, TRUE);/* rec spc fwd */ - if (st == ST_TMK) *skipped = *skipped + 1; /* count files */ - else if (st != ST_SUC) return st; } -return ST_SUC; -} - -uint32 tq_spacer (UNIT *uptr, uint32 cnt, uint32 *skipped, t_bool qrec) -{ -t_stat st; -t_mtrlnt tbc; - -*skipped = 0; -while (*skipped < cnt) { /* loop */ - st = sim_tape_sprecr (uptr, &tbc); /* spc rec rev */ - if ((st != MTSE_OK) && (st != MTSE_TMK)) /* real error? */ - return tq_map_status (uptr, st); /* map status */ - uptr->objp = uptr->objp - 1; /* upd obj cnt */ - if ((st == MTSE_TMK) && qrec) return ST_TMK; /* tape mark, stop? */ - *skipped = *skipped + 1; } /* # obj skipped */ -return ST_SUC; -} - -uint32 tq_skipfr (UNIT *uptr, uint32 cnt, uint32 *skipped) -{ -uint32 st, skrec; - -*skipped = 0; -while (*skipped < cnt) { /* loopo */ - st = tq_spacer (uptr, 0x7FFFFFFF, &skrec, TRUE);/* rec spc rev */ - if (st == ST_TMK) *skipped = *skipped + 1; /* tape mark? */ - else if (st != 0) return st; } /* error? */ -return ST_SUC; -} - -/* Read buffer - can return ST_TMK, ST_FMT, or ST_DRV */ - -uint32 tq_rdbuff (UNIT *uptr, t_mtrlnt *tbc) -{ -t_stat st; - -st = sim_tape_rdrecf (uptr, tqxb, tbc, MT_MAXFR); /* read rec fwd */ -if (st == MTSE_TMK) { /* tape mark? */ - uptr->flags = uptr->flags | UNIT_SXC | UNIT_TMK;/* serious exc */ - uptr->objp = uptr->objp + 1; /* update obj cnt */ - return ST_TMK; } -if (st != MTSE_OK) return tq_map_status (uptr, st); /* other error? */ -uptr->flags = uptr->flags & ~UNIT_TMK; /* clr tape mark */ -uptr->objp = uptr->objp + 1; /* upd obj cnt */ -return ST_SUC; -} - -uint32 tq_rdbufr (UNIT *uptr, t_mtrlnt *tbc) -{ -t_stat st; - -st = sim_tape_rdrecr (uptr, tqxb, tbc, MT_MAXFR); /* read rec rev */ -if (st == MTSE_TMK) { /* tape mark? */ - uptr->flags = uptr->flags | UNIT_SXC; /* serious exc */ - uptr->objp = uptr->objp - 1; /* update obj cnt */ - return ST_TMK; } -if (st != MTSE_OK) return tq_map_status (uptr, st); /* other error? */ -uptr->objp = uptr->objp - 1; /* upd obj cnt */ -return ST_SUC; -} - -/* Data transfer error log packet */ - -t_bool tq_dte (UNIT *uptr, uint32 err) -{ -int32 pkt, tpkt; -uint32 lu; - -if ((tq_cflgs & CF_THS) == 0) return OK; /* logging? */ -if (!tq_deqf (&pkt)) return ERR; /* get log pkt */ -tpkt = uptr->cpkt; /* rw pkt */ -lu = tq_pkt[tpkt].d[CMD_UN]; /* unit # */ - -tq_pkt[pkt].d[ELP_REFL] = tq_pkt[tpkt].d[CMD_REFL]; /* copy cmd ref */ -tq_pkt[pkt].d[ELP_REFH] = tq_pkt[tpkt].d[CMD_REFH]; /* copy cmd ref */ -tq_pkt[pkt].d[ELP_UN] = lu; /* copy unit */ -tq_pkt[pkt].d[ELP_SEQ] = 0; /* clr seq # */ -tq_pkt[pkt].d[DTE_CIDA] = 0; /* ctrl ID */ -tq_pkt[pkt].d[DTE_CIDB] = 0; -tq_pkt[pkt].d[DTE_CIDC] = 0; -tq_pkt[pkt].d[DTE_CIDD] = (TQ_CLASS << DTE_CIDD_V_CLS) | - (drv_tab[tq_typ].cmod << DTE_CIDD_V_MOD); -tq_pkt[pkt].d[DTE_VER] = drv_tab[tq_typ].cver; /* ctrl ver */ -tq_pkt[pkt].d[DTE_MLUN] = lu; /* MLUN */ -tq_pkt[pkt].d[DTE_UIDA] = lu; /* unit ID */ -tq_pkt[pkt].d[DTE_UIDB] = 0; -tq_pkt[pkt].d[DTE_UIDC] = 0; -tq_pkt[pkt].d[DTE_UIDD] = (UID_TAPE << DTE_UIDD_V_CLS) | - (drv_tab[tq_typ].umod << DTE_UIDD_V_MOD); -tq_pkt[pkt].d[DTE_UVER] = drv_tab[tq_typ].uver; /* unit ver */ -PUTP32 (pkt, DTE_POSL, uptr->objp); /* position */ -tq_pkt[pkt].d[DTE_FVER] = drv_tab[tq_typ].fver; /* fmtr ver */ -tq_putr (pkt, FM_TAP, LF_SNR, err, DTE_LNT, UQ_TYP_DAT); -return tq_putpkt (pkt, TRUE); -} - -/* Host bus error log packet */ - -t_bool tq_hbe (UNIT *uptr, uint32 ba) -{ -int32 pkt, tpkt; - -if ((tq_cflgs & CF_THS) == 0) return OK; /* logging? */ -if (!tq_deqf (&pkt)) return ERR; /* get log pkt */ -tpkt = uptr->cpkt; /* rw pkt */ -tq_pkt[pkt].d[ELP_REFL] = tq_pkt[tpkt].d[CMD_REFL]; /* copy cmd ref */ -tq_pkt[pkt].d[ELP_REFH] = tq_pkt[tpkt].d[CMD_REFH]; /* copy cmd ref */ -tq_pkt[pkt].d[ELP_UN] = tq_pkt[tpkt].d[CMD_UN]; /* copy unit */ -tq_pkt[pkt].d[ELP_SEQ] = 0; /* clr seq # */ -tq_pkt[pkt].d[HBE_CIDA] = 0; /* ctrl ID */ -tq_pkt[pkt].d[HBE_CIDB] = 0; -tq_pkt[pkt].d[HBE_CIDC] = 0; -tq_pkt[pkt].d[DTE_CIDD] = (TQ_CLASS << DTE_CIDD_V_CLS) | - (drv_tab[tq_typ].cmod << DTE_CIDD_V_MOD); -tq_pkt[pkt].d[HBE_VER] = drv_tab[tq_typ].cver; /* ctrl ver */ -tq_pkt[pkt].d[HBE_RSV] = 0; -PUTP32 (pkt, HBE_BADL, ba); /* bad addr */ -tq_putr (pkt, FM_BAD, LF_SNR, ST_HST | SB_HST_NXM, HBE_LNT, UQ_TYP_DAT); -return tq_putpkt (pkt, TRUE); -} - -/* Port last failure error log packet */ - -t_bool tq_plf (uint32 err) -{ -int32 pkt; - -if (!tq_deqf (&pkt)) return ERR; /* get log pkt */ -tq_pkt[pkt].d[ELP_REFL] = tq_pkt[pkt].d[ELP_REFH] = 0; /* ref = 0 */ -tq_pkt[pkt].d[ELP_UN] = tq_pkt[pkt].d[ELP_SEQ] = 0; /* no unit, seq */ -tq_pkt[pkt].d[PLF_CIDA] = 0; /* cntl ID */ -tq_pkt[pkt].d[PLF_CIDB] = 0; -tq_pkt[pkt].d[PLF_CIDC] = 0; -tq_pkt[pkt].d[PLF_CIDD] = (TQ_CLASS << PLF_CIDD_V_CLS) | - (drv_tab[tq_typ].cmod << PLF_CIDD_V_MOD); -tq_pkt[pkt].d[PLF_VER] = drv_tab[tq_typ].cver; -tq_pkt[pkt].d[PLF_ERR] = err; -tq_putr (pkt, FM_CNT, LF_SNR, ST_CNT, PLF_LNT, UQ_TYP_DAT); -tq_pkt[pkt].d[UQ_HCTC] |= (UQ_CID_DIAG << UQ_HCTC_V_CID); -return tq_putpkt (pkt, TRUE); -} - -/* Unit now available attention packet */ - -int32 tq_una (UNIT *uptr) -{ -int32 pkt; -uint32 lu; - -if (!tq_deqf (&pkt)) return ERR; /* get log pkt */ -lu = uptr - tq_dev.units; /* get unit */ -tq_pkt[pkt].d[RSP_REFL] = tq_pkt[pkt].d[RSP_REFH] = 0; /* ref = 0 */ -tq_pkt[pkt].d[RSP_UN] = lu; -tq_pkt[pkt].d[RSP_RSV] = 0; -tq_putr_unit (pkt, uptr, lu, FALSE); /* fill unit fields */ -tq_putr (pkt, OP_AVA, 0, 0, UNA_LNT, UQ_TYP_SEQ); /* fill std fields */ -return tq_putpkt (pkt, TRUE); -} - -/* List handling - - tq_deqf - dequeue head of free list (fatal err if none) - tq_deqh - dequeue head of list - tq_enqh - enqueue at head of list - tq_enqt - enqueue at tail of list -*/ - -t_bool tq_deqf (int32 *pkt) -{ -if (tq_freq == 0) return tq_fatal (PE_NSR); /* no free pkts?? */ -tq_pbsy = tq_pbsy + 1; /* cnt busy pkts */ -*pkt = tq_freq; /* head of list */ -tq_freq = tq_pkt[tq_freq].link; /* next */ -return OK; -} - -int32 tq_deqh (int32 *lh) -{ -int32 ptr = *lh; /* head of list */ - -if (ptr) *lh = tq_pkt[ptr].link; /* next */ -return ptr; -} - -void tq_enqh (int32 *lh, int32 pkt) -{ -if (pkt == 0) return; /* any pkt? */ -tq_pkt[pkt].link = *lh; /* link is old lh */ -*lh = pkt; /* pkt is new lh */ -return; -} - -void tq_enqt (int32 *lh, int32 pkt) -{ -if (pkt == 0) return; /* any pkt? */ -tq_pkt[pkt].link = 0; /* it will be tail */ -if (*lh == 0) *lh = pkt; /* if empty, enqh */ -else { uint32 ptr = *lh; /* chase to end */ - while (tq_pkt[ptr].link) ptr = tq_pkt[ptr].link; - tq_pkt[ptr].link = pkt; } /* enq at tail */ -return; -} - -/* Packet and descriptor handling */ - -/* Get packet from command ring */ - -t_bool tq_getpkt (int32 *pkt) -{ -uint32 addr, desc; - -if (!tq_getdesc (&tq_cq, &desc)) return ERR; /* get cmd desc */ -if ((desc & UQ_DESC_OWN) == 0) { /* none */ - *pkt = 0; /* pkt = 0 */ - return OK; } /* no error */ -if (!tq_deqf (pkt)) return ERR; /* get cmd pkt */ -tq_hat = 0; /* dsbl hst timer */ -addr = desc & UQ_ADDR; /* get Q22 addr */ -if (Map_ReadW (addr + UQ_HDR_OFF, TQ_PKT_SIZE, tq_pkt[*pkt].d, MAP)) - return tq_fatal (PE_PRE); /* read pkt */ -return tq_putdesc (&tq_cq, desc); /* release desc */ -} - -/* Put packet to response ring - note the clever hack about credits. - The controller sends all its credits to the host. Thereafter, it - supplies one credit for every response packet sent over. Simple! -*/ - -t_bool tq_putpkt (int32 pkt, t_bool qt) -{ -uint32 addr, desc, lnt, cr; - -if (pkt == 0) return OK; /* any packet? */ -if (DBG_LOG (LOG_TQ)) { - UNIT *up = tq_getucb (tq_pkt[pkt].d[CMD_UN]); - 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"); - 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 */ - else tq_enqh (&tq_rspq, pkt); /* resp q call */ - sim_activate (&tq_unit[TQ_QUEUE], tq_qtime); /* activate q thrd */ - return OK; } -addr = desc & UQ_ADDR; /* get Q22 addr */ -lnt = tq_pkt[pkt].d[UQ_HLNT] - UQ_HDR_OFF; /* size, with hdr */ -if ((GETP (pkt, UQ_HCTC, TYP) == UQ_TYP_SEQ) && /* seq packet? */ - (GETP (pkt, CMD_OPC, OPC) & OP_END)) { /* end packet? */ - cr = (tq_credits >= 14)? 14: tq_credits; /* max 14 credits */ - tq_credits = tq_credits - cr; /* decr credits */ - tq_pkt[pkt].d[UQ_HCTC] |= ((cr + 1) << UQ_HCTC_V_CR); } -if (Map_WriteW (addr + UQ_HDR_OFF, lnt, tq_pkt[pkt].d, MAP)) - return tq_fatal (PE_PWE); /* write pkt */ -tq_enqh (&tq_freq, pkt); /* pkt is free */ -tq_pbsy = tq_pbsy - 1; /* decr busy cnt */ -if (tq_pbsy == 0) tq_hat = tq_htmo; /* idle? strt hst tmr */ -return tq_putdesc (&tq_rq, desc); /* release desc */ -} - -/* Get a descriptor from the host */ - -t_bool tq_getdesc (struct uq_ring *ring, uint32 *desc) -{ -uint32 addr = ring->ba + ring->idx; -uint16 d[2]; - -if (Map_ReadW (addr, 4, d, MAP)) /* fetch desc */ - return tq_fatal (PE_QRE); /* err? dead */ -*desc = ((uint32) d[0]) | (((uint32) d[1]) << 16); -return OK; -} - -/* Return a descriptor to the host, clearing owner bit - If rings transitions from "empty" to "not empty" or "full" to - "not full", and interrupt bit was set, interrupt the host. - Actually, test whether previous ring entry was owned by host. -*/ - -t_bool tq_putdesc (struct uq_ring *ring, uint32 desc) -{ -uint32 prvd, newd = (desc & ~UQ_DESC_OWN) | UQ_DESC_F; -uint32 prva, addr = ring->ba + ring->idx; -uint16 d[2]; - -d[0] = newd & 0xFFFF; /* 32b to 16b */ -d[1] = (newd >> 16) & 0xFFFF; -if (Map_WriteW (addr, 4, d, MAP)) /* store desc */ - return tq_fatal (PE_QWE); /* err? dead */ -if (desc & UQ_DESC_F) { /* was F set? */ - if (ring->lnt <= 4) tq_ring_int (ring); /* lnt = 1? intr */ - else { prva = ring->ba + /* prv desc */ - ((ring->idx - 4) & (ring->lnt - 1)); - if (Map_ReadW (prva, 4, d, MAP)) /* read prv */ - return tq_fatal (PE_QRE); - prvd = ((uint32) d[0]) | (((uint32) d[1]) << 16); - if (prvd & UQ_DESC_OWN) tq_ring_int (ring); } } -ring->idx = (ring->idx + 4) & (ring->lnt - 1); -return OK; -} - -/* Get unit descriptor for logical unit - trivial now, - but eventually, hide multiboard complexities here */ - -UNIT *tq_getucb (uint32 lu) -{ -UNIT *uptr; - -if (lu >= TQ_NUMDR) return NULL; -uptr = tq_dev.units + lu; -if (uptr->flags & UNIT_DIS) return NULL; -return uptr; -} - -/* Hack unit flags */ - -void tq_setf_unit (int32 pkt, UNIT *uptr) -{ -uptr->uf = tq_pkt[pkt].d[ONL_UFL] & UF_MSK; /* settable flags */ -if ((tq_pkt[pkt].d[CMD_MOD] & MD_SWP) && /* swre wrp enb? */ - (tq_pkt[pkt].d[ONL_UFL] & UF_WPS)) /* swre wrp on? */ - uptr->uf = uptr->uf | UF_WPS; /* simon says... */ -return; -} - -/* Hack end flags */ - -uint32 tq_efl (UNIT *uptr) -{ -uint32 t = 0; - -if (uptr) { /* any unit? */ - if (uptr->flags & UNIT_POL) t = t | EF_PLS; /* note pos lost */ - if (uptr->flags & UNIT_SXC) t = t | EF_SXC; /* note ser exc */ - if (TEST_EOT (uptr)) t = t | EF_EOT; } /* note EOT */ -return t; -} - -/* Unit response fields */ - -void tq_putr_unit (int32 pkt, UNIT *uptr, uint32 lu, t_bool all) -{ -tq_pkt[pkt].d[ONL_MLUN] = lu; /* multi-unit */ -tq_pkt[pkt].d[ONL_UFL] = uptr->uf | TQ_WPH (uptr); /* unit flags */ -tq_pkt[pkt].d[ONL_RSVL] = tq_pkt[pkt].d[ONL_RSVH] = 0; /* reserved */ -tq_pkt[pkt].d[ONL_UIDA] = lu; /* UID low */ -tq_pkt[pkt].d[ONL_UIDB] = 0; -tq_pkt[pkt].d[ONL_UIDC] = 0; -tq_pkt[pkt].d[ONL_UIDD] = (UID_TAPE << ONL_UIDD_V_CLS) | - (drv_tab[tq_typ].umod << ONL_UIDD_V_MOD); /* UID hi */ -PUTP32 (pkt, ONL_MEDL, drv_tab[tq_typ].med); /* media type */ -if (all) { /* if long form */ - tq_pkt[pkt].d[ONL_FMT] = drv_tab[tq_typ].fmt; /* format */ - tq_pkt[pkt].d[ONL_SPD] = 0; /* speed */ - PUTP32 (pkt, ONL_MAXL, TQ_MAXFR); /* max xfr */ - tq_pkt[pkt].d[ONL_NREC] = 0; /* noise rec */ - tq_pkt[pkt].d[ONL_RSVE] = 0; } /* reserved */ -return; -} - -/* UQ_HDR and RSP_OP fields */ - -void tq_putr (int32 pkt, uint32 cmd, uint32 flg, uint32 sts, uint32 lnt, uint32 typ) -{ -tq_pkt[pkt].d[RSP_OPF] = (cmd << RSP_OPF_V_OPC) | /* set cmd, flg */ - (flg << RSP_OPF_V_FLG); -tq_pkt[pkt].d[RSP_STS] = sts; -tq_pkt[pkt].d[UQ_HLNT] = lnt; /* length */ -tq_pkt[pkt].d[UQ_HCTC] = (typ << UQ_HCTC_V_TYP) | /* type, cid */ - (UQ_CID_TMSCP << UQ_HCTC_V_CID); /* clr credits */ -return; -} - -/* Post interrupt during init */ - -void tq_init_int (void) -{ -if ((tq_s1dat & SA_S1H_IE) && tq_dib.vec) SET_INT (TQ); -return; -} - -/* Post interrupt during putpkt - note that NXMs are ignored! */ - -void tq_ring_int (struct uq_ring *ring) -{ -uint32 iadr = tq_comm + ring->ioff; /* addr intr wd */ -uint16 flag = 1; - -Map_WriteW (iadr, 2, &flag, MAP); /* write flag */ -if (tq_dib.vec) SET_INT (TQ); /* if enb, intr */ -return; -} - -/* Return interrupt vector */ - -int32 tq_inta (void) -{ -return tq_dib.vec; /* prog vector */ -} - -/* Fatal error */ - -t_bool tq_fatal (uint32 err) -{ -if (DBG_LOG (LOG_TQ)) fprintf (sim_log, ">>TQ: fatal err=%X\n", err); -tq_reset (&tq_dev); /* reset device */ -tq_sa = SA_ER | err; /* SA = dead code */ -tq_csta = CST_DEAD; /* state = dead */ -tq_perr = err; /* save error */ -return ERR; -} - -/* Device attach */ - -t_stat tq_attach (UNIT *uptr, char *cptr) -{ -t_stat r; - -r = sim_tape_attach (uptr, cptr); -if (r != SCPE_OK) return r; -if (tq_csta == CST_UP) uptr->flags = (uptr->flags | UNIT_ATP) & - ~(UNIT_SXC | UNIT_POL | UNIT_TMK); -return SCPE_OK; -} - -/* Device detach */ - -t_stat tq_detach (UNIT *uptr) -{ -t_stat r; - -r = sim_tape_detach (uptr); /* detach unit */ -if (r != SCPE_OK) return r; -uptr->flags = uptr->flags & ~(UNIT_ONL | UNIT_ATP | UNIT_SXC | UNIT_POL | UNIT_TMK); -uptr->uf = 0; /* clr unit flgs */ -return SCPE_OK; -} - -/* Device reset */ - -t_stat tq_reset (DEVICE *dptr) -{ -int32 i, j; -UNIT *uptr; - -tq_csta = CST_S1; /* init stage 1 */ -tq_s1dat = 0; /* no S1 data */ -tq_dib.vec = 0; /* no vector */ -tq_sa = SA_S1 | SA_S1C_Q22 | SA_S1C_DI | SA_S1C_MP; /* init SA val */ -tq_cflgs = CF_RPL; /* ctrl flgs off */ -tq_htmo = TQ_DHTMO; /* default timeout */ -tq_hat = tq_htmo; /* default timer */ -tq_cq.ba = tq_cq.lnt = tq_cq.idx = 0; /* clr cmd ring */ -tq_rq.ba = tq_rq.lnt = tq_rq.idx = 0; /* clr rsp ring */ -tq_credits = (TQ_NPKTS / 2) - 1; /* init credits */ -tq_freq = 1; /* init free list */ -for (i = 0; i < TQ_NPKTS; i++) { /* all pkts free */ - if (i) tq_pkt[i].link = (i + 1) & TQ_M_NPKTS; - else tq_pkt[i].link = 0; - for (j = 0; j < TQ_PKT_SIZE_W; j++) tq_pkt[i].d[j] = 0; } -tq_rspq = 0; /* no q'd rsp pkts */ -tq_pbsy = 0; /* all pkts free */ -tq_pip = 0; /* not polling */ -CLR_INT (TQ); /* clr intr req */ -for (i = 0; i < TQ_NUMDR + 2; i++) { /* init units */ - uptr = tq_dev.units + i; - sim_cancel (uptr); /* clr activity */ - sim_tape_reset (uptr); - uptr->flags = uptr->flags & /* not online */ - ~(UNIT_ONL|UNIT_ATP|UNIT_SXC|UNIT_POL|UNIT_TMK); - uptr->uf = 0; /* clr unit flags */ - uptr->cpkt = uptr->pktq = 0; } /* clr pkt q's */ -if (tqxb == NULL) tqxb = calloc (TQ_MAXFR, sizeof (uint8)); -if (tqxb == NULL) return SCPE_MEM; -return SCPE_OK; -} - -/* Device bootstrap */ - -#if defined (VM_PDP11) - -#define BOOT_START 016000 /* start */ -#define BOOT_ENTRY (BOOT_START + 002) /* entry */ -#define BOOT_UNIT (BOOT_START + 010) /* unit number */ -#define BOOT_CSR (BOOT_START + 014) /* CSR */ -#define BOOT_LEN (sizeof (boot_rom) / sizeof (int16)) - - -/* Data structure definitions */ - -#define B_CMDINT (BOOT_START - 01000) /* cmd int */ -#define B_RSPINT (B_CMDINT + 002) /* rsp int */ -#define B_RING (B_RSPINT + 002) /* ring base */ -#define B_RSPH (B_RING + 010) /* resp pkt hdr */ -#define B_TKRSP (B_RSPH + 004) /* resp pkt */ -#define B_CMDH (B_TKRSP + 060) /* cmd pkt hdr */ -#define B_TKCMD (B_CMDH + 004) /* cmd pkt */ -#define B_UNIT (B_TKCMD + 004) /* unit # */ - -static const uint16 boot_rom[] = { - - 0046525, /* ST: "UM" */ - - 0012706, 0016000, /* mov #st,sp */ - 0012700, 0000000, /* mov #unitno,r0 */ - 0012701, 0174500, /* mov #174500,r1 ; ip addr */ - 0005021, /* clr (r1)+ ; init */ - 0012704, 0004000, /* mov #4000,r4 ; s1 mask */ - 0005002, /* clr r2 */ - 0005022, /* 10$: clr (r2)+ ; clr up to boot */ - 0020237, BOOT_START - 2, /* cmp r2,#st-2 */ - 0103774, /* blo 10$ */ - 0012705, BOOT_START+0312, /* mov #cmdtbl,r5 ; addr of tbl */ - - /* Four step init process */ - - 0005711, /* 20$: tst (r1) ; err? */ - 0100001, /* bpl 30$ */ - 0000000, /* halt */ - 0030411, /* 30$: bit r4,(r1) ; step set? */ - 0001773, /* beq 20$ ; wait */ - 0012511, /* mov (r5)+,(r1) ; send next */ - 0006304, /* asl r4 ; next mask */ - 0100370, /* bpl 20$ ; s4 done? */ - - /* Set up rings, issue ONLINE, REWIND, READ */ - - 0012737, 0000400, B_CMDH + 2, /* mov #400,cmdh+2 ; VCID = 1 */ - 0012737, 0000044, B_CMDH, /* mov #36.,cmdh ; cmd pkt lnt */ - 0010037, B_UNIT, /* mov r0,unit ; unit # */ - 0012737, 0000011, B_TKCMD + 8, /* mov #11,tkcmd+8. ; online op */ - 0012737, 0020000, B_TKCMD + 10, /* mov #20000,tkcmd+10. ; clr ser ex */ - 0012702, B_RING, /* mov #ring,r2 ; init rings */ - 0012722, B_TKRSP, /* mov #tkrsp,(r2)+ ; rsp pkt addr */ - 0010203, /* mov r2,r3 ; save ring+2 */ - 0010423, /* mov r4,(r3)+ ; set TK own */ - 0012723, B_TKCMD, /* mov #tkcmd,(r3)+ ; cmd pkt addr */ - 0010423, /* mov r4,(r3)+ ; set TK own */ - 0005741, /* tst -(r1) ; start poll */ - 0005712, /* 40$: tst (r2) ; wait for resp */ - 0100776, /* bmi 40$ */ - 0105737, B_TKRSP + 10, /* tstb tkrsp+10. ; check stat */ - 0001401, /* beq 50$ */ - 0000000, /* halt */ - 0012703, B_TKCMD + 8, /* 50$: mov #tkcmd+8.,r3 */ - 0012723, 0000045, /* mov #45,(r3)+ ; reposition */ - 0012723, 0020002, /* mov #20002,(r3)+ ; rew, clr exc */ - 0012723, 0000001, /* mov #1,(r3)+ ; lo rec skp */ - 0005023, /* clr (r3)+ ; hi rec skp */ - 0005023, /* clr (r3)+ ; lo tmk skp */ - 0005023, /* clr (r3)+ ; hi tmk skp */ - 0010412, /* mov r4,(r2) ; TK own rsp */ - 0010437, B_RING + 6, /* mov r4,ring+6 ; TK own cmd */ - 0005711, /* tst (r1) ; start poll */ - 0005712, /* 60$: tst (r2) ; wait for resp */ - 0100776, /* bmi 60$ */ - 0105737, B_TKRSP + 10, /* tstb tkrsp+10. ; check stat */ - 0001401, /* beq 70$ */ - 0000000, /* halt */ - 0012703, B_TKCMD + 8, /* 70$: mov #tkcmd+8.,r3 */ - 0012723, 0000041, /* mov #41,(r3)+ ; read */ - 0012723, 0020000, /* mov #20000,(r3)+ ; clr exc */ - 0012723, 0001000, /* mov #512.,(r3)+ ; bc = 512 */ - 0005023, /* clr (r3)+ ; clr args */ - 0005023, /* clr (r3)+ ; ba = 0 */ - 0010412, /* mov r4,(r2) ; TK own rsp */ - 0010437, B_RING + 6, /* mov r4,ring+6 ; TK own cmd */ - 0005711, /* tst (r1) ; start poll */ - 0005712, /* 80$: tst (r2) ; wait for resp */ - 0100776, /* bmi 80$ */ - 0105737, B_TKRSP + 10, /* tstb tkrsp+10. ; check stat */ - 0001401, /* beq 90$ */ - 0000000, /* halt */ - - /* Boot block read in, jump to 0 - leave controller init'd */ - - 0005003, /* clr r3 */ - 0012704, BOOT_START+020, /* mov #st+020,r4 */ - 0005005, /* clr r5 */ - 0005007, /* clr pc */ - - 0100000, /* cmdtbl: init step 1 */ - B_RING, /* ring base */ - 0000000, /* high ring base */ - 0000001 /* go */ -}; - -t_stat tq_boot (int32 unitno, DEVICE *dptr) -{ -int32 i; -extern int32 saved_PC; -extern uint16 *M; - -for (i = 0; i < BOOT_LEN; i++) M[(BOOT_START >> 1) + i] = boot_rom[i]; -M[BOOT_UNIT >> 1] = unitno & 3; -M[BOOT_CSR >> 1] = tq_dib.ba & DMASK; -saved_PC = BOOT_ENTRY; -return SCPE_OK; -} - -#else - -t_stat tq_boot (int32 unitno, DEVICE *dptr) -{ -return SCPE_NOFNC; -} -#endif - -/* Special show commands */ - -void tq_show_ring (FILE *st, struct uq_ring *rp) -{ -uint32 i, desc; -uint16 d[2]; - -#if defined (VM_PDP11) -fprintf (st, "ring, base = %o, index = %d, length = %d\n", - rp->ba, rp->idx >> 2, rp->lnt >> 2); -#else -fprintf (st, "ring, base = %x, index = %d, length = %d\n", - rp->ba, rp->idx >> 2, rp->lnt >> 2); -#endif -for (i = 0; i < (rp->lnt >> 2); i++) { - if (Map_ReadW (rp->ba + (i << 2), 4, d, MAP)) { - fprintf (st, " %3d: non-existent memory\n", i); - break; } - desc = ((uint32) d[0]) | (((uint32) d[1]) << 16); -#if defined (VM_PDP11) - fprintf (st, " %3d: %011o\n", i, desc); -#else - fprintf (st, " %3d: %08x\n", i, desc); -#endif - } -return; -} - -void tq_show_pkt (FILE *st, int32 pkt) -{ -int32 i, j; -uint32 cr = GETP (pkt, UQ_HCTC, CR); -uint32 typ = GETP (pkt, UQ_HCTC, TYP); -uint32 cid = GETP (pkt, UQ_HCTC, CID); - -fprintf (st, "packet %d, credits = %d, type = %d, cid = %d\n", - pkt, cr, typ, cid); -for (i = 0; i < TQ_SH_MAX; i = i + TQ_SH_PPL) { - fprintf (st, " %2d:", i); - for (j = i; j < (i + TQ_SH_PPL); j++) -#if defined (VM_PDP11) - fprintf (st, " %06o", tq_pkt[pkt].d[j]); -#else - fprintf (st, " %04x", tq_pkt[pkt].d[j]); -#endif - fprintf (st, "\n"); - } -return; -} - -t_stat tq_show_unitq (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -int32 pkt, u = uptr - tq_dev.units; - -if (tq_csta != CST_UP) { - fprintf (st, "Controller is not initialized\n"); - return SCPE_OK; } -if ((uptr->flags & UNIT_ONL) == 0) { - if (uptr->flags & UNIT_ATT) - fprintf (st, "Unit %d is available\n", u); - else fprintf (st, "Unit %d is offline\n", u); - return SCPE_OK; } -if (uptr->cpkt) { - fprintf (st, "Unit %d current ", u); - tq_show_pkt (st, uptr->cpkt); - if (pkt = uptr->pktq) { - do { fprintf (st, "Unit %d queued ", u); - tq_show_pkt (st, pkt); } - while (pkt = tq_pkt[pkt].link); } } -else fprintf (st, "Unit %d queues are empty\n", u); -return SCPE_OK; -} - -t_stat tq_show_ctrl (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -int32 i, pkt; - -if (tq_csta != CST_UP) { - fprintf (st, "Controller is not initialized\n"); - return SCPE_OK; } -if (val & TQ_SH_RI) { - if (tq_pip) fprintf (st, "Polling in progress, host timer = %d\n", tq_hat); - else fprintf (st, "Host timer = %d\n", tq_hat); - fprintf (st, "Command "); - tq_show_ring (st, &tq_cq); - fprintf (st, "Response "); - tq_show_ring (st, &tq_rq); - } -if (val & TQ_SH_FR) { - if (pkt = tq_freq) { - for (i = 0; pkt != 0; i++, pkt = tq_pkt[pkt].link) { - if (i == 0) fprintf (st, "Free queue = %d", pkt); - else if ((i % 16) == 0) fprintf (st, ",\n %d", pkt); - else fprintf (st, ", %d", pkt); } - fprintf (st, "\n"); } - else fprintf (st, "Free queue is empty\n"); - } -if (val & TQ_SH_RS) { - if (pkt = tq_rspq) { - do { fprintf (st, "Response "); - tq_show_pkt (st, pkt); } - while (pkt = tq_pkt[pkt].link); } - else fprintf (st, "Response queue is empty\n"); - } -if (val & TQ_SH_UN) { - for (i = 0; i < TQ_NUMDR; i++) - tq_show_unitq (st, &tq_unit[i], 0, NULL); - } -return SCPE_OK; -} - -/* Set controller type (and capacity for user-defined type) */ - -tq_set_type (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -uint32 i, cap; -uint32 max = sim_taddr_64? TQU_EMAXC: TQU_MAXC; -t_stat r; - -if ((val < 0) || (val > TQU_TYPE) || ((val != TQU_TYPE) && cptr)) - return SCPE_ARG; -for (i = 0; i < TQ_NUMDR; i++) { - if (tq_unit[i].flags & UNIT_ATT) return SCPE_ALATT; } -if (cptr) { - cap = (uint32) get_uint (cptr, 10, max, &r); - if ((r != SCPE_OK) || (cap < TQU_MINC)) return SCPE_ARG; - drv_tab[TQU_TYPE].cap = ((t_addr) cap) << 20; } -tq_typ = val; -return SCPE_OK; -} - -/* Show controller type (and capacity for user-defined type) */ - -tq_show_type (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -fprintf (st, "%s", drv_tab[tq_typ].name); -if (tq_typ == TQU_TYPE) fprintf (st, " (%dMB)", drv_tab[tq_typ].cap >> 20); -return SCPE_OK; -} diff --git a/PDP11/pdp11_ts.c b/PDP11/pdp11_ts.c deleted file mode 100644 index caa95439..00000000 --- a/PDP11/pdp11_ts.c +++ /dev/null @@ -1,1011 +0,0 @@ -/* pdp11_ts.c: TS11/TSV05 magnetic tape simulator - - 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. - - ts TS11/TSV05 magtape - - 19-May-03 RMS Revised for new conditional compilation scheme - 25-Apr-03 RMS Revised for extended file support - 28-Mar-03 RMS Added multiformat support - 28-Feb-03 RMS Revised to use magtape library - 30-Sep-02 RMS Added variable address support to bootstrap - Added vector change/display support - Fixed CTL unload/clean decode - Implemented XS0_MOT in extended status - New data structures, revamped error recovery - 28-Aug-02 RMS Added end of medium support - 30-May-02 RMS Widened POS to 32b - 22-Apr-02 RMS Added maximum record length protection - 04-Apr-02 RMS Fixed bug in residual frame count after space operation - 16-Feb-02 RMS Fixed bug in message header logic - 26-Jan-02 RMS Revised bootstrap to conform to M9312 - 06-Jan-02 RMS Revised enable/disable support - 30-Nov-01 RMS Added read only unit, extended SET/SHOW support - 09-Nov-01 RMS Added bus map, VAX support - 15-Oct-01 RMS Integrated debug logging across simulator - 27-Sep-01 RMS Implemented extended characteristics and status - Fixed bug in write characteristics status return - 19-Sep-01 RMS Fixed bug in bootstrap - 15-Sep-01 RMS Fixed bug in NXM test - 07-Sep-01 RMS Revised device disable and interrupt mechanism - 13-Jul-01 RMS Fixed bug in space reverse (found by Peter Schorn) - - 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. - - The TS11 functions in three environments: - - - PDP-11 Q22 systems - the I/O map is one for one, so it's safe to - go through the I/O map - - PDP-11 Unibus 22b systems - the TS11 behaves as an 18b Unibus - peripheral and must go through the I/O map - - VAX Q22 systems - the TS11 must go through the I/O map -*/ - -#if defined (VM_PDP10) /* PDP10 version */ -#error "TS11 not supported on PDP10!" - -#elif defined (VM_VAX) /* VAX version */ -#include "vax_defs.h" -#define TS_DIS 0 /* on by default */ -#define ADDRTEST 0177700 -#define DMASK 0xFFFF -extern int32 ReadB (uint32 pa); -extern void WriteB (uint32 pa, int32 val); -extern int32 ReadW (uint32 pa); -extern void WriteW (uint32 pa, int32 val); -extern int32 int_req[IPL_HLVL]; -extern int32 int_vec[IPL_HLVL][32]; - -#else /* PDP-11 version */ -#include "pdp11_defs.h" -#define TS_DIS DEV_DIS /* off by default */ -#define ADDRTEST (UNIBUS? 0177774: 0177700) -extern uint16 *M; -extern int32 cpu_18b, cpu_ubm; -#define ReadB(p) ((M[(p) >> 1] >> (((p) & 1)? 8: 0)) & 0377) -#define WriteB(p,v) M[(p) >> 1] = ((p) & 1)? \ - ((M[(p) >> 1] & 0377) | ((v) << 8)): \ - ((M[(p) >> 1] & ~0377) | (v)) -#define ReadW(p) M[(p) >> 1] -#define WriteW(p,v) M[(p) >> 1] = (v) -#endif - -#include "sim_tape.h" - -/* TSBA/TSDB - 17772520: base address/data buffer register - - read: most recent memory address - write word: initiate command - write byte: diagnostic use -*/ - -/* TSSR - 17772522: subsystem status register - TSDBX - 17772523: extended address register - - read: return status - write word: initialize - write byte: if odd, set extended packet address register -*/ - -#define TSSR_SC 0100000 /* special condition */ -#define TSSR_RMR 0010000 /* reg mod refused */ -#define TSSR_NXM 0004000 /* nxm */ -#define TSSR_NBA 0002000 /* need buf addr */ -#define TSSR_V_EMA 8 /* mem addr<17:16> */ -#define TSSR_EMA 0001400 -#define TSSR_SSR 0000200 /* subsystem ready */ -#define TSSR_OFL 0000100 /* offline */ -#define TSSR_V_TC 1 /* term class */ -#define TSSR_M_TC 07 -#define TSSR_TC (TSSR_M_TC << TSSR_V_TC) -#define TC0 (0 << TSSR_V_TC) /* ok */ -#define TC1 (1 << TSSR_V_TC) /* attention */ -#define TC2 (2 << TSSR_V_TC) /* status alert */ -#define TC3 (3 << TSSR_V_TC) /* func reject */ -#define TC4 (4 << TSSR_V_TC) /* retry, moved */ -#define TC5 (5 << TSSR_V_TC) /* retry */ -#define TC6 (6 << TSSR_V_TC) /* pos lost */ -#define TC7 (7 << TSSR_V_TC) /* fatal err */ -#define TSSR_MBZ 0060060 -#define GET_TC(x) (((x) >> TSSR_V_TC) & TSSR_M_TC) - -#define TSDBX_M_XA 017 /* ext addr */ -#define TSDBX_BOOT 0000200 /* boot */ - -/* Command packet offsets */ - -#define CMD_PLNT 4 /* cmd pkt length */ -#define cmdhdr tscmdp[0] /* header */ -#define cmdadl tscmdp[1] /* address low */ -#define cmdadh tscmdp[2] /* address high */ -#define cmdlnt tscmdp[3] /* length */ - -/* Command packet header */ - -#define CMD_ACK 0100000 /* acknowledge */ -#define CMD_CVC 0040000 /* clear vol chk */ -#define CMD_OPP 0020000 /* opposite */ -#define CMD_SWP 0010000 /* swap bytes */ -#define CMD_V_MODE 8 /* mode */ -#define CMD_M_MODE 017 -#define CMD_IE 0000200 /* int enable */ -#define CMD_V_FNC 0 /* function */ -#define CMD_M_FNC 037 /* function */ -#define CMD_N_FNC (CMD_M_FNC + 1) -#define FNC_READ 001 /* read */ -#define FNC_WCHR 004 /* write char */ -#define FNC_WRIT 005 /* write */ -#define FNC_WSSM 006 /* write mem */ -#define FNC_POS 010 /* position */ -#define FNC_FMT 011 /* format */ -#define FNC_CTL 012 /* control */ -#define FNC_INIT 013 /* init */ -#define FNC_GSTA 017 /* get status */ -#define CMD_MBZ 0000140 -#define GET_FNC(x) (((x) >> CMD_V_FNC) & CMD_M_FNC) -#define GET_MOD(x) (((x) >> CMD_V_MODE) & CMD_M_MODE) - -/* Function test flags */ - -#define FLG_MO 001 /* motion */ -#define FLG_WR 002 /* write */ -#define FLG_AD 004 /* addr mem */ - -/* Message packet offsets */ - -#define MSG_PLNT 8 /* packet length */ -#define msghdr tsmsgp[0] /* header */ -#define msglnt tsmsgp[1] /* length */ -#define msgrfc tsmsgp[2] /* residual frame */ -#define msgxs0 tsmsgp[3] /* ext status 0 */ -#define msgxs1 tsmsgp[4] /* ext status 1 */ -#define msgxs2 tsmsgp[5] /* ext status 2 */ -#define msgxs3 tsmsgp[6] /* ext status 3 */ -#define msgxs4 tsmsgp[7] /* ext status 4 */ - -/* Message packet header */ - -#define MSG_ACK 0100000 /* acknowledge */ -#define MSG_MATN 0000000 /* attention */ -#define MSG_MILL 0000400 /* illegal */ -#define MSG_MNEF 0001000 /* non exec fnc */ -#define MSG_CEND 0000020 /* end */ -#define MSG_CFAIL 0000021 /* fail */ -#define MSG_CERR 0000022 /* error */ -#define MSG_CATN 0000023 /* attention */ - -/* Extended status register 0 */ - -#define XS0_TMK 0100000 /* tape mark */ -#define XS0_RLS 0040000 /* rec lnt short */ -#define XS0_LET 0020000 /* log end tape */ -#define XS0_RLL 0010000 /* rec lnt long */ -#define XS0_WLE 0004000 /* write lock err */ -#define XS0_NEF 0002000 /* non exec fnc */ -#define XS0_ILC 0001000 /* illegal cmd */ -#define XS0_ILA 0000400 /* illegal addr */ -#define XS0_MOT 0000200 /* tape has moved */ -#define XS0_ONL 0000100 /* online */ -#define XS0_IE 0000040 /* int enb */ -#define XS0_VCK 0000020 /* volume check */ -#define XS0_PET 0000010 /* 1600 bpi */ -#define XS0_WLK 0000004 /* write lock */ -#define XS0_BOT 0000002 /* BOT */ -#define XS0_EOT 0000001 /* EOT */ -#define XS0_ALLCLR 0177600 /* clear at start */ - -/* Extended status register 1 */ - -#define XS1_UCOR 0000002 /* uncorrectable */ - -/* Extended status register 2 */ - -#define XS2_XTF 0000200 /* ext features */ - -/* Extended status register 3 */ - -#define XS3_OPI 0000100 /* op incomplete */ -#define XS3_REV 0000040 /* reverse */ -#define XS3_RIB 0000001 /* reverse to BOT */ - -/* Extended status register 4 */ - -#define XS4_HDS 0100000 /* high density */ - -/* Write characteristics packet offsets */ - -#define WCH_PLNT 5 /* packet length */ -#define wchadl tswchp[0] /* address low */ -#define wchadh tswchp[1] /* address high */ -#define wchlnt tswchp[2] /* length */ -#define wchopt tswchp[3] /* options */ -#define wchxopt tswchp[4] /* ext options */ - -/* Write characteristics options */ - -#define WCH_ESS 0000200 /* stop dbl tmk */ -#define WCH_ENB 0000100 /* BOT = tmk */ -#define WCH_EAI 0000040 /* enb attn int */ -#define WCH_ERI 0000020 /* enb mrls int */ - -/* Write characteristics extended options */ - -#define WCHX_HDS 0000040 /* high density */ - -#define MAX(a,b) (((a) >= (b))? (a): (b)) - -extern int32 int_req[IPL_HLVL]; -extern int32 int_vec[IPL_HLVL][32]; - -extern UNIT cpu_unit; -extern int32 cpu_log; -extern FILE *sim_log; -uint8 *tsxb = NULL; /* xfer buffer */ -int32 tssr = 0; /* status register */ -int32 tsba = 0; /* mem addr */ -int32 tsdbx = 0; /* data buf ext */ -int32 tscmdp[CMD_PLNT] = { 0 }; /* command packet */ -int32 tsmsgp[MSG_PLNT] = { 0 }; /* message packet */ -int32 tswchp[WCH_PLNT] = { 0 }; /* wr char packet */ -int32 ts_ownc = 0; /* tape owns cmd */ -int32 ts_ownm = 0; /* tape owns msg */ -int32 ts_qatn = 0; /* queued attn */ -int32 ts_bcmd = 0; /* boot cmd */ -int32 ts_time = 10; /* record latency */ - -DEVICE ts_dev; -t_stat ts_rd (int32 *data, int32 PA, int32 access); -t_stat ts_wr (int32 data, int32 PA, int32 access); -t_stat ts_svc (UNIT *uptr); -t_stat ts_reset (DEVICE *dptr); -t_stat ts_attach (UNIT *uptr, char *cptr); -t_stat ts_detach (UNIT *uptr); -t_stat ts_boot (int32 unitno, DEVICE *dptr); -int32 ts_updtssr (int32 t); -int32 ts_updxs0 (int32 t); -void ts_cmpendcmd (int32 s0, int32 s1); -void ts_endcmd (int32 ssf, int32 xs0f, int32 msg); -int32 ts_map_status (t_stat st); - -/* TS data structures - - ts_dev TS device descriptor - ts_unit TS unit list - ts_reg TS register list - ts_mod TS modifier list -*/ - -DIB ts_dib = { IOBA_TS, IOLN_TS, &ts_rd, &ts_wr, - 1, IVCL (TS), VEC_TS, { NULL } }; - -UNIT ts_unit = { UDATA (&ts_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) }; - -REG ts_reg[] = { - { GRDATA (TSSR, tssr, DEV_RDX, 16, 0) }, - { GRDATA (TSBA, tsba, DEV_RDX, 22, 0) }, - { GRDATA (TSDBX, tsdbx, DEV_RDX, 8, 0) }, - { GRDATA (CHDR, cmdhdr, DEV_RDX, 16, 0) }, - { GRDATA (CADL, cmdadl, DEV_RDX, 16, 0) }, - { GRDATA (CADH, cmdadh, DEV_RDX, 16, 0) }, - { GRDATA (CLNT, cmdlnt, DEV_RDX, 16, 0) }, - { GRDATA (MHDR, msghdr, DEV_RDX, 16, 0) }, - { GRDATA (MRFC, msgrfc, DEV_RDX, 16, 0) }, - { GRDATA (MXS0, msgxs0, DEV_RDX, 16, 0) }, - { GRDATA (MXS1, msgxs1, DEV_RDX, 16, 0) }, - { GRDATA (MXS2, msgxs2, DEV_RDX, 16, 0) }, - { GRDATA (MXS3, msgxs3, DEV_RDX, 16, 0) }, - { GRDATA (MSX4, msgxs4, DEV_RDX, 16, 0) }, - { GRDATA (WADL, wchadl, DEV_RDX, 16, 0) }, - { GRDATA (WADH, wchadh, DEV_RDX, 16, 0) }, - { GRDATA (WLNT, wchlnt, DEV_RDX, 16, 0) }, - { GRDATA (WOPT, wchopt, DEV_RDX, 16, 0) }, - { GRDATA (WXOPT, wchxopt, DEV_RDX, 16, 0) }, - { FLDATA (INT, IREQ (TS), INT_V_TS) }, - { FLDATA (ATTN, ts_qatn, 0) }, - { FLDATA (BOOT, ts_bcmd, 0) }, - { FLDATA (OWNC, ts_ownc, 0) }, - { FLDATA (OWNM, ts_ownm, 0) }, - { DRDATA (TIME, ts_time, 24), PV_LEFT + REG_NZ }, - { DRDATA (POS, ts_unit.pos, T_ADDR_W), PV_LEFT + REG_RO }, - { GRDATA (DEVADDR, ts_dib.ba, DEV_RDX, 32, 0), REG_HRO }, - { GRDATA (DEVVEC, ts_dib.vec, DEV_RDX, 16, 0), REG_HRO }, - { NULL } }; - -MTAB ts_mod[] = { - { MTUF_WLK, 0, "write enabled", "WRITEENABLED", NULL }, - { MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL }, - { MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT", - &sim_tape_set_fmt, &sim_tape_show_fmt, NULL }, - { MTAB_XTD|MTAB_VDV, 004, "ADDRESS", "ADDRESS", - &set_addr, &show_addr, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "VECTOR", "VECTOR", - &set_vec, &show_vec, NULL }, - { 0 } }; - -DEVICE ts_dev = { - "TS", &ts_unit, ts_reg, ts_mod, - 1, 10, 31, 1, DEV_RDX, 8, - NULL, NULL, &ts_reset, - &ts_boot, &ts_attach, &ts_detach, - &ts_dib, DEV_DISABLE | TS_DIS | DEV_UBUS | DEV_QBUS }; - -/* I/O dispatch routine, I/O addresses 17772520 - 17772522 - - 17772520 TSBA read/write - 17772522 TSSR read/write -*/ - -t_stat ts_rd (int32 *data, int32 PA, int32 access) -{ -switch ((PA >> 1) & 01) { /* decode PA<1> */ -case 0: /* TSBA */ - *data = tsba & DMASK; /* low 16b of ba */ - break; -case 1: /* TSSR */ - *data = tssr = ts_updtssr (tssr); /* update tssr */ - break; } -return SCPE_OK; -} - -t_stat ts_wr (int32 data, int32 PA, int32 access) -{ -int32 i; -uint32 pa; - -switch ((PA >> 1) & 01) { /* decode PA<1> */ -case 0: /* TSDB */ - if ((tssr & TSSR_SSR) == 0) { /* ready? */ - 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 */ - tssr = ts_updtssr (tssr & TSSR_NBA); /* clr ssr, err */ - msgxs0 = ts_updxs0 (msgxs0 & ~XS0_ALLCLR); /* clr, upd xs0 */ - 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 */ - 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 */ - else if (access == WRITE) ts_reset (&ts_dev); /* reset */ - break; } -return SCPE_OK; -} - -/* Tape motion routines */ - -#define XTC(x,t) (((unsigned) (x) << 16) | (t)) -#define GET_X(x) (((x) >> 16) & 0177777) -#define GET_T(x) ((x) & 0177777) - -int32 ts_map_status (t_stat st) -{ -switch (st) { -case MTSE_OK: - break; -case MTSE_TMK: - msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */ - return (XTC (XS0_TMK | XS0_RLS, TC2)); -case MTSE_RECE: /* record in error */ - msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */ -case MTSE_INVRL: /* invalid rec lnt */ -case MTSE_IOERR: /* IO error */ - msgxs1 = msgxs1 | XS1_UCOR; /* uncorrectable */ - return (XTC (XS0_RLS, TC6)); /* pos lost */ -case MTSE_FMT: -case MTSE_UNATT: -case MTSE_EOM: /* end of medium */ - msgxs3 = msgxs3 | XS3_OPI; /* incomplete */ - return (XTC (XS0_RLS, TC6)); /* pos lost */ -case MTSE_BOT: /* reverse into BOT */ - msgxs3 = msgxs3 | XS3_RIB; /* set status */ - return (XTC (XS0_BOT | XS0_RLS, TC2)); /* tape alert */ -case MTSE_WRP: /* write protect */ - msgxs0 = msgxs0 | XS0_WLE | XS0_NEF; /* can't execute */ - return (XTC (XS0_WLE | XS0_NEF, TC3)); } -return 0; -} - -int32 ts_spacef (UNIT *uptr, int32 fc, t_bool upd) -{ -t_stat st; -t_mtrlnt tbc; - -do { fc = (fc - 1) & DMASK; /* decr wc */ - if (upd) msgrfc = fc; - if (st = sim_tape_sprecf (uptr, &tbc)) /* space rec fwd, err? */ - return ts_map_status (st); /* map status */ - msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */ - } -while (fc != 0); -return 0; -} - -int32 ts_skipf (UNIT *uptr, int32 fc) -{ -t_stat st; -t_mtrlnt tbc; -t_bool tmkprv = FALSE; - -msgrfc = fc; -if (sim_tape_bot (uptr) && (wchopt & WCH_ENB)) tmkprv = TRUE; -do { st = sim_tape_sprecf (uptr, &tbc); /* space rec fwd */ - if (st == MTSE_TMK) { /* tape mark? */ - msgrfc = (msgrfc - 1) & DMASK; /* decr count */ - msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */ - if (tmkprv && (wchopt & WCH_ESS)) /* 2nd tmk & ESS? */ - return (XTC ((msgrfc? XS0_RLS: 0) | - XS0_TMK | XS0_LET, TC2)); - tmkprv = TRUE; } /* flag tmk */ - else if (st != MTSE_OK) return ts_map_status (st); - else tmkprv = FALSE; /* not a tmk */ - msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */ - } -while (msgrfc != 0); -return 0; -} - -int32 ts_spacer (UNIT *uptr, int32 fc, t_bool upd) -{ -int32 st; -t_mtrlnt tbc; - -do { fc = (fc - 1) & DMASK; /* decr wc */ - if (upd) msgrfc = fc; - if (st = sim_tape_sprecr (uptr, &tbc)) /* space rec rev, err? */ - return ts_map_status (st); /* map status */ - msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */ - } -while (fc != 0); -return 0; -} - -int32 ts_skipr (UNIT *uptr, int32 fc) -{ -t_stat st; -t_mtrlnt tbc; -t_bool tmkprv = FALSE; - -msgrfc = fc; -do { st = sim_tape_sprecr (uptr, &tbc); /* space rec rev */ - if (st == MTSE_TMK) { /* tape mark? */ - msgrfc = (msgrfc - 1) & DMASK; /* decr count */ - msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */ - if (tmkprv && (wchopt & WCH_ESS)) /* 2nd tmk & ESS? */ - return (XTC ((msgrfc? XS0_RLS: 0) | - XS0_TMK | XS0_LET, TC2)); - tmkprv = TRUE; } /* flag tmk */ - else if (st != MTSE_OK) return ts_map_status (st); - else tmkprv = FALSE; /* not a tmk */ - msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */ - } -while (msgrfc != 0); -return 0; -} - -int32 ts_readf (UNIT *uptr, uint32 fc) -{ -t_stat st; -t_mtrlnt i, tbc, wbc; -uint32 wa, pa; - -msgrfc = fc; -st = sim_tape_rdrecf (uptr, tsxb, &tbc, MT_MAXFR); /* read rec fwd */ -if (st != MTSE_OK) return ts_map_status (st); /* error? */ -if (fc == 0) fc = 0200000; /* byte count */ -tsba = (cmdadh << 16) | cmdadl; /* buf addr */ -wbc = (tbc > fc)? fc: tbc; /* cap buf size */ -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)); } - tsba = tsba + 1; - 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? */ -return 0; -} - -int32 ts_readr (UNIT *uptr, uint32 fc) -{ -t_stat st; -t_mtrlnt i, tbc, wbc; -uint32 wa, pa; - -msgrfc = fc; -st = sim_tape_rdrecr (uptr, tsxb, &tbc, MT_MAXFR); /* read rec rev */ -if (st != MTSE_OK) return ts_map_status (st); /* error? */ -if (fc == 0) fc = 0200000; /* byte count */ -tsba = (cmdadh << 16) | cmdadl + fc; /* buf addr */ -wbc = (tbc > fc)? fc: tbc; /* cap buf size */ -msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */ -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)); } - 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? */ -return 0; -} - -int32 ts_write (UNIT *uptr, int32 fc) -{ -int32 i; -uint32 wa, pa; -t_stat st; - -msgrfc = fc; -if (fc == 0) fc = 0200000; /* byte count */ -tsba = (cmdadh << 16) | cmdadl; /* buf addr */ -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; } - tsba = tsba + 1; } -if (st = sim_tape_wrrecf (uptr, tsxb, fc)) /* write rec, err? */ - return ts_map_status (st); /* return status */ -msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */ -msgrfc = 0; -return 0; -} - -int32 ts_wtmk (UNIT *uptr) -{ -t_stat st; - -if (st = sim_tape_wrtmk (uptr)) /* write tmk, err? */ - return ts_map_status (st); /* return status */ -msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */ -return XTC (XS0_TMK, TC0); -} - -/* Unit service */ - -t_stat ts_svc (UNIT *uptr) -{ -int32 i, fnc, mod, st0, st1; -uint32 pa; - -static const int32 fnc_mod[CMD_N_FNC] = { /* max mod+1 0 ill */ - 0, 4, 0, 0, 1, 2, 1, 0, /* 00 - 07 */ - 5, 3, 5, 1, 0, 0, 0, 1, /* 10 - 17 */ - 0, 0, 0, 0, 0, 0, 0, 0, /* 20 - 27 */ - 0, 0, 0, 0, 0, 0, 0, 0 }; /* 30 - 37 */ -static const int32 fnc_flg[CMD_N_FNC] = { - 0, FLG_MO+FLG_AD, 0, 0, 0, FLG_MO+FLG_WR+FLG_AD, FLG_AD, 0, - FLG_MO, FLG_MO+FLG_WR, FLG_MO, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, /* 20 - 27 */ - 0, 0, 0, 0, 0, 0, 0, 0 }; /* 30 - 37 */ - -if (ts_bcmd) { /* boot? */ - ts_bcmd = 0; /* clear flag */ - sim_tape_rewind (uptr); /* 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); } - else tssr = ts_updtssr (tssr | TSSR_SSR | TC3); - if (cmdhdr & CMD_IE) SET_INT (TS); - return SCPE_OK; } - -if (!(cmdhdr & CMD_ACK)) { /* no acknowledge? */ - tssr = ts_updtssr (tssr | TSSR_SSR); /* set rdy, int */ - if (cmdhdr & CMD_IE) SET_INT (TS); - ts_ownc = ts_ownm = 0; /* CPU owns all */ - return SCPE_OK; } -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); -if ((fnc != FNC_WCHR) && (tssr & TSSR_NBA)) { /* ~wr chr & nba? */ - ts_endcmd (TC3, 0, 0); /* error */ - return SCPE_OK; } -if (ts_qatn && (wchopt & WCH_EAI)) { /* attn pending? */ - ts_endcmd (TC1, 0, MSG_MATN | MSG_CATN); /* send attn msg */ - SET_INT (TS); /* set interrupt */ - ts_qatn = 0; /* not pending */ - return SCPE_OK; } -if (cmdhdr & CMD_CVC) /* cvc? clr vck */ - msgxs0 = msgxs0 & ~XS0_VCK; -if ((cmdhdr & CMD_MBZ) || (mod >= fnc_mod[fnc])) { /* test mbz */ - ts_endcmd (TC3, XS0_ILC, MSG_ACK | MSG_MILL | MSG_CFAIL); - return SCPE_OK; } -if ((fnc_flg[fnc] & FLG_MO) && /* mot+(vck|!att)? */ - ((msgxs0 & XS0_VCK) || !(uptr->flags & UNIT_ATT))) { - ts_endcmd (TC3, XS0_NEF, MSG_ACK | MSG_MNEF | MSG_CFAIL); - return SCPE_OK; } -if ((fnc_flg[fnc] & FLG_WR) && /* write? */ - sim_tape_wrp (uptr)) { /* write lck? */ - ts_endcmd (TC3, XS0_WLE | XS0_NEF, MSG_ACK | MSG_MNEF | MSG_CFAIL); - return SCPE_OK; } -if ((((fnc == FNC_READ) && (mod == 1)) || /* read rev */ - ((fnc == FNC_POS) && (mod & 1))) && /* space rev */ - sim_tape_bot (uptr)) { /* BOT? */ - ts_endcmd (TC3, XS0_NEF, MSG_ACK | MSG_MNEF | MSG_CFAIL); - return SCPE_OK; } -if ((fnc_flg[fnc] & FLG_AD) && (cmdadh & ADDRTEST)) { /* buf addr > 22b? */ - ts_endcmd (TC3, XS0_ILA, MSG_ACK | MSG_MILL | MSG_CFAIL); - return SCPE_OK; } - -st0 = st1 = 0; -switch (fnc) { /* case on func */ -case FNC_INIT: /* init */ - if (!sim_tape_bot (uptr)) msgxs0 = msgxs0 | XS0_MOT; /* set if tape moves */ - sim_tape_rewind (uptr); /* rewind */ -case FNC_WSSM: /* write mem */ -case FNC_GSTA: /* get status */ - ts_endcmd (TC0, 0, MSG_ACK | MSG_CEND); /* send end packet */ - return SCPE_OK; -case FNC_WCHR: /* write char */ - if ((cmdadh & ADDRTEST) || (cmdadl & 1) || (cmdlnt < 6)) { - 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 ((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); } - 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; - case 01: /* rewind and unload */ - if (!sim_tape_bot (uptr)) msgxs0 = msgxs0 | XS0_MOT; /* if tape moves */ - sim_tape_detach (uptr); /* unload */ - ts_endcmd (TC0, 0, MSG_ACK | MSG_CEND); - break; - case 02: /* clean */ - 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; - case 04: /* rewind */ - if (!sim_tape_bot (uptr)) msgxs0 = msgxs0 | XS0_MOT; /* if tape moves */ - sim_tape_rewind (uptr); - 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; - case 01: /* back */ - 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; - 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; } - ts_cmpendcmd (st0, st1); - break; -case FNC_WRIT: /* write */ - switch (mod) { /* case mode */ - case 00: /* write */ - st0 = ts_write (uptr, cmdlnt); - break; - case 01: /* rewrite */ - 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; - case 01: /* erase */ - break; - case 02: /* retry tmk */ - 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; - case 01: /* space rev */ - st0 = ts_spacer (uptr, cmdadl, TRUE); - break; - case 02: /* space ffwd */ - st0 = ts_skipf (uptr, cmdadl); - break; - case 03: /* space frev */ - st0 = ts_skipr (uptr, cmdadl); - break; - case 04: /* rewind */ - if (!sim_tape_bot (uptr)) msgxs0 = msgxs0 | XS0_MOT; /* if tape moves */ - sim_tape_rewind (uptr); - break; } - ts_cmpendcmd (st0, 0); - break; } -return SCPE_OK; -} - -/* Utility routines */ - -int32 ts_updtssr (int32 t) -{ -t = (t & ~TSSR_EMA) | ((tsba >> (16 - TSSR_V_EMA)) & TSSR_EMA); -if (ts_unit.flags & UNIT_ATT) t = t & ~TSSR_OFL; -else t = t | TSSR_OFL; -return (t & ~TSSR_MBZ); -} - -int32 ts_updxs0 (int32 t) -{ -t = (t & ~(XS0_ONL | XS0_WLK | XS0_BOT | XS0_IE)) | XS0_PET; -if (ts_unit.flags & UNIT_ATT) { - t = t | XS0_ONL; - if (sim_tape_wrp (&ts_unit)) t = t | XS0_WLK; - if (sim_tape_bot (&ts_unit)) t = (t | XS0_BOT) & ~XS0_EOT; } -else t = t & ~XS0_EOT; -if (cmdhdr & CMD_IE) t = t | XS0_IE; -return t; -} - -void ts_cmpendcmd (int32 s0, int32 s1) -{ -int32 xs0, ssr, tc; -static const int32 msg[8] = { - MSG_ACK | MSG_CEND, MSG_ACK | MSG_MATN | MSG_CATN, - MSG_ACK | MSG_CEND, MSG_ACK | MSG_CFAIL, - MSG_ACK | MSG_CERR, MSG_ACK | MSG_CERR, - MSG_ACK | MSG_CERR, MSG_ACK | MSG_CERR }; - -xs0 = GET_X (s0) | GET_X (s1); /* or XS0 errs */ -s0 = GET_T (s0); /* get SSR errs */ -s1 = GET_T (s1); -ssr = (s0 | s1) & ~TSSR_TC; /* or SSR errs */ -tc = MAX (GET_TC (s0), GET_TC (s1)); /* max term code */ -ts_endcmd (ssr | (tc << TSSR_V_TC), xs0, msg[tc]); /* end cmd */ -return; -} - -void ts_endcmd (int32 tc, int32 xs0, int32 msg) -{ -int32 i; -uint32 pa; - -msgxs0 = ts_updxs0 (msgxs0 | xs0); /* update XS0 */ -if (wchxopt & WCHX_HDS) msgxs4 = msgxs4 | XS4_HDS; /* update XS4 */ -if (msg && !(tssr & TSSR_NBA)) { /* send end pkt */ - msghdr = msg; - 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; } } -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); -return; -} - -/* Device reset */ - -t_stat ts_reset (DEVICE *dptr) -{ -int32 i; - -sim_tape_rewind (&ts_unit); -tsba = tsdbx = 0; -ts_ownc = ts_ownm = 0; -ts_bcmd = 0; -ts_qatn = 0; -tssr = ts_updtssr (TSSR_NBA | TSSR_SSR); -for (i = 0; i < CMD_PLNT; i++) tscmdp[i] = 0; -for (i = 0; i < WCH_PLNT; i++) tswchp[i] = 0; -for (i = 0; i < MSG_PLNT; i++) tsmsgp[i] = 0; -msgxs0 = ts_updxs0 (XS0_VCK); -CLR_INT (TS); -if (tsxb == NULL) tsxb = calloc (MT_MAXFR, sizeof (unsigned int8)); -if (tsxb == NULL) return SCPE_MEM; -return SCPE_OK; -} - -/* Attach */ - -t_stat ts_attach (UNIT *uptr, char *cptr) -{ -t_stat r; - -r = sim_tape_attach (uptr, cptr); /* attach unit */ -if (r != SCPE_OK) return r; /* error? */ -tssr = tssr & ~TSSR_OFL; /* clr offline */ -if ((tssr & TSSR_NBA) || !(wchopt & WCH_EAI)) return r; /* attn msg? */ -if (ts_ownm) { /* own msg buf? */ - ts_endcmd (TC1, 0, MSG_MATN | MSG_CATN); /* send attn */ - SET_INT (TS); /* set interrupt */ - ts_qatn = 0; } /* don't queue */ -else ts_qatn = 1; /* else queue */ -return r; -} - -/* Detach routine */ - -t_stat ts_detach (UNIT* uptr) -{ -t_stat r; - -r = sim_tape_detach (uptr); /* detach unit */ -if (r != SCPE_OK) return r; /* error? */ -tssr = tssr | TSSR_OFL; /* set offline */ -if ((tssr & TSSR_NBA) || !(wchopt & WCH_EAI)) return r; /* attn msg? */ -if (ts_ownm) { /* own msg buf? */ - ts_endcmd (TC1, 0, MSG_MATN | MSG_CATN); /* send attn */ - SET_INT (TS); /* set interrupt */ - ts_qatn = 0; } /* don't queue */ -else ts_qatn = 1; /* else queue */ -return r; -} - -/* Boot */ - -#if defined (VM_PDP11) -#define BOOT_START 01000 -#define BOOT_CSR0 (BOOT_START + 006) -#define BOOT_CSR1 (BOOT_START + 012) -#define BOOT_LEN (sizeof (boot_rom) / sizeof (int16)) - -static const uint16 boot_rom[] = { - 0012706, 0001000, /* mov #boot_start, sp */ - 0012700, 0172520, /* mov #tsba, r0 */ - 0012701, 0172522, /* mov #tssr, r1 */ - 0005011, /* clr (r1) ; init, rew */ - 0105711, /* tstb (r1) ; wait */ - 0100376, /* bpl .-2 */ - 0012710, 0001070, /* mov #pkt1, (r0) ; set char */ - 0105711, /* tstb (r1) ; wait */ - 0100376, /* bpl .-2 */ - 0012710, 0001110, /* mov #pkt2, (r0) ; read, skip */ - 0105711, /* tstb (r1) ; wait */ - 0100376, /* bpl .-2 */ - 0012710, 0001110, /* mov #pkt2, (r0) ; read */ - 0105711, /* tstb (r1) ; wait */ - 0100376, /* bpl .-2 */ - 0005711, /* tst (r1) ; err? */ - 0100421, /* bmi hlt */ - 0005000, /* clr r0 */ - 0012704, 0001066+020, /* mov #sgnt+20, r4 */ - 0005007, /* clr r7 */ - 0046523, /* sgnt: "SM" */ - 0140004, /* pkt1: 140004, wcpk, 0, 8. */ - 0001100, - 0000000, - 0000010, - 0001122, /* wcpk: msg, 0, 14., 0 */ - 0000000, - 0000016, - 0000000, - 0140001, /* pkt2: 140001, 0, 0, 512. */ - 0000000, - 0000000, - 0001000, - 0000000 /* hlt: halt */ - /* msg: .blk 4 */ -}; - -t_stat ts_boot (int32 unitno, DEVICE *dptr) -{ -int32 i; -extern int32 saved_PC; - -sim_tape_rewind (&ts_unit); -for (i = 0; i < BOOT_LEN; i++) - M[(BOOT_START >> 1) + i] = boot_rom[i]; -M[BOOT_CSR0 >> 1] = ts_dib.ba & DMASK; -M[BOOT_CSR1 >> 1] = (ts_dib.ba & DMASK) + 02; -saved_PC = BOOT_START; -return SCPE_OK; -} -#else - -t_stat ts_boot (int32 unitno, DEVICE *dptr) -{ -return SCPE_NOFNC; -} -#endif diff --git a/PDP11/pdp11_uqssp.h b/PDP11/pdp11_uqssp.h deleted file mode 100644 index 257d41bc..00000000 --- a/PDP11/pdp11_uqssp.h +++ /dev/null @@ -1,169 +0,0 @@ -/* pdp11_uqssp.h: Unibus/Qbus storage systems port definitions file - - 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 - 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. - - 30-Aug-02 RMS Added TMSCP support -*/ - -#ifndef _PDP11_UQSSP_H_ -#define _PDP11_UQSSP_H_ 0 - -/* IP register - initialization and polling - - read - controller polls command queue - write - controller re-initializes -*/ - -/* SA register - status, address, and purge - - read - data and error information - write - host startup information, purge complete -*/ - -#define SA_ER 0x8000 /* error */ -#define SA_S4 0x4000 /* init step 4 */ -#define SA_S3 0x2000 /* init step 3 */ -#define SA_S2 0x1000 /* init step 2 */ -#define SA_S1 0x0800 /* init step 1 */ - -/* Init step 1, controller to host */ - -#define SA_S1C_NV 0x0400 /* fixed vec NI */ -#define SA_S1C_Q22 0x0200 /* Q22 device */ -#define SA_S1C_DI 0x0100 /* ext diags */ -#define SA_S1C_OD 0x0080 /* odd addrs NI */ -#define SA_S1C_MP 0x0040 /* mapping */ -#define SA_S1C_SM 0x0020 /* spec fncs NI */ -#define SA_S1C_CN 0x0010 /* node name NI */ - -/* Init step 1, host to controller */ - -#define SA_S1H_VL 0x8000 /* valid */ -#define SA_S1H_WR 0x4000 /* wrap mode */ -#define SA_S1H_V_CQ 11 /* cmd q len */ -#define SA_S1H_M_CQ 0x7 -#define SA_S1H_V_RQ 8 /* resp q len */ -#define SA_S1H_M_RQ 0x7 -#define SA_S1H_IE 0x0080 /* int enb */ -#define SA_S1H_VEC 0x007F /* vector */ -#define SA_S1H_CQ(x) (1 << (((x) >> SA_S1H_V_CQ) & SA_S1H_M_CQ)) -#define SA_S1H_RQ(x) (1 << (((x) >> SA_S1H_V_RQ) & SA_S1H_M_RQ)) - -/* Init step 2, controller to host */ - -#define SA_S2C_PT 0x0000 /* port type */ -#define SA_S2C_V_EC 8 /* info to echo */ -#define SA_S2C_M_EC 0xFF -#define SA_S2C_EC(x) (((x) >> SA_S2C_V_EC) & SA_S2C_M_EC) - -/* Init step 2, host to controller */ - -#define SA_S2H_CLO 0xFFFE /* comm addr lo */ -#define SA_S2H_PI 0x0001 /* adp prg int */ - -/* Init step 3, controller to host */ - -#define SA_S3C_V_EC 0 /* info to echo */ -#define SA_S3C_M_EC 0xFF -#define SA_S3C_EC(x) (((x) >> SA_S3C_V_EC) & SA_S3C_M_EC) - -/* Init step 3, host to controller */ - -#define SA_S3H_PP 0x8000 /* purge, poll test */ -#define SA_S3H_CHI 0x7FFF /* comm addr hi */ - -/* Init step 4, controller to host */ - -#define SA_S4C_V_MOD 4 /* adapter # */ -#define SA_S4C_V_VER 0 /* version # */ - -/* Init step 4, host to controller */ - -#define SA_S4H_CS 0x0400 /* host scrpad NI */ -#define SA_S4H_NN 0x0200 /* snd node name NI */ -#define SA_S4H_SF 0x0100 /* spec fnc NI */ -#define SA_S4H_LF 0x0002 /* send last fail */ -#define SA_S4H_GO 0x0001 /* go */ - -/* Fatal error codes (generic through 32) */ - -#define PE_PRE 1 /* packet read err */ -#define PE_PWE 2 /* packet write err */ -#define PE_QRE 6 /* queue read err */ -#define PE_QWE 7 /* queue write err */ -#define PE_HAT 9 /* host access tmo */ -#define PE_ICI 14 /* inv conn ident */ -#define PE_PIE 20 /* prot incompat */ -#define PE_PPF 21 /* prg/poll err */ -#define PE_MRE 22 /* map reg rd err */ -#define PE_T11 475 /* T11 err NI */ -#define PE_SND 476 /* SND err NI */ -#define PE_RCV 477 /* RCV err NI */ -#define PE_NSR 478 /* no such rsrc */ - -/* Comm region offsets */ - -#define SA_COMM_QQ -8 /* unused */ -#define SA_COMM_PI -6 /* purge int */ -#define SA_COMM_CI -4 /* cmd int */ -#define SA_COMM_RI -2 /* resp int */ -#define SA_COMM_MAX ((4 << SA_S1H_M_CQ) + (4 << SA_S1H_M_RQ) - SA_COMM_QQ) - -/* Command/response rings */ - -struct uq_ring { - int32 ioff; /* intr offset */ - uint32 ba; /* base addr */ - uint32 lnt; /* size in bytes */ - uint32 idx; /* current index */ - }; - -/* Ring descriptor entry */ - -#define UQ_DESC_OWN 0x80000000 /* ownership */ -#define UQ_DESC_F 0x40000000 /* flag */ -#define UQ_ADDR 0x003FFFFE /* addr, word aligned */ - -/* Packet header */ - -#define UQ_HDR_OFF -4 /* offset */ - -#define UQ_HLNT 0 /* length */ -#define UQ_HCTC 1 /* credits, type, CID */ - -#define UQ_HCTC_V_CR 0 /* credits */ -#define UQ_HCTC_M_CR 0xF -#define UQ_HCTC_V_TYP 4 /* type */ -#define UQ_HCTC_M_TYP 0xF -#define UQ_TYP_SEQ 0 /* sequential */ -#define UQ_TYP_DAT 1 /* datagram */ -#define UQ_HCTC_V_CID 8 /* conn ID */ -#define UQ_HCTC_M_CID 0xFF -#define UQ_CID_MSCP 0 /* MSCP */ -#define UQ_CID_TMSCP 1 /* TMSCP */ -#define UQ_CID_DUP 2 /* DUP */ -#define UQ_CID_DIAG 0xFF /* diagnostic */ - -#endif diff --git a/PDP11/pdp11_xq.c b/PDP11/pdp11_xq.c deleted file mode 100644 index 8b3e96a9..00000000 --- a/PDP11/pdp11_xq.c +++ /dev/null @@ -1,2240 +0,0 @@ -/* pdp11_xq.c: DEQNA/DELQA ethernet controller simulator - ------------------------------------------------------------------------------ - - Copyright (c) 2002-2003, David T. Hittner - - 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 - THE AUTHOR 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 the author shall not be - used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from the author. - - ------------------------------------------------------------------------------ - - 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: - Ethernet transceiver power flag CSR<12> is ON when attached. - External Loopback does not go out to the physical adapter, it is - 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 - - Certain advantages are derived from this emulation: - If the real ethernet controller is faster than 10Mbit/sec, the speed is - seen by the simulated cpu since there are no minimum response times. - - Known Bugs or Unsupported features, in priority order: - 1) PDP11 (modified) bootrom loader [done! 10-Apr-03] - 2) Second controller [done! 05-May-03] - 3) Cannot split inbound packet into multiple buffers [done! 05-Jun-03] - 4) PDP11 bootstrap - 5) MOP functionality not implemented - 6) Local packet processing not implemented - - Regression Tests used by the Author: - VAX: - 1. Console SHOW DEVICE - 2. VMS v7.2 boots/initializes/shows device - 3. VMS DECNET - SET HOST and COPY tests - 4. VMS MultiNet - SET HOST/TELNET and FTP tests - 5. VMS LAT - SET HOST/LAT tests - 6. VMS Cluster - SHOW CLUSTER, SHOW DEVICE, and cluster disk COPY tests - 7. Console boot into VMSCluster (>>>B XQAO) - PDP11: - 1. RT-11 v5.3 - FTPSB copy test - - ------------------------------------------------------------------------------ - - Modification history: - - 05-Jun-03 DTH Added receive packet splitting - 03-Jun-03 DTH Added SHOW XQ FILTERS - 02-Jun-03 DTH Added SET/SHOW XQ STATS (packet statistics), runt & giant processing - 28-May-03 DTH Modified message queue for dynamic size to shrink executable - 28-May-03 MP Fixed bug in xq_setmac - 06-May-03 DTH Changed 32-bit t_addr to uint32 for v3.0 - Removed SET ADDRESS functionality - 05-May-03 DTH Added second controller - 26-Mar-03 DTH Added PDP11 bootrom loader - Adjusted xq_ex and xq_dev to allow pdp11 to look at bootrom - Patched bootrom to allow "pass" of diagnostics on RSTS/E - 06-Mar-03 DTH Corrected interrupts on IE state transition (code by Tom Evans) - Added interrupt clear on soft reset (first noted by Bob Supnik) - Removed interrupt when setting XL or RL (multiple people) - 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 - 23-Oct-02 DTH Beta 5 released - 22-Oct-02 DTH Added all_multicast and promiscuous support - 21-Oct-02 DTH Added write buffer max size check (code by Jason Thorpe) - Corrected copyright again - Implemented NXM testing and recovery - 16-Oct-02 DTH Beta 4 released - 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 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] - Added xq_make_checksum - Added rejection of multicast addresses in SET XQ MAC - 08-Oct-02 DTH Beta 2 released; Integrated with 2.10-0p4 - Added variable vector (fixes PDP11) and copyrights - 03-Oct-02 DTH Beta version of xq/sim_ether released for SIMH 2.09-11 - 24-Sep-02 DTH Moved more code to Sim_Ether module, added SHOW ETH command - 23-Sep-02 DTH Added SET/SHOW MAC command - 22-Sep-02 DTH Multinet TCP/IP loaded, tests OK via SET HOST/TELNET - 20-Sep-02 DTH Cleaned up code fragments, fixed non-DECNET MAC use - 19-Sep-02 DTH DECNET finally stays up; successful SET HOST to another node - 15-Sep-02 DTH Added ethernet packet read/write - 13-Sep-02 DTH DECNET starts, but circuit keeps going up & down - 26-Aug-02 DTH DECNET loaded, returns device timeout - 22-Aug-02 DTH VMS 7.2 recognizes device as XQA0 - 18-Aug-02 DTH VAX sees device as XQA0; shows hardcoded MAC correctly - 15-Aug-02 DTH Started XQ simulation - - ------------------------------------------------------------------------------ -*/ - -/* compiler directives to help the Author keep the code clean :-) */ -#if defined (__BORLANDC__) -#pragma warn +8070 /* function should return value */ -/* #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__ */ - -#include -#include "pdp11_xq.h" -#include "pdp11_xq_bootrom.h" - -#define XQ_MAX_CONTROLLERS 2 /* maximum controllers allowed */ - -extern int32 int_req[IPL_HLVL]; -extern int32 tmr_poll, clk_tps; -extern FILE *sim_log; - -/* forward declarations */ -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); -t_stat xq_showmac (FILE* st, UNIT* uptr, int32 val, void* desc); -t_stat xq_setmac (UNIT* uptr, int32 val, char* cptr, void* desc); -t_stat xq_show_filters (FILE* st, UNIT* uptr, int32 val, void* desc); -t_stat xq_show_stats (FILE* st, UNIT* uptr, int32 val, void* desc); -t_stat xq_set_stats (UNIT* uptr, int32 val, char* cptr, void* desc); -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_showeth (FILE* st, UNIT* uptr, int32 val, void* desc); -t_stat xq_process_xbdl(CTLR* xq); -t_stat xq_dispatch_xbdl(CTLR* xq); -void xq_start_receiver(void); -void xq_sw_reset(CTLR* xq); -int32 xq_inta (void); -int32 xq_intb (void); -t_stat xq_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw); -t_stat xq_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw); -void xq_start_santmr(CTLR* xq); -void xq_cancel_santmr(CTLR* xq); -void xq_reset_santmr(CTLR* xq); -t_stat xq_boot_host(void); -void xq_start_idtmr(CTLR* xq); -t_stat xq_system_id(CTLR* xq, const ETH_MAC dst, uint16 receipt_id); -void xqa_read_callback(int status); -void xqb_read_callback(int status); -void xqa_write_callback(int status); -void xqb_write_callback(int status); - -struct xq_device xqa = { - xqa_read_callback, /* read callback routine */ - xqa_write_callback, /* write callback routine */ - {0x08, 0x00, 0x2B, 0xAA, 0xBB, 0xCC}, /* mac */ - XQ_T_DELQA, /* type */ - {0} /* sanity */ - }; - -struct xq_device xqb = { - xqb_read_callback, /* read callback routine */ - xqb_write_callback, /* write callback routine */ - {0x08, 0x00, 0x2B, 0xBB, 0xCC, 0xDD}, /* mac */ - XQ_T_DELQA, /* type */ - {0} /* sanity */ - }; - -/* SIMH device structures */ -DIB xqa_dib = { IOBA_XQ, IOLN_XQ, &xq_rd, &xq_wr, - 1, IVCL (XQ), 0, { &xq_inta } }; - -UNIT xqa_unit[] = { - { UDATA (&xq_svc, UNIT_ATTABLE + UNIT_DISABLE, 2047) }, /* receive timer */ - { UDATA (&xq_sansvc, UNIT_DIS, 0) }, /* sanity timer */ - { UDATA (&xq_idsvc, UNIT_DIS, 0) } /* system id timer */ -}; - -REG xqa_reg[] = { - { GRDATA ( SA0, xqa.addr[0], XQ_RDX, 16, 0), REG_RO}, - { GRDATA ( SA1, xqa.addr[1], XQ_RDX, 16, 0), REG_RO}, - { GRDATA ( SA2, xqa.addr[2], XQ_RDX, 16, 0), REG_RO}, - { GRDATA ( SA3, xqa.addr[3], XQ_RDX, 16, 0), REG_RO}, - { GRDATA ( SA4, xqa.addr[4], XQ_RDX, 16, 0), REG_RO}, - { GRDATA ( SA5, xqa.addr[5], XQ_RDX, 16, 0), REG_RO}, - { GRDATA ( RBDL, xqa.rbdl, XQ_RDX, 32, 0) }, - { GRDATA ( XBDL, xqa.xbdl, XQ_RDX, 32, 0) }, - { GRDATA ( VAR, xqa.var, XQ_RDX, 16, 0) }, - { GRDATA ( CSR, xqa.csr, XQ_RDX, 16, 0) }, - { GRDATA ( SETUP_PRM, xqa.setup.promiscuous, XQ_RDX, 32, 0), REG_HRO}, - { GRDATA ( SETUP_MLT, xqa.setup.multicast, XQ_RDX, 32, 0), REG_HRO}, - { GRDATA ( SETUP_L1, xqa.setup.l1, XQ_RDX, 32, 0), REG_HRO}, - { GRDATA ( SETUP_L2, xqa.setup.l2, XQ_RDX, 32, 0), REG_HRO}, - { GRDATA ( SETUP_L3, xqa.setup.l3, XQ_RDX, 32, 0), REG_HRO}, - { GRDATA ( SETUP_SAN, xqa.setup.sanity_timer, XQ_RDX, 32, 0), REG_HRO}, - { BRDATA ( SETUP_MACS, &xqa.setup.macs, XQ_RDX, 8, sizeof(xqa.setup.macs)), REG_HRO}, - { NULL }, -}; - -DIB xqb_dib = { IOBA_XQB, IOLN_XQB, &xq_rd, &xq_wr, - 1, IVCL (XQ), 0, { &xq_intb } }; - -UNIT xqb_unit[] = { - { UDATA (&xq_svc, UNIT_ATTABLE + UNIT_DISABLE, 2047) }, /* receive timer */ - { UDATA (&xq_sansvc, UNIT_DIS, 0) }, /* sanity timer */ - { UDATA (&xq_idsvc, UNIT_DIS, 0) } /* system id timer */ -}; - -REG xqb_reg[] = { - { GRDATA ( SA0, xqb.addr[0], XQ_RDX, 16, 0), REG_RO}, - { GRDATA ( SA1, xqb.addr[1], XQ_RDX, 16, 0), REG_RO}, - { GRDATA ( SA2, xqb.addr[2], XQ_RDX, 16, 0), REG_RO}, - { GRDATA ( SA3, xqb.addr[3], XQ_RDX, 16, 0), REG_RO}, - { GRDATA ( SA4, xqb.addr[4], XQ_RDX, 16, 0), REG_RO}, - { GRDATA ( SA5, xqb.addr[5], XQ_RDX, 16, 0), REG_RO}, - { GRDATA ( RBDL, xqb.rbdl, XQ_RDX, 32, 0) }, - { GRDATA ( XBDL, xqb.xbdl, XQ_RDX, 32, 0) }, - { GRDATA ( VAR, xqb.var, XQ_RDX, 16, 0) }, - { GRDATA ( CSR, xqb.csr, XQ_RDX, 16, 0) }, - { GRDATA ( SETUP_PRM, xqb.setup.promiscuous, XQ_RDX, 32, 0), REG_HRO}, - { GRDATA ( SETUP_MLT, xqb.setup.multicast, XQ_RDX, 32, 0), REG_HRO}, - { GRDATA ( SETUP_L1, xqb.setup.l1, XQ_RDX, 32, 0), REG_HRO}, - { GRDATA ( SETUP_L2, xqb.setup.l2, XQ_RDX, 32, 0), REG_HRO}, - { GRDATA ( SETUP_L3, xqb.setup.l3, XQ_RDX, 32, 0), REG_HRO}, - { GRDATA ( SETUP_SAN, xqb.setup.sanity_timer, XQ_RDX, 32, 0), REG_HRO}, - { BRDATA ( SETUP_MACS, &xqb.setup.macs, XQ_RDX, 8, sizeof(xqb.setup.macs)), REG_HRO}, - { NULL }, -}; - -MTAB xq_mod[] = { - { MTAB_XTD|MTAB_VDV, 004, "ADDRESS", NULL, - NULL, &show_addr, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "VECTOR", NULL, - NULL, &show_vec, NULL }, - { MTAB_XTD | MTAB_VDV, 0, "MAC", "MAC", - &xq_setmac, &xq_showmac, NULL }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "ETH", NULL, - NULL, &xq_showeth, NULL }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "FILTERS", NULL, - NULL, &xq_show_filters, NULL }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "STATS", "STATS", - &xq_set_stats, &xq_show_stats, NULL }, - { MTAB_XTD | MTAB_VDV, 0, "TYPE", "TYPE", - &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", xqa_unit, xqa_reg, xq_mod, - 3, XQ_RDX, 11, 1, XQ_RDX, 16, - &xq_ex, &xq_dep, &xq_reset, - NULL, &xq_attach, &xq_detach, - &xqa_dib, DEV_DISABLE | DEV_QBUS -}; - -DEVICE xqb_dev = { - "XQB", xqb_unit, xqb_reg, xq_mod, - 3, XQ_RDX, 11, 1, XQ_RDX, 16, - &xq_ex, &xq_dep, &xq_reset, - NULL, &xq_attach, &xq_detach, - &xqb_dib, DEV_DISABLE | DEV_DIS | DEV_QBUS -}; - -CTLR xq_ctrl[] = { - {&xq_dev, xqa_unit, &xqa_dib, &xqa}, /* XQA controller */ - {&xqb_dev, xqb_unit, &xqb_dib, &xqb} /* XQB controller */ -}; - -#ifdef XQ_DEBUG - -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" -}; - -/* internal debugging routines */ -void xq_debug_setup(CTLR* xq); -void xq_dump_csr(CTLR* xq); -void xq_dump_var(CTLR* xq); -void xq_csr_changes(CTLR* xq, uint16 data); -void xq_var_changes(CTLR* xq, uint16 data); - -/* sanity timer debugging */ -#include -struct timeb start, finish; - -#endif /* XQ_DEBUG */ - -/* -================================================================================ - Queue Management -================================================================================ -*/ - -t_stat xq_init_queue(CTLR* xq, struct xq_msg_que* que) -{ - /* create dynamic queue if it does not exist */ - if (!que->item) { - size_t size = sizeof(struct xq_msg_itm) * XQ_QUE_MAX; - que->item = malloc(size); - if (que->item) { - /* init dynamic memory */ - memset(que->item, 0, size); - } else { - /* failed to allocate memory */ - printf("%s: failed to allocate dynamic queue\n", xq->dev->name); - if (sim_log) fprintf(sim_log, "%s: failed to allocate dynamic queue\n", xq->dev->name); - return SCPE_MEM; - }; - }; - return SCPE_OK; -} - -void xq_clear_queue(struct xq_msg_que* que) -{ - int i; - struct xq_msg_itm* item; - - for (i = 0; i < XQ_QUE_MAX; i++) { - item = &que->item[i]; - item->type = 0; - item->packet.len = 0; - item->packet.used = 0; - item->status = 0; - }; - que->count = que->head = que->tail = que->loss = 0; -} - -void xq_remove_queue(struct xq_msg_que* que) -{ - struct xq_msg_itm* item = &que->item[que->head]; - - if (que->count) { - item->type = 0; - item->packet.len = 0; - item->packet.used = 0; - item->status = 0; - if (++que->head == XQ_QUE_MAX) - que->head = 0; - que->count--; - } -} - -void xq_insert_queue(struct xq_msg_que* que, int32 type, ETH_PACK* packet, int32 status) -{ - struct xq_msg_itm* item; - - /* if queue empty, set pointers to beginning */ - if (!que->count) { - que->head = 0; - que->tail = -1; - } - - /* find new tail of the circular queue */ - if (++que->tail == XQ_QUE_MAX) - que->tail = 0; - if (++que->count > XQ_QUE_MAX) { - que->count = XQ_QUE_MAX; - /* lose oldest packet */ - if (++que->head == XQ_QUE_MAX) - que->head = 0; - que->loss++; -#ifdef XQ_DEBUG - fprintf(stderr, "Packet Lost\n"); -#endif - } - if (que->count > que->high) - que->high = que->count; - - /* set information in (new) tail item */ - item = &que->item[que->tail]; - item->type = type; - item->packet.len = packet->len; - item->packet.used = 0; - memcpy(item->packet.msg, packet->msg, packet->len); - item->status = status; -} - -/* -================================================================================ -*/ - -/*============================================================================*/ - -/* Multicontroller support */ - -CTLR* xq_unit2ctlr(UNIT* uptr) -{ - unsigned int i,j; - for (i=0; inumunits; j++) - if (&xq_ctrl[i].unit[j] == uptr) return &xq_ctrl[i]; - /* not found */ - return 0; -} - -CTLR* xq_dev2ctlr(DEVICE* dptr) -{ - int i; - for (i=0; i= xq_ctrl[i].dib->ba) && (PA < (xq_ctrl[i].dib->ba + xq_ctrl[i].dib->lnt))) - return &xq_ctrl[i]; - /* not found */ - return 0; -} - -/*============================================================================*/ - -/* stop simh from reading non-existant unit data stream */ -t_stat xq_ex (t_value* vptr, t_addr addr, UNIT* uptr, int32 sw) -{ - /* on PDP-11, allow EX command to look at bootrom */ -#ifdef VM_PDP11 - if (addr <= sizeof(xq_bootrom)/2) - *vptr = xq_bootrom[addr]; - else - *vptr = 0; - return SCPE_OK; -#else - return SCPE_NOFNC; -#endif -} - -/* stop simh from writing non-existant unit data stream */ -t_stat xq_dep (t_value val, t_addr addr, UNIT* uptr, int32 sw) -{ - return SCPE_NOFNC; -} - -t_stat xq_showmac (FILE* st, UNIT* uptr, int32 val, void* desc) -{ - CTLR* xq = xq_unit2ctlr(uptr); - char buffer[20]; - - eth_mac_fmt((ETH_MAC*)xq->var->mac, buffer); - fprintf(st, "MAC=%s", buffer); - return SCPE_OK; -} - -void xq_make_checksum(CTLR* xq) -{ - /* checksum calculation routine detailed in vaxboot.zip/xqbtdrivr.mar */ - uint32 checksum = 0; - const uint32 wmask = 0xFFFF; - int i; - - for (i = 0; i < sizeof(ETH_MAC); i += 2) { - checksum <<= 1; - if (checksum > wmask) - checksum -= wmask; - checksum += (xq->var->mac[i] << 8) | xq->var->mac[i+1]; - if (checksum > wmask) - checksum -= wmask; - } - if (checksum == wmask) - checksum = 0; - - /* set checksum bytes */ - xq->var->mac_checksum[0] = checksum & 0xFF; - xq->var->mac_checksum[1] = checksum >> 8; -} - -t_stat xq_setmac (UNIT* uptr, int32 val, char* cptr, void* desc) -{ - int i, j, len; - short int num; - ETH_MAC newmac = {0,0,0,0,0,0}; - const ETH_MAC zeros = {0,0,0,0,0,0}; - const ETH_MAC ones = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; - CTLR* xq = xq_unit2ctlr(uptr); - - if (!cptr) return SCPE_IERR; - /* parse new mac and validate */ - len = strlen(cptr); - if (len != 17) return SCPE_ARG; - /* make sure byte separators are OK */ - for (i=2; ivar->mac, newmac, sizeof(ETH_MAC)); - /* calculate MAC checksum */ - xq_make_checksum(xq); - return SCPE_OK; -} - -t_stat xq_showeth (FILE* st, UNIT* uptr, int32 val, void* desc) -{ -#define XQ_MAX_LIST 10 - int i; - ETH_LIST list[XQ_MAX_LIST]; - int number = eth_devices(XQ_MAX_LIST, list); - - fprintf(st, "ETH devices:\n"); - if (number) - for (i=0; ivar->stats; - int elements = sizeof(struct xq_stats)/sizeof(int); - int i; - for (i=0; ivar->stats, 0, sizeof(struct xq_stats)); -#endif - return SCPE_OK; -} - -t_stat xq_show_stats (FILE* st, UNIT* uptr, int32 val, void* desc) -{ - char* fmt = " %-15s%d\n"; - CTLR* xq = xq_unit2ctlr(uptr); - - fprintf(st, "Ethernet statistics:\n"); - fprintf(st, fmt, "Recv:", xq->var->stats.recv); - fprintf(st, fmt, "Filtered:", xq->var->stats.filter); - fprintf(st, fmt, "Xmit:", xq->var->stats.xmit); - fprintf(st, fmt, "Xmit Fail:", xq->var->stats.fail); - fprintf(st, fmt, "Runts:", xq->var->stats.runt); - fprintf(st, fmt, "Oversize:", xq->var->stats.giant); - fprintf(st, fmt, "Setup:", xq->var->stats.setup); - fprintf(st, fmt, "Loopback:", xq->var->stats.loop); - fprintf(st, fmt, "ReadQ high:", xq->var->ReadQ.high); - return SCPE_OK; -} - -t_stat xq_show_filters (FILE* st, UNIT* uptr, int32 val, void* desc) -{ - CTLR* xq = xq_unit2ctlr(uptr); - char buffer[20]; - int i; - - fprintf(st, "Filters:\n"); - for (i=0; ivar->setup.macs[i], buffer); - fprintf(st, " [%2d]: %s\n", i, buffer); - }; - return SCPE_OK; -} - -t_stat xq_show_type (FILE* st, UNIT* uptr, int32 val, void* desc) -{ - CTLR* xq = xq_unit2ctlr(uptr); - fprintf(st, "type="); - switch (xq->var->type) { - case XQ_T_DEQNA: fprintf(st, "DEQNA"); break; - case XQ_T_DELQA: fprintf(st, "DELQA"); break; - } - return SCPE_OK; -} - -t_stat xq_set_type (UNIT* uptr, int32 val, char* cptr, void* desc) -{ - CTLR* xq = xq_unit2ctlr(uptr); - if (!cptr) return SCPE_IERR; - - /* this assumes that the parameter has already been upcased */ - if (!strcmp(cptr, "DEQNA")) xq->var->type = XQ_T_DEQNA; - else if (!strcmp(cptr, "DELQA")) xq->var->type = XQ_T_DELQA; - else return SCPE_ARG; - - return SCPE_OK; -} - -t_stat xq_show_sanity (FILE* st, UNIT* uptr, int32 val, void* desc) -{ - CTLR* xq = xq_unit2ctlr(uptr); - - fprintf(st, "sanity="); - switch (xq->var->sanity.enabled) { - case 0: fprintf(st, "OFF"); break; - case 1: fprintf(st, "ON"); break; - } - return SCPE_OK; -} - -t_stat xq_set_sanity (UNIT* uptr, int32 val, char* cptr, void* desc) -{ - CTLR* xq = xq_unit2ctlr(uptr); - if (!cptr) return SCPE_IERR; - - /* this assumes that the parameter has already been upcased */ - if (!strcmp(cptr, "ON")) xq->var->sanity.enabled = 1; - else if (!strcmp(cptr, "OFF")) xq->var->sanity.enabled = 0; - else return SCPE_ARG; - - return SCPE_OK; -} - -t_stat xq_nxm_error(CTLR* xq) -{ -#ifdef XQ_DEBUG - fprintf(stderr,"%s: Non Existent Memory Error\n", xq->dev->name); -#endif - /* set NXM and associated bits in CSR */ - xq->var->csr |= (XQ_CSR_NI | XQ_CSR_XI | XQ_CSR_XL | XQ_CSR_RL); - - /* interrupt if required */ - if (xq->var->csr & XQ_CSR_IE) - SET_INT(XQ); - - return SCPE_OK; -} - -/* -** write callback -*/ -void xq_write_callback (CTLR* xq, int status) -{ - t_stat rstatus; - int32 wstatus; - const uint16 TDR = 100 + xq->var->write_buffer.len * 8; /* arbitrary value */ - uint16 write_success[2] = {0}; - uint16 write_failure[2] = {XQ_DSC_C}; - write_success[1] = TDR & 0x03FF; /* Does TDR get set on successful packets ?? */ - write_failure[1] = TDR & 0x03FF; /* TSW2<09:00> */ - - xq->var->stats.xmit += 1; - /* update write status words */ - if (status == 0) { /* success */ - wstatus = Map_WriteW(xq->var->xbdl_ba + 8, 4, write_success, NOMAP); - } else { /* failure */ -#ifdef XQ_DEBUG - fprintf(stderr, "%s: Packet Write Error\n", xq->dev->name); -#endif - xq->var->stats.fail += 1; - wstatus = Map_WriteW(xq->var->xbdl_ba + 8, 4, write_failure, NOMAP); - } - if (wstatus) { - xq_nxm_error(xq); - return; - } - - /* update csr */ - xq->var->csr |= XQ_CSR_XI; - if (xq->var->csr & XQ_CSR_IE) - SET_INT(XQ); - - /* reset sanity timer */ - xq_reset_santmr(xq); - - /* clear write buffer */ - xq->var->write_buffer.len = 0; - - /* next descriptor (implicit) */ - xq->var->xbdl_ba += 12; - - /* finish processing xbdl */ - rstatus = xq_process_xbdl(xq); -} - -void xqa_write_callback (int status) -{ - xq_write_callback(&xq_ctrl[0], status); -} - -void xqb_write_callback (int status) -{ - xq_write_callback(&xq_ctrl[1], status); -} - -/* read registers: */ -t_stat xq_rd(int32* data, int32 PA, int32 access) -{ - CTLR* xq = xq_pa2ctlr(PA); - int index = (PA >> 1) & 07; /* word index */ - -#ifdef XQ_DEBUG - if (index != 7) -#if defined(VM_VAX) - fprintf (stderr,"%s: %s %08X %08X read: %X\n", - xq->dev->name, xq_recv_regnames[index], fault_PC, PSL, *data); -#else - fprintf (stderr,"%s: %s read: %X\n", - xq->dev->name, xq_recv_regnames[index], *data); -#endif /* VM_VAX */ -#endif - - switch (index) { - case 0: - case 1: - /* return checksum in external loopback mode */ - if (xq->var->csr & XQ_CSR_EL) - *data = 0xFF00 | xq->var->mac_checksum[index]; - else - *data = 0xFF00 | xq->var->mac[index]; - break; - case 2: - case 3: - case 4: - case 5: - *data = 0xFF00 | xq->var->mac[index]; - break; - case 6: -#if 0 -#ifdef XQ_DEBUG - xq_dump_var(xq); -#endif -#endif - *data = xq->var->var; - break; - case 7: -#ifdef XQ_DEBUG - xq_dump_csr(xq); -#endif - *data = xq->var->csr; - break; - } - return SCPE_OK; -} - - -/* dispatch ethernet read request - procedure documented in sec. 3.2.2 */ - -t_stat xq_process_rbdl(CTLR* xq) -{ - int32 rstatus, wstatus; - uint16 b_length, w_length, rbl; - uint32 address; - struct xq_msg_itm* item; - char* rbuf; - -#ifdef XQ_DEBUG - fprintf(stderr,"%s: CSR - Processing read\n", xq->dev->name); -#endif - /* process buffer descriptors */ - while(1) { - - /* get receive bdl from memory */ - xq->var->rbdl_buf[0] = 0xFFFF; - wstatus = Map_WriteW(xq->var->rbdl_ba, 2, &xq->var->rbdl_buf[0], NOMAP); - rstatus = Map_ReadW (xq->var->rbdl_ba + 2, 6, &xq->var->rbdl_buf[1], NOMAP); - if (rstatus || wstatus) return xq_nxm_error(xq); - - /* invalid buffer? */ - if (~xq->var->rbdl_buf[1] & XQ_DSC_V) { - xq->var->csr |= XQ_CSR_RL; - return SCPE_OK; - } - - /* explicit chain buffer? */ - if (xq->var->rbdl_buf[1] & XQ_DSC_C) { - xq->var->rbdl_ba = ((xq->var->rbdl_buf[1] & 0x3F) << 16) | xq->var->rbdl_buf[2]; - continue; - } - - /* stop processing if nothing in read queue */ - if (!xq->var->ReadQ.count) break; - - /* get status words */ - rstatus = Map_ReadW(xq->var->rbdl_ba + 8, 4, &xq->var->rbdl_buf[4], NOMAP); - if (rstatus) return xq_nxm_error(xq); - - /* get host memory address */ - address = ((xq->var->rbdl_buf[1] & 0x3F) << 16) | xq->var->rbdl_buf[2]; - - /* decode buffer length - two's complement (in words) */ - w_length = ~xq->var->rbdl_buf[3] + 1; - b_length = w_length * 2; - if (xq->var->rbdl_buf[1] & XQ_DSC_H) b_length -= 1; - if (xq->var->rbdl_buf[1] & XQ_DSC_L) b_length -= 1; - - item = &xq->var->ReadQ.item[xq->var->ReadQ.head]; - rbl = item->packet.len; - rbuf = item->packet.msg; - - /* see if packet must be size-adjusted or is splitting */ - if (item->packet.used) { - int used = item->packet.used; - rbl -= used; - rbuf = &item->packet.msg[used]; - } else { - /* adjust runt packets */ - if (rbl < ETH_MIN_PACKET) { - xq->var->stats.runt += 1; -#ifdef XQ_DEBUG - printf("%s: Runt detected, size = %d\n", xq->dev->name, rbl); -#endif - /* pad runts with zeros up to minimum size - this allows "legal" (size - 60) - processing of those weird short ARP packets that seem to occur occasionally */ - memset(&item->packet.msg[rbl], 0, ETH_MIN_PACKET); - rbl = ETH_MIN_PACKET; - }; - - /* adjust oversized packets */ - if (rbl > ETH_MAX_PACKET) { - xq->var->stats.giant += 1; -#ifdef XQ_DEBUG - printf("%s: Giant detected, size = %d\n", xq->dev->name, rbl); -#endif - /* trim giants down to maximum size - no documentation on how to handle the data loss */ - item->packet.len = ETH_MAX_PACKET; - rbl = ETH_MAX_PACKET; - }; - }; - - /* make sure entire packet fits in buffer - if not, will need to split into multiple buffers */ - /* assert(rbl <= b_length); */ /* abort if packet won't fit into single buffer */ - if (rbl > b_length) - rbl = b_length; - item->packet.used += rbl; - - /* send data to host */ - wstatus = Map_WriteB(address, rbl, rbuf, NOMAP); - if (wstatus) return xq_nxm_error(xq); - - /* set receive size into RBL - RBL<10:8> maps into Status1<10:8>, - RBL<7:0> maps into Status2<7:0>, and Status2<15:8> (copy) */ - - xq->var->rbdl_buf[4] = 0; - switch (item->type) { - case 0: /* setup packet */ - xq->var->stats.setup += 1; - xq->var->rbdl_buf[4] = 0x2700; /* set esetup and RBL 10:8 */ - break; - case 1: /* loopback packet */ - xq->var->stats.loop += 1; - xq->var->rbdl_buf[4] = 0x2000; /* loopback flag */ - xq->var->rbdl_buf[4] |= (rbl & 0x0700); /* high bits of rbl */ - break; - case 2: /* normal packet */ - rbl -= 60; /* keeps max packet size in 11 bits */ - xq->var->rbdl_buf[4] = (rbl & 0x0700); /* high bits of rbl */ - break; - } - if (item->packet.used < item->packet.len) - xq->var->rbdl_buf[4] |= 0xC000; /* not last segment */ - xq->var->rbdl_buf[5] = ((rbl & 0x00FF) << 8) | (rbl & 0x00FF); - if (xq->var->ReadQ.loss) { -#ifdef XQ_DEBUG - fprintf(stderr, "%s: ReadQ overflow\n", xq->dev->name); -#endif - xq->var->rbdl_buf[4] |= 0x0001; /* set overflow bit */ - xq->var->ReadQ.loss = 0; /* reset loss counter */ - } - - /* update read status words*/ - wstatus = Map_WriteW(xq->var->rbdl_ba + 8, 4, &xq->var->rbdl_buf[4], NOMAP); - if (wstatus) return xq_nxm_error(xq); - - /* remove packet from queue */ - if (item->packet.used >= item->packet.len) - xq_remove_queue(&xq->var->ReadQ); - - /* reset sanity timer */ - xq_reset_santmr(xq); - - /* mark transmission complete */ - xq->var->csr |= XQ_CSR_RI; - if (xq->var->csr & XQ_CSR_IE) - SET_INT(XQ); - - /* set to next bdl (implicit chain) */ - xq->var->rbdl_ba += 12; - - } /* while */ - - return SCPE_OK; -} - -t_stat xq_process_mop(CTLR* xq) -{ - uint32 address; - uint16 size; - int32 wstatus; - struct xq_meb* meb = (struct xq_meb*) &xq->var->write_buffer.msg[0200]; - const struct xq_meb* limit = (struct xq_meb*) &xq->var->write_buffer.msg[0400]; - -#ifdef XQ_DEBUG - fprintf(stderr, "%s: Processing MOP data\n", xq->dev->name); -#endif - if (xq->var->type == XQ_T_DEQNA) /* DEQNA's don't MOP */ - return SCPE_NOFNC; - - while ((meb->type != 0) && (meb < limit)) { - address = (meb->add_hi << 16) || (meb->add_mi << 8) || meb->add_lo; - size = (meb->siz_hi << 8) || meb->siz_lo; - - /* MOP stuff here - NOT YET FULLY IMPLEMENTED */ - -#ifdef XQ_DEBUG - printf("%s: Processing MEB type: %d\n", xq->dev->name, meb->type); -#endif - switch (meb->type) { - case 0: /* MOP Termination */ - break; - case 1: /* MOP Read Ethernet Address */ - wstatus = Map_WriteB(address, sizeof(ETH_MAC), (uint8*) &xq->var->setup.macs[0], NOMAP); - if (wstatus) return xq_nxm_error(xq); - break; - case 2: /* MOP Reset System ID */ - break; - case 3: /* MOP Read Last MOP Boot */ - break; - case 4: /* MOP Read Boot Password */ - break; - case 5: /* MOP Write Boot Password */ - break; - case 6: /* MOP Read System ID */ - break; - case 7: /* MOP Write System ID */ - break; - case 8: /* MOP Read Counters */ - break; - case 9: /* Mop Read/Clear Counters */ - break; - } /* switch */ - - /* process next meb */ - meb += sizeof(struct xq_meb); - - } /* while */ - return SCPE_OK; -} - -t_stat xq_process_setup(CTLR* xq) -{ - int i,j; - int count = 0; - float secs; - t_stat status; - ETH_MAC zeros = {0, 0, 0, 0, 0, 0}; - ETH_MAC filters[XQ_FILTER_MAX + 1]; - - /* extract filter addresses from setup packet */ - memset(xq->var->setup.macs, '\0', sizeof(xq->var->setup.macs)); - for (i = 0; i < 7; i++) - for (j = 0; j < 6; j++) { - xq->var->setup.macs[i] [j] = xq->var->write_buffer.msg[(i + 01) + (j * 8)]; - if (xq->var->write_buffer.len > 112) - xq->var->setup.macs[i+7][j] = xq->var->write_buffer.msg[(i + 0101) + (j * 8)]; - } - - /* process high byte count */ - if (xq->var->write_buffer.len > 128) { - uint16 len = xq->var->write_buffer.len; - uint16 led, san; - - if (len & XQ_SETUP_MC) - xq->var->setup.multicast = 1; - if (len & XQ_SETUP_PM) - xq->var->setup.promiscuous = 1; - if (led = (len & XQ_SETUP_LD) >> 2) { - switch (led) { - case 1: xq->var->setup.l1 = 0; break; - case 2: xq->var->setup.l2 = 0; break; - case 3: xq->var->setup.l3 = 0; break; - } /* switch */ - } /* if led */ - /* set sanity timer timeout */ - san = (len & XQ_SETUP_ST) >> 4; - switch(san) { - case 0: secs = 0.25; break; /* 1/4 second */ - case 1: secs = 1; break; /* 1 second */ - case 2: secs = 4; break; /* 4 seconds */ - case 3: secs = 16; break; /* 16 seconds */ - case 4: secs = 1 * 60; break; /* 1 minute */ - case 5: secs = 4 * 60; break; /* 4 minutes */ - case 6: secs = 16 * 60; break; /* 16 minutes */ - case 7: secs = 64 * 60; break; /* 64 minutes */ - } - xq->var->sanity.quarter_secs = (int) (secs * 4); - - /* if sanity timer enabled, start sanity timer */ - if (xq->var->csr & XQ_CSR_SE || xq->var->sanity.enabled) - xq_start_santmr(xq); - else - xq_cancel_santmr(xq); - } - - /* set ethernet filter */ - /* memcpy (filters[count++], xq->mac, sizeof(ETH_MAC)); */ - for (i = 0; i < XQ_FILTER_MAX; i++) - if (memcmp(zeros, &xq->var->setup.macs[i], sizeof(ETH_MAC))) - memcpy (filters[count++], xq->var->setup.macs[i], sizeof(ETH_MAC)); - status = eth_filter (xq->var->etherface, count, filters, xq->var->setup.multicast, xq->var->setup.promiscuous); - - /* process MOP information */ - if (xq->var->write_buffer.msg[0]) - status = xq_process_mop(xq); - - /* mark setup block valid */ - xq->var->setup.valid = 1; - -#ifdef XQ_DEBUG - xq_debug_setup(xq); -#endif - return SCPE_OK; -} - -/* - Dispatch Write Operation - - The DELQA manual does not explicitly state whether or not multiple packets - can be written in one transmit operation, so a maximum of 1 packet is assumed. - -*/ -t_stat xq_process_xbdl(CTLR* xq) -{ - 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; - int32 rstatus, wstatus; - uint32 address; - t_stat status; - -#ifdef XQ_DEBUG - fprintf(stderr,"%s: xq_process_xbdl - Processing write\n", xq->dev->name); -#endif - /* clear write buffer */ - xq->var->write_buffer.len = 0; - - /* process buffer descriptors until not valid */ - while (1) { - - /* Get transmit bdl from memory */ - rstatus = Map_ReadW (xq->var->xbdl_ba, 12, &xq->var->xbdl_buf[0], NOMAP); - xq->var->xbdl_buf[0] = 0xFFFF; - wstatus = Map_WriteW(xq->var->xbdl_ba, 2, &xq->var->xbdl_buf[0], NOMAP); - if (rstatus || wstatus) return xq_nxm_error(xq); - - /* invalid buffer? */ - if (~xq->var->xbdl_buf[1] & XQ_DSC_V) { - xq->var->csr |= XQ_CSR_XL; -#ifdef XQ_DEBUG - fprintf(stderr,"%s: xq_process_xbdl - List Empty - Done Processing write\n", xq->dev->name); -#endif - return SCPE_OK; - } - -#ifdef XQ_DEBUG - fprintf(stderr,"%s: xq_process_xbdl: Buffer Descriptor Information: %04X %04X %04X %04X %04X \n", - xq->dev->name, xq->var->xbdl_buf[1], xq->var->xbdl_buf[2], - xq->var->xbdl_buf[3], xq->var->xbdl_buf[4], xq->var->xbdl_buf[5]); -#endif - /* compute host memory address */ - address = ((xq->var->xbdl_buf[1] & 0x3F) << 16) | xq->var->xbdl_buf[2]; - - /* decode buffer length - two's complement (in words) */ - w_length = ~xq->var->xbdl_buf[3] + 1; - b_length = w_length * 2; - if (xq->var->xbdl_buf[1] & XQ_DSC_H) b_length -= 1; - if (xq->var->xbdl_buf[1] & XQ_DSC_L) b_length -= 1; - - /* explicit chain buffer? */ - if (xq->var->xbdl_buf[1] & XQ_DSC_C) { - xq->var->xbdl_ba = address; -#ifdef XQ_DEBUG - fprintf(stderr,"%s: xq_process_xbdl: Chained Buffer Encountered: %d\n", xq->dev->name, b_length); -#endif - continue; - } - - /* add to transmit buffer, making sure it's not too big */ - if ((xq->var->write_buffer.len + b_length) > sizeof(xq->var->write_buffer.msg)) - b_length = sizeof(xq->var->write_buffer.msg) - xq->var->write_buffer.len; - rstatus = Map_ReadB(address, b_length, &xq->var->write_buffer.msg[xq->var->write_buffer.len], NOMAP); - if (rstatus) return xq_nxm_error(xq); - xq->var->write_buffer.len += b_length; - - /* end of message? */ - if (xq->var->xbdl_buf[1] & XQ_DSC_E) { - if (((~xq->var->csr & XQ_CSR_RE) && ((~xq->var->csr & XQ_CSR_IL) || (xq->var->csr & XQ_CSR_EL))) || /* loopback */ - (xq->var->xbdl_buf[1] & XQ_DSC_S)) { /* or setup packet (forces loopback regardless of state) */ - if (xq->var->xbdl_buf[1] & XQ_DSC_S) { /* setup packet */ - status = xq_process_setup(xq); - - /* put packet in read buffer */ - xq_insert_queue (&xq->var->ReadQ, 0, &xq->var->write_buffer, status); - } else { /* loopback */ - /* put packet in read buffer */ - xq_insert_queue (&xq->var->ReadQ, 1, &xq->var->write_buffer, 0); - } - - /* update write status */ - wstatus = Map_WriteW(xq->var->xbdl_ba + 8, 4, (uint16*) write_success, NOMAP); - if (wstatus) return xq_nxm_error(xq); - - /* clear write buffer */ - xq->var->write_buffer.len = 0; - - /* reset sanity timer */ - xq_reset_santmr(xq); - - /* mark transmission complete */ - xq->var->csr |= XQ_CSR_XI; - if (xq->var->csr & XQ_CSR_IE) - SET_INT(XQ); - - /* now trigger "read" of setup or loopback packet */ - if (~xq->var->csr & XQ_CSR_RL) - status = xq_process_rbdl(xq); - - } else { /* not loopback */ - - status = eth_write(xq->var->etherface, &xq->var->write_buffer, xq->var->wcallback); - if (status != SCPE_OK) /* not implemented or unattached */ - xq_write_callback(xq, 1); /* fake failure */ - else - xq_svc(&xq->unit[0]); /* service any received data */ -#ifdef XQ_DEBUG - fprintf(stderr,"%s: xq_process_xbdl: Completed Processing write\n", xq->dev->name); -#endif - return SCPE_OK; - - } /* loopback/non-loopback */ - } else { /* not at end-of-message */ - -#ifdef XQ_DEBUG - fprintf(stderr,"%s: xq_process_xbdl: Processing Implicit Chained Buffer Segment\n", xq->dev->name); -#endif - /* update bdl status words */ - wstatus = Map_WriteW(xq->var->xbdl_ba + 8, 4, (uint16*) implicit_chain_status, NOMAP); - if(wstatus) return xq_nxm_error(xq); - } - - /* set to next bdl (implicit chain) */ - xq->var->xbdl_ba += 12; - - } /* while */ -} - -t_stat xq_dispatch_rbdl(CTLR* xq) -{ - int i; - int32 rstatus, wstatus; - t_stat status; - -#ifdef XQ_DEBUG - fprintf(stderr,"%s: CSR - Dispatching read\n", xq->dev->name); -#endif - - /* mark receive bdl valid */ - xq->var->csr &= ~XQ_CSR_RL; - - /* init receive bdl buffer */ - for (i=0; i<6; i++) - xq->var->rbdl_buf[i] = 0; - - /* get address of first receive buffer */ - xq->var->rbdl_ba = ((xq->var->rbdl[1] & 0x3F) << 16) | (xq->var->rbdl[0] & ~01); - - /* get first receive buffer */ - xq->var->rbdl_buf[0] = 0xFFFF; - wstatus = Map_WriteW(xq->var->rbdl_ba, 2, &xq->var->rbdl_buf[0], NOMAP); - rstatus = Map_ReadW (xq->var->rbdl_ba + 2, 6, &xq->var->rbdl_buf[1], NOMAP); - if (rstatus || wstatus) return xq_nxm_error(xq); - - /* is buffer valid? */ - if (~xq->var->rbdl_buf[1] & XQ_DSC_V) { - xq->var->csr |= XQ_CSR_RL; - return SCPE_OK; - } - - /* process any waiting packets in receive queue */ - if (xq->var->ReadQ.count) - status = xq_process_rbdl(xq); - - return SCPE_OK; -} - -t_stat xq_dispatch_xbdl(CTLR* xq) -{ - int i; - t_stat status; -#ifdef XQ_DEBUG - fprintf(stderr,"%s: CSR - Dispatching write\n", xq->dev->name); -#endif - /* mark transmit bdl valid */ - xq->var->csr &= ~XQ_CSR_XL; - - /* initialize transmit bdl buffers */ - for (i=0; i<6; i++) - xq->var->xbdl_buf[i] = 0; - - /* clear transmit buffer */ - xq->var->write_buffer.len = 0; - - /* get base address of first transmit descriptor */ - xq->var->xbdl_ba = ((xq->var->xbdl[1] & 0x3F) << 16) | (xq->var->xbdl[0] & ~01); - - /* process xbdl */ - status = xq_process_xbdl(xq); - - return status; -} - -t_stat xq_process_loopback(CTLR* xq, 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->var->setup.valid ? xq->var->setup.macs[0] : xq->var->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->var->etherface, &reply, NULL); - - return status; -} - -t_stat xq_process_remote_console (CTLR* xq, 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 (xq, 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 (CTLR* xq, 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->var->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(xq, pack); - break; - case 0x0260: /* MOP remote console */ - return xq_process_remote_console(xq, pack); - break; - } - return SCPE_NOFNC; -} - -void xq_read_callback(CTLR* xq, int status) -{ - xq->var->stats.recv += 1; - if (xq->var->csr & XQ_CSR_RE) { /* receiver enabled */ - - /* process any packets locally that can be */ - t_stat status = xq_process_local (xq, &xq->var->read_buffer); - - /* add packet to read queue */ - if (status != SCPE_OK) - xq_insert_queue(&xq->var->ReadQ, 2, &xq->var->read_buffer, status); - } -#ifdef XQ_DEBUG - else - fprintf(stderr, "%s: packet received with receiver disabled\n", xq->dev->name); -#endif -} - -void xqa_read_callback(int status) -{ - xq_read_callback(&xq_ctrl[0], status); -} - -void xqb_read_callback(int status) -{ - xq_read_callback(&xq_ctrl[1], status); -} - -void xq_sw_reset(CTLR* xq) -{ - int i; - - /* cancel all timers (ethernet, sanity, system_id) */ - for (i=0; i<3; i++) - sim_cancel(&xq->unit[i]); - - /* reset csr bits */ - xq->var->csr = XQ_CSR_XL | XQ_CSR_RL; - - if (xq->var->etherface) - xq->var->csr |= XQ_CSR_OK; - - /* clear CPU interrupts */ - CLR_INT(XQ); - - /* flush read queue */ - xq_clear_queue(&xq->var->ReadQ); - - /* clear setup info */ - memset (&xq->var->setup, 0, sizeof(xq->var->setup)); -} - -/* write registers: */ - -t_stat xq_wr_var(CTLR* xq, int32 data) -{ - -#ifdef XQ_DEBUG - xq_var_changes(xq, data); -#endif - - switch (xq->var->type) { - case XQ_T_DEQNA: - xq->var->var = (data & XQ_VEC_IV); - break; - case XQ_T_DELQA: - xq->var->var = (xq->var->var & XQ_VEC_RO) | (data & XQ_VEC_RW); - - /* if switching to DEQNA-LOCK mode clear VAR<14:10> */ - if (~xq->var->var & XQ_VEC_MS) - xq->var->var &= ~(XQ_VEC_OS | XQ_VEC_RS | XQ_VEC_ST); - break; - } - - /* set vector of SIMH device */ - if (data & XQ_VEC_IV) - xq->dib->vec = (data & XQ_VEC_IV) + VEC_Q; - else - xq->dib->vec = 0; - - return SCPE_OK; -} - -#ifdef VM_PDP11 -t_stat xq_process_bootrom (CTLR* xq) -{ - /* - NOTE: BOOT ROMs are a PDP-11ism, since they contain PDP-11 binary code. - the host is responsible for creating two *2KB* receive buffers. - - RSTS/E v10.1 source (INIONE.MAR/XHLOOK:) indicates that both the DEQNA and - DELQA will set receive status word 1 bits 15 & 14 on both packets. It also - states that a hardware bug in the DEQNA will set receive status word 1 bit 15 - (only) in the *third* receive buffer (oops!). - - RSTS/E v10.1 will run the Citizenship test from the bootrom after loading it. - Documentation on the Boot ROM can be found in INIQNA.MAR. - */ - - int32 rstatus, wstatus; - uint16 b_length, w_length; - uint32 address; - uint8* bootrom = (uint8*) xq_bootrom; - int i, checksum; - -#ifdef XQ_DEBUG - fprintf(stderr,"%s: CSR - Processing boot rom load\n", xq->dev->name); -#endif - - /* - RSTS/E v10.1 invokes the Citizenship tests in the Bootrom. For some - reason, the current state of the XQ emulator cannot pass these. So, - to get moving on RSTE/E support, we will replace the following line in - INIQNA.MAR/CITQNA:: - 70$: MOV (R2),R0 ;get the status word - with - 70$: CLR R0 ;force success - to cause the Citizenship test to return success to RSTS/E. - - At some point, the real problem (failure to pass citizenship diagnostics) - does need to be corrected to find incompatibilities in the emulation, and to - ultimately allow it to pass Digital hardware diagnostic tests. - */ - for (i=0; ivar->rbdl_buf[0] = 0xFFFF; - wstatus = Map_WriteW(xq->var->rbdl_ba, 2, &xq->var->rbdl_buf[0], NOMAP); - rstatus = Map_ReadW (xq->var->rbdl_ba + 2, 6, &xq->var->rbdl_buf[1], NOMAP); - if (rstatus || wstatus) return xq_nxm_error(xq); - - /* invalid buffer? */ - if (~xq->var->rbdl_buf[1] & XQ_DSC_V) { - xq->var->csr |= XQ_CSR_RL; - return SCPE_OK; - } - - /* get status words */ - rstatus = Map_ReadW(xq->var->rbdl_ba + 8, 4, &xq->var->rbdl_buf[4], NOMAP); - if (rstatus) return xq_nxm_error(xq); - - /* get host memory address */ - address = ((xq->var->rbdl_buf[1] & 0x3F) << 16) | xq->var->rbdl_buf[2]; - -#ifdef XQ_DEBUG - fprintf(stderr,"%s: BootRom1 load address: 0%o\n", xq->dev->name, address); -#endif - - /* decode buffer length - two's complement (in words) */ - w_length = ~xq->var->rbdl_buf[3] + 1; - b_length = w_length * 2; - if (xq->var->rbdl_buf[1] & XQ_DSC_H) b_length -= 1; - if (xq->var->rbdl_buf[1] & XQ_DSC_L) b_length -= 1; - - /* make sure entire packet fits in buffer */ - assert(b_length >= sizeof(xq_bootrom)/2); - - /* send data to host */ - wstatus = Map_WriteB(address, sizeof(xq_bootrom)/2, bootrom, NOMAP); - if (wstatus) return xq_nxm_error(xq); - - /* update read status words */ - xq->var->rbdl_buf[4] = XQ_DSC_V | XQ_DSC_C; /* valid, chain */ - xq->var->rbdl_buf[5] = 0; - - /* update read status words*/ - wstatus = Map_WriteW(xq->var->rbdl_ba + 8, 4, &xq->var->rbdl_buf[4], NOMAP); - if (wstatus) return xq_nxm_error(xq); - - /* set to next bdl (implicit chain) */ - xq->var->rbdl_ba += 12; - - /* --------------------------- bootrom part 2 -----------------------------*/ - - /* get receive bdl from memory */ - xq->var->rbdl_buf[0] = 0xFFFF; - wstatus = Map_WriteW(xq->var->rbdl_ba, 2, &xq->var->rbdl_buf[0], NOMAP); - rstatus = Map_ReadW (xq->var->rbdl_ba + 2, 6, &xq->var->rbdl_buf[1], NOMAP); - if (rstatus || wstatus) return xq_nxm_error(xq); - - /* invalid buffer? */ - if (~xq->var->rbdl_buf[1] & XQ_DSC_V) { - xq->var->csr |= XQ_CSR_RL; - return SCPE_OK; - } - - /* get status words */ - rstatus = Map_ReadW(xq->var->rbdl_ba + 8, 4, &xq->var->rbdl_buf[4], NOMAP); - if (rstatus) return xq_nxm_error(xq); - - /* get host memory address */ - address = ((xq->var->rbdl_buf[1] & 0x3F) << 16) | xq->var->rbdl_buf[2]; - -#ifdef XQ_DEBUG - fprintf(stderr,"%s: BootRom2 load address: 0%o\n", xq->dev->name, address); -#endif - - /* decode buffer length - two's complement (in words) */ - w_length = ~xq->var->rbdl_buf[3] + 1; - b_length = w_length * 2; - if (xq->var->rbdl_buf[1] & XQ_DSC_H) b_length -= 1; - if (xq->var->rbdl_buf[1] & XQ_DSC_L) b_length -= 1; - - /* make sure entire packet fits in buffer */ - assert(b_length >= sizeof(xq_bootrom)/2); - - /* send data to host */ - wstatus = Map_WriteB(address, sizeof(xq_bootrom)/2, &bootrom[2048], NOMAP); - if (wstatus) return xq_nxm_error(xq); - - /* update read status words */ - xq->var->rbdl_buf[4] = XQ_DSC_V | XQ_DSC_C; /* valid, chain */ - xq->var->rbdl_buf[5] = 0; - - /* update read status words*/ - wstatus = Map_WriteW(xq->var->rbdl_ba + 8, 4, &xq->var->rbdl_buf[4], NOMAP); - if (wstatus) return xq_nxm_error(xq); - - /* set to next bdl (implicit chain) */ - xq->var->rbdl_ba += 12; - - /* --------------------------- bootrom part 3 -----------------------------*/ - - switch (xq->var->type) { - case XQ_T_DEQNA: - - /* get receive bdl from memory */ - xq->var->rbdl_buf[0] = 0xFFFF; - wstatus = Map_WriteW(xq->var->rbdl_ba, 2, &xq->var->rbdl_buf[0], NOMAP); - rstatus = Map_ReadW (xq->var->rbdl_ba + 2, 6, &xq->var->rbdl_buf[1], NOMAP); - if (rstatus || wstatus) return xq_nxm_error(xq); - - /* invalid buffer? */ - if (~xq->var->rbdl_buf[1] & XQ_DSC_V) { - xq->var->csr |= XQ_CSR_RL; - return SCPE_OK; - } - - /* get status words */ - rstatus = Map_ReadW(xq->var->rbdl_ba + 8, 4, &xq->var->rbdl_buf[4], NOMAP); - if (rstatus) return xq_nxm_error(xq); - - /* update read status words */ - xq->var->rbdl_buf[4] = XQ_DSC_V; /* valid */ - xq->var->rbdl_buf[5] = 0; - - /* update read status words*/ - wstatus = Map_WriteW(xq->var->rbdl_ba + 8, 4, &xq->var->rbdl_buf[4], NOMAP); - if (wstatus) return xq_nxm_error(xq); - - /* set to next bdl (implicit chain) */ - xq->var->rbdl_ba += 12; - break; - } /* switch */ - - /* --------------------------- Done, finish up -----------------------------*/ - - /* mark transmission complete */ - xq->var->csr |= XQ_CSR_RI; - if (xq->var->csr & XQ_CSR_IE) - SET_INT(XQ); - - /* reset sanity timer */ - xq_reset_santmr(xq); - - return SCPE_OK; -} -#endif /* ifdef VM_PDP11 */ - -t_stat xq_wr_csr(CTLR* xq, int32 data) -{ -#ifdef VM_PDP11 - static const uint16 bd_bits_on = XQ_CSR_BD | XQ_CSR_EL; -#endif - int old_int_state, new_int_state; - const uint16 saved_csr = xq->var->csr; - -#ifdef XQ_DEBUG - xq_csr_changes(xq, data); -#endif - - /* reset controller when SR transitions to cleared */ - if (xq->var->csr & XQ_CSR_SR & ~data) { - xq_sw_reset(xq); - return SCPE_OK; - } - - /* write the writeable bits */ - xq->var->csr = (xq->var->csr & XQ_CSR_RO) | (data & XQ_CSR_RW); - - /* clear write-one-to-clear bits */ - xq->var->csr &= ~(data & XQ_CSR_W1); - if (data & XQ_CSR_XI) /* clearing XI clears NI too */ - xq->var->csr &= ~XQ_CSR_NI; - - /* start receiver timer when RE transitions to set */ - if (~saved_csr & XQ_CSR_RE & data) { - 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]); - } - - /* check and correct CPU interrupt state */ - old_int_state = (saved_csr & XQ_CSR_IE) && (saved_csr & (XQ_CSR_XI | XQ_CSR_RI)); - new_int_state = (xq->var->csr & XQ_CSR_IE) && (xq->var->csr & (XQ_CSR_XI | XQ_CSR_RI)); - if ( old_int_state && !new_int_state) CLR_INT(XQ); - if (!old_int_state && new_int_state) SET_INT(XQ); - -#ifdef VM_PDP11 - /* request boot/diagnostic rom? [PDP-11 only] */ - if ((bd_bits_on & data) == bd_bits_on) /* all bits must be on */ - xq_process_bootrom(xq); -#endif - - return SCPE_OK; -} - -t_stat xq_wr(int32 data, int32 PA, int32 access) -{ - t_stat status; - CTLR* xq = xq_pa2ctlr(PA); - int index = (PA >> 1) & 07; /* word index */ - -#ifdef XQ_DEBUG - if (index != 7) - fprintf (stderr,"%s: %s", xq->dev->name, xq_xmit_regnames[index]); -#if defined(VM_VAX) - fprintf (stderr," %08X %08X", fault_PC, PSL); -#endif /* VM_VAX */ - fprintf (stderr," write: %X\n", data); -#endif - - switch (index) { - case 0: /* these should not be written */ - case 1: - break; - case 2: /* receive bdl low bits */ - xq->var->rbdl[0] = data; - break; - case 3: /* receive bdl high bits */ - xq->var->rbdl[1] = data; - status = xq_dispatch_rbdl(xq); /* start receive operation */ - break; - case 4: /* transmit bdl low bits */ - xq->var->xbdl[0] = data; - break; - case 5: /* transmit bdl high bits */ - xq->var->xbdl[1] = data; - status = xq_dispatch_xbdl(xq); /* start transmit operation */ - break; - case 6: /* vector address register */ - status = xq_wr_var(xq, data); - break; - case 7: /* control and status register */ - status = xq_wr_csr(xq, data); - break; - } - return SCPE_OK; -} - - -/* reset device */ -t_stat xq_reset(DEVICE* dptr) -{ - t_stat status; - CTLR* xq = xq_dev2ctlr(dptr); - - /* calculate MAC checksum */ - xq_make_checksum(xq); - - /* init vector address register */ - switch (xq->var->type) { - case XQ_T_DEQNA: - xq->var->var = 0; - break; - case XQ_T_DELQA: - xq->var->var = XQ_VEC_MS | XQ_VEC_OS; - break; - } - xq->dib->vec = 0; - - /* init control status register */ - xq->var->csr = XQ_CSR_RL | XQ_CSR_XL; - - /* reset ethernet interface */ - if (xq->var->etherface) { - status = eth_filter (xq->var->etherface, 1, &xq->var->mac, 0, 0); - xq->var->csr |= XQ_CSR_OK; - } - - /* init read queue (first time only) */ - status = xq_init_queue (xq, &xq->var->ReadQ); - if (status != SCPE_OK) - return status; - - /* clear read queue */ - xq_clear_queue(&xq->var->ReadQ); - - /* start sanity timer if power-on SANITY is set */ - switch (xq->var->type) { - case XQ_T_DEQNA: - if (xq->var->sanity.enabled) { - xq->var->sanity.quarter_secs = 4 * (4 * 60); /* default is 4 minutes */; - xq_start_santmr(xq); - } - break; - case XQ_T_DELQA: - /* note that the DELQA in NORMAL mode has no power-on SANITY state! */ - xq_start_idtmr(xq); - break; - }; - - return SCPE_OK; -} - -void xq_start_santmr(CTLR* xq) -{ - UNIT* xq_santmr = &xq->unit[1]; /* sanity timer uses unit 1 */ - - /* must be recalculated each time since tmr_poll is a dynamic number */ - const int32 quarter_sec = (clk_tps * tmr_poll) / 4; - -#if 0 -#ifdef XQ_DEBUG - fprintf(stderr,"%s: SANITY TIMER ENABLED, qsecs: %d, poll:%d\n", - xq->dev->name, xq->var->sanity.quarter_secs, tmr_poll); -#endif -#endif - if (sim_is_active(xq_santmr)) /* cancel timer, just in case */ - sim_cancel(xq_santmr); - xq_reset_santmr(xq); - sim_activate(xq_santmr, quarter_sec); -} - -void xq_cancel_santmr(CTLR* xq) -{ - UNIT* xq_santmr = &xq->unit[1]; /* sanity timer uses unit 1 */ - - /* can't cancel hardware switch sanity timer */ - if (sim_is_active(xq_santmr) && !xq->var->sanity.enabled) { -#if 0 -#ifdef XQ_DEBUG - fprintf(stderr,"%s: SANITY TIMER CANCELLED, qsecs: %d\n", - xq->dev->name, xq->var->sanity.quarter_secs); -#endif -#endif - sim_cancel(xq_santmr); - } -} - -void xq_reset_santmr(CTLR* xq) -{ -#if 0 -#ifdef XQ_DEBUG - ftime(&start); - fprintf(stderr,"%s: SANITY TIMER RESETTING, qsecs: %d\n", - xq->dev->name, xq->var->sanity.quarter_secs); -#endif -#endif - xq->var->sanity.countdown = xq->var->sanity.quarter_secs; -} - -t_stat xq_sansvc(UNIT* uptr) -{ - CTLR* xq = xq_unit2ctlr(uptr); - UNIT* xq_santmr = &xq->unit[1]; /* sanity timer uses unit 1 */ - - if (--xq->var->sanity.countdown) { - /* must be recalculated each time since tmr_poll is a dynamic number */ - const int32 quarter_sec = (clk_tps * tmr_poll) / 4; - - /* haven't hit the end of the countdown timer yet, resubmit */ - sim_activate(xq_santmr, quarter_sec); - } else { - /* - If this section is entered, it means that the sanity timer has expired - without being reset, and the controller must reboot the processor. - */ -#if 0 -#ifdef XQ_DEBUG - ftime(&finish); - fprintf(stderr,"%s: SANITY TIMER EXPIRED, qsecs: %d, poll: %d, elapsed: %d\n", - xq->dev->name, xq->var->sanity.quarter_secs, tmr_poll, finish.time - start.time); -#endif -#endif - 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(CTLR* xq) -{ - UNIT* xq_idtmr = &xq->unit[2]; /* system id timer uses unit 2 */ - - /* 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_idtmr)) /* cancel timer, just in case */ - sim_cancel(xq_idtmr); - xq->var->id.enabled = 1; - /* every 8-10 minutes (9 in this case) the DELQA broadcasts a system id message */ - xq->var->id.countdown = 9 * 60; - sim_activate(xq_idtmr, one_sec); -} - -t_stat xq_system_id (CTLR* xq, 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->var->setup.valid ? xq->var->setup.macs[0] : xq->var->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->var->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->var->etherface, &system_id, NULL); - - return status; -} - -t_stat xq_idsvc(UNIT* uptr) -{ - CTLR* xq = xq_unit2ctlr(uptr); - UNIT* xq_idtmr = &xq->unit[2]; /* system id timer uses unit 2 */ - - /* 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->var->type == XQ_T_DEQNA) - return SCPE_NOFNC; - - if (--xq->var->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(xq, mop_multicast, 0); - /* every 8-10 minutes (9 in this case) the DELQA broadcasts a system id message */ - xq->var->id.countdown = 9 * 60; - } - - /* resubmit - for one second to get a well calibrated value of tmr_poll */ - sim_activate(xq_idtmr, one_sec); - return SCPE_OK; -} - -/* -** service routine - used for ethernet reading loop -*/ -t_stat xq_svc(UNIT* uptr) -{ - t_stat status; - int queue_size; - CTLR* xq = xq_unit2ctlr(uptr); - UNIT* xq_svctmr = &xq->unit[0]; - - /* Don't try a read if the receiver is disabled */ - if (!(xq->var->csr & XQ_CSR_RE)) return SCPE_OK; - - /* First pump any queued packets into the system */ - if ((xq->var->ReadQ.count > 0) && (~xq->var->csr & XQ_CSR_RL)) - status = xq_process_rbdl(xq); - - /* 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->var->ReadQ.count; - /* read a packet from the ethernet - processing is via the callback */ - status = eth_read (xq->var->etherface, &xq->var->read_buffer, xq->var->rcallback); - } while (queue_size != xq->var->ReadQ.count); - - /* Now pump any still queued packets into the system */ - if ((xq->var->ReadQ.count > 0) && (~xq->var->csr & XQ_CSR_RL)) - status = xq_process_rbdl(xq); - - /* resubmit if still receive enabled */ - if (xq->var->csr & XQ_CSR_RE) - sim_activate(xq_svctmr, (clk_tps * tmr_poll)/100); - - return SCPE_OK; -} - - - -/* attach device: */ -t_stat xq_attach(UNIT* uptr, char* cptr) -{ - t_stat status; - char* tptr; - CTLR* xq = xq_unit2ctlr(uptr); - - tptr = malloc(strlen(cptr) + 1); - if (tptr == NULL) return SCPE_MEM; - strcpy(tptr, cptr); - - xq->var->etherface = malloc(sizeof(ETH_DEV)); - if (!xq->var->etherface) return SCPE_MEM; - - status = eth_open(xq->var->etherface, cptr); - if (status != SCPE_OK) { - free(tptr); - free(xq->var->etherface); - xq->var->etherface = 0; - return status; - } - uptr->filename = tptr; - uptr->flags |= UNIT_ATT; - - /* turn on transceiver power indicator */ - xq->var->csr |= XQ_CSR_OK; - - return SCPE_OK; -} - -/* detach device: */ - -t_stat xq_detach(UNIT* uptr) -{ - t_stat status; - CTLR* xq = xq_unit2ctlr(uptr); - - if (uptr->flags & UNIT_ATT) { - status = eth_close (xq->var->etherface); - free(xq->var->etherface); - xq->var->etherface = 0; - free(uptr->filename); - uptr->filename = NULL; - uptr->flags &= ~UNIT_ATT; - } - - /* turn off transceiver power indicator */ - xq->var->csr &= ~XQ_CSR_OK; - - return SCPE_OK; -} - -int32 xq_inta (void) -{ - return xqa_dib.vec; -} - -int32 xq_intb (void) -{ - return xqb_dib.vec; -} - -/*============================================================================== -/ debugging routines -/=============================================================================*/ - -#ifdef XQ_DEBUG - -void xq_dump_csr (CTLR* xq) -{ - static int cnt = 0; - /* tell user what is changing in register */ - int i; - int mask = 1; - uint16 csr = xq->var->csr; - char hi[256] = "Set: "; - char lo[256] = "Reset: "; - for (i=0; i<16; i++, mask <<= 1) { - if ((csr & mask)) strcat (hi, xq_csr_bits[i]); - if ((~csr & mask)) strcat (lo, xq_csr_bits[i]); - } -#if defined (VM_VAX) - printf ("%s: CSR %08X %08X read: %s %s\n", xq->dev->name, fault_PC, PSL, hi, lo); -#else -if (cnt < 20) - printf ("%s: CSR read[%d]: %s %s\n", xq->dev->name, cnt++, hi, lo); -#endif /* VM_VAX */ -} - -void xq_dump_var (CTLR* xq) -{ - /* tell user what is changing in register */ - uint16 var = xq->var->var; - char hi[256] = "Set: "; - char lo[256] = "Reset: "; - int vec = (var & XQ_VEC_IV) >> 2; - strcat((var & XQ_VEC_MS) ? hi : lo, "MS "); - strcat((var & XQ_VEC_OS) ? hi : lo, "OS "); - strcat((var & XQ_VEC_RS) ? hi : lo, "RS "); - strcat((var & XQ_VEC_S3) ? hi : lo, "S3 "); - strcat((var & XQ_VEC_S2) ? hi : lo, "S2 "); - strcat((var & XQ_VEC_S1) ? hi : lo, "S1 "); - strcat((var & XQ_VEC_RR) ? hi : lo, "RR "); - strcat((var & XQ_VEC_ID) ? hi : lo, "ID "); - printf ("%s: VAR read: %s %s - Vec: %d \n", xq->dev->name, hi, lo, vec); -} - -void xq_csr_changes (CTLR* xq, uint16 data) -{ - /* tell user what is changing in register */ - int i; - int mask = 1; - uint16 csr = xq->var->csr; - char hi[256] = "Setting: "; - char lo[256] = "Resetting: "; - for (i=0; i<16; i++, mask <<= 1) { - if ((csr & mask) && (~data & mask)) strcat (lo, xq_csr_bits[i]); - if ((~csr & mask) && (data & mask)) strcat (hi, xq_csr_bits[i]); - } - /* 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 ("%s: CSR %08X %08X write: %s %s\n", xq->dev->name, fault_PC, PSL, hi, lo); -#else - printf ("%s: CSR write: %s %s\n", xq->dev->name, hi, lo); -#endif /* VM_VAX */ -} - -void xq_var_changes (CTLR* xq, uint16 data) -{ - /* tell user what is changing in register */ - uint16 vec; - uint16 var = xq->var->var; - char hi[256] = "Setting: "; - char lo[256] = "Resetting: "; - if (~var & XQ_VEC_MS & data) strcat (hi, "MS "); - if (var & XQ_VEC_MS & ~data) strcat (lo, "MS "); - if (~var & XQ_VEC_OS & data) strcat (hi, "OS "); - if (var & XQ_VEC_OS & ~data) strcat (lo, "OS "); - if (~var & XQ_VEC_RS & data) strcat (hi, "RS "); - if (var & XQ_VEC_RS & ~data) strcat (lo, "RS "); - 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)) { - vec = (data & XQ_VEC_IV) >> 2; - printf ("%s: VAR write: %s %s - Vec: %d\n", xq->dev->name, hi, lo, vec); - } else - printf ("%s: VAR write: %s %s\n", xq->dev->name, hi, lo); -} - -void xq_debug_setup(CTLR* xq) -{ - int i; - char buffer[20]; - if (xq->var->write_buffer.msg[0]) - printf ("%s: Setup: MOP info present!\n", xq->dev->name); - - for (i = 0; i < XQ_FILTER_MAX; i++) { - eth_mac_fmt(&xq->var->setup.macs[i], buffer); - printf ("%s: Setup: set addr[%d]: %s\n", xq->dev->name, i, buffer); - } - - if (xq->var->write_buffer.len > 128) { - char buffer[20] = {0}; - uint16 len = xq->var->write_buffer.len; - if (len & XQ_SETUP_MC) strcat(buffer, "MC "); - 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 ("%s: Setup: Length [%d =0x%X, LD:%d, ST:%d] info: %s\n", - xq->dev->name, 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 deleted file mode 100644 index 6f174ceb..00000000 --- a/PDP11/pdp11_xq.h +++ /dev/null @@ -1,230 +0,0 @@ -/* pdp11_xq.h: DEQNA/DELQA ethernet controller information - ------------------------------------------------------------------------------ - - Copyright (c) 2002-2003, David T. Hittner - - 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 - THE AUTHOR 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 the author shall not be - used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from the author. - - ------------------------------------------------------------------------------ - - Modification history: - - 02-Jun-03 DTH Added struct xq_stats - 28-May-03 DTH Made xq_msg_que.item dynamic - 28-May-03 MP Optimized structures, removed rtime variable - 06-May-03 DTH Changed 32-bit t_addr to uint32 for v3.0 - 28-Apr-03 DTH Added callbacks for multicontroller identification - 25-Mar-03 DTH Removed bootrom field - no longer needed; Updated copyright - 15-Jan-03 DTH Merged Mark Pizzolato's changes into main source - 13-Jan-03 MP Added countdown for System Id multicast packets - 10-Jan-03 DTH Added bootrom field - 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 - 08-Oct-02 DTH Integrated with 2.10-0p4, added variable vector and copyrights - 03-Oct-02 DTH Beta version of xq/sim_ether released for SIMH 2.09-11 - 15-Aug-02 DTH Started XQ simulation - - ------------------------------------------------------------------------------ -*/ - -#ifndef _PDP11_XQ_H -#define _PDP11_XQ_H - -#if defined (VM_PDP10) /* PDP10 version */ -#error "DEQNA/DELQA not supported on PDP10!" - -#elif defined (VM_VAX) /* VAX version */ -#include "vax_defs.h" -#define XQ_RDX 16 -#define XQ_WID 32 -extern int32 PSL; /* PSL */ -extern int32 fault_PC; /* fault PC */ -extern int32 int_req[IPL_HLVL]; -extern int32 int_vec[IPL_HLVL][32]; - -#else /* PDP-11 version */ -#include "pdp11_defs.h" -#define XQ_RDX 8 -#define XQ_WID 16 -extern int32 int_req[IPL_HLVL]; -extern int32 int_vec[IPL_HLVL][32]; -#endif - -#include "sim_ether.h" - -/* message queue arrays */ -#define XQ_QUE_MAX 500 -#define XQ_FILTER_MAX 14 - -enum xq_type {XQ_T_DEQNA, XQ_T_DELQA}; - -struct xq_sanity { - int enabled; /* sanity timer enabled ? */ - int quarter_secs; /* sanity timer value in 1/4 seconds */ - 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) */ - int32 status; /* message size */ - ETH_PACK packet; /* packet */ -}; - -struct xq_msg_que { - int count; - int head; - int tail; - int loss; - int high; - struct xq_msg_itm* item; -}; - -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 */ - int l2; /* second diagnostic led state */ - int l3; /* third diagnostic led state */ - int sanity_timer; /* sanity timer value (encoded) */ - ETH_MAC macs[XQ_FILTER_MAX]; /* MAC addresses to respond to */ -}; - -struct xq_stats { - int recv; /* received packets */ - int filter; /* filtered packets */ - int xmit; /* transmitted packets */ - int fail; /* transmit failed */ - int runt; /* runts */ - int giant; /* oversize packets */ - int setup; /* setup packets */ - int loop; /* loopback packets */ -}; - -struct xq_meb { /* MEB block */ - uint8 type; - uint8 add_lo; - uint8 add_mi; - uint8 add_hi; - uint8 siz_lo; - uint8 siz_hi; -}; - -struct xq_device { - /*+ initialized values - DO NOT MOVE */ - ETH_PCALLBACK rcallback; /* read callback routine */ - ETH_PCALLBACK wcallback; /* write callback routine */ - 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 */ - uint16 addr[6]; - uint16 rbdl[2]; - uint16 xbdl[2]; - uint16 var; - uint16 csr; - - /* buffers, etc. */ - struct xq_setup setup; - struct xq_stats stats; - uint8 mac_checksum[2]; - uint16 rbdl_buf[6]; - uint16 xbdl_buf[6]; - uint32 rbdl_ba; - uint32 xbdl_ba; - ETH_DEV* etherface; - int receiving; - ETH_PACK read_buffer; - ETH_PACK write_buffer; - struct xq_msg_que ReadQ; -}; - -struct xq_controller { - DEVICE* dev; /* device block */ - UNIT* unit; /* unit block */ - DIB* dib; /* device interface block */ - struct xq_device* var; /* controller-specific variables */ -}; - -typedef struct xq_controller CTLR; - - -#define XQ_CSR_RI 0x8000 /* Receive Interrupt Request (RI) [RO/W1] */ -#define XQ_CSR_PE 0x4000 /* Parity Error in Host Memory (PE) [RO] */ -#define XQ_CSR_CA 0x2000 /* Carrier from Receiver Enabled (CA) [RO] */ -#define XQ_CSR_OK 0x1000 /* Ethernet Transceiver Power (OK) [RO] */ -#define XQ_CSR_RR 0x0800 /* Reserved : Set to Zero (RR) [RO] */ -#define XQ_CSR_SE 0x0400 /* Sanity Timer Enable (SE) [RW] */ -#define XQ_CSR_EL 0x0200 /* External Loopback (EL) [RW] */ -#define XQ_CSR_IL 0x0100 /* Internal Loopback (IL) [RW] */ -#define XQ_CSR_XI 0x0080 /* Transmit Interrupt Request (XI) [RO/W1] */ -#define XQ_CSR_IE 0x0040 /* Interrupt Enable (IE) [RW] */ -#define XQ_CSR_RL 0x0020 /* Receive List Invalid/Empty (RL) [RO] */ -#define XQ_CSR_XL 0x0010 /* Transmit List Invalid/Empty (XL) [RO] */ -#define XQ_CSR_BD 0x0008 /* Boot/Diagnostic ROM Load (BD) [RW] */ -#define XQ_CSR_NI 0x0004 /* NonExistant Memory Timeout (NXM) [RO] */ -#define XQ_CSR_SR 0x0002 /* Software Reset (SR) [RW] */ -#define XQ_CSR_RE 0x0001 /* Receiver Enable (RE) [RW] */ - -/* special access bitmaps */ -#define XQ_CSR_RO 0xF8B4 /* Read-Only bits */ -#define XQ_CSR_RW 0x074B /* Read/Write bits */ -#define XQ_CSR_W1 0x8080 /* Write-one-to-clear bits */ - -#define XQ_VEC_MS 0x8000 /* Mode Select (MO) [RW] */ -#define XQ_VEC_OS 0x4000 /* Option Switch Setting (OS) [RO] */ -#define XQ_VEC_RS 0x2000 /* Request Self-Test (RS) [RW] */ -#define XQ_VEC_S3 0x1000 /* Self-Test Status (S3) [RO] */ -#define XQ_VEC_S2 0x0800 /* Self-Test Status (S2) [RO] */ -#define XQ_VEC_S1 0x0400 /* Self-Test Status (S1) [RO] */ -#define XQ_VEC_ST 0x1C00 /* Self-Test (S1 + S2 + S3) [RO] */ -#define XQ_VEC_IV 0x03FC /* Interrupt Vector (IV) [RW] */ -#define XQ_VEC_RR 0x0002 /* Reserved (RR) [RO] */ -#define XQ_VEC_ID 0x0001 /* Identity Test Bit (ID) [RW] */ - -/* special access bitmaps */ -#define XQ_VEC_RO 0x5C02 /* Read-Only bits */ -#define XQ_VEC_RW 0xA3FD /* Read/Write bits */ - -#define XQ_DSC_V 0x8000 /* Valid bit */ -#define XQ_DSC_C 0x4000 /* Chain bit */ -#define XQ_DSC_E 0x2000 /* End of Message bit [Transmit only] */ -#define XQ_DSC_S 0x1000 /* Setup bit [Transmit only] */ -#define XQ_DSC_L 0x0080 /* Low Byte Termination bit [Transmit only] */ -#define XQ_DSC_H 0x0040 /* High Byte Start bit [Transmit only] */ - -#define XQ_SETUP_MC 0x0001 /* multicast bit */ -#define XQ_SETUP_PM 0x0002 /* promiscuous bit */ -#define XQ_SETUP_LD 0x000C /* led bits */ -#define XQ_SETUP_ST 0x0070 /* sanity timer bits */ - -#endif /* _PDP11_XQ_H */ diff --git a/PDP11/pdp11_xq_bootrom.h b/PDP11/pdp11_xq_bootrom.h deleted file mode 100644 index 9a0b954c..00000000 --- a/PDP11/pdp11_xq_bootrom.h +++ /dev/null @@ -1,312 +0,0 @@ -/* pdp11_xq_bootrom.h: DEQNA/DELQA bootrom data - ------------------------------------------------------------------------------ - - Copyright (c) 2003, David T. Hittner - - 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 - THE AUTHOR 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 the author shall not be - used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from the author. - - ------------------------------------------------------------------------------ - - Modification history: - - 26-Mar-03 DTH Removed 'static' declaration - 23-Mar-03 DTH Created by extracting from merged DEQNA bootrom dumps - - ------------------------------------------------------------------------------ -*/ - -#ifndef _PDP11_XQ_BOOTROM_H -#define _PDP11_XQ_BOOTROM_H - -#ifdef VM_PDP11 - /* - Bootrom code is from merged file 23-334e5.bin, offset 050000, for 4096. bytes. - - Word 0: NOP - Word 1: Branch to extended primary boot - Word 2: Branch/Vector to Citizenship tests - Word 3: Offset from beginning to checksum word - - See INIQNA.MAR for further information on format and contents. - */ - - uint16 xq_bootrom[] = { - 0000240,0000423,0000546,0007776,0000520,0000000,0100000,0100000, - 0002000,0176000,0000000,0000000,0100000,0100000,0006000,0176000, - 0000000,0000000,0100000,0020000,0140000,0012706,0001776,0010046, - 0012761,0000014,0000004,0005061,0000006,0012761,0001010,0000016, - 0005000,0005300,0001376,0005061,0000016,0005000,0005300,0001376, - 0012761,0000002,0000016,0005061,0000016,0042767,0037777,0177664, - 0026767,0177660,0177702,0001057,0042767,0037777,0177652,0026767, - 0177646,0177664,0001050,0042767,0037777,0177650,0026767,0177644, - 0177646,0001041,0012704,0007776,0005003,0005002,0116200,0002000, - 0005202,0042700,0177400,0060003,0005304,0001370,0013700,0000006, - 0026003,0002000,0001020,0000137,0002010,0012702,0012000,0004767, - 0000040,0005700,0001010,0011602,0001002,0000167,0004530,0022702, - 0000777,0103001,0000112,0013703,0000012,0001401,0000113,0000000, - 0000776,0010637,0000764,0062701,0000016,0032761,0100000,0177776, - 0001421,0052761,0020000,0177776,0012703,0000777,0005000,0005300, - 0001376,0032761,0016000,0177776,0001405,0005303,0001370,0012700, - 0000200,0000454,0004767,0000136,0052711,0000002,0042711,0000002, - 0012703,0017777,0005303,0001376,0004567,0003514,0177700,0001014, - 0005712,0001014,0032762,0002000,0000050,0001402,0052711,0002000, - 0004567,0003464,0177622,0001402,0052712,0000100,0012711,0000002, - 0005011,0012703,0017777,0005303,0001376,0011100,0042700,0064000, - 0022700,0010060,0001402,0052712,0000100,0011200,0162701,0000016, - 0000207,0052400,0177652,0013746,0000034,0013746,0000036,0010703, - 0062703,0000210,0010337,0000034,0012737,0000340,0000036,0104400, - 0012637,0000036,0012637,0000034,0013700,0000762,0052700,0000340, - 0062703,0000010,0010337,0000004,0010037,0000006,0010637,0000766, - 0010137,0000772,0010237,0000770,0062703,0000012,0010337,0000024, - 0010037,0000026,0062703,0000022,0012761,0000774,0177776,0052761, - 0100000,0177776,0010337,0000774,0010037,0000776,0005062,0000002, - 0005012,0012700,0000162,0060200,0012704,0000112,0005020,0005304, - 0001375,0004567,0003202,0177666,0001434,0005262,0000002,0022762, - 0000002,0000002,0003355,0000207,0016637,0000002,0000762,0000006, - 0052712,0002000,0013706,0000764,0000207,0052712,0020000,0013706, - 0000766,0013701,0000772,0013702,0000770,0000207,0052712,0004000, - 0000002,0106427,0000000,0010103,0162703,0000016,0010204,0062704, - 0000012,0012705,0000006,0012300,0110024,0005305,0001374,0010204, - 0062704,0000012,0010405,0005724,0001004,0005724,0001002,0005714, - 0001421,0010504,0012700,0177777,0020024,0001016,0020024,0001014, - 0020014,0001410,0001011,0010504,0022724,0000252,0001003,0122714, - 0000004,0103002,0052712,0000001,0012700,0177777,0004767,0003314, - 0013705,0000774,0010703,0062703,0000044,0010337,0000774,0052711, - 0000100,0010461,0177772,0005000,0010061,0177774,0012703,0010000, - 0005303,0001376,0052712,0004000,0000207,0062706,0000004,0010537, - 0000774,0005200,0001767,0011100,0032700,0000200,0001763,0011400, - 0042700,0037777,0022700,0140000,0001355,0005764,0000010,0001752, - 0005764,0000012,0001747,0052711,0000002,0042711,0000002,0012711, - 0002000,0106437,0000762,0004567,0002576,0177666,0001402,0000207, - 0010703,0062703,0177160,0010362,0000002,0010362,0000006,0062703, - 0000005,0010362,0000004,0005062,0000010,0010203,0062703,0000162, - 0012700,0000002,0012705,0000006,0105023,0012704,0000007,0026262, - 0000004,0000006,0003003,0016262,0000002,0000006,0117223,0000006, - 0005262,0000006,0005304,0001363,0005305,0001356,0012704,0000020, - 0105023,0005304,0001375,0005300,0001345,0004567,0002432,0177705, - 0001403,0052712,0000002,0000207,0005262,0000010,0022762,0000764, - 0000010,0003323,0042761,0100000,0177776,0005062,0000006,0010204, - 0062704,0000163,0010462,0000010,0005304,0012703,0000060,0105024, - 0005303,0001375,0062762,0000010,0000002,0016262,0000010,0000002, - 0012762,0000060,0000004,0105062,0000012,0000261,0106162,0000012, - 0103041,0106162,0000012,0062762,0000010,0000002,0000433,0016204, - 0000010,0005304,0012703,0000060,0112724,0000377,0005303,0001374, - 0012762,0000060,0000004,0016262,0000010,0000002,0112762,0000377, - 0000012,0000241,0106162,0000012,0103405,0106162,0000012,0062762, - 0000010,0000002,0016204,0000002,0012703,0000007,0105064,0177770, - 0116224,0000012,0005303,0001372,0004567,0002154,0177750,0001402, - 0000167,0000414,0005762,0000006,0001011,0000241,0106172,0000002, - 0103010,0106072,0000002,0106072,0000002,0000403,0000261,0106172, - 0000002,0016204,0000010,0010203,0062703,0004362,0012700,0000006, - 0111423,0062704,0000010,0005300,0001373,0012711,0000001,0012700, - 0177775,0004767,0002352,0010461,0177766,0005061,0177770,0004767, - 0002372,0010461,0177772,0005061,0177774,0012700,0077777,0032711, - 0100000,0001003,0005300,0001373,0000523,0005000,0004567,0002412, - 0000000,0040000,0001115,0016204,0000010,0005204,0010203,0062703, - 0004362,0012700,0000006,0111423,0062704,0000010,0005300,0001373, - 0042711,0100200,0012700,0177775,0004767,0002224,0010461,0177766, - 0005061,0177770,0012700,0177775,0004767,0002240,0010461,0177772, - 0005061,0177774,0012700,0077777,0032711,0100000,0001003,0005300, - 0001373,0000454,0005000,0004567,0002260,0000000,0000000,0001040, - 0042711,0000001,0010204,0062704,0001362,0010205,0062705,0004362, - 0012700,0000006,0122425,0001024,0005300,0001374,0005362,0000004, - 0001007,0005762,0000006,0001034,0005262,0000006,0000167,0177256, - 0005762,0000006,0001002,0000167,0177222,0000261,0000167,0177304, - 0052712,0000004,0000405,0052712,0004000,0000402,0052712,0001004, - 0052761,0100000,0177776,0000207,0000074,0001422,0002752,0177777, - 0052761,0100000,0177776,0052711,0001000,0010703,0062703,0176046, - 0010362,0000002,0010362,0000006,0062703,0000004,0010362,0000004, - 0010703,0062703,0177726,0010362,0000010,0010203,0062703,0004362, - 0017205,0000010,0026262,0000004,0000006,0003003,0016262,0000002, - 0000006,0117223,0000006,0005262,0000006,0005305,0001363,0017200, - 0000010,0004567,0001536,0103425,0017200,0000010,0004567,0001752, - 0000000,0020000,0001401,0000003,0010204,0062704,0001362,0010205, - 0062705,0004362,0017200,0000010,0122425,0001003,0005300,0001374, - 0000403,0052712,0000010,0000207,0062762,0000002,0000010,0022772, - 0177777,0000010,0001402,0000167,0177620,0012700,0177770,0004767, - 0001536,0010461,0177766,0005061,0177770,0010203,0062703,0000040, - 0010304,0012700,0000010,0012723,0100000,0012723,0100000,0010213, - 0062723,0000012,0012723,0177777,0005023,0005023,0005300,0001363, - 0010403,0052763,0000200,0000002,0052763,0000300,0000016,0012763, - 0177776,0000022,0052763,0000100,0000032,0062763,0000002,0000034, - 0062763,0000004,0000050,0012763,0040000,0000062,0010363,0000064, - 0062763,0000074,0000064,0010363,0000100,0062763,0000070,0000100, - 0012763,0177776,0000102,0012763,0120000,0000112,0012763,0177775, - 0000116,0012763,0020000,0000126,0010461,0177772,0005061,0177774, - 0012700,0077777,0032711,0100000,0001005,0005300,0001373,0052712, - 0001000,0000411,0012700,0000020,0004567,0001376,0100000,0020000, - 0001405,0052712,0040000,0052712,0000020,0000207,0010203,0062703, - 0000040,0012700,0000010,0016305,0000000,0042705,0037777,0022705, - 0140000,0001357,0022700,0000004,0001403,0022700,0000001,0001007, - 0005763,0000010,0001346,0005763,0000012,0001343,0000424,0022700, - 0000002,0001405,0032763,0100000,0000010,0001733,0000414,0016305, - 0000010,0042705,0026417,0022705,0000000,0001323,0016305,0000012, - 0042705,0176000,0001716,0062703,0000014,0005300,0001324,0010203, - 0062703,0000012,0010204,0062704,0001362,0010405,0022324,0001303, - 0022324,0001301,0022324,0001277,0005724,0001275,0005724,0001273, - 0022524,0001271,0022524,0001267,0022524,0001265,0010203,0062703, - 0000162,0010305,0012700,0000113,0005023,0005300,0001375,0010204, - 0062704,0000012,0004767,0000046,0062705,0000020,0004767,0000036, - 0004567,0000444,0177674,0001401,0000207,0012700,0177777,0032711, - 0020000,0001423,0005300,0001373,0052712,0100000,0000207,0010446, - 0012700,0000006,0005205,0012703,0000007,0111425,0005303,0001375, - 0005204,0005300,0001367,0012604,0000207,0005712,0001017,0052711, - 0001400,0012700,0000056,0004767,0000132,0012700,0000074,0004567, - 0000522,0103005,0042712,0001000,0052712,0100000,0000207,0012700, - 0000074,0004767,0000156,0001761,0001403,0052712,0000040,0000207, - 0012700,0000074,0004767,0000232,0001370,0012700,0002734,0004767, - 0000042,0012700,0002752,0004567,0000432,0103757,0012700,0002752, - 0004767,0000100,0001766,0001351,0012700,0002752,0004767,0000162, - 0001344,0000207,0010203,0062703,0004362,0010204,0062704,0000012, - 0010405,0012423,0012423,0012423,0012523,0012523,0012523,0012723, - 0000220,0005023,0012723,0000001,0110023,0005300,0001375,0005062, - 0000002,0000207,0004567,0000542,0000000,0020000,0001004,0062716, - 0000002,0005712,0000207,0016200,0000050,0042700,0137777,0001010, - 0016200,0000030,0032700,0137777,0001003,0042712,0040000,0000757, - 0005262,0000002,0022762,0000144,0000002,0003751,0042712,0040000, - 0000750,0010204,0062704,0001362,0010205,0062705,0004362,0122425, - 0001002,0005300,0001374,0000207,0010200,0062700,0000162,0010046, - 0011500,0005300,0004767,0000270,0010461,0177766,0005061,0177770, - 0012500,0004767,0000306,0012764,0130000,0000002,0011664,0000004, - 0010461,0177772,0005061,0177774,0012704,0017777,0032711,0100000, - 0001010,0005304,0001373,0052712,0001000,0005726,0052712,0010000, - 0000430,0016500,0177776,0006300,0005400,0004567,0000274,0000000, - 0020000,0001363,0016500,0177776,0006300,0005400,0010204,0062704, - 0001362,0012603,0122423,0001352,0005300,0001374,0022714,0051343, - 0001345,0000205,0005046,0006000,0005516,0061600,0005400,0004767, - 0000076,0010461,0177766,0005061,0177770,0004767,0000116,0005726, - 0001403,0052764,0000200,0000002,0010461,0177772,0005061,0177774, - 0012703,0000777,0005000,0032711,0100000,0001010,0005300,0001376, - 0005303,0001371,0052712,0001000,0000261,0000401,0000241,0000205, - 0010203,0062703,0001362,0012704,0000200,0012723,0051343,0005304, - 0001374,0004567,0000020,0000020,0001362,0000207,0004567,0000006, - 0000040,0004362,0000207,0012503,0060203,0010304,0012723,0100000, - 0012723,0120000,0012513,0060223,0010023,0012723,0100000,0012723, - 0100000,0012723,0100000,0005023,0000205,0010046,0005000,0011104, - 0052711,0100200,0042704,0077401,0022704,0100260,0001401,0010700, - 0016204,0000040,0042704,0037777,0022704,0140000,0001401,0010700, - 0016204,0000050,0100002,0042704,0077777,0042704,0076417,0022504, - 0001401,0010700,0016204,0000052,0042704,0176000,0001001,0010700, - 0016204,0000020,0042704,0037777,0022704,0140000,0001401,0010700, - 0016204,0000030,0010446,0042704,0007777,0022504,0001401,0010700, - 0012604,0042704,0174377,0022762,0177775,0000046,0001002,0005726, - 0000415,0032762,0010000,0000042,0001401,0005004,0016203,0000032, - 0042703,0177400,0060304,0022604,0001401,0010700,0010003,0001402, - 0052712,0040000,0000205,0000005,0012706,0017776,0010616,0011646, - 0162716,0003056,0010703,0062703,0000014,0010337,0000004,0011100, - 0000401,0000000,0004767,0000230,0011605,0012725,0022410,0012725, - 0000401,0105025,0105025,0012725,0000621,0112725,0000002,0012702, - 0002752,0110225,0000302,0110225,0012702,0000013,0005000,0004767, - 0000452,0001350,0012702,0002756,0004767,0000660,0001046,0011603, - 0112304,0005302,0120427,0000002,0001404,0105704,0001335,0162702, - 0000004,0105713,0001402,0121300,0001030,0112300,0105200,0005302, - 0003410,0012305,0005723,0162702,0000004,0003403,0112325,0005302, - 0003375,0105704,0001417,0005003,0011605,0112725,0000012,0110025, - 0110325,0005005,0012702,0000003,0000722,0105700,0001673,0012703, - 0000001,0000762,0004767,0001232,0112346,0112366,0000001,0000207, - 0042761,0000002,0000016,0016605,0000002,0010504,0062704,0177720, - 0010466,0000004,0012702,0000020,0005024,0077202,0010504,0062704, - 0177760,0005065,0177722,0010465,0177724,0005065,0177742,0010465, - 0177744,0052765,0100000,0177722,0012702,0002756,0006202,0005402, - 0010265,0177726,0052765,0120000,0177742,0016604,0000004,0010467, - 0001324,0005067,0001322,0062704,0000020,0010467,0001314,0005067, - 0001312,0116167,0000000,0001262,0116167,0000002,0001255,0116167, - 0000004,0001250,0116167,0000006,0001243,0116167,0000010,0001236, - 0116167,0000012,0001231,0105267,0001232,0042761,0000002,0000016, - 0052761,0000400,0000016,0004767,0001104,0005065,0000002,0016744, - 0001174,0016744,0001166,0016744,0001160,0012744,0000000,0012744, - 0001000,0012744,0000253,0004767,0000046,0000207,0016605,0000002, - 0010504,0010244,0012744,0000540,0016744,0001122,0016744,0001114, - 0016744,0001106,0016744,0001060,0016744,0001052,0016744,0001044, - 0062705,0177740,0062702,0000016,0020227,0000074,0002003,0012702, - 0000074,0000407,0032702,0000001,0001404,0052765,0000200,0000002, - 0005202,0006202,0005402,0010265,0000006,0005065,0000010,0005065, - 0000012,0016761,0001024,0000010,0016761,0001020,0000012,0012704, - 0000204,0004767,0000610,0103012,0001404,0032765,0001000,0000010, - 0001354,0042765,0000200,0000002,0000244,0000207,0042765,0000200, - 0000002,0032702,0040004,0001401,0000000,0000207,0016605,0000002, - 0062705,0177720,0005065,0000010,0005065,0000012,0016761,0000706, - 0000004,0016761,0000702,0000006,0052761,0000001,0000016,0012704, - 0100004,0004767,0000470,0103030,0001355,0052761,0000002,0000016, - 0012767,0000253,0000576,0012767,0000400,0000572,0012767,0000000, - 0000566,0105267,0000616,0005000,0042761,0000002,0000016,0052761, - 0000400,0000016,0000244,0000207,0042761,0000001,0000016,0052761, - 0000002,0000016,0016605,0000002,0016502,0177776,0042761,0000002, - 0000016,0052761,0000400,0000016,0022765,0000540,0177774,0001041, - 0105767,0000520,0001015,0026765,0000456,0177772,0001267,0026765, - 0000444,0177770,0001263,0026765,0000432,0177766,0001257,0000207, - 0122715,0000003,0001253,0016567,0177766,0000410,0016567,0177770, - 0000404,0016567,0177772,0000400,0105067,0000430,0000244,0005000, - 0000207,0022765,0000220,0177774,0001423,0022765,0001140,0177774, - 0001225,0122715,0000005,0001222,0004767,0000262,0016464,0177776, - 0177770,0016464,0177774,0177766,0016464,0177772,0177764,0000437, - 0010504,0060204,0010503,0062703,0177720,0016302,0000010,0042702, - 0174377,0156302,0000012,0062702,0000056,0022724,0000002,0001027, - 0062765,0000010,0177776,0032714,0000001,0001021,0010503,0062703, - 0177760,0012423,0012423,0012423,0010504,0062704,0177774,0016744, - 0000234,0016744,0000226,0016744,0000220,0004767,0177122,0000167, - 0177272,0016737,0000156,0000030,0016737,0000152,0000032,0016737, - 0000146,0000034,0052761,0000002,0000016,0000264,0000207,0012703, - 0037777,0000241,0012702,0000220,0030461,0000016,0001006,0005303, - 0001376,0005302,0001371,0000261,0000207,0016102,0000016,0010261, - 0000016,0032765,0040000,0000010,0001401,0000261,0000207,0010546, - 0010703,0062703,0000050,0012702,0000030,0012325,0005725,0112325, - 0005302,0001375,0012605,0010504,0012702,0000034,0010244,0012744, - 0001140,0000207,0000253,0000400,0000000,0000007,0000001,0001403, - 0000000,0000002,0000402,0003400,0003000,0000000,0000000,0000000, - 0000144,0022401,0000000,0000000,0000000,0000000,0000000,0000000, - 0000000,0000000,0000000,0000000,0000000,0000000,0000000,0000000, - 0000000,0000000,0000000,0000000,0000000,0000000,0000000,0000000, - 0000000,0000000,0000000,0000000,0000000,0000000,0000000,0000000, - 0000000,0000000,0000000,0000000,0000000,0000000,0000000,0000000, - 0000000,0000000,0000000,0000000,0000000,0000000,0000000,0000000, - 0000000,0000000,0000000,0000000,0000000,0000000,0000000,0000000, - 0000000,0000000,0000000,0000000,0000000,0000000,0000000,0000000, - 0000000,0000000,0000000,0000000,0000000,0000000,0000000,0000000, - 0000000,0000000,0000000,0000000,0000000,0000000,0000000,0000000, - 0000000,0000000,0000000,0000000,0000000,0000000,0000000,0000000, - 0000000,0000000,0000000,0000000,0000000,0000000,0000000,0000000, - 0000000,0000000,0000000,0000000,0000000,0000000,0000000,0000000, - 0000000,0000000,0000000,0000000,0000000,0000000,0000000,0000000, - 0000000,0000000,0000000,0000000,0000000,0000000,0000000,0000000, - 0000000,0000000,0000000,0000000,0000000,0000000,0000000,0000000, - 0000000,0000000,0000000,0000000,0000000,0000000,0000000,0000000, - 0000000,0000000,0000000,0000000,0000000,0000000,0000000,0000000, - 0000000,0000000,0000000,0000000,0000000,0000000,0000000,0000000, - 0000000,0000000,0000000,0000000,0000000,0000000,0000000,0000000, - 0000000,0000000,0000000,0000000,0000000,0000000,0000000,0000000, - 0000000,0000000,0000000,0000000,0000000,0000000,0000000,0000000, - 0000000,0000000,0000000,0000000,0000000,0000000,0000000,0000000, - 0000000,0000000,0000000,0000000,0000000,0000000,0000000,0000000, - 0000000,0000000,0000000,0000000,0000000,0000000,0000000,0000000, - 0000000,0000000,0000000,0000000,0000000,0000000,0000000,0000000, - 0000000,0000000,0000000,0000000,0000000,0000000,0000000,0000000, - 0000000,0000000,0000000,0000000,0000000,0000000,0000000,0000000, - 0000000,0000000,0000000,0000000,0000000,0000000,0000000,0000000, - 0000000,0000000,0000000,0000000,0000000,0000000,0000000,0000000, - 0000000,0000000,0000000,0000000,0000000,0000000,0000000,0000000, - 0000000,0000000,0000000,0000000,0000000,0000000,0000000,0000000, - 0000000,0000000,0000000,0000000,0000000,0000000,0000000,0102206 - }; -#endif /* VM_PDP11 */ - -#endif /* _PDP11_XQ_BOOTROM_H */ diff --git a/PDP11/pdp11_xu.c b/PDP11/pdp11_xu.c deleted file mode 100644 index 02867c65..00000000 --- a/PDP11/pdp11_xu.c +++ /dev/null @@ -1,63 +0,0 @@ -/* 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 (VM_PDP10) /* PDP10 version */ -#include "pdp10_defs.h" -extern int32 int_req; -extern int32 int_vec[32]; - -#elif defined (VM_VAX) /* VAX version */ -#error "DEUNA/DELUA not supported on VAX!" - -#else /* PDP-11 version */ -#include "pdp11_defs.h" -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 deleted file mode 100644 index 96c3ff16..00000000 --- a/PDP18B/pdp18b_cpu.c +++ /dev/null @@ -1,2006 +0,0 @@ -/* pdp18b_cpu.c: 18b PDP CPU simulator - - 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. - - cpu PDP-4/7/9/15 central processor - - 31-Aug-03 RMS Added instruction history - Fixed PDP-15-specific implementation of API priorities - 16-Aug-03 RMS Fixed PDP-15-specific handling of EAE unsigned mul/div - 27-Jul-03 RMS Added FP15 support - Added XVM support - Added EAE option to PDP-4 - Added PDP-15 "re-entrancy ECO" - Fixed memory protect/skip interaction - Fixed CAF not to reset CPU - 12-Mar-03 RMS Added logical name support - 18-Feb-03 RMS Fixed three EAE bugs (found by Hans Pufal) - 05-Oct-02 RMS Added DIBs, device number support - 25-Jul-02 RMS Added DECtape support for PDP-4 - 06-Jan-02 RMS Revised enable/disable support - 30-Dec-01 RMS Added old PC queue - 30-Nov-01 RMS Added extended SET/SHOW support - 25-Nov-01 RMS Revised interrupt structure - 19-Sep-01 RMS Fixed bug in EAE (found by Dave Conroy) - 17-Sep-01 RMS Fixed typo in conditional - 10-Aug-01 RMS Removed register from declarations - 17-Jul-01 RMS Moved function prototype - 27-May-01 RMS Added second Teletype support, fixed bug in API - 18-May-01 RMS Added PDP-9,-15 API option - 16-May-01 RMS Fixed bugs in protection checks - 26-Apr-01 RMS Added device enable/disable support - 25-Jan-01 RMS Added DECtape support - 18-Dec-00 RMS Added PDP-9,-15 memm init register - 30-Nov-00 RMS Fixed numerous PDP-15 bugs - 14-Apr-99 RMS Changed t_addr to unsigned - - The 18b PDP family has five distinct architectural variants: PDP-1, - PDP-4, PDP-7, PDP-9, and PDP-15. Of these, the PDP-1 is so unique - as to require a different simulator. The PDP-4, PDP-7, PDP-9, and - PDP-15 are "upward compatible", with each new variant adding - distinct architectural features and incompatibilities. - - The register state for the 18b PDP's is: - - all AC<0:17> accumulator - all MQ<0:17> multiplier-quotient - all L link flag - all PC<0:x> program counter - all IORS I/O status register - PDP-7, PDP-9 EXTM extend mode - PDP-15 BANKM bank mode - PDP-7 USMD trap mode - PDP-9, PDP-15 USMD user mode - PDP-9, PDP-15 BR bounds register - PDP-15 RR relocation register - PDP-15 XVM MMR memory management register - PDP-15 XR index register - PDP-15 LR limit register -*/ - -/* The PDP-4, PDP-7, and PDP-9 have five instruction formats: memory - reference, load immediate, I/O transfer, EAE, and operate. The PDP-15 - adds a sixth, index operate, and a seventh, floating point. The memory - reference format for the PDP-4, PDP-7, and PDP-9, and for the PDP-15 - in bank mode, is: - - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | op |in| address | memory reference - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - The PDP-15 in page mode trades an address bit for indexing capability: - - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | op |in| X| address | memory reference - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - <0:3> mnemonic action - - 00 CAL JMS with MA = 20 - 04 DAC M[MA] = AC - 10 JMS M[MA] = L'mem'user'PC, PC = MA + 1 - 14 DZM M[MA] = 0 - 20 LAC AC = M[MA] - 24 XOR AC = AC ^ M[MA] - 30 ADD L'AC = AC + M[MA] one's complement - 34 TAD L'AC = AC + M[MA] - 40 XCT M[MA] is executed as an instruction - 44 ISZ M[MA] = M[MA] + 1, skip if M[MA] == 0 - 50 AND AC = AC & M[MA] - 54 SAD skip if AC != M[MA] - 60 JMP PC = MA - - On the PDP-4, PDP-7, and PDP-9, and the PDP-15 in bank mode, memory - reference instructions can access an address space of 32K words. The - address space is divided into four 8K word fields. An instruction can - directly address, via its 13b address, the entire current field. On the - PDP-4, PDP-7, and PDP-9, if extend mode is off, indirect addresses access - the current field; if on (or a PDP-15), they can access all 32K. - - On the PDP-15 in page mode, memory reference instructions can access - an address space of 128K words. The address is divided into four 32K - word blocks, each of which consists of eight 4K pages. An instruction - can directly address, via its 12b address, the current page. Indirect - addresses can access the current block. Indexed and autoincrement - addresses can access all 128K. - - On the PDP-4 and PDP-7, if an indirect address in in locations 00010- - 00017 of any field, the indirect address is incremented and rewritten - to memory before use. On the PDP-9 and PDP-15, only locations 00010- - 00017 of field zero autoincrement; special logic will redirect indirect - references to 00010-00017 to field zero, even if (on the PDP-9) extend - mode is off. -*/ - -/* The EAE format is: - - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | 1 1 0 1| | | | | | | | | | | | | | | EAE - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | | | | | | | | | | | | | | - | | | | | | | | | | | | | +- or SC (3) - | | | | | | | | | | | | +---- or MQ (3) - | | | | | | | | | | | +------- compl MQ (3) - | | | | | | | | \______________/ - | | | | | | | | | - | | | | | \_____/ +--------- shift count - | | | | | | - | | | | | +---------------------- EAE command (3) - | | | | +---------------------------- clear AC (2) - | | | +------------------------------- or AC (2) - | | +---------------------------------- load EAE sign (1) - | +------------------------------------- clear MQ (1) - +---------------------------------------- load link (1) - - 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 0 0| device | sdv |cl| pulse | I/O transfer - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - The IO transfer instruction sends the the specified pulse to the - specified I/O device and sub-device. The I/O device may take data - from the AC, return data to the AC, initiate or cancel operations, - or skip on status. On the PDP-4, PDP-7, and PDP-9, bits <4:5> - were designated as subdevice bits but were never used; the PDP-15 - requires them to be zero. - - On the PDP-15, the floating point 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 1| subopcode | floating point - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - |in| address | - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - Indirection is always single level. -*/ - -/* On the PDP-15, the index operate 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| subopcode | immediate | index operate - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - The index operate instructions provide various operations on the - index and limit registers. - - 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 0| | | | | | | | | | | | | | operate - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | | | | | | | | | | | | | - | | | | | | | | | | | | +- CMA (3) - | | | | | | | | | | | +---- CML (3) - | | | | | | | | | | +------- OAS (3) - | | | | | | | | | +---------- RAL (3) - | | | | | | | | +------------- RAR (3) - | | | | | | | +---------------- HLT (4) - | | | | | | +------------------- SMA (1) - | | | | | +---------------------- SZA (1) - | | | | +------------------------- SNL (1) - | | | +---------------------------- invert skip (1) - | | +------------------------------- rotate twice (2) - | +---------------------------------- CLL (2) - +------------------------------------- CLA (2) - - The operate instruction can be microprogrammed to perform operations - on the AC and link. - - 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 1 1| immediate | LAW - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - <0:4> mnemonic action - - 76 LAW AC = IR -*/ - -/* This routine is the instruction decode routine for the 18b PDP's. - 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 - nested XCT's - I/O error in I/O simulator - - 2. Interrupts. Interrupt requests are maintained in the int_hwre - array. int_hwre[0:3] corresponds to API levels 0-3; int_hwre[4] - holds PI requests. - - 3. Arithmetic. The 18b PDP's implements both 1's and 2's complement - arithmetic for signed numbers. 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: - - pdp18b_defs.h add interrupt request definition - pdp18b_sys.c add sim_devices table entry -*/ - -#include "pdp18b_defs.h" - -#define SEXT(x) ((int32) (((x) & SIGN)? (x) | ~DMASK: (x) & DMASK)) - -#define UNIT_V_NOEAE (UNIT_V_UF + 0) /* EAE absent */ -#define UNIT_V_NOAPI (UNIT_V_UF + 1) /* API absent */ -#define UNIT_V_PROT (UNIT_V_UF + 2) /* protection */ -#define UNIT_V_RELOC (UNIT_V_UF + 3) /* relocation */ -#define UNIT_V_XVM (UNIT_V_UF + 4) /* XVM */ -#define UNIT_V_MSIZE (UNIT_V_UF + 5) /* dummy mask */ -#define UNIT_NOEAE (1 << UNIT_V_NOEAE) -#define UNIT_NOAPI (1 << UNIT_V_NOAPI) -#define UNIT_PROT (1 << UNIT_V_PROT) -#define UNIT_RELOC (1 << UNIT_V_RELOC) -#define UNIT_XVM (1 << UNIT_V_XVM) -#define UNIT_MSIZE (1 << UNIT_V_MSIZE) - -#define HIST_SIZE 4096 -#define HIST_API 0x40000000 -#define HIST_PI 0x20000000 -#define HIST_M_LVL 0x3F -#define HIST_V_LVL 6 -struct InstHistory { - int32 pc; - int32 ir; - int32 ir1; - int32 lac; - int32 mq; }; - -#define XVM (cpu_unit.flags & UNIT_XVM) -#define RELOC (cpu_unit.flags & UNIT_RELOC) -#define PROT (cpu_unit.flags & UNIT_PROT) - -#if defined (PDP4) -#define EAE_DFLT UNIT_NOEAE -#else -#define EAE_DFLT 0 -#endif -#if defined (PDP4) || defined (PDP7) -#define API_DFLT UNIT_NOAPI -#define PROT_DFLT 0 -#define ASW_DFLT 017763 -#else -#define API_DFLT UNIT_NOAPI /* for now */ -#define PROT_DFLT UNIT_PROT -#define ASW_DFLT 017720 -#endif - -int32 M[MAXMEMSIZE] = { 0 }; /* memory */ -int32 LAC = 0; /* link'AC */ -int32 MQ = 0; /* MQ */ -int32 PC = 0; /* PC */ -int32 iors = 0; /* IORS */ -int32 ion = 0; /* int on */ -int32 ion_defer = 0; /* int defer */ -int32 ion_inh = 0; /* int inhibit */ -int32 int_pend = 0; /* int pending */ -int32 int_hwre[API_HLVL+1] = { 0 }; /* int requests */ -int32 api_enb = 0; /* API enable */ -int32 api_req = 0; /* API requests */ -int32 api_act = 0; /* API active */ -int32 memm = 0; /* mem mode */ -#if defined (PDP15) -int32 memm_init = 1; /* mem init */ -#else -int32 memm_init = 0; -#endif -int32 usmd = 0; /* user mode */ -int32 usmd_buf = 0; /* user mode buffer */ -int32 usmd_defer = 0; /* user mode defer */ -int32 trap_pending = 0; /* trap pending */ -int32 emir_pending = 0; /* emir pending */ -int32 rest_pending = 0; /* restore pending */ -int32 BR = 0; /* mem mgt bounds */ -int32 RR = 0; /* mem mgt reloc */ -int32 MMR = 0; /* XVM mem mgt */ -int32 nexm = 0; /* nx mem flag */ -int32 prvn = 0; /* priv viol flag */ -int32 SC = 0; /* shift count */ -int32 eae_ac_sign = 0; /* EAE AC sign */ -int32 SR = 0; /* switch register */ -int32 ASW = ASW_DFLT; /* address switches */ -int32 XR = 0; /* index register */ -int32 LR = 0; /* limit register */ -int32 stop_inst = 0; /* stop on rsrv inst */ -int32 xct_max = 16; /* nested XCT limit */ -#if defined (PDP15) -int32 pcq[PCQ_SIZE] = { 0 }; /* PC queue */ -#else -int16 pcq[PCQ_SIZE] = { 0 }; /* PC queue */ -#endif -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 */ -static struct InstHistory hst[HIST_SIZE] = { { 0 } }; /* instruction history */ - -extern int32 sim_int_char; -extern int32 sim_interval; -extern int32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */ -extern DEVICE *sim_devices[]; -extern FILE *sim_log; - -t_bool build_dev_tab (void); -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_hist (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, void *desc); -void cpu_inst_hist (int32 addr, int32 inst); -void cpu_intr_hist (int32 flag, int32 lvl); -int32 upd_iors (void); -int32 api_eval (int32 *pend); -t_stat Read (int32 ma, int32 *dat, int32 cyc); -t_stat Write (int32 ma, int32 dat, int32 cyc); -t_stat Ia (int32 ma, int32 *ea, t_bool jmp); -int32 Incr_addr (int32 addr); -int32 Jms_word (int32 t); -#if defined (PDP15) -#define INDEX(i,x) if (!memm && ((i) & I_IDX)) x = ((x) + XR) & AMASK -int32 Prot15 (int32 ma, t_bool bndchk); -int32 Reloc15 (int32 ma, int32 acc); -int32 RelocXVM (int32 ma, int32 acc); -extern t_stat fp15 (int32 ir); -#else -#define INDEX(i,x) -#endif - -extern clk (int32 pulse, int32 AC); - -int32 (*dev_tab[DEV_MAX])(int32 pulse, int32 AC); /* device dispatch */ - -int32 (*dev_iors[DEV_MAX])(void); /* IORS dispatch */ - -static const int32 api_ffo[256] = { - 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - -static const int32 api_vec[API_HLVL][32] = { - { ACH_PWRFL }, /* API 0 */ - { ACH_DTA, ACH_MTA, ACH_DRM, ACH_RF, ACH_RP, ACH_RB }, /* API 1 */ - { ACH_PTR, ACH_LPT, ACH_LPT }, /* API 2 */ - { ACH_CLK, ACH_TTI1, ACH_TTO1 } }; /* API 3 */ - -/* 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+EAE_DFLT+API_DFLT+PROT_DFLT, - MAXMEMSIZE) }; - -REG cpu_reg[] = { - { ORDATA (PC, PC, ADDRSIZE) }, - { ORDATA (AC, LAC, 18) }, - { FLDATA (L, LAC, 18) }, - { ORDATA (MQ, MQ, 18) }, - { ORDATA (SC, SC, 6) }, - { FLDATA (EAE_AC_SIGN, eae_ac_sign, 18) }, - { ORDATA (SR, SR, 18) }, - { ORDATA (ASW, ASW, ADDRSIZE) }, - { ORDATA (IORS, iors, 18), REG_RO }, - { BRDATA (INT, int_hwre, 8, 32, API_HLVL+1), REG_RO }, - { FLDATA (INT_PEND, int_pend, 0), REG_RO }, - { FLDATA (ION, ion, 0) }, - { ORDATA (ION_DELAY, ion_defer, 2) }, -#if defined (PDP7) - { FLDATA (TRAPM, usmd, 0) }, - { FLDATA (TRAPP, trap_pending, 0) }, - { FLDATA (EXTM, memm, 0) }, - { FLDATA (EXTM_INIT, memm_init, 0) }, - { FLDATA (EMIRP, emir_pending, 0) }, -#endif -#if defined (PDP9) - { FLDATA (APIENB, api_enb, 0) }, - { ORDATA (APIREQ, api_req, 8) }, - { ORDATA (APIACT, api_act, 8) }, - { ORDATA (BR, BR, ADDRSIZE) }, - { FLDATA (USMD, usmd, 0) }, - { FLDATA (USMDBUF, usmd_buf, 0) }, - { FLDATA (USMDDEF, usmd_defer, 0) }, - { FLDATA (NEXM, nexm, 0) }, - { FLDATA (PRVN, prvn, 0) }, - { FLDATA (TRAPP, trap_pending, 0) }, - { FLDATA (EXTM, memm, 0) }, - { FLDATA (EXTM_INIT, memm_init, 0) }, - { FLDATA (EMIRP, emir_pending, 0) }, - { FLDATA (RESTP, rest_pending, 0) }, - { FLDATA (PWRFL, int_hwre[API_PWRFL], INT_V_PWRFL) }, -#endif -#if defined (PDP15) - { FLDATA (ION_INH, ion_inh, 0) }, - { FLDATA (APIENB, api_enb, 0) }, - { ORDATA (APIREQ, api_req, 8) }, - { ORDATA (APIACT, api_act, 8) }, - { ORDATA (XR, XR, 18) }, - { ORDATA (LR, LR, 18) }, - { ORDATA (BR, BR, 18) }, - { ORDATA (RR, RR, 18) }, - { ORDATA (MMR, MMR, 18) }, - { FLDATA (USMD, usmd, 0) }, - { FLDATA (USMDBUF, usmd_buf, 0) }, - { FLDATA (USMDDEF, usmd_defer, 0) }, - { FLDATA (NEXM, nexm, 0) }, - { FLDATA (PRVN, prvn, 0) }, - { FLDATA (TRAPP, trap_pending, 0) }, - { FLDATA (BANKM, memm, 0) }, - { FLDATA (BANKM_INIT, memm_init, 0) }, - { FLDATA (RESTP, rest_pending, 0) }, - { FLDATA (PWRFL, int_hwre[API_PWRFL], INT_V_PWRFL) }, -#endif - { BRDATA (PCQ, pcq, 8, ADDRSIZE, PCQ_SIZE), REG_RO+REG_CIRC }, - { ORDATA (PCQP, pcq_p, 6), REG_HRO }, - { FLDATA (STOP_INST, stop_inst, 0) }, - { DRDATA (XCT_MAX, xct_max, 8), PV_LEFT + REG_NZ }, - { ORDATA (WRU, sim_int_char, 8) }, - { NULL } }; - -MTAB cpu_mod[] = { - { UNIT_NOEAE, UNIT_NOEAE, "no EAE", "NOEAE", NULL }, - { UNIT_NOEAE, 0, "EAE", "EAE", NULL }, -#if defined (PDP9) || defined (PDP15) - { UNIT_NOAPI, UNIT_NOAPI, "no API", "NOAPI", NULL }, - { UNIT_NOAPI, 0, "API", "API", NULL }, - { UNIT_PROT+UNIT_RELOC+UNIT_XVM, 0, "no memory protect", - "NOPROTECT", NULL }, - { UNIT_PROT+UNIT_RELOC+UNIT_XVM, UNIT_PROT, "memory protect", - "PROTECT", NULL }, -#endif -#if defined (PDP15) - { UNIT_PROT+UNIT_RELOC+UNIT_XVM, UNIT_PROT+UNIT_RELOC, - "memory relocation", "RELOCATION", NULL }, - { UNIT_PROT+UNIT_RELOC+UNIT_XVM, UNIT_PROT+UNIT_RELOC+UNIT_XVM, - "XVM", "XVM", NULL }, -#endif -#if defined (PDP4) - { UNIT_MSIZE, 4096, NULL, "4K", &cpu_set_size }, -#endif - { UNIT_MSIZE, 8192, NULL, "8K", &cpu_set_size }, -#if (MAXMEMSIZE > 8192) - { 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 }, -#endif -#if (MAXMEMSIZE > 32768) - { UNIT_MSIZE, 49152, NULL, "48K", &cpu_set_size }, - { UNIT_MSIZE, 65536, NULL, "64K", &cpu_set_size }, - { UNIT_MSIZE, 81920, NULL, "80K", &cpu_set_size }, - { UNIT_MSIZE, 98304, NULL, "96K", &cpu_set_size }, - { UNIT_MSIZE, 114688, NULL, "112K", &cpu_set_size }, - { UNIT_MSIZE, 131072, NULL, "128K", &cpu_set_size }, -#endif - { MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, "HISTORY", "HISTORY", - &cpu_set_hist, &cpu_show_hist }, - { 0 } }; - -DEVICE cpu_dev = { - "CPU", &cpu_unit, cpu_reg, cpu_mod, - 1, 8, ADDRSIZE, 1, 8, 18, - &cpu_ex, &cpu_dep, &cpu_reset, - NULL, NULL, NULL }; - -t_stat sim_instr (void) -{ -int32 api_int, api_usmd, skp; -int32 iot_data, device, pulse; -t_stat reason; -extern UNIT clk_unit; - -if (build_dev_tab ()) return SCPE_STOP; /* build, chk tables */ -PC = PC & AMASK; /* clean variables */ -LAC = LAC & LACMASK; -MQ = MQ & DMASK; -reason = 0; -sim_rtc_init (clk_unit.wait); /* init calibration */ -if (cpu_unit.flags & UNIT_NOAPI) api_enb = api_req = api_act = 0; -api_int = api_eval (&int_pend); /* eval API */ -api_usmd = 0; /* not API user cycle */ - -/* Main instruction fetch/decode loop */ - -while (reason == 0) { /* loop until halted */ -int32 IR, MA, MB, esc, t, xct_count; -int32 link_init, fill; - -if (sim_interval <= 0) { /* check clock queue */ - if (reason = sim_process_event ()) break; - api_int = api_eval (&int_pend); } /* eval API */ - -/* PDP-4 and PDP-7 traps and interrupts - - PDP-4 no trap - PDP-7 trap: extend mode forced on, M[0] = PC, PC = 2 - PDP-4, PDP-7 programmable interrupts only */ - -#if defined (PDP4) || defined (PDP7) -#if defined (PDP7) -if (trap_pending) { /* trap pending? */ - PCQ_ENTRY; /* save old PC */ - MB = Jms_word (1); /* save state */ - ion = 0; /* interrupts off */ - memm = 1; /* extend on */ - emir_pending = trap_pending = 0; /* emir, trap off */ - usmd = usmd_buf = 0; /* user mode off */ - Write (0, MB, WR); /* save in 0 */ - PC = 2; } /* fetch next from 2 */ -#endif -if (int_pend && ion && !ion_defer) { /* interrupt? */ - PCQ_ENTRY; /* save old PC */ - MB = Jms_word (usmd); /* save state */ - ion = 0; /* interrupts off */ - memm = 0; /* extend off */ - emir_pending = rest_pending = 0; /* emir, restore off */ - usmd = usmd_buf = 0; /* user mode off */ - Write (0, MB, WR); /* physical write */ - PC = 1; } /* fetch next from 1 */ - -if (sim_brk_summ && sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */ - reason = STOP_IBKPT; /* stop simulation */ - break; } - -#endif /* end PDP-4/PDP-7 */ - -/* PDP-9 and PDP-15 traps and interrupts - - PDP-9 trap: extend mode ???, M[0/20] = PC, PC = 0/21 - PDP-15 trap: bank mode unchanged, M[0/20] = PC, PC = 0/21 - PDP-9, PDP-15 API and program interrupts */ - -#if defined (PDP9) || defined (PDP15) -if (trap_pending) { /* trap pending? */ - PCQ_ENTRY; /* save old PC */ - MB = Jms_word (1); /* save state */ - MA = ion? 0: 020; /* save in 0/20 */ - ion = 0; /* interrupts off */ - emir_pending = rest_pending = trap_pending = 0; /* emir,rest,trap off */ - usmd = usmd_buf = 0; /* user mode off */ - Write (MA, MB, WR); /* physical write */ - PC = MA + 1; } /* fetch next */ - -if (api_int && !ion_defer) { /* API intr? */ - int32 i, lvl = api_int - 1; /* get req level */ - if (hst_lnt) cpu_intr_hist (HIST_API, lvl); /* record */ - api_act = api_act | (API_ML0 >> lvl); /* set level active */ - if (lvl >= API_HLVL) { /* software req? */ - MA = ACH_SWRE + lvl - API_HLVL; /* vec = 40:43 */ - api_req = api_req & ~(API_ML0 >> 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; } - api_int = api_eval (&int_pend); /* no API int */ - api_usmd = usmd; /* API user mode cycle */ - usmd = usmd_buf = 0; /* user mode off */ - emir_pending = rest_pending = 0; /* emir, restore off */ - xct_count = 0; - goto xct_instr; } - -if (int_pend && ion && !ion_defer && /* int pending, enabled? */ - !(api_enb && (api_act & API_MASKPI))) { /* API off or not masking PI? */ - PCQ_ENTRY; /* save old PC */ - if (hst_lnt) cpu_intr_hist (HIST_PI, 0); /* record */ - MB = Jms_word (usmd); /* save state */ - ion = 0; /* interrupts off */ -#if defined (PDP9) /* PDP-9, */ - memm = 0; /* extend off */ -#else /* PDP-15 */ - ion_defer = 2; /* free instruction */ - if (!(cpu_unit.flags & UNIT_NOAPI)) { /* API? */ - api_act = api_act | API_ML3; /* set lev 3 active */ - api_int = api_eval (&int_pend); } /* re-evaluate */ -#endif - emir_pending = rest_pending = 0; /* emir, restore off */ - usmd = usmd_buf = 0; /* user mode off */ - Write (0, MB, WR); /* physical write */ - PC = 1; } /* fetch next from 1 */ - -if (sim_brk_summ && sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */ - reason = STOP_IBKPT; /* stop simulation */ - break; } -if (!usmd_defer) usmd = usmd_buf; /* no IOT? load usmd */ -else usmd_defer = 0; /* cancel defer */ - -#endif /* PDP-9/PDP-15 */ - -/* Instruction fetch and address decode */ - -xct_count = 0; /* track nested XCT's */ -MA = PC; /* fetch at PC */ -PC = Incr_addr (PC); /* increment PC */ - -xct_instr: /* label for XCT */ -if (Read (MA, &IR, FE)) continue; /* fetch instruction */ -if (hst_lnt) cpu_inst_hist (MA, IR); /* history? */ -if (ion_defer) ion_defer = ion_defer - 1; /* count down defer */ -if (sim_interval) sim_interval = sim_interval - 1; - -#if defined (PDP15) /* PDP15 */ -if (memm) MA = (MA & B_EPCMASK) | (IR & B_DAMASK); /* bank mode dir addr */ -else MA = (MA & P_EPCMASK) | (IR & P_DAMASK); /* page mode dir addr */ -#else /* others */ -MA = (MA & B_EPCMASK) | (IR & B_DAMASK); /* bank mode only */ -#endif -switch ((IR >> 13) & 037) { /* decode IR<0:4> */ - -/* LAC: opcode 20 */ - -case 011: /* LAC, indir */ - if (Ia (MA, &MA, 0)) break; -case 010: /* LAC, dir */ - INDEX (IR, MA); - if (Read (MA, &MB, RD)) break; - LAC = (LAC & LINK) | MB; - break; - -/* DAC: opcode 04 */ - -case 003: /* DAC, indir */ - if (Ia (MA, &MA, 0)) break; -case 002: /* DAC, dir */ - INDEX (IR, MA); - Write (MA, LAC & DMASK, WR); - break; - -/* DZM: opcode 14 */ - -case 007: /* DZM, indir */ - if (Ia (MA, &MA, 0)) break; -case 006: /* DZM, direct */ - INDEX (IR, MA); - Write (MA, 0, WR); - break; - -/* AND: opcode 50 */ - -case 025: /* AND, ind */ - if (Ia (MA, &MA, 0)) break; -case 024: /* AND, dir */ - INDEX (IR, MA); - if (Read (MA, &MB, RD)) break; - LAC = LAC & (MB | LINK); - break; - -/* XOR: opcode 24 */ - -case 013: /* XOR, ind */ - if (Ia (MA, &MA, 0)) break; -case 012: /* XOR, dir */ - INDEX (IR, MA); - if (Read (MA, &MB, RD)) break; - LAC = LAC ^ MB; - break; - -/* ADD: opcode 30 */ - -case 015: /* ADD, indir */ - if (Ia (MA, &MA, 0)) break; -case 014: /* ADD, dir */ - INDEX (IR, MA); - if (Read (MA, &MB, RD)) break; - t = (LAC & DMASK) + MB; - if (t > DMASK) t = (t + 1) & DMASK; /* end around carry */ - if (((~LAC ^ MB) & (LAC ^ t)) & SIGN) /* overflow? */ - LAC = LINK | t; /* set link */ - else LAC = (LAC & LINK) | t; - break; - -/* TAD: opcode 34 */ - -case 017: /* TAD, indir */ - if (Ia (MA, &MA, 0)) break; -case 016: /* TAD, dir */ - INDEX (IR, MA); - if (Read (MA, &MB, RD)) break; - LAC = (LAC + MB) & LACMASK; - break; - -/* ISZ: opcode 44 */ - -case 023: /* ISZ, indir */ - if (Ia (MA, &MA, 0)) break; -case 022: /* ISZ, dir */ - INDEX (IR, MA); - if (Read (MA, &MB, RD)) break; - MB = (MB + 1) & DMASK; - if (Write (MA, MB, WR)) break; - if (MB == 0) PC = Incr_addr (PC); - break; - -/* SAD: opcode 54 */ - -case 027: /* SAD, indir */ - if (Ia (MA, &MA, 0)) break; -case 026: /* SAD, dir */ - INDEX (IR, MA); - if (Read (MA, &MB, RD)) break; - if ((LAC & DMASK) != MB) PC = Incr_addr (PC); - break; - -/* XCT: opcode 40 */ - -case 021: /* XCT, indir */ - if (Ia (MA, &MA, 0)) break; -case 020: /* XCT, dir */ - INDEX (IR, MA); - if ((api_usmd | usmd) && (xct_count != 0)) { /* chained and usmd? */ - if (usmd) prvn = trap_pending = 1; /* trap if usmd */ - break; } /* nop if api_usmd */ - if (xct_count >= xct_max) { /* too many XCT's? */ - reason = STOP_XCT; - break; } - xct_count = xct_count + 1; /* count XCT's */ -#if defined (PDP9) - ion_defer = 1; /* defer intr */ -#endif - goto xct_instr; /* go execute */ - -/* CAL: opcode 00 - api_usmd records whether usmd = 1 at start of API cycle - - On the PDP-4 and PDP-7, CAL (I) is exactly the same as JMS (I) 20 - On the PDP-9 and PDP-15, CAL clears user mode - On the PDP-9 and PDP-15 with API, CAL activates level 4 - On the PDP-15, CAL goes to absolute 20, regardless of mode */ - -case 001: case 000: /* CAL */ - t = usmd; /* save user mode */ -#if defined (PDP15) /* PDP15 */ - MA = 020; /* MA = abs 20 */ - ion_defer = 1; /* "free instruction" */ -#else /* others */ - if (memm) MA = 020; /* if ext, abs 20 */ - else MA = (PC & B_EPCMASK) | 020; /* else bank-rel 20 */ -#endif -#if defined (PDP9) || defined (PDP15) - usmd = usmd_buf = 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); } -#endif - if (IR & I_IND) { /* indirect? */ - if (Ia (MA, &MA, 0)) break; } - PCQ_ENTRY; - MB = Jms_word (api_usmd | t); /* save state */ - Write (MA, MB, WR); - PC = Incr_addr (MA); - break; - -/* JMS: opcode 010 - api_usmd records whether usmd = 1 at start of API cycle */ - -case 005: /* JMS, indir */ - if (Ia (MA, &MA, 0)) break; -case 004: /* JMS, dir */ - INDEX (IR, MA); - PCQ_ENTRY; -#if defined (PDP15) /* PDP15 */ - if (!usmd) ion_defer = 1; /* "free instruction" */ -#endif - MB = Jms_word (api_usmd | usmd); /* save state */ - if (Write (MA, MB, WR)) break; - PC = Incr_addr (MA); - break; - -/* JMP: opcode 60 */ - -case 031: /* JMP, indir */ - if (Ia (MA, &MA, 1)) break; -case 030: /* JMP, dir */ - INDEX (IR, MA); - PCQ_ENTRY; /* save old PC */ - PC = MA; - break; - -/* OPR: opcode 74 */ - -case 037: /* OPR, indir */ - LAC = (LAC & LINK) | IR; /* LAW */ - break; - -case 036: /* OPR, dir */ - skp = 0; /* assume no skip */ - switch ((IR >> 6) & 017) { /* decode IR<8:11> */ - case 0: /* nop */ - break; - case 1: /* SMA */ - if ((LAC & SIGN) != 0) skp = 1; - break; - case 2: /* SZA */ - if ((LAC & DMASK) == 0) skp = 1; - break; - case 3: /* SZA | SMA */ - if (((LAC & DMASK) == 0) || ((LAC & SIGN) != 0)) - skp = 1; - break; - case 4: /* SNL */ - if (LAC >= LINK) skp = 1; - break; - case 5: /* SNL | SMA */ - if (LAC >= SIGN) skp = 1; - break; - case 6: /* SNL | SZA */ - if ((LAC >= LINK) || (LAC == 0)) skp = 1; - break; - case 7: /* SNL | SZA | SMA */ - if ((LAC >= SIGN) || (LAC == 0)) skp = 1; - break; - case 010: /* SKP */ - skp = 1; - break; - case 011: /* SPA */ - if ((LAC & SIGN) == 0) skp = 1; - break; - case 012: /* SNA */ - if ((LAC & DMASK) != 0) skp = 1; - break; - case 013: /* SNA & SPA */ - if (((LAC & DMASK) != 0) && ((LAC & SIGN) == 0)) - skp = 1; - break; - case 014: /* SZL */ - if (LAC < LINK) skp = 1; - break; - case 015: /* SZL & SPA */ - if (LAC < SIGN) skp = 1; - break; - case 016: /* SZL & SNA */ - if ((LAC < LINK) && (LAC != 0)) skp = 1; - break; - case 017: /* SZL & SNA & SPA */ - if ((LAC < SIGN) && (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; - case 1: /* CMA */ - LAC = LAC ^ DMASK; - break; - case 2: /* CML */ - LAC = LAC ^ LINK; - break; - case 3: /* CML CMA */ - LAC = LAC ^ LACMASK; - break; - case 4: /* CLL */ - LAC = LAC & DMASK; - break; - case 5: /* CLL CMA */ - LAC = (LAC & DMASK) ^ DMASK; - break; - case 6: /* CLL CML = STL */ - LAC = LAC | LINK; - break; - case 7: /* CLL CML CMA */ - LAC = (LAC | LINK) ^ DMASK; - break; - case 010: /* CLA */ - LAC = LAC & LINK; - break; - case 011: /* CLA CMA = STA */ - LAC = LAC | DMASK; - break; - case 012: /* CLA CML */ - LAC = (LAC & LINK) ^ LINK; - break; - case 013: /* CLA CML CMA */ - LAC = (LAC | DMASK) ^ LINK; - break; - case 014: /* CLA CLL */ - LAC = 0; - break; - case 015: /* CLA CLL CMA */ - LAC = DMASK; - break; - case 016: /* CLA CLL CML */ - LAC = LINK; - break; - case 017: /* CLA CLL CML CMA */ - LAC = LACMASK; - break; } /* end decode */ - -/* OPR, continued */ - - if (IR & 0000004) { /* OAS */ -#if defined (PDP9) || defined (PDP15) - if (usmd) prvn = trap_pending = 1; /* trap if usmd */ - else if (!api_usmd) /* nop if api_usmd */ -#endif - LAC = LAC | SR; } - - switch (((IR >> 8) & 04) | ((IR >> 3) & 03)) { /* decode IR<7,13:14> */ - case 1: /* RAL */ - LAC = ((LAC << 1) | (LAC >> 18)) & LACMASK; - break; - case 2: /* RAR */ - LAC = ((LAC >> 1) | (LAC << 18)) & LACMASK; - break; - case 3: /* RAL RAR */ -#if defined (PDP15) /* PDP-15 */ - LAC = (LAC + 1) & LACMASK; /* IAC */ -#else /* PDP-4,-7,-9 */ - reason = stop_inst; /* undefined */ -#endif - break; - case 5: /* RTL */ - LAC = ((LAC << 2) | (LAC >> 17)) & LACMASK; - break; - case 6: /* RTR */ - LAC = ((LAC >> 2) | (LAC << 17)) & LACMASK; - break; - case 7: /* RTL RTR */ -#if defined (PDP15) /* PDP-15 */ - LAC = ((LAC >> 9) & 0777) | ((LAC & 0777) << 9) | - (LAC & LINK); /* BSW */ -#else /* PDP-4,-7,-9 */ - reason = stop_inst; /* undefined */ -#endif - break; } /* end switch rotate */ - - if (IR & 0000040) { /* HLT */ - if (usmd) prvn = trap_pending = 1; /* trap if usmd */ - else if (!api_usmd) reason = STOP_HALT; } /* nop if api_usmd */ - if (skp) PC = Incr_addr (PC); /* if skip, inc PC */ - break; /* end OPR */ - -/* EAE: opcode 64 - - The EAE is microprogrammed to execute variable length signed and - unsigned shift, multiply, divide, and normalize. Most commands are - controlled by a six bit step counter (SC). In the hardware, the step - counter is complemented on load and then counted up to zero; timing - guarantees an initial increment, which completes the two's complement - load. In the simulator, the SC is loaded normally and then counted - down to zero; the read SC command compensates. */ - -case 033: case 032: /* EAE */ - if (cpu_unit.flags & UNIT_NOEAE) break; /* disabled? */ - if (IR & 0020000) /* IR<4>? AC0 to L */ - LAC = ((LAC << 1) & LINK) | (LAC & DMASK); - if (IR & 0010000) MQ = 0; /* IR<5>? clear MQ */ - if ((IR & 0004000) && (LAC & SIGN)) /* IR<6> and minus? */ - eae_ac_sign = LINK; /* set eae_ac_sign */ - else eae_ac_sign = 0; /* if not, unsigned */ - if (IR & 0002000) MQ = (MQ | LAC) & DMASK; /* IR<7>? or AC */ - else if (eae_ac_sign) LAC = LAC ^ DMASK; /* if not, |AC| */ - if (IR & 0001000) LAC = LAC & LINK; /* IR<8>? clear AC */ - link_init = LAC & LINK; /* link temporary */ - fill = link_init? DMASK: 0; /* fill = link */ - esc = IR & 077; /* get eff SC */ - - switch ((IR >> 6) & 07) { /* case on IR<9:11> */ - case 0: /* setup */ - if (IR & 04) MQ = MQ ^ DMASK; /* IR<15>? ~MQ */ - if (IR & 02) LAC = LAC | MQ; /* IR<16>? or MQ */ - if (IR & 01) LAC = LAC | ((-SC) & 077); /* IR<17>? or SC */ - break; - -/* EAE, continued - - Multiply uses a shift and add algorithm. The PDP-15, unlike prior - implementations, factors IR<6> (signed multiply) into the calculation - of the result sign. */ - - case 1: /* multiply */ - if (Read (PC, &MB, FE)) break; /* get next word */ - PC = Incr_addr (PC); /* increment PC */ - if (eae_ac_sign) MQ = MQ ^ DMASK; /* EAE AC sign? ~MQ */ - LAC = LAC & DMASK; /* clear link */ - SC = esc; /* init SC */ - do { /* loop */ - if (MQ & 1) LAC = LAC + MB; /* MQ<17>? add */ - MQ = (MQ >> 1) | ((LAC & 1) << 17); - LAC = LAC >> 1; /* shift AC'MQ right */ - SC = (SC - 1) & 077; } /* decrement SC */ - while (SC != 0); /* until SC = 0 */ -#if defined (PDP15) - if ((IR & 0004000) && (eae_ac_sign ^ link_init)) { -#else - if (eae_ac_sign ^ link_init) { /* result negative? */ -#endif - LAC = LAC ^ DMASK; - MQ = MQ ^ DMASK; } - break; - -/* Divide uses a non-restoring divide. Divide uses a subtract and shift - algorithm. The quotient is generated in true form. The PDP-15, unlike - prior implementations, factors IR<6> (signed multiply) into the calculation - of the result sign.*/ - - case 3: /* divide */ - if (Read (PC, &MB, FE)) break; /* get next word */ - PC = Incr_addr (PC); /* increment PC */ - if (eae_ac_sign) MQ = MQ ^ DMASK; /* EAE AC sign? ~MQ */ - if ((LAC & DMASK) >= MB) { /* overflow? */ - LAC = (LAC - MB) | LINK; /* set link */ - break; } - LAC = LAC & DMASK; /* clear link */ - t = 0; /* init loop */ - SC = esc; /* init SC */ - do { /* loop */ - if (t) LAC = (LAC + MB) & LACMASK; - else LAC = (LAC - MB) & LACMASK; - t = (LAC >> 18) & 1; /* quotient bit */ - if (SC > 1) LAC = /* skip if last */ - ((LAC << 1) | (MQ >> 17)) & LACMASK; - MQ = ((MQ << 1) | (t ^ 1)) & DMASK; /* shift in quo bit */ - SC = (SC - 1) & 077; } /* decrement SC */ - while (SC != 0); /* until SC = 0 */ - if (t) LAC = (LAC + MB) & LACMASK; - if (eae_ac_sign) LAC = LAC ^ DMASK; /* sgn rem = sgn divd */ -#if defined (PDP15) - if ((IR & 0004000) && (eae_ac_sign ^ link_init)) -#else - if (eae_ac_sign ^ link_init) /* result negative? */ -#endif - MQ = MQ ^ DMASK; - break; - -/* EAE, continued - - EAE shifts, whether left or right, fill from the link. If the - operand sign has been copied to the link, this provides correct - sign extension for one's complement numbers. */ - - case 4: /* normalize */ -#if defined (PDP15) - if (!usmd) ion_defer = 2; /* free instructions */ -#endif - for (SC = esc; ((LAC & SIGN) == ((LAC << 1) & SIGN)); ) { - LAC = (LAC << 1) | ((MQ >> 17) & 1); - MQ = (MQ << 1) | (link_init >> 18); - SC = (SC - 1) & 077; - if (SC == 0) break; } - LAC = link_init | (LAC & DMASK); /* trim AC, restore L */ - MQ = MQ & DMASK; /* trim MQ */ - SC = SC & 077; /* trim SC */ - break; - - case 5: /* long right shift */ - if (esc < 18) { - MQ = ((LAC << (18 - esc)) | (MQ >> esc)) & DMASK; - LAC = ((fill << (18 - esc)) | (LAC >> esc)) & LACMASK; } - else { - if (esc < 36) MQ = - ((fill << (36 - esc)) | (LAC >> (esc - 18))) & DMASK; - 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))) & DMASK); - MQ = ((MQ << esc) | (fill >> (18 - esc))) & DMASK; } - else { - if (esc < 36) LAC = link_init | - (((MQ << (esc - 18)) | (fill >> (36 - esc))) & DMASK); - 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))) & DMASK); - else LAC = link_init | fill; - SC = 0; /* clear step count */ - break; } /* end switch IR */ - break; /* end case EAE */ - -/* PDP-15 index operates: opcode 72 */ - -case 035: /* index operates */ -#if defined (PDP15) - t = (IR & 0400)? IR | 0777000: IR & 0377; /* sext immediate */ - switch ((IR >> 9) & 017) { /* case on IR<5:8> */ - case 000: /* AAS */ - LAC = (LAC & LINK) | ((LAC + t) & DMASK); - if (SEXT (LAC & DMASK) >= SEXT (LR)) - PC = Incr_addr (PC); - case 001: /* PAX */ - XR = LAC & DMASK; - break; - case 002: /* PAL */ - LR = LAC & DMASK; - break; - case 003: /* AAC */ - LAC = (LAC & LINK) | ((LAC + t) & DMASK); - break; - case 004: /* PXA */ - LAC = (LAC & LINK) | XR; - break; - case 005: /* AXS */ - XR = (XR + t) & DMASK; - if (SEXT (XR) >= SEXT (LR)) PC = Incr_addr (PC); - break; - case 006: /* PXL */ - LR = XR; - break; - case 010: /* PLA */ - LAC = (LAC & LINK) | LR; - break; - case 011: /* PLX */ - XR = LR; - break; - case 014: /* CLAC */ - LAC = LAC & LINK; - break; - case 015: /* CLX */ - XR = 0; - break; - case 016: /* CLLR */ - LR = 0; - break; - case 017: /* AXR */ - XR = (XR + t) & DMASK; - break; } /* end switch IR */ - break; /* end case */ -#endif - -/* IOT: opcode 70 - - The 18b PDP's have different definitions of various control IOT's. - - IOT PDP-4 PDP-7 PDP-9 PDP-15 - - 700002 IOF IOF IOF IOF - 700022 undefined undefined undefined ORMM (XVM) - 700042 ION ION ION ION - 700024 undefined undefined undefined LDMM (XVM) - 700062 undefined ITON undefined undefined - 701701 undefined undefined MPSK MPSK - 701741 undefined undefined MPSNE MPSNE - 701702 undefined undefined MPCV MPCV - 701722 undefined undefined undefined MPRC (XVM) - 701742 undefined undefined MPEU MPEU - 701704 undefined undefined MPLD MPLD - 701724 undefined undefined undefined MPLR (KT15, XVM) - 701744 undefined undefined MPCNE MPCNE - 701764 undefined undefined undefined IPFH (XVM) - 703201 undefined undefined PFSF PFSF - 703301 undefined TTS TTS TTS - 703341 undefined SKP7 SKP7 SPCO - 703302 undefined CAF CAF CAF - 703304 undefined undefined DBK DBK - 703344 undefined undefined DBR DBR - 705501 undefined undefined SPI SPI - 705521 undefined undefined undefined ENB - 705502 undefined undefined RPL RPL - 705522 undefined undefined undefined INH - 705504 undefined undefined ISA ISA - 707701 undefined SEM SEM undefined - 707741 undefined undefined undefined SKP15 - 707761 undefined undefined undefined SBA - 707702 undefined EEM EEM undefined - 707742 undefined EMIR EMIR RES - 707762 undefined undefined undefined DBA - 707704 undefined LEM LEM undefined - 707764 undefined undefined undefined EBA */ - -case 034: /* IOT */ -#if defined (PDP15) - if (IR & 0010000) { /* floating point? */ - reason = fp15 (IR); /* process */ - break; } -#endif - if ((api_usmd | usmd) && /* user, not XVM UIOT? */ - (!XVM || !(MMR & MM_UIOT))) { - if (usmd) prvn = trap_pending = 1; /* trap if user */ - break; } /* nop if api_usmd */ - device = (IR >> 6) & 077; /* device = IR<6:11> */ - pulse = IR & 067; /* pulse = IR<12:17> */ - if (IR & 0000010) LAC = LAC & LINK; /* clear AC? */ - iot_data = LAC & DMASK; /* AC unchanged */ - -/* PDP-4 system IOT's */ - -#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; -#endif - -/* PDP-7 system IOT's */ - -#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 = usmd_buf = 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 (1); /* CAF - skip CPU */ - 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; -#endif - -/* PDP-9 system IOT's */ - -#if defined (PDP9) - ion_defer = 1; /* delay interrupts */ - usmd_defer = 1; /* defer load user */ - 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; - case 017: /* mem protection */ - if (PROT) { /* enabled? */ - 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) usmd_buf = 1; - else if (pulse == 004) BR = LAC & BRMASK; - else if (pulse == 044) nexm = 0; } - else reason = stop_inst; - break; - case 032: /* power fail */ - 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) { /* CAF */ - reset_all (1); /* reset all exc CPU */ - api_enb = api_req = api_act = 0; } /* reset API system */ - 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 & ~(API_ML0 >> 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; - 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; -#endif - -/* PDP-15 system IOT's - includes "re-entrancy ECO" ENB/INH as standard */ - -#if defined (PDP15) - ion_defer = 1; /* delay interrupts */ - usmd_defer = 1; /* defer load user */ - 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 if (XVM && (pulse == 022)) /* ORMM/RDMM */ - iot_data = MMR; - else if (XVM && (pulse == 024)) /* LDMM */ - MMR = iot_data; - else iot_data = clk (pulse, iot_data); - break; - case 017: /* mem protection */ - if (PROT) { /* enabled? */ - t = XVM? BRMASK_XVM: BRMASK; - 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) usmd_buf = 1; - else if (pulse == 004) BR = LAC & t; - else if (RELOC && (pulse == 024)) RR = LAC & t; - else if (pulse == 044) nexm = 0; } - else reason = stop_inst; - break; - case 032: /* power fail */ - 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) { /* CAF */ - reset_all (2); /* reset all exc CPU, FP15 */ - api_enb = api_req = api_act = 0; } /* reset API system */ - 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 & ~(API_ML0 >> 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); } - else if (pulse == 021) ion_inh = 0; /* ENB */ - else if (pulse == 022) ion_inh = 1; /* INH */ - break; - 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 */ - 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 */ - LAC = LAC | (iot_data & DMASK); - if (iot_data & IOT_SKP) PC = Incr_addr (PC); - if (iot_data >= IOT_REASON) reason = iot_data >> IOT_V_REASON; - api_int = api_eval (&int_pend); /* eval API */ - break; /* end case IOT */ - } /* end switch opcode */ -api_usmd = 0; /* API cycle over */ -} /* end while */ - -/* Simulation halted */ - -iors = upd_iors (); /* get IORS */ -pcq_r->qptr = pcq_p; /* update pc q ptr */ -return reason; -} - -/* Evaluate API */ - -int32 api_eval (int32 *pend) -{ -int32 i, hi; - -*pend = 0; /* assume no intr */ -#if defined (PDP15) /* PDP15 only */ -if (ion_inh) return 0; /* inhibited? */ -#endif -for (i = 0; i < API_HLVL+1; i++) { /* any intr? */ - if (int_hwre[i]) *pend = 1; } -if (api_enb == 0) return 0; /* off? no req */ -api_req = api_req & ~(API_ML0|API_ML1|API_ML2|API_ML3); /* 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 | (API_ML0 >> 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; -} - -/* Process IORS instruction */ - -int32 upd_iors (void) -{ -int32 d, p; - -d = (ion? IOS_ION: 0); /* ION */ -for (p = 0; dev_iors[p] != NULL; p++) { /* loop thru table */ - d = d | dev_iors[p](); } /* OR in results */ -return d; -} - -#if defined (PDP4) || defined (PDP7) - -/* Read, write, indirect, increment routines - On the PDP-4 and PDP-7, - There are autoincrement locations in every field. If a field - does not exist, it is impossible to generate an - autoincrement reference (all instructions are CAL). - Indirect addressing range is determined by extend mode. - JMP I with EMIR pending can only clear extend - There is no memory protection, nxm reads zero and ignores writes. */ - -t_stat Read (int32 ma, int32 *dat, int32 cyc) -{ -ma = ma & AMASK; -if (MEM_ADDR_OK (ma)) *dat = M[ma] & DMASK; -else *dat = 0; -return MM_OK; -} - -t_stat Write (int32 ma, int32 dat, int32 cyc) -{ -ma = ma & AMASK; -if (MEM_ADDR_OK (ma)) M[ma] = dat & DMASK; -return MM_OK; -} - -t_stat Ia (int32 ma, int32 *ea, t_bool jmp) -{ -int32 t; -t_stat sta = MM_OK; - -if ((ma & B_DAMASK) == 010) { /* autoindex? */ - Read (ma, &t, DF); /* add 1 before use */ - t = (t + 1) & DMASK; - sta = Write (ma, t, DF); } -else sta = Read (ma, &t, DF); /* fetch indirect */ -if (jmp) { /* jmp i? */ - if (emir_pending && (((t >> 16) & 1) == 0)) memm = 0; - emir_pending = rest_pending = 0; } -if (memm) *ea = t & IAMASK; /* extend? 15b ia */ -else *ea = (ma & B_EPCMASK) | (t & B_DAMASK); /* bank-rel ia */ -return sta; -} - -int32 Incr_addr (int32 ma) -{ -return ((ma & B_EPCMASK) | ((ma + 1) & B_DAMASK)); -} - -int32 Jms_word (int32 t) -{ -return (((LAC & LINK) >> 1) | ((memm & 1) << 16) | - ((t & 1) << 15) | (PC & IAMASK)); -} - -#endif - -#if defined (PDP9) - -/* Read, write, indirect, increment routines - On the PDP-9, - The autoincrement registers are in field zero only. Regardless - of extend mode, indirect addressing through 00010-00017 - will access absolute locations 00010-00017. - Indirect addressing range is determined by extend mode. If - extend mode is off, and autoincrementing is used, the - resolved address is in bank 0 (KG09B maintenance manual). - JMP I with EMIR pending can only clear extend - JMP I with DBK pending restores L, user mode, extend mode - Memory protection is implemented for foreground/background operation. */ - -t_stat Read (int32 ma, int32 *dat, int32 cyc) -{ -ma = ma & AMASK; -if (usmd) { /* user mode? */ - if (!MEM_ADDR_OK (ma)) { /* nxm? */ - nexm = prvn = trap_pending = 1; /* set flags, trap */ - *dat = 0; - return MM_ERR; } - if ((cyc != DF) && (ma < BR)) { /* boundary viol? */ - prvn = trap_pending = 1; /* set flag, trap */ - *dat = 0; - return MM_ERR; } } -if (MEM_ADDR_OK (ma)) *dat = M[ma] & DMASK; /* valid mem? ok */ -else { *dat = 0; /* set flag, no trap */ - nexm = 1; } -return MM_OK; -} - -t_stat Write (int32 ma, int32 dat, int32 cyc) -{ -ma = ma & AMASK; -if (usmd) { - if (!MEM_ADDR_OK (ma)) { /* nxm? */ - nexm = prvn = trap_pending = 1; /* set flags, trap */ - return MM_ERR; } - if ((cyc != DF) && (ma < BR)) { /* boundary viol? */ - prvn = trap_pending = 1; /* set flag, trap */ - return MM_ERR; } } -if (MEM_ADDR_OK (ma)) M[ma] = dat & DMASK; /* valid mem? ok */ -else nexm = 1; /* set flag, no trap */ -return MM_OK; -} - -t_stat Ia (int32 ma, int32 *ea, t_bool jmp) -{ -int32 t; -t_stat sta = MM_OK; - -if ((ma & B_DAMASK) == 010) { /* autoindex? */ - ma = ma & 017; /* always in bank 0 */ - Read (ma, &t, DF); /* +1 before use */ - t = (t + 1) & DMASK; - sta = Write (ma, t, DF); } -else sta = Read (ma, &t, DF); -if (jmp) { /* jmp i? */ - if (emir_pending && (((t >> 16) & 1) == 0)) memm = 0; - if (rest_pending) { /* restore pending? */ - LAC = ((t << 1) & LINK) | (LAC & DMASK); /* restore L */ - memm = (t >> 16) & 1; /* restore extend */ - usmd = usmd_buf = (t >> 15) & 1; } /* restore user */ - emir_pending = rest_pending = 0; } -if (memm) *ea = t & IAMASK; /* extend? 15b ia */ -else *ea = (ma & B_EPCMASK) | (t & B_DAMASK); /* bank-rel ia */ -return sta; -} - -int32 Incr_addr (int32 ma) -{ -return ((ma & B_EPCMASK) | ((ma + 1) & B_DAMASK)); -} - -int32 Jms_word (int32 t) -{ -return (((LAC & LINK) >> 1) | ((memm & 1) << 16) | - ((t & 1) << 15) | (PC & IAMASK)); -} - -#endif - -#if defined (PDP15) - -/* Read, write, indirect, increment routines - On the PDP-15, - The autoincrement registers are in page zero only. Regardless - of bank mode, indirect addressing through 00010-00017 - will access absolute locations 00010-00017. - Indirect addressing range is determined by autoincrementing. - Any indirect can trigger a restore. - Memory protection is implemented for foreground/background operation. */ - -t_stat Read (int32 ma, int32 *dat, int32 cyc) -{ -int32 pa; - -if (usmd) { /* user mode? */ - if (XVM) pa = RelocXVM (ma, REL_R); /* XVM relocation? */ - else if (RELOC) pa = Reloc15 (ma, REL_R); /* PDP-15 relocation? */ - else pa = Prot15 (ma, cyc == FE); /* just protection */ - if (pa < 0) { /* error? */ - *dat = 0; - return MM_ERR; } } -else pa = ma & AMASK; /* no prot or reloc */ -if (MEM_ADDR_OK (pa)) *dat = M[pa] & DMASK; /* valid mem? ok */ -else { nexm = 1; /* set flag, no trap */ - *dat = 0; } -return MM_OK; -} - -t_stat Write (int32 ma, int32 dat, int32 cyc) -{ -int32 pa; - -if (usmd) { /* user mode? */ - if (XVM) pa = RelocXVM (ma, REL_W); /* XVM relocation? */ - else if (RELOC) pa = Reloc15 (ma, REL_W); /* PDP-15 relocation? */ - else pa = Prot15 (ma, cyc != DF); /* just protection */ - if (pa < 0) return MM_ERR; } /* error? */ -else pa = ma & AMASK; /* no prot or reloc */ -if (MEM_ADDR_OK (pa)) M[pa] = dat & DMASK; /* valid mem? ok */ -else nexm = 1; /* set flag, no trap */ -return MM_OK; -} - -/* XVM will do 18b defers if user_mode and G_Mode != 0 */ - -t_stat Ia (int32 ma, int32 *ea, t_bool jmp) -{ -int32 t; -int32 damask = memm? B_DAMASK: P_DAMASK; -t_stat sta = MM_OK; - -if ((ma & damask & ~07) == 010) { /* autoincrement? */ - ma = ma & 017; /* always in bank 0 */ - Read (ma, &t, DF); /* +1 before use */ - t = (t + 1) & DMASK; - sta = Write (ma, t, DF); } -else sta = Read (ma, &t, DF); -if (rest_pending) { /* restore pending? */ - LAC = ((t << 1) & LINK) | (LAC & DMASK); /* restore L */ - memm = (t >> 16) & 1; /* restore bank */ - usmd = usmd_buf = (t >> 15) & 1; /* restore user */ - emir_pending = rest_pending = 0; } -if (usmd && XVM && (MMR & MM_GM)) *ea = t; /* XVM G_mode? */ -else if ((ma & damask & ~07) == 010) *ea = t & AMASK; /* autoindex? */ -else *ea = (PC & BLKMASK) | (t & IAMASK); /* within 32K */ -return sta; -} - -t_stat Incr_addr (int32 ma) -{ -if (memm) return ((ma & B_EPCMASK) | ((ma + 1) & B_DAMASK)); -return ((ma & P_EPCMASK) | ((ma + 1) & P_DAMASK)); -} - -/* XVM will store all 18b of PC if user mode and G_mode != 0 */ - -int32 Jms_word (int32 t) -{ -if (usmd && XVM && (MMR & MM_GM)) return PC; -return (((LAC & LINK) >> 1) | ((memm & 1) << 16) | - ((t & 1) << 15) | (PC & IAMASK)); -} - -/* PDP-15 protection (KM15 option) */ - -int32 Prot15 (int32 ma, t_bool bndchk) -{ -ma = ma & AMASK; /* 17b addressing */ -if (!MEM_ADDR_OK (ma)) { /* nxm? */ - nexm = prvn = trap_pending = 1; /* set flags, trap */ - return -1; } -if (bndchk && (ma < BR)) { /* boundary viol? */ - prvn = trap_pending = 1; /* set flag, trap */ - return -1; } -return ma; /* no relocation */ -} - -/* PDP-15 relocation and protection (KT15 option) */ - -int32 Reloc15 (int32 ma, int32 rc) -{ -int32 pa; - -ma = ma & AMASK; /* 17b addressing */ -if (ma >= (BR | 0377)) { /* boundary viol? */ - if (rc != REL_C) prvn = trap_pending = 1; /* set flag, trap */ - return -1; } -pa = (ma + RR) & AMASK; /* relocate address */ -if (!MEM_ADDR_OK (pa)) { /* nxm? */ - if (rc != REL_C) nexm = prvn = trap_pending = 1; /* set flags, trap */ - return -1; } -return pa; -} - -/* XVM relocation and protection option */ - -int32 RelocXVM (int32 ma, int32 rc) -{ -int32 pa, gmode, slr; -static const int32 g_mask[4] = { MM_G_W0, MM_G_W1, MM_G_W2, MM_G_W3 }; -static const int32 g_base[4] = { MM_G_B0, MM_G_B1, MM_G_B2, MM_G_B3 }; -static const int32 slr_lnt[4] = { MM_SLR_L0, MM_SLR_L1, MM_SLR_L2, MM_SLR_L3 }; - -gmode = MM_GETGM (MMR); /* get G_mode */ -slr = MM_GETSLR (MMR); /* get segment length */ -ma = ma & g_mask[gmode]; /* mask address */ -if (MMR & MM_RDIS) pa = ma; /* reloc disabled? */ -else if ((MMR & MM_SH) && /* shared enabled and */ - (ma >= g_base[gmode]) && /* >= shared base and */ - (ma < (g_base[gmode] + slr_lnt[slr]))) { /* < shared end? */ - if (ma & 017400) { /* ESAS? */ - if ((rc == REL_W) && (MMR & MM_WP)) { /* write and protected? */ - prvn = trap_pending = 1; /* set flag, trap */ - return -1; } - pa = (((MMR & MM_SBR_MASK) << 8) + ma) & DMASK; } /* ESAS reloc */ - else pa = RR + (ma & 0377); } /* no, ISAS reloc */ -else { if (ma >= (BR | 0377)) { /* normal reloc, viol? */ - if (rc != REL_C) prvn = trap_pending = 1; /* set flag, trap */ - return -1; } - pa = (RR + ma) & DMASK; } /* relocate address */ -if (!MEM_ADDR_OK (pa)) { /* nxm? */ - if (rc != REL_C) nexm = prvn = trap_pending = 1; /* set flags, trap */ - return -1; } -return pa; -} - -#endif - -/* Reset routine */ - -t_stat cpu_reset (DEVICE *dptr) -{ -SC = 0; -eae_ac_sign = 0; -ion = ion_defer = ion_inh = 0; -CLR_INT (PWRFL); -api_enb = api_req = api_act = 0; -BR = 0; -RR = 0; -MMR = 0; -usmd = usmd_buf = usmd_defer = 0; -memm = memm_init; -nexm = prvn = trap_pending = 0; -emir_pending = rest_pending = 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 defined (PDP15) -if (usmd && (sw & SWMASK ('V'))) { - if (XVM) addr = RelocXVM (addr, REL_C); - else if (RELOC) addr = Reloc15 (addr, REL_C); - if (addr < 0) return STOP_MME; } -#endif -if (addr >= MEMSIZE) return SCPE_NXM; -if (vptr != NULL) *vptr = M[addr] & DMASK; -return SCPE_OK; -} - -/* Memory deposit */ - -t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw) -{ -#if defined (PDP15) -if (usmd && (sw & SWMASK ('V'))) { - if (XVM) addr = RelocXVM (addr, REL_C); - else if (RELOC) addr = Reloc15 (addr, REL_C); - if (addr < 0) return STOP_MME; } -#endif -if (addr >= MEMSIZE) return SCPE_NXM; -M[addr] = val & DMASK; -return SCPE_OK; -} - -/* Change memory size */ - -t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -int32 mc = 0; -uint32 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; -} - -/* Change device number for a device */ - -t_stat set_devno (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, 8, DEV_MAX - 1, &r); /* get new */ -if ((r != SCPE_OK) || (newdev == dibp->dev)) return r; -dibp->dev = newdev; /* store */ -return SCPE_OK; -} - -/* Show device number for a device */ - -t_stat show_devno (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, "devno=%02o", dibp->dev); -if (dibp->num > 1) fprintf (st, "-%2o", dibp->dev + dibp->num - 1); -return SCPE_OK; -} - -/* CPU device handler - should never get here! */ - -int32 bad_dev (int32 pulse, int32 AC) -{ -return (SCPE_IERR << IOT_V_REASON) | AC; /* broken! */ -} - -/* Build device dispatch table */ - -t_bool build_dev_tab (void) -{ -DEVICE *dptr; -DIB *dibp; -uint32 i, j, p; -static const uint8 std_dev[] = -#if defined (PDP4) - { 000 }; -#elif defined (PDP7) - { 000, 033, 077 }; -#else - { 000, 017, 033, 055, 077 }; -#endif - -for (i = 0; i < DEV_MAX; i++) { /* clr tables */ - dev_tab[i] = NULL; - dev_iors[i] = NULL; } -for (i = 0; i < ((uint32) sizeof (std_dev)); i++) /* std entries */ - dev_tab[std_dev[i]] = &bad_dev; -for (i = p = 0; (dptr = sim_devices[i]) != NULL; i++) { /* add devices */ - dibp = (DIB *) dptr->ctxt; /* get DIB */ - if (dibp && !(dptr->flags & DEV_DIS)) { /* enabled? */ - if (dibp->iors) dev_iors[p++] = dibp->iors; /* if IORS, add */ - for (j = 0; j < dibp->num; j++) { /* loop thru disp */ - if (dibp->dsp[j]) { /* any dispatch? */ - if (dev_tab[dibp->dev + j]) { /* already filled? */ - printf ("%s device number conflict at %02o\n", - sim_dname (dptr), dibp->dev + j); - if (sim_log) fprintf (sim_log, - "%s device number conflict at %02o\n", - sim_dname (dptr), dibp->dev + j); - return TRUE; } - dev_tab[dibp->dev + j] = dibp->dsp[j]; /* fill */ - } /* end if dsp */ - } /* end for j */ - } /* end if enb */ - } /* end for i */ -return FALSE; -} - -/* 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].pc = 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 l, j, k, di; -t_value sim_eval[2]; -struct InstHistory *h; -extern t_stat fprint_sym (FILE *ofile, t_addr addr, t_value *val, - UNIT *uptr, int32 sw); - -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->pc == 0) continue; /* filled in? */ - if (h->pc & (HIST_API | HIST_PI)) { /* interrupt event? */ - if (h->pc & HIST_PI) /* PI? */ - fprintf (st, "%06o PI LVL 0-4 =", h->pc & AMASK); - else fprintf (st, "%06o API %d LVL 0-4 =", h->pc & AMASK, h->mq); - for (j = API_HLVL; j >= 0; j--) - fprintf (st, " %02o", (h->ir >> (j * HIST_V_LVL)) & HIST_M_LVL); - } - else { /* instruction */ - l = (h->lac >> 18) & 1; /* link */ - fprintf (st, "%06o %o %06o %06o ", h->pc, l, h->lac & DMASK, h->mq); - sim_eval[0] = h->ir; - sim_eval[1] = h->ir1; - if ((fprint_sym (st, h->pc, sim_eval, &cpu_unit, SWMASK ('M'))) > 0) - fprintf (st, "(undefined) %06o", h->ir); - } /* end else instruction */ - fputc ('\n', st); /* end line */ - } /* end for */ -return SCPE_OK; -} - -/* Record events in history table */ - -void cpu_inst_hist (int32 addr, int32 inst) -{ -hst[hst_p].pc = addr; -hst[hst_p].ir = inst; -if (cpu_ex (&hst[hst_p].ir1, (addr + 1) & AMASK, &cpu_unit, SWMASK ('V'))) - hst[hst_p].ir1 = 0; -hst[hst_p].lac = LAC; -hst[hst_p].mq = MQ; -hst_p = (hst_p + 1) % HIST_SIZE; -return; -} - -void cpu_intr_hist (int32 flag, int32 lvl) -{ -int32 j; - -hst[hst_p].pc = PC | flag; -hst[hst_p].ir = 0; -for (j = 0; j < API_HLVL+1; j++) hst[hst_p].ir = - (hst[hst_p].ir << HIST_V_LVL) | (int_hwre[j] & HIST_M_LVL); -hst[hst_p].ir1 = 0; -hst[hst_p].lac = 0; -hst[hst_p].mq = lvl; -hst_p = (hst_p + 1) % HIST_SIZE; -return; -} diff --git a/PDP18B/pdp18b_defs.h b/PDP18B/pdp18b_defs.h deleted file mode 100644 index 12798f3c..00000000 --- a/PDP18B/pdp18b_defs.h +++ /dev/null @@ -1,488 +0,0 @@ -/* pdp18b_defs.h: 18b PDP simulator definitions - - 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. - - 18-Jul-03 RMS Added FP15 support - Added XVM support - Added EAE option for PDP-4 - 25-Apr-03 RMS Revised for extended file support - 04-Feb-03 RMS Added RB09, LP09 support - 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 - 25-Nov-01 RMS Revised interrupt structure - 27-May-01 RMS Added second Teletype support - 21-Jan-01 RMS Added DECtape support - 14-Apr-99 RMS Changed t_addr to unsigned - 02-Jan-96 RMS Added fixed head and moving head disks - 31-Dec-95 RMS Added memory management - 19-Mar-95 RMS Added dynamic memory size - - The author gratefully acknowledges the help of Craig St. Clair and - Deb Tevonian in locating archival material about the 18b PDP's, and of - Al Kossow and Max Burnet in making documentation and software available. -*/ - -#ifndef _PDP18B_DEFS_H_ -#define _PDP18B_DEFS_H_ 0 - -#include "sim_defs.h" /* simulator defns */ - -/* Models: only one should be defined - - model memory CPU options I/O options - - PDP4 8K Type 18 EAE Type 65 KSR-28 Teletype (Baudot) - ??Type 16 mem extension integral paper tape reader - Type 75 paper tape punch - 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 - integral real time clock - Type 647B line printer (sixbit) - Type 550/555 DECtape - Type 24 serial drum - - PDP9 32K KE09A EAE KSR-33 Teletype - KF09A auto pri intr PC09A paper tape reader and punch - KG09B mem extension integral real time clock - KP09A power detection Type 647D/E line printer (sixbit) - KX09A mem protection LP09 line printer (ASCII) - RF09/RS09 fixed head disk - RB09 fixed head disk - TC59 magnetic tape - TC02/TU55 DECtape - LT09A second Teletype - - PDP15 128K KE15 EAE KSR-35 Teletype - KA15 auto pri intr PC15 paper tape reader and punch - KF15 power detection KW15 real time clock - KM15 mem protection LP09 line printer - KT15 mem relocation LP15 line printer - FP15 floating point RP15 disk pack - XVM option RF15/RF09 fixed head disk - TC59D magnetic tape - TC15/TU56 DECtape - LT15 second Teletype - - ??Indicates not implemented. The PDP-4 manual refers to a memory - ??extension control; there is no documentation on it. -*/ - -#if !defined (PDP4) && !defined (PDP7) && !defined (PDP9) && !defined (PDP15) -#define PDP15 0 /* default to PDP-15 */ -#endif - -/* 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_API 5 /* invalid API int */ -#define STOP_NONSTD 6 /* non-std dev num */ -#define STOP_MME 7 /* mem mgt error */ -#define STOP_FPDIS 8 /* fp inst, fpp disabled */ - -/* Peripheral configuration */ - -#if defined (PDP4) -#define ADDRSIZE 13 -#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 */ -#define TYPE550 0 /* DECtape */ -#define DRM 0 /* drum */ -#elif defined (PDP9) -#define ADDRSIZE 15 -#define TYPE647 0 /* sixbit printer */ -#define LP09 0 /* ASCII printer */ -#define RB 0 /* fixed head disk */ -#define RF 0 /* fixed head disk */ -#define MTA 0 /* magtape */ -#define TC02 0 /* DECtape */ -#define TTY1 0 /* second Teletype */ -#define BRMASK 0076000 /* bounds mask */ -#elif defined (PDP15) -#define ADDRSIZE 17 -#define LP09 0 /* ASCII printer */ -#define LP15 0 /* DMA printer */ -#define RF 0 /* fixed head disk */ -#define RP 0 /* disk pack */ -#define MTA 0 /* magtape */ -#define TC02 0 /* DECtape */ -#define TTY1 0 /* second Teletype */ -#define BRMASK 0377400 /* bounds mask */ -#define BRMASK_XVM 0777400 /* bounds mask, XVM */ -#endif - -/* Memory */ - -#define AMASK ((1 << ADDRSIZE) - 1) /* address mask */ -#define IAMASK 077777 /* ind address mask */ -#define BLKMASK (AMASK & (~IAMASK)) /* block mask */ -#define MAXMEMSIZE (1 << ADDRSIZE) /* max memory size */ -#define MEMSIZE (cpu_unit.capac) /* actual memory size */ -#define MEM_ADDR_OK(x) (((uint32) (x)) < MEMSIZE) - -/* Instructions */ - -#define I_V_OP 14 /* opcode */ -#define I_M_OP 017 -#define I_V_IND 13 /* indirect */ -#define I_V_IDX 12 /* index */ -#define I_IND (1 << I_V_IND) -#define I_IDX (1 << I_V_IDX) -#define B_DAMASK 017777 /* bank mode address */ -#define B_EPCMASK (AMASK & ~B_DAMASK) -#define P_DAMASK 007777 /* page mode address */ -#define P_EPCMASK (AMASK & ~P_DAMASK) - -/* Memory cycles */ - -#define FE 0 -#define DF 1 -#define RD 2 -#define WR 3 - -/* Memory status codes */ - -#define MM_OK 0 -#define MM_ERR 1 - -/* Memory management relocation checks (PDP-15 KT15 and XVM only) */ - -#define REL_C -1 /* console */ -#define REL_R 0 /* read */ -#define REL_W 1 /* write */ - -/* Architectural constants */ - -#define DMASK 0777777 /* data mask */ -#define LINK (DMASK + 1) /* link */ -#define LACMASK (LINK | DMASK) /* link + data */ -#define SIGN 0400000 /* sign bit */ -#define OP_JMS 0100000 /* JMS */ -#define OP_JMP 0600000 /* JMP */ -#define OP_HLT 0740040 /* HLT */ - -/* IOT subroutine return codes */ - -#define IOT_V_SKP 18 /* skip */ -#define IOT_V_REASON 19 /* reason */ -#define IOT_SKP (1 << IOT_V_SKP) -#define IOT_REASON (1 << IOT_V_REASON) - -#define IORETURN(f,v) ((f)? (v): SCPE_OK) /* stop on error */ - -/* PC change queue */ - -#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 - -/* XVM memory management registers */ - -#define MM_RDIS 0400000 /* reloc disabled */ -#define MM_V_GM 15 /* G mode */ -#define MM_M_GM 03 -#define MM_GM (MM_M_GM << MM_V_GM) -#define MM_G_W0 0077777 /* virt addr width */ -#define MM_G_W1 0177777 -#define MM_G_W2 0777777 -#define MM_G_W3 0377777 -#define MM_G_B0 0060000 /* SAS base */ -#define MM_G_B1 0160000 -#define MM_G_B2 0760000 -#define MM_G_B3 0360000 -#define MM_UIOT 0040000 /* user mode IOT's */ -#define MM_WP 0020000 /* share write prot */ -#define MM_SH 0010000 /* share enabled */ -#define MM_V_SLR 10 /* segment length reg */ -#define MM_M_SLR 03 -#define MM_SLR_L0 001000 /* SAS length */ -#define MM_SLR_L1 002000 -#define MM_SLR_L2 010000 -#define MM_SLR_L3 020000 -#define MM_SBR_MASK 01777 /* share base reg */ -#define MM_GETGM(x) (((x) >> MM_V_GM) & MM_M_GM) -#define MM_GETSLR(x) (((x) >> MM_V_SLR) & MM_M_SLR) - -/* Device information block */ - -#define DEV_MAXBLK 8 /* max dev block */ -#define DEV_MAX 64 /* total devices */ - -struct pdp18b_dib { - uint32 dev; /* base dev number */ - uint32 num; /* number of slots */ - int32 (*iors)(void); /* IORS responder */ - int32 (*dsp[DEV_MAXBLK])(int32 pulse, int32 dat); -}; - -typedef struct pdp18b_dib DIB; - -/* Standard device numbers */ - -#define DEV_PTR 001 /* paper tape reader */ -#define DEV_PTP 002 /* paper tape punch */ -#define DEV_TTI 003 /* console input */ -#define DEV_TTO 004 /* console output */ -#define DEV_TTI1 041 /* extra terminals */ -#define DEV_TTO1 040 -#define DEV_DRM 060 /* drum */ -#define DEV_RP 063 /* RP15 */ -#define DEV_LPT 065 /* line printer */ -#define DEV_RF 070 /* RF09 */ -#define DEV_RB 071 /* RB09 */ -#define DEV_MT 073 /* magtape */ -#define DEV_DTA 075 /* dectape */ - -/* Interrupt system - - The interrupt system can be modelled on either the flag driven system - of the PDP-4 and PDP-7 or the API driven system of the PDP-9 and PDP-15. - If flag based, API is hard to implement; if API based, IORS requires - extra code for implementation. I've chosen an API based model. - - API channel Device API priority Notes - - 00 software 4 4 - 01 software 5 5 - 02 software 6 6 - 03 software 7 7 - 04 TC02/TC15 1 - 05 TC59D 1 - 06 drum 1 PDP-9 only - 07 RB09 1 PDP-9 only - 10 paper tape reader 2 - 11 real time clock 3 - 12 power fail 0 - 13 memory parity 0 - 14 display 2 - 15 card reader 2 - 16 line printer 2 - 17 A/D converter 0 - 20 interprocessor buffer 3 - 21 360 link 3 PDP-9 only - 22 data phone 2 PDP-15 only - 23 RF09/RF15 1 - 24 RP15 1 PDP-15 only - 25 plotter 1 PDP-15 only - 26 - - 27 - - 30 - - 31 - - 32 - - 33 - - 34 LT15 TTO 3 PDP-15 only - 35 LT15 TTI 3 PDP-15 only - 36 - - 37 - -*/ - -#define API_ML0 0200 /* API masks: level 0 */ -#define API_ML1 0100 -#define API_ML2 0040 -#define API_ML3 0020 -#define API_ML4 0010 -#define API_ML5 0004 -#define API_ML6 0002 -#define API_ML7 0001 /* level 7 */ - -#if defined (PDP9) /* levels which mask PI */ -#define API_MASKPI (API_ML0|API_ML1|API_ML2|API_ML3|API_ML4|API_ML5|API_ML6|API_ML7) -#else -#define API_MASKPI (API_ML0|API_ML1|API_ML2|API_ML3) -#endif - -#define API_HLVL 4 /* hwre levels */ -#define ACH_SWRE 040 /* swre int vec */ - -/* API level 0 */ - -#define INT_V_PWRFL 0 /* powerfail */ - -#define INT_PWRFL (1 << INT_V_PWRFL) - -#define API_PWRFL 0 - -#define ACH_PWRFL 052 - -/* API level 1 */ - -#define INT_V_DTA 0 /* DECtape */ -#define INT_V_MTA 1 /* magtape */ -#define INT_V_DRM 2 /* drum */ -#define INT_V_RF 3 /* fixed head disk */ -#define INT_V_RP 4 /* disk pack */ -#define INT_V_RB 5 /* RB disk */ - -#define INT_DTA (1 << INT_V_DTA) -#define INT_MTA (1 << INT_V_MTA) -#define INT_DRM (1 << INT_V_DRM) -#define INT_RF (1 << INT_V_RF) -#define INT_RP (1 << INT_V_RP) -#define INT_RB (1 << INT_V_RB) - -#define API_DTA 1 -#define API_MTA 1 -#define API_DRM 1 -#define API_RF 1 -#define API_RP 1 -#define API_RB 1 - -#define ACH_DTA 044 -#define ACH_MTA 045 -#define ACH_DRM 046 -#define ACH_RB 047 -#define ACH_RF 063 -#define ACH_RP 064 - -/* API level 2 */ - -#define INT_V_PTR 0 /* paper tape reader */ -#define INT_V_LPT 1 /* line printer */ -#define INT_V_LPTSPC 2 /* line printer spc */ - -#define INT_PTR (1 << INT_V_PTR) -#define INT_LPT (1 << INT_V_LPT) -#define INT_LPTSPC (1 << INT_V_LPTSPC) - -#define API_PTR 2 -#define API_LPT 2 -#define API_LPTSPC 2 - -#define ACH_PTR 050 -#define ACH_LPT 056 - -/* API level 3 */ - -#define INT_V_CLK 0 /* clock */ -#define INT_V_TTI1 1 /* LT15 keyboard */ -#define INT_V_TTO1 2 /* LT15 output */ - -#define INT_CLK (1 << INT_V_CLK) -#define INT_TTI1 (1 << INT_V_TTI1) -#define INT_TTO1 (1 << INT_V_TTO1) - -#define API_CLK 3 -#define API_TTI1 3 -#define API_TTO1 3 - -#define ACH_CLK 051 -#define ACH_TTI1 075 -#define ACH_TTO1 074 - -/* PI level */ - -#define INT_V_TTI 0 /* console keyboard */ -#define INT_V_TTO 1 /* console output */ -#define INT_V_PTP 2 /* paper tape punch */ - -#define INT_TTI (1 << INT_V_TTI) -#define INT_TTO (1 << INT_V_TTO) -#define INT_PTP (1 << INT_V_PTP) - -#define API_TTI 4 /* PI level */ -#define API_TTO 4 -#define API_PTP 4 - -/* Interrupt macros */ - -#define SET_INT(dv) int_hwre[API_##dv] = int_hwre[API_##dv] | INT_##dv -#define CLR_INT(dv) int_hwre[API_##dv] = int_hwre[API_##dv] & ~INT_##dv -#define TST_INT(dv) (int_hwre[API_##dv] & INT_##dv) - -/* I/O status flags for the IORS instruction - - bit PDP-4 PDP-7 PDP-9 PDP-15 - - 0 intr on intr on intr on intr on - 1 tape rdr flag* tape rdr flag* tape rdr flag* tape rdr flag* - 2 tape pun flag* tape pun flag* tape pun flag* tape pun flag* - 3 keyboard flag* keyboard flag* keyboard flag* keyboard flag* - 4 type out flag* type out flag* type out flag* type out flag* - 5 display flag* display flag* light pen flag* light pen flag* - 6 clk ovflo flag* clk ovflo flag* clk ovflo flag* clk ovflo flag* - 7 clk enable flag clk enable flag clk enable flag clk enable flag - 8 mag tape flag* mag tape flag* tape rdr empty* tape rdr empty* - 9 card rdr col* * tape pun empty tape pun empty - 10 card rdr ~busy DECtape flag* DECtape flag* - 11 card rdr error magtape flag* magtape flag* - 12 card rdr EOF disk pack flag* - 13 card pun row* DECdisk flag* DECdisk flag* - 14 card pun error lpt flag* - 15 lpt flag* lpt flag* lpt flag* - 16 lpt space flag* lpt error flag lpt error flag - 17 drum flag* drum flag* -*/ - -#define IOS_ION 0400000 /* interrupts on */ -#define IOS_PTR 0200000 /* tape reader */ -#define IOS_PTP 0100000 /* tape punch */ -#define IOS_TTI 0040000 /* keyboard */ -#define IOS_TTO 0020000 /* terminal */ -#define IOS_LPEN 0010000 /* light pen */ -#define IOS_CLK 0004000 /* clock */ -#define IOS_CLKON 0002000 /* clock enable */ -#define IOS_DTA 0000200 /* DECtape */ -#define IOS_RP 0000040 /* disk pack */ -#define IOS_RF 0000020 /* fixed head disk */ -#define IOS_DRM 0000001 /* drum */ -#if defined (PDP4) || defined (PDP7) -#define IOS_MTA 0001000 /* magtape */ -#define IOS_LPT 0000004 /* line printer */ -#define IOS_LPT1 0000002 /* line printer stat */ -#elif defined (PDP9) -#define IOS_PTRERR 0001000 /* reader empty */ -#define IOS_PTPERR 0000400 /* punch empty */ -#define IOS_MTA 0000100 /* magtape */ -#define IOS_LPT 0000004 /* line printer */ -#define IOS_LPT1 0000002 /* line printer stat */ -#elif defined (PDP15) -#define IOS_PTRERR 0001000 /* reader empty */ -#define IOS_PTPERR 0000400 /* punch empty */ -#define IOS_MTA 0000100 /* magtape */ -#define IOS_LPT 0000010 /* line printer */ -#define IOS_LPT1 0000000 /* not used */ -#endif - -/* Function prototypes */ - -t_stat set_devno (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat show_devno (FILE *st, UNIT *uptr, int32 val, void *desc); - -#endif - diff --git a/PDP18B/pdp18b_doc.txt b/PDP18B/pdp18b_doc.txt deleted file mode 100644 index 881c75f9..00000000 --- a/PDP18B/pdp18b_doc.txt +++ /dev/null @@ -1,993 +0,0 @@ -To: Users -From: Bob Supnik -Subj: 18b PDP Simulator Usage -Date: 25-Aug-2003 - - COPYRIGHT NOTICE - -The following copyright notice applies to both the SIMH source and binary: - - 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"), - 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-4, PDP-7, PDP-9, and PDP-15 simulators. - - -1. Simulator Files - -To compile a particular model in the 18b family, you must include the appropriate -switch in the compilation command line: - -PDP-4/ PDP4 -PDP-7/ PDP7 -PDP-9/ PDP9 -PDP-15/ PDP15 - -If no model is specified, the default is the PDP-15. - - PDP-4 PDP-7 PDP-9 PDP-15 -sim/ sim_defs.h x x x x - sim_rev.h x x x x - sim_sock.h x x x x - sim_tape.h x x - sim_tmxr.h x x x x - scp.c x x x x - scp_tty.c x x x x - sim_sock.c x x x x - sim_tape.c x x - sim_tmxr.c x x x x - -sim/pdp18b/ pdp18b_defs.h x x x x - pdp18b_cpu.c x x x x - pdp18b_drm.c x x - pdp18b_dt.c x x x x - pdp18b_fpp.c x - pdp18b_lp.c x x x x - pdp18b_mt.c x x - pdp18b_rb.c x - pdp18b_rf.c x x - pdp18b_rp.c x - pdp18b_stddev.c x x x x - pdp18b_sys.c x x x x - pdp18b_tt1.c x x - -2. 18b PDP Features - -The other four 18b PDP's (PDP-4, PDP-7, PDP-9, PDP-15) are very similar -and are configured as follows: - -system device simulates - name(s) - -PDP-4 CPU PDP-4 CPU with 8KW of memory - - Type 18 extended arithmetic element (EAE) - PTR,PTP integral paper tape/Type 75 punch - TTI,TTO KSR28 console terminal (Baudot code) - 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) - - Type 148 memory extension - PTR,PTP Type 444 paper tape reader/Type 75 punch - TTI,TTO KSR 33 console terminal - LPT Type 647 line printer - CLK integral real-time clock - DT Type 550/555 DECtape - DRM Type 24 serial drum - -PDP-9 CPU PDP-9 CPU with 32KW of memory - - KE09A extended arithmetic element (EAE) - - KF09A automatic priority interrupt (API) - - KG09B memory extension - - KP09A power detection - - KX09A memory protection - PTR,PTP PC09A paper tape reader/punch - TTI,TTO KSR 33 console terminal - TTI1,TTO1 LT09A second console terminal - LP9 LP09 line printer - LPT Type 647E line printer - CLK integral real-time clock - RB RB09 fixed-head disk - RF RF09/RS09 fixed-head disk - DT TC02/TU55 DECtape - MT TC59/TU10 magnetic tape - -PDP-15 CPU PDP-15 CPU with 32KW of memory - - KE15 extended arithmetic element (EAE) - - KA15 automatic priority interrupt (API) - - KF15 power detection - - KM15 memory protection - - KT15 memory relocation and protection - - XVM memory relocation and protection - FPP FP15 floating point processor - PTR,PTP PC15 paper tape reader/punch - TTI,TTO KSR 35 console terminal - TTI1,TTO1 LT15 second console terminal - LP9 LP09 line printer - LPT LP15 line printer - CLK integral real-time clock - RP RP15/RP02 disk pack - RF RF15/RS09 fixed-head disk - DT TC15/TU56 DECtape - MT TC59/TU10 magnetic tape - -Most devices can be disabled or enabled, by the commands: - - SET DISABLED - SET ENABLED - -The simulator allows most device numbers to be changed, by the command: - - SET DEV= - -However, devices can only be BOOTed with their default device numbers. - -The 18b PDP simulators implement several unique stop conditions: - - - an unimplemented instruction is decoded, and register - STOP_INST is set - - more than XCT_MAX nested executes are detected during - instruction execution - - an FP15 instruction is decoded, the FP15 is disabled, - and register STOP_FPP is set - -The PDP-4 and PDP-7 LOAD command supports only "second stage" RIM format -files (alternating DAC address instructions and data): - - LOAD file load PDP-4/PDP-7 RIM format file - -The PDP-9 and PDP-15 LOAD commands support hardware RIM format (data only), -PDP-4/PDP-7 RIM loader format (for compatability with Macro7), and BIN -loader format: - - LOAD -S file load PDP-4/PDP-7 RIM format file - LOAD -R file address load PDP-9/PDP-15 RIM format - file starting at address - LOAD file.RIM address assume file is PDP-9/PDP-15 - RIM format - LOAD -B file load PDP-9/PDP-15 BIN format file - LOAD file.BIN assume file is PDP-9/PDP-15 - BIN format - -If no address is given for a RIM format load, a starting address of 200 -(octal) is assumed. If no switch is specified, and the file extension is -neither RIM nor BIN, the file format is assumed to be BIN. - -2.1 CPU - -The CPU options are the presence of the EAE, the presense of the API and -memory protection (for the PDP-9 and PDP-15), the presense of relocation -or XVM (PDP-15 only), and the size of main memory. - - system option comment - - all SET CPU EAE enable EAE - all SET CPU NOEAE disable EAE - 9,15 SET CPU API enable API - 9,15 SET CPU NOAPI disable API - 9,15 SET CPU PROT enable memory protection - 15 SET CPU RELOC enable memory relocation - 15 SET CPU XVM enable XVM relocation - 9,15 SET CPU NOPROT disable protection, relocation, XVM - 4 SET CPU 4K set memory size = 4K - all SET CPU 8K set memory size = 8K - all SET CPU 12K set memory size = 12K - all SET CPU 16K set memory size = 16K - all SET CPU 20K set memory size = 20K - all SET CPU 24K set memory size = 24K - all SET CPU 28K set memory size = 28K - all SET CPU 32K set memory size = 32K - 15 SET CPU 48K set memory size = 48K - 15 SET CPU 64K set memory size = 64K - 15 SET CPU 80K set memory size = 80K - 15 SET CPU 96K set memory size = 96K - 15 SET CPU 112K set memory size = 112K - 15 SET CPU 128K set memory size = 128K - -Memory sizes greater than 8K are only available on the PDP-7, PDP-9, and -PDP-15; memory sizes greater than 32KW are only available on the PDP-15. -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 8K for the PDP-4, 32K -for the PDP-7 and PDP-9, and 128K for the PDP-15. - -The PROT option corresponds to the KX09A on the PDP-9 and the KM15 for the -PDP-15. The PROT option is required to run the Foreground/Background -Monitor. The RELOC option corresponds to the KT15 on the PDP-15, and the -XVM option corresponds to the XM15 on the PDP-15. ADSS-15, ADSS-15 Foreground/ -Background, and standard DOS-15 will run if these options are enabled. - -CPU registers include the visible state of the processor as well as the -control registers for the interrupt system. - - system name size comments - - all PC addr program counter - all AC 18 accumulator - all L 1 link - all MQ 18 multiplier-quotient - all SC 6 shift counter - all EAE_AC_SIGN 1 EAE AC sign - all SR 18 front panel switches - all ASW addr address switches for RIM load - all INT[0:4] 32 interrupt requests, - 0:3 = API levels 0-3 - 4 = PI level - all IORS 18 IORS register - all ION 1 interrupt enable - all ION_DELAY 2 interrupt enable delay - 15 ION_INH 1 interrupt inhibit - 9,15 APIENB 1 API enable - 9,15 APIREQ 8 API requesting levels - 9,15 APIACT 8 API active levels - 9,15 BR 18 memory protection bounds - 15 XR 18 index register - 15 LR 18 limit register - 9,15 BR 18 memory protection bounds - 15 RR 18 memory protection relocation - 15 MMR 18 memory protection control - 9,15 USMD 1 user mode - 9,15 USMDBUF 1 user mode buffer - 9,15 USMDDEF 1 user mode load defer - 9,15 NEXM 1 non-existent memory violation - 9,15 PRVN 1 privilege violation - 7,9 EXTM 1 extend mode - 7,9 EXTM_INIT 1 extend mode value after reset - 15 BANKM 1 bank mode - 15 BANKM_INIT 1 bank mode value after reset - 7 TRAPM 1 trap mode - 7,9,15 TRAPP 1 trap pending - 7,9 EMIRP 1 EMIR instruction pending - 9,15 RESTP 1 DBR or RES instruction pending - 9,15 PWRFL 1 power fail flag - all PCQ[0:63] addr PC prior to last JMP, JMS, CAL, or - interrupt; most recent PC change first - all STOP_INST 1 stop on undefined instruction - all XCT_MAX 8 maximum number of chained XCT's allowed - all WRU 8 interrupt character - -"addr" signifies the address width of the system (13b for the PDP-4, 15b for -the PDP-7 and PDP-9, 17b for the PDP-15). - -2.2 Floating Point Processor (FPP) - -The PDP-15 features an optional floating point processor, the FP15 (FPP). -The FPP can be enabled and disabled; by default it is disabled. - -The FPP implements these registers: - - name size comments - - FIR 12 floating instruction register - EPA 18 EPA (A exponent) - FMAS 1 FMA sign - FMAH 17 FMA<1:17> - FMAL 18 FMA<18:35> - EPB 18 EPB (B exponent) - FMBS 1 FMB sign - FMBH 17 FMB<1:17> - FMBL 18 FMB<18:35> - FGUARD 1 guard bit - FMQH 17 FMQ<1:17> - FMQL 18 FMQ<18:35> - JEA 18 exception address register - STOP_FPP 1 stop if FP15 instruction decoded - while FP15 is disabled - -2.3 Programmed I/O Devices - -2.3.1 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 supports the BOOT command. The specific forms -recognized vary from system to system: - - BOOT PTR PDP-4, PDP-7: load RIM loader and start it running - BOOT -F PTR PDP-4, PDP-7: load funny format loader and start - it running - BOOT -H PTR PDP-7: start hardware RIM load at address given - by address switches (ASW) - BOOT {-H} PTR PDP-9, PDP-15: start hardware RIM load at address - given by address switches (ASW) - -The PDP-4 did not have a hardware read-in mode load capability. - -The PTR ATTACH command recognizes one switch, -A for ASCII mode. In -ASCII mode, data returned by the read alphabetic command has even parity. -This allows normal text files to be used as input to the paper tape reader. - -The paper tape reader implements these registers: - - name size comments - - BUF 8 last data item processed - INT 1 interrupt pending flag - DONE 1 device done flag - ERR 1 error flag (PDP-9, PDP-15 only) - 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.3.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 PTP ATTACH command recognizes one switch, -A for ASCII mode. In -ASCII mode, data is punched with the high order bit clear, and NULL and -DEL characters are supressed. This allows punch output to be processed -with normal text editing utilities. - -The paper tape punch implements these registers: - - name size comments - - BUF 8 last data item processed - INT 1 interrupt pending flag - DONE 1 device done flag - ERR 1 error flag (PDP-9, PDP-15 only) - 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 or paper - - OS I/O error x report error and stop - -2.3.3 Terminal Input (TTI) - -On the PDP-7, PDP-9, and PDP-15, the terminal interfaces (TTI, TTO) -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, the high order bit is forced to one on input, and printing of -ALTmode characters is supressed. In 7B mode, input and output characters -are masked to 7 bits. In 8B mode, characters are not modified. Changing -the mode of either interface changes both. The default mode is KSR. - -On the PDP-9 and PDP-15, the console terminal operates, by default, -with local echo. For backward compatibility, the terminal input can -be set to FDX (full duplex), which supresses local echo. - -The terminal input (TTI) polls the console keyboard for input. It -implements these registers: - - name size comments - - BUF 8 last data item processed - INT 1 interrupt pending flag - DONE 1 device done flag - POS 32 number of characters input - TIME 24 keyboard polling interval - -If the simulator is debugged under Windows Visual C++, typing ^C to the -terminal input causes a fatal run-time error. Use the following command -to simulate typing ^C: - - SET TTI CTRL-C - -2.3.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 - INT 1 interrupt pending flag - DONE 1 device done flag - POS 32 number of chararacters output - TIME 24 time from I/O initiation to interrupt - -2.3.5 Line Printers (LPT, LP9) - -The line printers (LPT, LP9) write 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. - -LPT is the "default" line printer for a CPU: Type 62 for the PDP-4, -Type 647 for the PDP-7 and PDP-9, and LP15 for the PDP-15. LP9 is -the LP09 line printer controller for the PDP-9. It may be needed -on the PDP-15 to run certain software packages. LP9 is disabled by -default. - -The Type 62 printer controller implements these registers: - - name size comments - - BUF 8 last data item processed - INT 1 interrupt pending flag - DONE 1 device done flag - SPC 1 spacing done 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 - -The Type 647 printer controller implements these registers: - - name size comments - - BUF 8 last data item processed - INT 1 interrupt pending flag - DONE 1 device done flag - ENABLE 1 interrupt enable (PDP-9 only) - ERR 1 error flag - BPTR 7 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 - -The LP09 printer controller implements these registers: - - name size comments - - BUF 7 output character - INT 1 interrupt pending flag - DONE 1 device done flag - ENABLE 1 interrupt enable - ERR 1 error flag - POS 32 position in the output file - TIME 24 time from I/O initiation to interrupt - -The LP15 printer controller implements these registers: - - name size comments - - STA 18 status register - MA 18 DMA memory address - INT 1 interrupt pending flag - ENABLE 1 interrupt enable - LCNT 8 line counter - BPTR 7 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:131] 8 line buffer - -For all printers, 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.6 Real-Time Clock (CLK) - -The real-time clock (CLK) frequency can be adjusted as follows: - - SET CLK 60HZ set frequency to 60Hz - SET CLK 50HZ set frequency to 50Hz - -The default is 60Hz. - -The clock implements these registers: - - name size comments - - INT 1 interrupt pending flag - DONE 1 device done flag - ENABLE 1 clock enable - TIME 24 clock frequency - -The real-time clock autocalibrates; the clock interval is adjusted up or -down so that the clock tracks actual elapsed time. - -2.3.7 Second Terminal (TTI1, TTO1) - -The second terminal consists of two independent devices, TTI1 and TTO1. -The second terminal performs input and output through a Telnet session -connected to a user-specified port. The ATTACH command specifies the -port to be used: - - ATTACH TTI1 set up listening port - -where port is a decimal number between 1 and 65535 that is not being used -for other TCP/IP activities. - -Once TTI1 is attached and the simulator is running, the terminal listens -for a connection on the specified port. It assumes that the incoming -connection is a Telnet connection. The connection remain opens until -disconnected by the Telnet client, or by a DETACH TTI1 command. - -The second terminal (TTI1,TTO1) can be set to one of three modes: KSR, 7B, -or 8B. In KSR mode, lower case input and output characters are converted -automatically to upper case, the high order bit is forced to one on input, -and printing of ALTmode characters is supressed. In 7B mode, input and -output characters are masked to 7 bits. In 8B mode, characters are not -modified. Changing the mode of either device changes both. The default -mode is KSR. - -The SHOW TTI1 CONNECTIONS command displays the current connection to TTI1. -The SHOW TTI1 STATISTICS command displays statistics for the current connection. -The SET TTI1 DISCONNECT{=0} disconnects the current connection. - -The second terminal input implements these registers: - - name size comments - - BUF 8 last data item processed - INT 1 interrupt pending flag - DONE 1 device done flag - TIME 24 keyboard polling interval - -The second terminal output implements these registers: - - name size comments - - BUF 8 last data item processed - INT 1 interrupt pending flag - DONE 1 device done flag - TIME 24 time from I/O initiation to interrupt - -2.4 RP15/RP02 Disk Pack (RP) - -RP15 options include the ability to make units write enabled or write locked: - - SET RPn LOCKED set unit n write locked - SET RPn WRITEENABLED set unit n write enabled - -Units can also be set ONLINE or OFFLINE. - -The RP15 implements these registers: - - name size comments - - STA 18 status A - STB 18 status B - DA 18 disk address - MA 18 current memory address - WC 18 word count - INT 1 interrupt pending flag - BUSY 1 control busy flag - STIME 24 seek time, per cylinder - RTIME 24 rotational delay - 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 - -2.5 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.6 RB09 Fixed Head Disk (RB) - -The RB09 was an early fixed-head disk for the PDP-9. It was superceded -by the RF09/RS09. It is disabled by default. - -The RB09 implements these registers: - - name size comments - - STA 18 status - DA 20 current disk address - WC 16 word count - MA 15 memory address - INT 1 interrupt pending flag - WLK 20 write lock switches for track groups, - 10 tracks per group - TIME 24 rotational delay, per word - BURST 1 burst flag - STOP_IOE 1 stop on I/O error - -The RB09 is a data break device. If BURST = 0, word transfers are -scheduled individually; if BURST = 1, the entire transfer occurs in -a single data break. - -Error handling is as follows: - - error STOP_IOE processed as - - not attached 1 report error and stop - 0 disk not ready - -RB09 data files are buffered in memory; therefore, end of file and OS -I/O errors cannot occur. - -2.7 RF09/RF15/RS09 Fixed Head Disk (RF) - -RF09/RF15 options include the ability to set the number of platters -to a fixed value between 1 and 8, or to autosize the number of platters -from the attached file: - - SET RF 1P one platter (256K) - SET RF 2P two platters (512K) - SET RF 3P three platters (768K) - SET RF 4P four platters (1024K) - SET RF 5P five platters (1280K) - SET RF 6P six platters (1536K) - SET RF 7P seven platters (1792K) - SET RF 8P eight platters (2048K) - SET RF AUTOSIZE autosize on attach - -The default is AUTOSIZE. - -The RF09/RF15 implements these registers: - - name size comments - - STA 18 status - DA 21 current disk address - WC 18 word count (in memory) - CA 18 memory address (in memory) - BUF 18 data buffer (diagnostic only) - INT 1 interrupt pending flag - WLK[0:7] 16 write lock switches for disks 0-7 - TIME 24 rotational delay, per word - BURST 1 burst flag - STOP_IOE 1 stop on I/O error - -The RF09/RF15 is a three-cycle data break device. If BURST = 0, word -transfers are scheduled individually; if BURST = 1, the entire transfer -occurs in a single data break. - -Error handling is as follows: - - error STOP_IOE processed as - - not attached 1 report error and stop - 0 disk not ready - -RF15/RF09 data files are buffered in memory; therefore, end of file and OS -I/O errors cannot occur. - -2.8 Type 550/555, TC02/TU55, and TC15/TU56 DECtape (DT) - -The PDP-4 and PDP-7 use the Type 550 DECtape, a programmed I/O controller. -The PDP-9 uses the TC02, and the PDP-15 uses the TC15. The TC02 and TC15 -are DMA controllers and programmatically identical. PDP-4/7 DECtape format -had 4 18b words in its block headers and trailers; PDP-9/15 DECtape format -had 5 18b words. - -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 Type 550, TC02, and TC15 support 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: - - system name size comments - - all DTSA 12 status register A - all DTSB 12 status register B - all DTDB 18 data buffer - all INT 1 interrupt pending flag - 9,15 ENB 1 interrupt enable flag - all DTF 1 DECtape flag - 7 BEF 1 block end flag - all ERF 1 error flag - 9,15 CA 18 current address (memory location 30) - 9,15 WC 18 word count (memory location 31) - all LTIME 31 time between lines - all ACTIME 31 time to accelerate to full speed - all DCTIME 31 time to decelerate to a full stop - all SUBSTATE 2 read/write command substate - all POS[0:7] 32 position, in lines, units 0-7 - all 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.9 TC59/TU10 Magnetic Tape (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 controller implements these registers: - - name size comments - - CMD 18 command - STA 18 main status - CA 18 memory address (in memory) - WC 18 word count (in memory) - INT 1 interrupt pending flag - STOP_IOE 1 stop on I/O error - TIME 24 record delay - UST[0:7] 24 unit status, units 0-7 - POS[0:7] 32 position, units 0-7 - -Error handling is as follows: - - error processed as - - not attached tape not ready; if STOP_IOE, stop - - end of file bad tape - - OS I/O error parity error; if STOP_IOE, stop - -2.10 Symbolic Display and Input - -The 18b PDP simulators implement symbolic display and input. Display is -controlled by command line switches: - - -a display as ASCII character - -c display as (sixbit) character string - -m display instruction mnemonics - -The PDP-15 also recognizes an additional switch: - - -p display as packed ASCII (five 7b ASCII - characters in two 18b words) - -Input parsing is controlled by the first character typed in or by command -line switches: - - ' or -a ASCII character - " or -c three character sixbit string - alphabetic instruction mnemonic - numeric octal number - -The PDP-15 also recognizes an additional input mode: - - # or -p five character packed ASCII string in - two 18b words - -Instruction input uses standard 18b PDP assembler syntax. There are eight -instruction classes: memory reference, EAE, index (PDP-15 only), IOT, -operate, LAW, FP15 memory reference (PDP-15 only), and FP15 no operand -(PDP-15 only). - -Memory reference instructions have the format - - PDP-4, PDP-7: memref {I} address - PDP-9: memref{*} address - PDP-15: memref{*} address{,X} - -where I (PDP-4, PDP-7) /* (PDP-9, PDP-15) signifies indirect reference, -and X signifies indexing (PDP-15 in page mode only). The address is an -octal number in the range 0 - 017777 (PDP-4, PDP-7, PDP-9, and PDP-15 in -bank mode) or 0 - 07777 (PDP-15 in page mode). - -IOT instructions consist of single mnemonics, eg, KRB, TLS. IOT instructions -may be or'd together - - iot iot iot... - -IOT's may also include the number 10, signifying clear the accumulator - - iot 10 - -The simulator does not check the legality of IOT combinations. IOT's for -which there is no opcode may be specified as IOT n, where n is an octal -number in the range 0 - 07777. - -EAE instructions have the format - - eae {+/- shift count} - -EAE instructions may be or'd together - - eae eae eae... - -The simulator does not check the legality of EAE combinations. EAE's for -which there is no opcode may be specified as EAE n, where n is an octal -number in the range 0 - 037777. - -Index instructions (PDP-15 only) have the format - - index {immediate} - -The immediate, if allowed, must be in the range of -0400 to +0377. - -Operate instructions have the format - - opr opr opr... - -The simulator does not check the legality of the proposed combination. The -operands for MUY and DVI must be deposited explicitly. - -The LAW instruction has the format - - LAW immediate - -where immediate is in the range of 0 to 017777. - -FP15 memory reference instructions occupy two successive words and have -the format - - fpmem{*} address - -where * signifies indirect addressing. The address is a number in the range -0 - 0377777. - -FP15 no operand instructions occupy two successive words and have the format - - fpop - -The second word is ignored on output and set to 0 on input. - -2.11 Character Sets - -The PDP-4's console was an ASR-28 Teletype; its character encoding was -Baudot. The PDP-4's line printer used a modified Hollerith character -set. The PDP-7's and PDP-9's consoles were KSR-33 Teletypes; their -character sets were basically ASCII. The PDP-7's and PDP-9's line -printers used sixbit encoding (ASCII codes 040 - 0137 masked to six -bits). The PDP-15's I/O devices were all ASCII. The following table -provides equivalences between ASCII characters and the PDP-4's I/O devices. -In the console table, FG stands for figures (upper case). - - PDP-4 PDP-4 -ASCII console line printer - -000 - 006 none none -bell FG+024 none -010 - 011 none none -lf 010 none -013 - 014 none none -cr 002 none -016 - 037 none none -space 004 000 -! FG+026 none -" FG+021 none -# FG+005 none -$ FG+062 none -% none none -& FG+013 none -' FG+032 none -( FG+036 057 -) FG+011 055 -* none 072 -+ none 074 -, FG+006 033 -- FG+030 054 -. FG+007 073 -/ FG+027 021 -0 FG+015 020 -1 FG+035 001 -2 FG+031 002 -3 FG+020 003 -4 FG+012 004 -5 FG+001 005 -6 FG+025 006 -7 FG+034 007 -8 FG+014 010 -9 FG+003 011 -: FG+016 none -; FG+017 none -< none 034 -= none 053 -> none 034 -? FG+023 037 -@ none {MID DOT} 040 -A 030 061 -B 023 062 -C 016 063 -D 022 064 -E 020 065 -F 026 066 -G 013 067 -H 005 070 -I 014 071 -J 032 041 -K 036 042 -L 011 043 -M 007 044 -N 006 045 -O 003 046 -P 015 047 -Q 035 050 -R 012 051 -S 024 022 -T 001 023 -U 034 024 -V 017 025 -W 031 026 -X 027 027 -Y 025 030 -Z 021 031 -[ none none -\ none {OVERLINE} 056 -] none none -^ none {UP ARROW} 035 -_ none UC+040 -0140 - 0177 none none diff --git a/PDP18B/pdp18b_drm.c b/PDP18B/pdp18b_drm.c deleted file mode 100644 index 4c3b917f..00000000 --- a/PDP18B/pdp18b_drm.c +++ /dev/null @@ -1,230 +0,0 @@ -/* pdp18b_drm.c: drum/fixed head disk simulator - - 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. - - 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 - 25-Nov-01 RMS Revised interrupt structure - 10-Jun-01 RMS Cleaned up IOT decoding to reflect hardware - 26-Apr-01 RMS Added device enable/disable support - 14-Apr-99 RMS Changed t_addr to unsigned -*/ - -#include "pdp18b_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 040 /* write */ - -#define GET_POS(x) ((int) fmod (sim_gtime() / ((double) (x)), \ - ((double) DRM_NUMWDT))) - -extern int32 M[]; -extern int32 int_hwre[API_HLVL+1]; -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 */ - -DEVICE drm_dev; -int32 drm60 (int32 pulse, int32 AC); -int32 drm61 (int32 pulse, int32 AC); -int32 drm62 (int32 pulse, int32 AC); -int32 drm_iors (void); -t_stat drm_svc (UNIT *uptr); -t_stat drm_reset (DEVICE *dptr); -t_stat drm_boot (int32 unitno, DEVICE *dptr); - -/* DRM data structures - - drm_dev DRM device descriptor - drm_unit DRM unit descriptor - drm_reg DRM register list -*/ - -DIB drm_dib = { DEV_DRM, 3 ,&drm_iors, { &drm60, &drm61, &drm62 } }; - -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 (INT, int_hwre[API_DRM], INT_V_DRM) }, - { FLDATA (DONE, int_hwre[API_DRM], INT_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) }, - { ORDATA (DEVNO, drm_dib.dev, 6), REG_HRO }, - { NULL } }; - -MTAB drm_mod[] = { - { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", &set_devno, &show_devno }, - { 0 } }; - -DEVICE drm_dev = { - "DRM", &drm_unit, drm_reg, drm_mod, - 1, 8, 20, 1, 8, 18, - NULL, NULL, &drm_reset, - &drm_boot, NULL, NULL, - &drm_dib, DEV_DISABLE }; - -/* IOT routines */ - -int32 drm60 (int32 pulse, int32 AC) -{ -if ((pulse & 027) == 06) { /* DRLR, DRLW */ - drm_ma = AC & 0177777; /* load mem addr */ - drm_unit.FUNC = pulse & DRM_WRITE; } /* save function */ -return AC; -} - -int32 drm61 (int32 pulse, int32 AC) -{ -int32 t; - -if (pulse & 001) { /* DRSF */ - if (TST_INT (DRM)) AC = AC | IOT_SKP; } -if (pulse & 002) { /* DRCF */ - CLR_INT (DRM); /* clear done */ - drm_err = 0; } /* clear error */ -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? */ - sim_activate (&drm_unit, t * drm_time); } /* schedule op */ -return AC; -} - -int32 drm62 (int32 pulse, int32 AC) -{ -int32 t; - -if (pulse & 001) { /* DRSN */ - if (drm_err == 0) AC = AC | IOT_SKP; } -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? */ - sim_activate (&drm_unit, t * drm_time); } /* schedule op */ -return AC; -} - -/* Unit service - - This code assumes the entire drum is buffered. -*/ - -t_stat drm_svc (UNIT *uptr) -{ -int32 i; -uint32 da; - -if ((uptr->flags & UNIT_BUF) == 0) { /* not buf? abort */ - drm_err = 1; /* set error */ - SET_INT (DRM); /* set done */ - 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 */ -SET_INT (DRM); /* set done */ -return SCPE_OK; -} - -/* Reset routine */ - -t_stat drm_reset (DEVICE *dptr) -{ -drm_da = drm_ma = drm_err = 0; -CLR_INT (DRM); /* clear done */ -sim_cancel (&drm_unit); -return SCPE_OK; -} - -/* IORS routine */ - -int32 drm_iors (void) -{ -return (TST_INT (DRM)? IOS_DRM: 0); -} - -/* Bootstrap routine */ - -#define BOOT_START 02000 -#define BOOT_LEN (sizeof (boot_rom) / sizeof (int)) - -static const int32 boot_rom[] = { - 0750000, /* CLA ; dev, mem addr */ - 0706006, /* DRLR ; load ma */ - 0706106, /* DRSS ; load da, start */ - 0706101, /* DRSF ; wait for done */ - 0602003, /* JMP .-1 */ - 0600000 /* JMP 0 ; enter boot */ -}; - -t_stat drm_boot (int32 unitno, DEVICE *dptr) -{ -int32 i; -extern int32 PC; - -if (drm_dib.dev != DEV_DRM) return STOP_NONSTD; /* non-std addr? */ -for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i]; -PC = BOOT_START; -return SCPE_OK; -} diff --git a/PDP18B/pdp18b_dt.c b/PDP18B/pdp18b_dt.c deleted file mode 100644 index 1a5620ae..00000000 --- a/PDP18B/pdp18b_dt.c +++ /dev/null @@ -1,1338 +0,0 @@ -/* pdp18b_dt.c: 18b DECtape simulator - - 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. - - dt (PDP-4, PDP-7) Type 550/555 DECtape - (PDP-9) TC02/TU55 DECtape - (PDP-15) TC15/TU56 DECtape - - 25-Apr-03 RMS Revised for extended file support - 14-Mar-03 RMS Fixed variable size interaction with save/restore - 17-Oct-02 RMS Fixed bug in end of reel logic - 05-Oct-02 RMS Added DIB, device number support - 12-Sep-02 RMS Added 16b format support - 13-Aug-02 RMS Corrected Type 550 unit select logic - 25-Jul-02 RMS Added PDP-4 support - 30-May-02 RMS Widened POS to 32b - 10-Feb-02 RMS Added PDP-7 support - 06-Jan-02 RMS Revised enable/disable support - 29-Nov-01 RMS Added read only unit support - 25-Nov-01 RMS Revised interrupt structure - Changed POS, STATT, LASTT, FLG to arrays - 29-Aug-01 RMS Added casts to PDP-8 unpack routine - 17-Jul-01 RMS Moved function prototype - 11-May-01 RMS Fixed bug in reset - 26-Apr-01 RMS Added device enable/disable support - 15-Mar-01 RMS Added 129th word to PDP-8 format - - 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-4/7 DECtape has only four 18b - header words; for consistency, the PDP-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 "pdp18b_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 */ - -#if defined (TC02) /* TC02/TC15 */ -#define DTA_V_UNIT 15 /* unit select */ -#define DTA_M_UNIT 07 -#define DTA_UNIT (DTA_M_UNIT << DTA_V_UNIT) -#define DTA_V_MOT 13 /* motion */ -#define DTA_M_MOT 03 -#define DTA_V_MODE 12 /* mode */ -#define DTA_V_FNC 9 /* function */ -#define DTA_M_FNC 07 -#define FNC_MOVE 00 /* move */ -#define FNC_SRCH 01 /* search */ -#define FNC_READ 02 /* read */ -#define FNC_RALL 03 /* read all */ -#define FNC_WRIT 04 /* write */ -#define FNC_WALL 05 /* write all */ -#define FNC_WMRK 06 /* write timing */ -#define DTA_V_ENB 8 /* int enable */ -#define DTA_V_CERF 7 /* clr error flag */ -#define DTA_V_CDTF 6 /* clr DECtape flag */ -#define DTA_FWDRV (1u << (DTA_V_MOT + 1)) -#define DTA_STSTP (1u << DTA_V_MOT) -#define DTA_MODE (1u << DTA_V_MODE) -#define DTA_ENB (1u << DTA_V_ENB) -#define DTA_CERF (1u << DTA_V_CERF) -#define DTA_CDTF (1u << DTA_V_CDTF) -#define DTA_RW (0777700 & ~(DTA_CERF | DTA_CDTF)) -#define DTA_GETUNIT(x) (((x) >> DTA_V_UNIT) & DTA_M_UNIT) -#define DT_UPDINT if ((dtsa & DTA_ENB) && (dtsb & (DTB_ERF | DTB_DTF))) \ - SET_INT (DTA); \ - else CLR_INT (DTA); - -#else /* Type 550 */ -#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)) \ - SET_INT (DTA); \ - else CLR_INT (DTA); -#endif - -#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 */ - -#if defined (TC02) /* TC02/TC15 */ -#define DTB_V_ERF 17 /* error flag */ -#define DTB_V_MRK 16 /* mark trk err */ -#define DTB_V_END 15 /* end zone err */ -#define DTB_V_SEL 14 /* select err */ -#define DTB_V_PAR 13 /* parity err */ -#define DTB_V_TIM 12 /* timing err */ -#define DTB_V_DTF 6 /* DECtape flag */ -#define DTB_ERF (1u << DTB_V_ERF) -#define DTB_MRK (1u << DTB_V_MRK) -#define DTB_END (1u << DTB_V_END) -#define DTB_SEL (1u << DTB_V_SEL) -#define DTB_PAR (1u << DTB_V_PAR) -#define DTB_TIM (1u << DTB_V_TIM) -#define DTB_DTF (1u << DTB_V_DTF) -#define DTB_ALLERR (DTB_ERF | DTB_MRK | DTB_END | DTB_SEL | \ - DTB_PAR | DTB_TIM) - -#else /* Type 550 */ -#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) -#endif - -/* 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 int_hwre[API_HLVL+1], dev_enb; -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 }; - -DEVICE dt_dev; -int32 dt75 (int32 pulse, int32 dat); -int32 dt76 (int32 pulse, int32 dat); -int32 dt_iors (void); -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 -*/ - -DIB dt_dib = { DEV_DTA, 2, &dt_iors, { &dt75, &dt76 } }; - -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 (INT, int_hwre[API_DTA], INT_V_DTA) }, -#if defined (DTA_V_ENB) - { FLDATA (ENB, dtsa, DTA_V_ENB) }, -#endif - { FLDATA (DTF, dtsb, DTB_V_DTF) }, -#if defined (DTB_V_BEF) - { FLDATA (BEF, dtsb, DTB_V_BEF) }, -#endif - { FLDATA (ERF, dtsb, DTB_V_ERF) }, -#if defined (TC02) /* TC02/TC15 */ - { ORDATA (WC, M[DT_WC], 18) }, - { ORDATA (CA, M[DT_CA], 18) }, -#endif - { 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, T_ADDR_W, 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, T_ADDR_W, 0, - DT_NUMDR, REG_HRO) }, - { ORDATA (DEVNO, dt_dib.dev, 6), 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 }, - { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", &set_devno, &show_devno }, - { 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, - &dt_dib, DEV_DISABLE }; - -/* IOT routines */ - -#if defined (TC02) /* TC02/TC15 */ -int32 dt75 (int32 pulse, int32 dat) -{ -int32 old_dtsa = dtsa, fnc; -UNIT *uptr; - -if (((pulse & 060) == 040) && (pulse & 05)) { /* select */ - if (pulse & 01) dtsa = 0; /* DTCA */ - if (pulse & 02) dat = dtsa; /* DTRA!... */ - if (pulse & 04) { /* DTXA */ - if ((dat & DTA_CERF) == 0) dtsb = dtsb & ~DTB_ALLERR; - if ((dat & DTA_CDTF) == 0) dtsb = dtsb & ~DTB_DTF; - dtsa = dtsa ^ (dat & 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 */ - if (((uptr->flags) & UNIT_DIS) || /* disabled? */ - (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 */ - else dt_newsa (dtsa); /* new func */ - DT_UPDINT; - return dat; } -if ((pulse & 067) == 042) return dtsa; /* DTRA */ -if ((pulse & 067) == 061) /* DTEF */ - return ((dtsb & DTB_ERF)? IOT_SKP + dat: dat); -if ((pulse & 067) == 062) return dtsb; /* DTRB */ -if ((pulse & 067) == 063) /* DTEF!DTRB */ - return ((dtsb & DTB_ERF)? IOT_SKP + dtsb: dtsb); -return dat; -} - -int32 dt76 (int32 pulse, int32 dat) -{ -if ((pulse & 01) && (dtsb & DTB_DTF)) /* DTDF */ - return IOT_SKP + dat; -return dat; -} - -#else /* Type 550 */ -int32 dt75 (int32 pulse, int32 dat) -{ -if (((pulse & 041) == 001) && (dtsb & DTB_DTF)) /* MMDF */ - dat = dat | IOT_SKP; -else if (((pulse & 041) == 041) && (dtsb & DTB_ERF)) /* MMEF */ - dat = dat | IOT_SKP; -if (pulse & 002) { /* MMRD */ - dat = (dat & ~DMASK) | dtdb; - dtsb = dtsb & ~(DTB_DTF | DTB_BEF); } -if (pulse & 004) { /* MMWR */ - dtdb = dat & DMASK; - dtsb = dtsb & ~(DTB_DTF | DTB_BEF); } -DT_UPDINT; -return dat; -} - -int32 dt76 (int32 pulse, int32 dat) -{ -int32 fnc, mot, unum; -UNIT *uptr = NULL; - -unum = DTA_GETUNIT (dtsa); /* get unit no */ -if (unum >= 0) uptr = dt_dev.units + unum; /* get unit */ -if ((pulse & 001) && (dtsb & DTB_BEF)) /* MMBF */ - dat = dat | IOT_SKP; -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 */ - dat = (dat & ~DMASK) | dtsb; } -if ((pulse & 044) == 044) { /* MMSE */ - if ((dtsa ^ dat) & DTA_UNIT) dt_deselect (dtsa); /* new unit? */ - dtsa = (dtsa & ~DTA_UNIT) | (dat & DTA_UNIT); - dtsb = dtsb & ~(DTB_DTF | DTB_BEF | DTB_ERF | DTB_ALLERR); } -else if ((pulse & 044) == 004) { /* MMLC */ - dtsa = (dtsa & ~DTA_RW) | (dat & 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); } -DT_UPDINT; -return dat; -} -#endif - -/* 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, relpos, 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 */ -#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; } - 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; } - if (dir) newpos = DT_BLK2LN (((relpos >= (DTU_LPERB (uptr) - DT_HTLIN))? - blk + 1: blk), uptr) - DT_HTLIN - DT_WSIZE; - else newpos = DT_BLK2LN (((relpos < DT_HTLIN)? - 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 ((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 defined (TYPE550) /* Type 550 */ -if ((fnc == FNC_WRIT) || (fnc == FNC_WALL)) { /* write function? */ - dtsb = dtsb | DTB_DTF; /* set data flag */ - DT_UPDINT; } -#endif -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; -uint32 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; - -/* TC02/TC15 service */ -/* Search */ - -#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; } - 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] & AMASK; /* get mem addr */ - if (MEM_ADDR_OK (ma)) M[ma] = blk; /* store block # */ - if (((dtsa & DTA_MODE) == 0) || (M[DT_WC] == 0)) - dtsb = dtsb | DTB_DTF; /* set DTF */ - break; - -/* Read has four subcases - - Start of block, not wc ovf - check that DTF is clear, otherwise normal - Normal - increment MA, WC, copy word from tape to memory - if read dir != write dir, bits must be scrambled - if wc overflow, next state is wc overflow - if end of block, possibly set DTF, next state is start of block - Wc ovf, not start of block - - if end of block, possibly set DTF, next state is start of block - Wc ovf, start of block - if end of block reached, timing error, - otherwise, continue to next word -*/ - -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 */ - 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] & AMASK; /* 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 */ - 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; } - break; - -/* Write has four subcases - - Start of block, not wc ovf - check that DTF is clear, set block direction - Normal - increment MA, WC, copy word from memory to tape - if wc overflow, next state is wc overflow - if end of block, possibly set DTF, next state is start of block - Wc ovf, not start of block - - copy 0 to tape - if end of block, possibly set DTF, next state is start of block - Wc ovf, start of block - schedule end zone -*/ - -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 */ - case 0: /* normal write */ - 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] & AMASK; /* 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 */ - break; } - break; - -/* Read all has two subcases - - Not word count overflow - increment MA, WC, copy word from tape to memory - Word count overflow - schedule end zone -*/ - -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] & AMASK; /* 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 */ - break; - -/* Write all has two subcases - - Not word count overflow - increment MA, WC, copy word from memory to tape - Word count overflow - schedule end zone -*/ - -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] & AMASK; /* 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; - case DTO_WCO: case DTO_WCO | DTO_SOB: /* all done */ - dt_schedez (uptr, dir); /* sched end zone */ - break; } /* end case substate */ - break; - -/* Type 550 service */ -/* Search */ - -#else /* Type 550 */ -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; -#endif - -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 ^ DMASK; /* 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; - -#if defined (TC02) /* TC02/TC15 */ -csum = 077; /* init csum */ -for (i = 0; i < DTU_BSIZE (uptr); i++) { /* loop thru buf */ - wrd = bptr[ba + i] ^ DMASK; /* get ~word */ - csum = csum ^ (wrd >> 12) ^ (wrd >> 6) ^ wrd; } -return (csum & 077); -#else /* Type 550 */ -csum = DMASK; -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 > DMASK) csum = (csum + 1) & DMASK; } -return (csum ^ DMASK); /* 1's comp res */ -#endif -} - -/* 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 defined (TC02) /* TC02/TC15 */ -if (wrd == (2 * DT_HTWRD + DTU_BSIZE (uptr) - DT_CSMWD - 1)) /* fwd csum */ - return (dt_csum (uptr, blk) << 12); -#else -if (wrd == DT_CSMWD) return DMASK; /* rev csum */ -if (wrd == (2 * DT_HTWRD + DTU_BSIZE (uptr) - DT_CSMWD - 1)) /* fwd csum */ - return (dt_csum (uptr, blk)); -#endif /* Type 550 */ -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 ba, sz, k, *bptr; -int32 u = uptr - dt_dev.units; -t_stat r; - -r = attach_unit (uptr, cptr); /* attach */ -if (r != SCPE_OK) return r; /* error? */ -if ((sim_switches & SIM_SW_REST) == 0) { /* not from rest? */ - 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? */ - (sz = sim_fsize (cptr))) { - if (sz == D8_FILSIZ) - uptr->flags = uptr->flags | UNIT_8FMT; - else if (sz == 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 */ -printf ("%s%d: ", sim_dname (&dt_dev), u); -if (uptr->flags & UNIT_8FMT) printf ("12b format"); -else if (uptr->flags & UNIT_11FMT) printf ("16b format"); -else printf ("18b/36b format"); -printf (", buffering file in memory\n"); -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 ba, k, *bptr; -int32 u = uptr - dt_dev.units; - -if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; -if (sim_is_active (uptr)) { - sim_cancel (uptr); - if ((u == 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 ("%s%d: writing buffer to file\n", sim_dname (&dt_dev), u); - 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/PDP18B/pdp18b_fpp.c b/PDP18B/pdp18b_fpp.c deleted file mode 100644 index 4b8eb99d..00000000 --- a/PDP18B/pdp18b_fpp.c +++ /dev/null @@ -1,781 +0,0 @@ -/* pdp18b_fpp.c: FP15 floating point processor simulator - - 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. - - fpp PDP-15 floating point processor - - The FP15 instruction 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 1| subop | microcoded modifiers | floating point - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - |in| address | - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - Indirection is always single level. - - The FP15 supports four data formats: - - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | S| 2's complement integer | A: integer - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | S| 2's complement integer (high) | A: extended integer - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | 2's complement integer (low) | A+1 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | fraction (low) |SE|2's complement exponent| A: single floating - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - |SF| fraction (high) | A+1 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - |SE| 2's complement exponent | A: double floating - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - |SF| fraction (high) | A+1 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | fraction (low) | A+2 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - -*/ - -#include "pdp18b_defs.h" - -/* Instruction */ - -#define FI_V_OP 8 /* subopcode */ -#define FI_M_OP 017 -#define FI_GETOP(x) (((x) >> FI_V_OP) & FI_M_OP) -#define FI_NOLOAD 0200 /* don't load */ -#define FI_DP 0100 /* single/double */ -#define FI_FP 0040 /* int/flt point */ -#define FI_NONORM 0020 /* don't normalize */ -#define FI_NORND 0010 /* don't round */ -#define FI_V_SGNOP 0 /* A sign change */ -#define FI_M_SGNOP 03 -#define FI_GETSGNOP(x) (((x) >> FI_V_SGNOP) & FI_M_SGNOP) - -/* Exception register */ - -#define JEA_V_SIGN 17 /* A sign */ -#define JEA_V_GUARD 16 /* guard */ -#define JEA_EAMASK 077777 /* exc address */ -#define JEA_OFF_OVF 0 /* ovf offset */ -#define JEA_OFF_UNF 2 /* unf offset */ -#define JEA_OFF_DIV 4 /* div offset */ -#define JEA_OFF_MM 6 /* mem mgt offset */ - -/* Status codes - must relate directly to JEA offsets */ - -#define FP_OK 0 /* no error - mbz */ -#define FP_OVF (JEA_OFF_OVF + 1) /* overflow */ -#define FP_UNF (JEA_OFF_UNF + 1) /* underflow */ -#define FP_DIV (JEA_OFF_DIV + 1) /* divide exception */ -#define FP_MM (JEA_OFF_MM + 1) /* mem mgt error */ - -/* Unpacked floating point fraction */ - -#define UFP_FH_CARRY 0400000 /* carry out */ -#define UFP_FH_NORM 0200000 /* normalized */ -#define UFP_FH_MASK 0377777 /* hi mask */ -#define UFP_FL_MASK 0777777 /* low mask */ -#define UFP_FL_SMASK 0777000 /* low mask, single */ -#define UFP_FL_SRND 0000400 /* round bit, single */ - -#define GET_SIGN(x) (((x) >> 17) & 1) -#define SEXT18(x) (((x) & SIGN)? ((x) | ~DMASK): ((x) & DMASK)) -#define SEXT9(x) (((x) & 0400)? ((x) | ~0377): ((x) & 0377)) - -enum fop { - FOP_TST, FOP_SUB, FOP_RSUB, FOP_MUL, - FOP_DIV, FOP_RDIV, FOP_LD, FOP_ST, - FOP_FLT, FOP_FIX, FOP_LFMQ, FOP_JEA, - FOP_ADD, FOP_BR, FOP_DIAG, FOP_UND }; - -struct ufp { - int32 exp; /* exponent */ - int32 sign; /* sign */ - int32 hi; /* hi frac, 17b */ - int32 lo; }; /* lo frac, 18b */ - -typedef struct ufp UFP; - -static int32 fir; /* instruction */ -static int32 jea; /* exc address */ -static int32 fguard; /* guard bit */ -static int32 stop_fpp = STOP_RSRV; /* stop if fp dis */ -static UFP fma; /* FMA */ -static UFP fmb; /* FMB */ -static UFP fmq; /* FMQ - hi,lo only */ - -extern int32 M[MAXMEMSIZE]; -extern int32 pcq[PCQ_SIZE]; -extern int32 pcq_p; -extern int32 PC; -extern int32 trap_pending, usmd; - -t_stat fp15_reset (DEVICE *dptr); -t_stat fp15_opnd (int32 ir, int32 addr, UFP *a); -t_stat fp15_store (int32 ir, int32 addr, UFP *a); -t_stat fp15_iadd (int32 ir, UFP *a, UFP *b, t_bool sub); -t_stat fp15_imul (int32 ir, UFP *a, UFP *b); -t_stat fp15_idiv (int32 ir, UFP *a, UFP *b); -t_stat fp15_fadd (int32 ir, UFP *a, UFP *b, t_bool sub); -t_stat fp15_fmul (int32 ir, UFP *a, UFP *b); -t_stat fp15_fdiv (int32 ir, UFP *a, UFP *b); -t_stat fp15_fix (int32 ir, UFP *a); -t_stat fp15_norm (int32 ir, UFP *a, UFP *b, t_bool rnd); -t_stat fp15_exc (int32 sta); -void fp15_asign (int32 ir, UFP *a); -void dp_add (UFP *a, UFP *b); -void dp_sub (UFP *a, UFP *b); -void dp_inc (UFP *a); -int32 dp_cmp (UFP *a, UFP *b); -void dp_mul (UFP *a, UFP *b); -void dp_lsh_1 (UFP *a, UFP *b); -void dp_rsh_1 (UFP *a, UFP *b); -void dp_dnrm_r (int32 ir, UFP *a, int32 sc); -void dp_swap (UFP *a, UFP *b); - -extern t_stat Read (int32 ma, int32 *dat, int32 cyc); -extern t_stat Write (int32 ma, int32 dat, int32 cyc); -extern t_stat Ia (int32 ma, int32 *ea, t_bool jmp); -extern int32 Incr_addr (int32 addr); -extern int32 Jms_word (int32 t); - -/* FPP data structures - - fpp_dev FPP device descriptor - fpp_unit FPP unit - fpp_reg FPP register list - fpp_mod FPP modifier list -*/ - -UNIT fpp_unit = { UDATA (NULL, 0, 0) }; - -REG fpp_reg[] = { - { ORDATA (FIR, fir, 12) }, - { ORDATA (EPA, fma.exp, 18) }, - { FLDATA (FMAS, fma.sign, 0) }, - { ORDATA (FMAH, fma.hi, 17) }, - { ORDATA (FMAL, fma.lo, 18) }, - { ORDATA (EPB, fmb.exp, 18) }, - { FLDATA (FMBS, fmb.sign, 0) }, - { ORDATA (FMBH, fmb.hi, 17) }, - { ORDATA (FMBL, fmb.lo, 18) }, - { FLDATA (FGUARD, fguard, 0) }, - { ORDATA (FMQH, fmq.hi, 17) }, - { ORDATA (FMQL, fmq.lo, 18) }, - { ORDATA (JEA, jea, 18) }, - { FLDATA (STOP_FPP, stop_fpp, 0) }, - { NULL } }; - -DEVICE fpp_dev = { - "FPP", &fpp_unit, fpp_reg, NULL, - 1, 8, 1, 1, 8, 18, - NULL, NULL, &fp15_reset, - NULL, NULL, NULL, - NULL, DEV_DISABLE | DEV_DIS }; - -/* Instruction decode for FP15 - - The CPU actually fetches the instruction and the word after. If the - instruction is 71XXXX, the CPU executes it as a NOP, and the FP15 fools - the CPU into thinking that the second word is also a NOP. - - Indirect addresses are resolved during fetch, unless the NOLOAD modifier - is set and the instruction is not a store. */ - -t_stat fp15 (int32 ir) -{ -int32 ar, ma, fop, dat; -t_stat sta = FP_OK; - -if (fpp_dev.flags & DEV_DIS) /* disabled? */ - return (stop_fpp? STOP_FPDIS: SCPE_OK); -fir = ir & 07777; /* save subop + mods */ -ma = PC; /* fetch next word */ -PC = Incr_addr (PC); -if (Read (ma, &ar, RD)) return fp15_exc (FP_MM); /* error? MM exc */ -fop = FI_GETOP (fir); /* get subopcode */ -if ((ar & SIGN) && /* indirect? */ - ((fop == FOP_ST) || !(ir & FI_NOLOAD))) { /* store or load? */ - ma = ar & AMASK; /* fetch indirect */ - if (Read (ma, &ar, RD)) return fp15_exc (FP_MM); } -fma.exp = SEXT18 (fma.exp); /* sext exponents */ -fmb.exp = SEXT18 (fmb.exp); -switch (fop) { /* case on subop */ - -case FOP_TST: /* NOP */ - break; - -case FOP_SUB: /* subtract */ - if (sta = fp15_opnd (fir, ar, &fmb)) break; /* fetch op to FMB */ - if (fir & FI_FP) /* fp? */ - sta = fp15_fadd (fir, &fma, &fmb, 1); /* yes, fp sub */ - else sta = fp15_iadd (fir, &fma, &fmb, 1); /* no, int sub */ - break; - -case FOP_RSUB: /* reverse sub */ - fmb = fma; /* FMB <- FMA */ - if (sta = fp15_opnd (fir, ar, &fma)) break; /* fetch op to FMA */ - if (fir & FI_FP) /* fp? */ - sta = fp15_fadd (fir, &fma, &fmb, 1); /* yes, fp sub */ - else sta = fp15_iadd (fir, &fma, &fmb, 1); /* no, int sub */ - break; - -case FOP_MUL: /* multiply */ - if (sta = fp15_opnd (fir, ar, &fmb)) break; /* fetch op to FMB */ - if (fir & FI_FP) /* fp? */ - sta = fp15_fmul (fir, &fma, &fmb); /* yes, fp mul */ - else sta = fp15_imul (fir, &fma, &fmb); /* no, int mul */ - break; - -case FOP_DIV: /* divide */ - if (sta = fp15_opnd (fir, ar, &fmb)) break; /* fetch op to FMB */ - if (fir & FI_FP) /* fp? */ - sta = fp15_fadd (fir, &fma, &fmb, 1); /* yes, fp sub */ - else sta = fp15_idiv (fir, &fma, &fmb); /* no, int div */ - break; - -case FOP_RDIV: /* reverse divide */ - fmb = fma; /* FMB <- FMA */ - if (sta = fp15_opnd (fir, ar, &fma)) break; /* fetch op to FMA */ - if (fir & FI_FP) /* fp? */ - sta = fp15_fadd (fir, &fma, &fmb, 1); /* yes, fp sub */ - else sta = fp15_idiv (fir, &fma, &fmb); /* no, int div */ - break; - -case FOP_LD: /* load */ - if (sta = fp15_opnd (fir, ar, &fma)) break; /* fetch op to FMA */ - fp15_asign (fir, &fma); /* modify A sign */ - if (fir & FI_FP) /* fp? */ - sta = fp15_norm (ir, &fma, NULL, 0); /* norm, no round */ - break; - -case FOP_ST: /* store */ - fp15_asign (fir, &fma); /* modify A sign */ - sta = fp15_store (fir, ar, &fma); /* store result */ - break; - -case FOP_FLT: /* float */ - if (sta = fp15_opnd (fir, ar, &fma)) break; /* fetch op to FMA */ - fma.exp = 35; - fp15_asign (fir, &fma); /* adjust A sign */ - sta = fp15_norm (ir, &fma, NULL, 0); /* norm, no found */ - break; - -case FOP_FIX: /* fix */ - if (sta = fp15_opnd (fir, ar, &fma)) break; /* fetch op to FMA */ - sta = fp15_fix (fir, &fma); /* fix */ - break; - -case FOP_LFMQ: /* load FMQ */ - if (sta = fp15_opnd (fir, ar, &fma)) break; /* fetch op to FMA */ - dp_swap (&fma, &fmq); /* swap FMA, FMQ */ - fp15_asign (fir, &fma); /* adjust A sign */ - if (fir & FI_FP) /* fp? */ - sta = fp15_norm (ir, &fma, &fmq, 0); /* yes, norm, no rnd */ - break; - -case FOP_JEA: /* JEA */ - if (ir & 0200) { /* store? */ - dat = jea | (fma.sign << JEA_V_SIGN) | (fguard << JEA_V_GUARD); - sta = Write (ar, dat, WR); } - else { /* no, load */ - if (sta = Read (ar, &dat, RD)) break; - fguard = (dat >> JEA_V_GUARD) & 1; - jea = dat; } - break; - -case FOP_ADD: /* add */ - if (sta = fp15_opnd (fir, ar, &fmb)) break; /* fetch op to FMB */ - if (fir & FI_FP) /* fp? */ - sta = fp15_fadd (fir, &fma, &fmb, 0); /* yes, fp add */ - else sta = fp15_iadd (fir, &fma, &fmb, 0); /* no, int add */ - break; - -case FOP_BR: /* branch */ - if (((fir & 001) && ((fma.hi | fma.lo) == 0)) || - ((fir & 002) && fma.sign) || - ((fir & 004) && !fma.sign) || - ((fir & 010) && ((fma.hi | fma.lo) != 0)) || - ((fir & 020) && fguard)) { /* cond met? */ - PCQ_ENTRY; /* save current PC */ - PC = (PC & BLKMASK) | (ar & IAMASK); } /* branch within 32K */ - break; - -default: - break; } - -fma.exp = fma.exp & DMASK; /* mask exp to 18b */ -fmb.exp = fmb.exp & DMASK; -if (sta != FP_OK) return fp15_exc (sta); /* error? */ -return SCPE_OK; -} - -/* Operand load and store */ - -t_stat fp15_opnd (int32 ir, int32 addr, UFP *fpn) -{ -int32 i, numwd, wd[3]; - -fguard = 0; /* clear guard */ -if (ir & FI_NOLOAD) return FP_OK; /* no load? */ -if (ir & FI_FP) numwd = 2; /* fp? at least 2 */ -else numwd = 1; /* else at least 1 */ -if (ir & FI_DP) numwd = numwd + 1; /* dp? 1 more */ -for (i = 0; i < numwd; i++) { /* fetch words */ - if (Read (addr, &wd[i], RD)) return FP_MM; - addr = (addr + 1) & AMASK; } -if (ir & FI_FP) { /* fp? */ - fpn->sign = GET_SIGN (wd[1]); /* frac sign */ - fpn->hi = wd[1] & UFP_FH_MASK; /* frac high */ - if (ir & FI_DP) { /* dp? */ - fpn->exp = SEXT18 (wd[0]); /* exponent */ - fpn->lo = wd[2]; } /* frac low */ - else { /* sp */ - fpn->exp = SEXT9 (wd[0]); /* exponent */ - fpn->lo = wd[0] & UFP_FL_SMASK; } /* frac low */ - } -else { fpn->sign = GET_SIGN (wd[0]); /* int, get sign */ - if (ir & FI_DP) { /* dp? */ - fpn->lo = wd[1]; /* 2 words */ - fpn->hi = wd[0]; } - else { /* single */ - fpn->lo = wd[0]; /* 1 word */ - fpn->hi = fpn->sign? DMASK: 0; } /* sign extended */ - if (fpn->sign) { /* negative? */ - fpn->lo = (-fpn->lo) & UFP_FL_MASK; /* take abs val */ - fpn->hi = (~fpn->hi + (fpn->lo == 0)) & UFP_FH_MASK; } - } -return FP_OK; -} - -t_stat fp15_store (int32 ir, int32 addr, UFP *a) -{ -int32 i, numwd, wd[3]; -t_stat sta; - -fguard = 0; /* clear guard */ -if (ir & FI_FP) { /* fp? */ - if (sta = fp15_norm (ir, a, NULL, 0)) return sta; /* normalize */ - wd[1] = (a->sign << 17) | a->hi; /* hi frac */ - if (ir & FI_DP) { /* dp? */ - numwd = 3; /* 3 words */ - wd[0] = a->exp & DMASK; /* exponent */ - wd[2] = a->lo; } /* low frac */ - else { /* single */ - if (!(ir & FI_NORND) && (a->lo & UFP_FL_SRND)) { /* round? */ - a->lo = (a->lo + UFP_FL_SRND) & UFP_FL_SMASK; - a->hi = (a->hi + (a->lo == 0)) & UFP_FH_MASK; - if ((a->hi | a->lo) == 0) { /* carry out? */ - a->hi = UFP_FH_NORM; /* shift back */ - a->exp = a->exp + 1; } } - if (a->exp > 0377) return FP_OVF; /* sp ovf? */ - if (a->exp < -0400) return FP_UNF; /* sp unf? */ - numwd = 2; /* 2 words */ - wd[0] = (a->exp & 0777) | a->lo; } /* low frac'exp */ - } -else { fmb.lo = (-a->lo) & UFP_FL_MASK; /* 2's complement */ - fmb.hi = (~a->hi + (fmb.lo == 0)) & UFP_FH_MASK;/* to FMB */ - if (ir & FI_DP) { /* dp? */ - numwd = 2; /* 2 words */ - if (a->sign) { /* negative? */ - wd[0] = fmb.hi | SIGN; /* store FMB */ - wd[1] = fmb.lo; } - else { /* pos, store FMA */ - wd[0] = a->hi; - wd[1] = a->lo; } } - else { /* single */ - if (a->hi || (a->lo & SIGN)) return FP_OVF; /* check int ovf */ - numwd = 1; /* 1 word */ - if (a->sign) wd[0] = fmb.lo; /* neg? store FMB */ - else wd[0] = a->lo; } /* pos, store FMA */ - } -for (i = 0; i < numwd; i++) { /* store words */ - if (Write (addr, wd[i], WR)) return FP_MM; - addr = (addr + 1) & AMASK; } -return FP_OK; -} - -/* Integer arithmetic routines */ - -/* Integer add - overflow only on add, if carry out of high fraction */ - -t_stat fp15_iadd (int32 ir, UFP *a, UFP *b, t_bool sub) -{ -fmq.hi = fmq.lo = 0; /* clear FMQ */ -if (a->sign ^ b->sign ^ sub) dp_sub (a, b); /* eff subtract? */ -else { dp_add (a, b); /* no, add */ - if (a->hi & UFP_FH_CARRY) { /* carry out? */ - a->hi = a->hi & UFP_FH_MASK; /* mask to 35b */ - return FP_OVF; } } /* overflow */ -fp15_asign (ir, a); /* adjust A sign */ -return FP_OK; -} - -/* Integer multiply - overflow if high result (FMQ after swap) non-zero */ - -t_stat fp15_imul (int32 ir, UFP *a, UFP *b) -{ -a->sign = a->sign ^ b->sign; /* sign of result */ -dp_mul (a, b); /* a'FMQ <- a * b */ -dp_swap (a, &fmq); /* swap a, FMQ */ -if (fmq.hi | fmq.lo) return FP_OVF; /* FMQ != 0? ovf */ -fp15_asign (ir, a); /* adjust A sign */ -return FP_OK; -} - -/* Integer divide - actually done as fraction divide - - - If divisor zero, error - - If dividend zero, done - - Normalize dividend and divisor together - - If divisor normalized but dividend not, result is zero - - If divisor not normalized, normalize and count shifts - - Do fraction divide for number of shifts, +1, steps - - Note that dp_lsh_1 returns a 72b result; the last right shift - guarantees a 71b remainder. The quotient cannot exceed 71b */ - -t_stat fp15_idiv (int32 ir, UFP *a, UFP *b) -{ -int32 i, sc; - -a->sign = a->sign ^ b->sign; /* sign of result */ -fmq.hi = fmq.lo = 0; /* clear quotient */ -a->exp = 0; /* clear a exp */ -if ((b->hi | b->lo) == 0) return FP_DIV; /* div by 0? */ -if ((a->hi | a->lo) == 0) return FP_OK; /* div into 0? */ -while (((a->hi & UFP_FH_NORM) == 0) && /* normalize divd */ - ((b->hi & UFP_FH_NORM) == 0)) { /* and divr */ - dp_lsh_1 (a, NULL); /* lsh divd, divr */ - dp_lsh_1 (b, NULL); } /* can't carry out */ -if (!(a->hi & UFP_FH_NORM) && (b->hi & UFP_FH_NORM)) { /* divr norm, divd not? */ - a->hi = a->lo = 0; /* result is 0 */ - return FP_OK; } -while ((b->hi & UFP_FH_NORM) == 0) { /* normalize divr */ - dp_lsh_1 (b, NULL); /* can't carry out */ - a->exp = a->exp + 1; } /* count steps */ -sc = a->exp; -for (i = 0; i <= sc; i++) { /* n+1 steps */ - dp_lsh_1 (&fmq, NULL); /* left shift quo */ - if (dp_cmp (a, b) >= 0) { /* sub work? */ - dp_sub (a, b); /* a -= b */ - if (i == 0) a->exp = a->exp + 1; /* first step? */ - fmq.lo = fmq.lo | 1; } /* set quo bit */ - dp_lsh_1 (a, NULL); } /* left shift divd */ -dp_rsh_1 (a, NULL); /* shift back */ -dp_swap (a, &fmq); /* swap a, FMQ */ -fp15_asign (ir, a); /* adjust A sign */ -return FP_OK; -} - -/* Floating point arithmetic routines */ - -/* Floating add - - Special add case, overflow if carry out increments exp out of range - - All cases, overflow/underflow detected in normalize */ - -t_stat fp15_fadd (int32 ir, UFP *a, UFP *b, t_bool sub) -{ -int32 ediff; - -fmq.hi = fmq.lo = 0; /* clear FMQ */ -ediff = a->exp - b->exp; /* exp diff */ -if (((a->hi | a->lo) == 0) || (ediff < -35)) { /* a = 0 or "small"? */ - *a = *b; /* rslt is b */ - a->sign = a->sign ^ sub; } /* or -b if sub */ -else if (((b->hi | b->lo) != 0) && (ediff <= 35)) { /* b!=0 && ~"small"? */ - if (ediff > 0) dp_dnrm_r (ir, b, ediff); /* |a| > |b|? dnorm b */ - else if (ediff < 0) { /* |a| < |b|? */ - a->exp = b->exp; /* b exp is rslt */ - dp_dnrm_r (ir, a, -ediff); } /* denorm A */ - if (a->sign ^ b->sign ^ sub) dp_sub (a, b); /* eff sub? */ - else { /* eff add */ - dp_add (a, b); /* add */ - if (a->hi & UFP_FH_CARRY) { /* carry out? */ - fguard = a->lo & 1; /* set guard */ - dp_rsh_1 (a, NULL); /* right shift */ - a->exp = a->exp + 1; /* incr exponent */ - if (!(ir & FI_NORND) && fguard) /* rounding? */ - dp_inc (a); - if (a->exp > 0377777) return FP_OVF; } } - } /* end if b != 0 */ -fp15_asign (ir, a); /* adjust A sign */ -return fp15_norm (ir, a, NULL, 0); /* norm, no round */ -} - -/* Floating multiply - overflow/underflow detected in normalize */ - -t_stat fp15_fmul (int32 ir, UFP *a, UFP *b) -{ -a->sign = a->sign ^ b->sign; /* sign of result */ -a->exp = a->exp + b->exp; /* exp of result */ -dp_mul (a, b); /* mul fractions */ -fp15_asign (ir, a); /* adjust A sign */ -return fp15_norm (ir, a, &fmq, 1); /* norm and round */ -} - -/* Floating divide - overflow/underflow detected in normalize */ - -t_stat fp15_fdiv (int32 ir, UFP *a, UFP *b) -{ -int32 i; - -a->sign = a->sign ^ b->sign; /* sign of result */ -a->exp = a->exp - b->exp; /* exp of result */ -fmq.hi = fmq.lo = 0; /* clear quotient */ -if (!(b->hi & UFP_FH_NORM)) return FP_DIV; /* divr not norm? */ -if (a->hi | a->lo) { /* divd non-zero? */ - fp15_norm (0, a, NULL, 0); /* normalize divd */ - for (i = 0; (fmq.hi & UFP_FH_NORM) == 0; i++) { /* until quo */ - dp_lsh_1 (&fmq, NULL); /* left shift quo */ - if (dp_cmp (a, b) >= 0) { /* sub work? */ - dp_sub (a, b); /* a -= b */ - if (i == 0) a->exp = a->exp + 1; - fmq.lo = fmq.lo | 1; } /* set quo bit */ - dp_lsh_1 (a, NULL); } /* left shift divd */ - dp_rsh_1 (a, NULL); /* shift back */ - dp_swap (a, &fmq); } /* swap a, FMQ */ -fp15_asign (ir, a); /* adjust A sign */ -return fp15_norm (ir, a, &fmq, 1); /* norm and round */ -} - -/* Floating to integer - overflow only if exponent out of range */ - -t_stat fp15_fix (int32 ir, UFP *a) -{ -int32 i; - -fmq.hi = fmq.lo = 0; /* clear FMQ */ -if (a->exp > 35) return FP_OVF; /* exp > 35? ovf */ -if (a->exp < 0) a->hi = a->lo = 0; /* exp <0 ? rslt 0 */ -else { for (i = a->exp; i < 35; i++) /* denorm frac */ - dp_rsh_1 (a, &fmq); - if (fmq.hi & UFP_FH_NORM) { /* last out = 1? */ - fguard = 1; /* set guard */ - if (!(ir & FI_NORND)) dp_inc (a); } } /* round */ -fp15_asign (ir, a); /* adjust A sign */ -return FP_OK; -} - -/* Double precision routines */ - -/* Double precision add - returns 72b result (including carry) */ - -void dp_add (UFP *a, UFP *b) -{ -a->lo = (a->lo + b->lo) & UFP_FL_MASK; /* add low */ -a->hi = a->hi + b->hi + (a->lo < b->lo); /* add hi + carry */ -return; -} - -/* Double precision increment - returns 72b result (including carry) */ - -void dp_inc (UFP *a) -{ -a->lo = (a->lo + 1) & UFP_FL_MASK; /* inc low */ -a->hi = a->hi + (a->lo == 0); /* propagate carry */ -return; -} - -/* Double precision subtract - result always fits in 71b */ - -void dp_sub (UFP *a, UFP *b) -{ -if (dp_cmp (a,b) >= 0) { /* |a| >= |b|? */ - a->hi = (a->hi - b->hi - (a->lo < b->lo)) & UFP_FH_MASK; - a->lo = (a->lo - b->lo) & UFP_FL_MASK; } /* a - b */ -else { a->hi = (b->hi - a->hi - (b->lo < a->lo)) & UFP_FH_MASK; - a->lo = (b->lo - a->lo) & UFP_FL_MASK; /* b - a */ - a->sign = a->sign ^ 1; } /* change a sign */ -return; -} - -/* Double precision compare - returns +1 (>), 0 (=), -1 (<) */ - -int32 dp_cmp (UFP *a, UFP *b) -{ -if (a->hi < b->hi) return -1; -if (a->hi > b->hi) return +1; -if (a->lo < b->lo) return -1; -if (a->lo > b->lo) return +1; -return 0; -} - -/* Double precision multiply - returns 70b result */ - -void dp_mul (UFP *a, UFP *b) -{ -int32 i; - -fmq.hi = a->hi; /* FMQ <- a */ -fmq.lo = a->lo; -a->hi = a->lo = 0; /* a <- 0 */ -if (((fmq.hi | fmq.lo) == 0) || ((b->hi | b->lo) == 0)) return; -for (i = 0; i < 35; i++) { /* 35 iterations */ - if (fmq.lo & 1) dp_add (a, b); /* FMQ<35>? a += b */ - dp_rsh_1 (a, &fmq); } /* rsh a'FMQ */ -return; -} - -/* Double (quad) precision left shift - returns 72b (143b) result */ - -void dp_lsh_1 (UFP *a, UFP *b) -{ -int32 t = b? b->lo: 0; - -a->hi = (a->hi << 1) | (a->lo >> 17); -a->lo = ((a->lo << 1) | (t >> 16)) & UFP_FL_MASK; -if (b) { - b->hi = ((b->hi << 1) | (b->lo >> 17)) & UFP_FH_MASK; - b->lo = (b->lo << 1) & UFP_FL_MASK; } -return; -} - -/* Double (quad) precision right shift - returns 71b (142b) result */ - -void dp_rsh_1 (UFP *a, UFP *b) -{ -if (b) { - b->lo = (b->lo >> 1) | ((b->hi & 1) << 17); - b->hi = (b->hi >> 1) | ((a->lo & 1) << 16); } -a->lo = (a->lo >> 1) | ((a->hi & 1) << 17); -a->hi = a->hi >> 1; -return; -} - -/* Double precision denormalize and round - returns 71b result */ - -void dp_dnrm_r (int32 ir, UFP *a, int32 sc) -{ -int32 i; - -if (sc <= 0) return; /* legit? */ -for (i = 0; i < sc; i++) dp_rsh_1 (a, &fmq); /* dnorm to fmq */ -if (!(ir & FI_NORND) && (fmq.hi & UFP_FH_NORM)) /* round & fmq<1>? */ - dp_inc (a); /* incr a */ -return; -} - -/* Double precision swap */ - -void dp_swap (UFP *a, UFP *b) -{ -int32 t; - -t = a->hi; /* swap fractions */ -a->hi = b->hi; -b->hi = t; -t = a->lo; -a->lo = b->lo; -b->lo = t; -return; -} - -/* Support routines */ - -void fp15_asign (int32 fir, UFP *a) -{ -int32 sgnop = FI_GETSGNOP (fir); - -switch (sgnop) { /* modify FMA sign */ -case 1: - a->sign = 0; - break; -case 2: - a->sign = 1; - break; -case 3: - a->sign = a->sign ^ 1; - break; -default: - break; } -return; -} - -/* FP15 normalization and rounding - - - Do normalization if enabled (NOR phase, part 1) - Normalization also does zero detect - - Do rounding if enabled (NOR phase, part 2) */ - -t_stat fp15_norm (int32 ir, UFP *a, UFP *b, t_bool rnd) -{ -if (!(ir & FI_NONORM)) { /* norm enabled? */ - if ((a->hi | a->lo) || (b && (b->hi | b->lo))) { /* frac != 0? */ - while ((a->hi & UFP_FH_NORM) == 0) { /* until norm */ - dp_lsh_1 (a, b); /* lsh a'b, no cry */ - a->exp = a->exp - 1; } } /* decr exp */ - else a->sign = a->exp = 0; } /* true zero */ -if (rnd && b && (b->hi & UFP_FH_NORM)) { /* rounding? */ - fguard = 1; /* set guard */ - if (!(ir & FI_NORND)) { /* round enabled? */ - dp_inc (a); /* add 1 */ - if (a->hi & UFP_FH_CARRY) { /* carry out? */ - a->hi = UFP_FH_NORM; /* set hi bit */ - a->exp = a->exp + 1; } } } /* incr exp */ -if (a->exp > 0377777) return FP_OVF; /* overflow? */ -if (a->exp < -0400000) return FP_UNF; /* underflow? */ -return FP_OK; -} - -/* Exception */ - -t_stat fp15_exc (t_stat sta) -{ -int32 ma, mb; - -if (sta == FP_MM) trap_pending = 0; /* if mm, kill trap */ -ma = (jea & JEA_EAMASK) + sta - 1; /* JEA address */ -PCQ_ENTRY; /* record branch */ -PC = Incr_addr (PC); /* PC+1 for "JMS" */ -mb = Jms_word (usmd); /* form JMS word */ -if (Write (ma, mb, WR)) return SCPE_OK; /* store */ -PC = (jea + 1) & IAMASK; /* new PC */ -return SCPE_OK; -} - -/* Reset routine */ - -t_stat fp15_reset (DEVICE *dptr) -{ -jea = 0; -fir = 0; -fguard = 0; -fma.exp = fma.hi = fma.lo = fma.sign = 0; -fmb.exp = fmb.hi = fmb.lo = fmb.sign = 0; -fmq.exp = fmq.hi = fmq.lo = fmq.sign = 0; -return SCPE_OK; -} diff --git a/PDP18B/pdp18b_lp.c b/PDP18B/pdp18b_lp.c deleted file mode 100644 index 3ef218a6..00000000 --- a/PDP18B/pdp18b_lp.c +++ /dev/null @@ -1,783 +0,0 @@ -/* pdp18b_lp.c: 18b PDP's line printer simulator - - 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. - - lp62 (PDP-4) Type 62 line printer - lp647 (PDP-7,9) Type 647 line printer - lp09 (PDP-9,15) LP09 line printer - lp15 (PDP-15) LP15 line printer - - 23-Jul-03 RMS Fixed overprint bug in Type 62 - 25-Apr-03 RMS Revised for extended file support - 05-Feb-03 RMS Added LP09, fixed conditionalization - 05-Oct-02 RMS Added DIB, device number support - 30-May-02 RMS Widened POS to 32b - 03-Feb-02 RMS Fixed typo (found by Robert Alan Byer) - 25-Nov-01 RMS Revised interrupt structure - 19-Sep-01 RMS Fixed bug in 647 - 13-Feb-01 RMS Revised for register arrays - 15-Feb-01 RMS Fixed 3 cycle data break sequence - 30-Oct-00 RMS Standardized register naming - 20-Aug-98 RMS Fixed compilation problem in BeOS - 03-Jan-97 RMS Fixed bug in Type 62 state handling -*/ - -#include "pdp18b_defs.h" -extern int32 int_hwre[API_HLVL+1]; - -#if defined (TYPE62) - -/* Type 62 line printer */ - -#define LP62_BSIZE 120 /* line size */ -#define BPTR_MAX 40 /* pointer max */ -#define BPTR_MASK 077 /* buf ptr max */ - -int32 lp62_spc = 0; /* print vs spc */ -int32 lp62_ovrpr = 0; /* overprint */ -int32 lp62_stopioe = 0; -int32 lp62_bp = 0; /* buffer ptr */ -char lp62_buf[LP62_BSIZE + 1] = { 0 }; -static const char lp62_trans[64] = { - ' ','1','2','3','4','5','6','7','8','9','\'','~','#','V','^','<', - '0','/','S','T','U','V','W','X','Y','Z','"',',','>','^','-','?', - 'o','J','K','L','M','N','O','P','Q','R','$','=','-',')','-','(', - '_','A','B','C','D','E','F','G','H','I','*','.','+',']','|','[' }; -static const char *lp62_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" }; - -DEVICE lp62_dev; -int32 lp62_65 (int32 pulse, int32 dat); -int32 lp62_66 (int32 pulse, int32 dat); -int32 lp62_iors (void); -t_stat lp62_svc (UNIT *uptr); -t_stat lp62_reset (DEVICE *dptr); - -/* Type 62 LPT data structures - - lp62_dev LPT device descriptor - lp62_unit LPT unit - lp62_reg LPT register list -*/ - -DIB lp62_dib = { DEV_LPT, 2, &lp62_iors, { &lp62_65, &lp62_66 } }; - -UNIT lp62_unit = { - UDATA (&lp62_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT }; - -REG lp62_reg[] = { - { ORDATA (BUF, lp62_unit.buf, 8) }, - { FLDATA (INT, int_hwre[API_LPT], INT_V_LPT) }, - { FLDATA (DONE, int_hwre[API_LPT], INT_V_LPT) }, - { FLDATA (SPC, int_hwre[API_LPTSPC], INT_V_LPTSPC) }, - { DRDATA (BPTR, lp62_bp, 6) }, - { ORDATA (STATE, lp62_spc, 6), REG_HRO }, - { FLDATA (OVRPR, lp62_ovrpr, 0), REG_HRO }, - { DRDATA (POS, lp62_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, lp62_unit.wait, 24), PV_LEFT }, - { FLDATA (STOP_IOE, lp62_stopioe, 0) }, - { BRDATA (LBUF, lp62_buf, 8, 8, LP62_BSIZE) }, - { ORDATA (DEVNO, lp62_dib.dev, 6), REG_HRO }, - { NULL } }; - -MTAB lp62_mod[] = { - { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", &set_devno, &show_devno }, - { 0 } }; - -DEVICE lp62_dev = { - "LPT", &lp62_unit, lp62_reg, lp62_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &lp62_reset, - NULL, NULL, NULL, - &lp62_dib, DEV_DISABLE }; - -/* IOT routines */ - -int32 lp62_65 (int32 pulse, int32 dat) -{ -int32 i; - -if ((pulse & 01) && TST_INT (LPT)) dat = IOT_SKP | dat; /* LPSF */ -if (pulse & 02) { - int32 sb = pulse & 060; /* subopcode */ - if (sb == 000) CLR_INT (LPT); /* LPCF */ - if ((sb == 040) && (lp62_bp < BPTR_MAX)) { /* LPLD */ - i = lp62_bp * 3; /* cvt to chr ptr */ - lp62_buf[i] = lp62_trans[(dat >> 12) & 077]; - lp62_buf[i + 1] = lp62_trans[(dat >> 6) & 077]; - lp62_buf[i + 2] = lp62_trans[dat & 077]; - lp62_bp = (lp62_bp + 1) & BPTR_MASK; } - } -if (pulse & 04) { /* LPSE */ - lp62_spc = 0; /* print */ - sim_activate (&lp62_unit, lp62_unit.wait); } /* activate */ -return dat; -} - -int32 lp62_66 (int32 pulse, int32 dat) -{ -if ((pulse & 01) && TST_INT (LPTSPC)) /* LSSF */ - dat = IOT_SKP | dat; -if (pulse & 02) CLR_INT (LPTSPC); /* LSCF */ -if (pulse & 04) { /* LSPR */ - lp62_spc = 020 | (dat & 07); /* space */ - sim_activate (&lp62_unit, lp62_unit.wait); } /* activate */ -return dat; -} - -/* Unit service, action based on lp62_spc - - lp62_spc = 0 write buffer to file, set overprint - lp62_spc = 2x space command x, clear overprint -*/ - -t_stat lp62_svc (UNIT *uptr) -{ -int32 i; - -if (lp62_spc) { /* space? */ - SET_INT (LPTSPC); /* set flag */ - if ((uptr->flags & UNIT_ATT) == 0) /* attached? */ - return IORETURN (lp62_stopioe, SCPE_UNATT); - fputs (lp62_cc[lp62_spc & 07], uptr->fileref); /* print cctl */ - if (ferror (uptr->fileref)) { /* error? */ - perror ("LPT I/O error"); - clearerr (uptr->fileref); - return SCPE_IOERR; } - lp62_ovrpr = 0; } /* clear overprint */ -else { SET_INT (LPT); /* print */ - if ((uptr->flags & UNIT_ATT) == 0) /* attached? */ - return IORETURN (lp62_stopioe, SCPE_UNATT); - if (lp62_ovrpr) fputc ('\r', uptr->fileref); /* overprint? */ - fputs (lp62_buf, uptr->fileref); /* print buffer */ - if (ferror (uptr->fileref)) { /* test error */ - perror ("LPT I/O error"); - clearerr (uptr->fileref); - return SCPE_IOERR; } - lp62_bp = 0; - for (i = 0; i <= LP62_BSIZE; i++) lp62_buf[i] = 0; /* clear buffer */ - lp62_ovrpr = 1; } /* set overprint */ -uptr->pos = ftell (uptr->fileref); /* update position */ -return SCPE_OK; -} - -/* Reset routine */ - -t_stat lp62_reset (DEVICE *dptr) -{ -int32 i; - -CLR_INT (LPT); /* clear intrs */ -CLR_INT (LPTSPC); -sim_cancel (&lp62_unit); /* deactivate unit */ -lp62_bp = 0; /* clear buffer ptr */ -for (i = 0; i <= LP62_BSIZE; i++) lp62_buf[i] = 0; /* clear buffer */ -lp62_spc = 0; /* clear state */ -lp62_ovrpr = 0; /* clear overprint */ -return SCPE_OK; -} - -/* IORS routine */ - -int32 lp62_iors (void) -{ -return (TST_INT (LPT)? IOS_LPT: 0) | - (TST_INT (LPTSPC)? IOS_LPT1: 0); -} - -#endif - -#if defined (TYPE647) - -/* Type 647 line printer */ - -#define LP647_BSIZE 120 /* line size */ - -int32 lp647_don = 0; /* ready */ -int32 lp647_ie = 1; /* int enable */ -int32 lp647_err = 0; /* error */ -int32 lp647_iot = 0; /* saved state */ -int32 lp647_stopioe = 0; -int32 lp647_bp = 0; /* buffer ptr */ -char lp647_buf[LP647_BSIZE] = { 0 }; -static const char *lp647_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" }; - -DEVICE lp647_dev; -int32 lp647_65 (int32 pulse, int32 dat); -int32 lp647_66 (int32 pulse, int32 dat); -int32 lp647_iors (void); -t_stat lp647_svc (UNIT *uptr); -t_stat lp647_reset (DEVICE *dptr); -t_stat lp647_attach (UNIT *uptr, char *cptr); -t_stat lp647_detach (UNIT *uptr); - -/* Type 647 LPT data structures - - lp647_dev LPT device descriptor - lp647_unit LPT unit - lp647_reg LPT register list -*/ - -DIB lp647_dib = { DEV_LPT, 2, &lp647_iors, { &lp647_65, &lp647_66 } }; - -UNIT lp647_unit = { - UDATA (&lp647_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT }; - -REG lp647_reg[] = { - { ORDATA (BUF, lp647_unit.buf, 8) }, - { FLDATA (INT, int_hwre[API_LPT], INT_V_LPT) }, - { FLDATA (DONE, lp647_don, 0) }, -#if defined (PDP9) - { FLDATA (ENABLE, lp647_ie, 0) }, -#endif - { FLDATA (ERR, lp647_err, 0) }, - { DRDATA (BPTR, lp647_bp, 7) }, - { ORDATA (SCMD, lp647_iot, 6), REG_HRO }, - { DRDATA (POS, lp647_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, lp647_unit.wait, 24), PV_LEFT }, - { FLDATA (STOP_IOE, lp647_stopioe, 0) }, - { BRDATA (LBUF, lp647_buf, 8, 8, LP647_BSIZE) }, - { ORDATA (DEVNO, lp647_dib.dev, 6), REG_HRO }, - { NULL } }; - -MTAB lp647_mod[] = { - { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", &set_devno, &show_devno }, - { 0 } }; - -DEVICE lp647_dev = { - "LPT", &lp647_unit, lp647_reg, lp647_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &lp647_reset, - NULL, &lp647_attach, &lp647_detach, - &lp647_dib, DEV_DISABLE }; - -/* IOT routines */ - -int32 lp647_65 (int32 pulse, int32 dat) -{ -int32 i, sb; - -sb = pulse & 060; /* subcode */ -if ((pulse & 01) && lp647_don) dat = IOT_SKP | dat; /* LPSF */ -if (pulse & 02) { /* pulse 02 */ - lp647_don = 0; /* clear done */ - CLR_INT (LPT); /* clear int req */ - if (sb == 000) { /* LPCB */ - for (i = 0; i < LP647_BSIZE; i++) lp647_buf[i] = 0; - lp647_bp = 0; /* reset buf ptr */ - lp647_don = 1; /* set done */ - if (lp647_ie) SET_INT (LPT); } /* set int */ - } -if (pulse & 004) { /* LPDI */ - switch (sb) { /* case on subcode */ - case 000: /* LPDI */ -#if defined (PDP9) - lp647_ie = 0; /* clear int enable */ - CLR_INT (LPT); /* clear int req */ -#endif - break; - case 040: /* LPB3 */ - if (lp647_bp < LP647_BSIZE) { - lp647_buf[lp647_bp] = lp647_buf[lp647_bp] | ((dat >> 12) & 077); - lp647_bp = lp647_bp + 1; } - case 020: /* LPB2 */ - if (lp647_bp < LP647_BSIZE) { - lp647_buf[lp647_bp] = lp647_buf[lp647_bp] | ((dat >> 6) & 077); - lp647_bp = lp647_bp + 1; } - case 060: /* LPB1 */ - if (lp647_bp < LP647_BSIZE) { - lp647_buf[lp647_bp] = lp647_buf[lp647_bp] | (dat & 077); - lp647_bp = lp647_bp + 1; } - lp647_don = 1; /* set done */ - if (lp647_ie) SET_INT (LPT); /* set int */ - break; } /* end case */ - } -return dat; -} - -int32 lp647_66 (int32 pulse, int32 dat) -{ -if ((pulse & 01) && lp647_err) dat = IOT_SKP | dat; /* LPSE */ -if (pulse & 02) { /* LPCF */ - lp647_don = 0; /* clear done, int */ - CLR_INT (LPT); } -if (pulse & 04) { - if ((pulse & 060) < 060) { /* LPLS, LPPB, LPPS */ - lp647_iot = (pulse & 060) | (dat & 07); /* save parameters */ - sim_activate (&lp647_unit, lp647_unit.wait); } /* activate */ -#if defined (PDP9) - else { /* LPEI */ - lp647_ie = 1; /* set int enable */ - if (lp647_don) SET_INT (LPT); } -#endif - } -return dat; -} - -/* Unit service. lp647_iot specifies the action to be taken - - lp647_iot = 0x print only - lp647_iot = 2x space only, x is spacing command - lp647_iot = 4x print then space, x is spacing command -*/ - -t_stat lp647_svc (UNIT *uptr) -{ -int32 i; -char pbuf[LP647_BSIZE + 1]; - -lp647_don = 1; -if (lp647_ie) SET_INT (LPT); /* set flag */ -if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */ - lp647_err = 1; /* set error */ - return IORETURN (lp647_stopioe, SCPE_UNATT); } -if ((lp647_iot & 020) == 0) { /* print? */ - for (i = 0; i < lp647_bp; i++) /* translate buffer */ - pbuf[i] = lp647_buf[i] | ((lp647_buf[i] >= 040)? 0: 0100); - if ((lp647_iot & 060) == 0) pbuf[lp647_bp++] = '\r'; - for (i = 0; i < LP647_BSIZE; i++) lp647_buf[i] = 0; /* clear buffer */ - fwrite (pbuf, 1, lp647_bp, uptr->fileref); /* print buffer */ - if (ferror (uptr->fileref)) { /* error? */ - perror ("LPT I/O error"); - clearerr (uptr->fileref); - lp647_bp = 0; - return SCPE_IOERR; } - lp647_bp = 0; } /* clear buffer ptr */ -if (lp647_iot & 060) { /* space? */ - fputs (lp647_cc[lp647_iot & 07], uptr->fileref); /* write cctl */ - if (ferror (uptr->fileref)) { /* error? */ - perror ("LPT I/O error"); - clearerr (uptr->fileref); - return SCPE_IOERR; } } -uptr->pos = ftell (uptr->fileref); /* update position */ -return SCPE_OK; -} - -/* Reset routine */ - -t_stat lp647_reset (DEVICE *dptr) -{ -int32 i; - -lp647_don = 0; /* clear done */ -lp647_err = (lp647_unit.flags & UNIT_ATT)? 0: 1; /* clr/set error */ -lp647_ie = 1; /* set enable */ -CLR_INT (LPT); /* clear int */ -sim_cancel (&lp647_unit); /* deactivate unit */ -lp647_bp = 0; /* clear buffer ptr */ -lp647_iot = 0; /* clear state */ -for (i = 0; i < LP647_BSIZE; i++) lp647_buf[i] = 0; /* clear buffer */ -return SCPE_OK; -} - -/* IORS routine */ - -int32 lp647_iors (void) -{ -return (lp647_don? IOS_LPT: 0) | (lp647_err? IOS_LPT1: 0); -} - -/* Attach routine */ - -t_stat lp647_attach (UNIT *uptr, char *cptr) -{ -t_stat reason; - -reason = attach_unit (uptr, cptr); -lp647_err = (lp647_unit.flags & UNIT_ATT)? 0: 1; /* clr/set error */ -return reason; -} - -/* Detach routine */ - -t_stat lp647_detach (UNIT *uptr) -{ -lp647_err = 1; -return detach_unit (uptr); -} - -#endif - -#if defined (LP09) - -/* LP09 line printer */ - -#define LP09_BSIZE 132 /* line size */ - -int32 lp09_don = 0; /* ready */ -int32 lp09_err = 0; /* error */ -int32 lp09_ie = 1; /* int enable */ -int32 lp09_stopioe = 0; -DEVICE lp09_dev; - -int32 lp09_66 (int32 pulse, int32 dat); -int32 lp09_iors (void); -t_stat lp09_svc (UNIT *uptr); -t_stat lp09_reset (DEVICE *dptr); -t_stat lp09_attach (UNIT *uptr, char *cptr); -t_stat lp09_detach (UNIT *uptr); - -/* LP09 LPT data structures - - lp09_dev LPT device descriptor - lp09_unit LPT unit - lp09_reg LPT register list -*/ - -DIB lp09_dib = { DEV_LPT, 2, &lp09_iors, { NULL, &lp09_66 } }; - -UNIT lp09_unit = { - UDATA (&lp09_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT }; - -REG lp09_reg[] = { - { ORDATA (BUF, lp09_unit.buf, 7) }, - { FLDATA (INT, int_hwre[API_LPT], INT_V_LPT) }, - { FLDATA (DONE, lp09_don, 0) }, - { FLDATA (ENABLE, lp09_ie, 0) }, - { FLDATA (ERR, lp09_err, 0) }, - { DRDATA (POS, lp09_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, lp09_unit.wait, 24), PV_LEFT }, - { FLDATA (STOP_IOE, lp09_stopioe, 0) }, - { ORDATA (DEVNO, lp09_dib.dev, 6), REG_HRO }, - { NULL } }; - -MTAB lp09_mod[] = { - { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", &set_devno, &show_devno }, - { 0 } }; - -DEVICE lp09_dev = { - "LP9", &lp09_unit, lp09_reg, lp09_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &lp09_reset, - NULL, &lp09_attach, &lp09_detach, - &lp09_dib, DEV_DISABLE | DEV_DIS }; - -/* IOT routines */ - -int32 lp09_66 (int32 pulse, int32 dat) -{ -int32 sb = pulse & 060; /* subopcode */ - -if (pulse & 001) { - if ((sb == 000) && lp09_don) dat = IOT_SKP | dat; /* LSDF */ - if ((sb == 020) && lp09_err) dat = IOT_SKP | dat; /* LSEF */ - } -if (pulse & 002) { - if (sb == 000) { /* LSCF */ - lp09_don = 0; /* clear done, int */ - CLR_INT (LPT); } - else if (sb == 020) { /* LPLD */ - lp09_don = 0; /* clear done, int */ - CLR_INT (LPT); - lp09_unit.buf = dat & 0177; /* load char */ - if ((lp09_unit.buf == 015) || (lp09_unit.buf == 014) || - (lp09_unit.buf == 012)) - sim_activate (&lp09_unit, lp09_unit.wait); - else dat = dat | (lp09_svc (&lp09_unit) << IOT_V_REASON); } - } -if (pulse & 004) { - if (sb == 000) { /* LIOF */ - lp09_ie = 0; /* clear int enab */ - CLR_INT (LPT); } /* clear int */ - else if (sb == 040) { /* LION */ - lp09_ie = 1; /* set int enab */ - if (lp09_don) SET_INT (LPT); } /* if done, set int */ - } -return dat; -} - -/* Unit service */ - -t_stat lp09_svc (UNIT *uptr) -{ -int32 c; - -lp09_don = 1; /* set done */ -if (lp09_ie) SET_INT (LPT); /* int enb? req int */ -if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */ - lp09_err = 1; /* set error */ - return IORETURN (lp09_stopioe, SCPE_UNATT); } -c = uptr->buf & 0177; /* get char */ -if ((c == 0) || (c == 0177)) return SCPE_OK; /* skip NULL, DEL */ -if (fputc (c, uptr->fileref) == EOF) { /* print char */ - perror ("LPT I/O error"); - clearerr (uptr->fileref); - return SCPE_IOERR; } -uptr->pos = uptr->pos + 1; /* update position */ -return SCPE_OK; -} - -/* Reset routine */ - -t_stat lp09_reset (DEVICE *dptr) -{ -lp09_don = 0; /* clear done */ -lp09_err = (lp09_unit.flags & UNIT_ATT)? 0: 1; /* compute error */ -lp09_ie = 1; /* set enable */ -CLR_INT (LPT); /* clear int */ -return SCPE_OK; -} - -/* IORS routine */ - -int32 lp09_iors (void) -{ -return (lp09_don? IOS_LPT: 0); -} - -/* Attach routine */ - -t_stat lp09_attach (UNIT *uptr, char *cptr) -{ -t_stat reason; - -reason = attach_unit (uptr, cptr); -lp09_err = (lp09_unit.flags & UNIT_ATT)? 0: 1; /* clr/set error */ -return reason; -} - -/* Detach routine */ - -t_stat lp09_detach (UNIT *uptr) -{ -lp09_err = 1; -return detach_unit (uptr); -} - -#endif - -#if defined (LP15) - -/* LP15 line printer */ - -#define LP15_BSIZE 132 /* line size */ -#define LPT_WC 034 /* word count */ -#define LPT_CA 035 /* current addr */ - -/* Status register */ - -#define STA_ERR 0400000 /* error */ -#define STA_ALM 0200000 /* alarm */ -#define STA_OVF 0100000 /* line overflow */ -#define STA_IHT 0040000 /* illegal HT */ -#define STA_BUSY 0020000 /* busy */ -#define STA_DON 0010000 /* done */ -#define STA_ILK 0004000 /* interlock */ -#define STA_EFLGS (STA_ALM | STA_OVF | STA_IHT | STA_ILK) -#define STA_CLR 0003777 /* always clear */ - -extern int32 M[]; -int32 lp15_sta = 0; -int32 lp15_ie = 1; -int32 lp15_stopioe = 0; -int32 lp15_mode = 0; -int32 lp15_lc = 0; -int32 lp15_bp = 0; -char lp15_buf[LP15_BSIZE] = { 0 }; - -DEVICE lp15_dev; -int32 lp15_65 (int32 pulse, int32 dat); -int32 lp15_66 (int32 pulse, int32 dat); -int32 lp15_iors (void); -t_stat lp15_svc (UNIT *uptr); -t_stat lp15_reset (DEVICE *dptr); - -int32 lp15_updsta (int32 new); - -/* LP15 LPT data structures - - lp15_dev LPT device descriptor - lp15_unit LPT unit - lp15_reg LPT register list -*/ - -DIB lp15_dib = { DEV_LPT, 2, &lp15_iors, { &lp15_65, &lp15_66 } }; - -UNIT lp15_unit = { - UDATA (&lp15_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT }; - -REG lp15_reg[] = { - { ORDATA (STA, lp15_sta, 18) }, - { ORDATA (CA, M[LPT_CA], 18) }, - { FLDATA (INT, int_hwre[API_LPT], INT_V_LPT) }, - { FLDATA (ENABLE, lp15_ie, 0) }, - { DRDATA (LCNT, lp15_lc, 9) }, - { DRDATA (BPTR, lp15_bp, 8) }, - { FLDATA (MODE, lp15_mode, 0) }, - { DRDATA (POS, lp15_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, lp15_unit.wait, 24), PV_LEFT }, - { FLDATA (STOP_IOE, lp15_stopioe, 0) }, - { BRDATA (LBUF, lp15_buf, 8, 8, LP15_BSIZE) }, - { ORDATA (DEVNO, lp15_dib.dev, 6), REG_HRO }, - { NULL } }; - -MTAB lp15_mod[] = { - { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", &set_devno, &show_devno }, - { 0 } }; - -DEVICE lp15_dev = { - "LPT", &lp15_unit, lp15_reg, lp15_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &lp15_reset, - NULL, NULL, NULL, - &lp15_dib, DEV_DISABLE }; - -/* IOT routines */ - -int32 lp15_65 (int32 pulse, int32 dat) -{ -int32 header, sb; - -sb = pulse & 060; /* subopcode */ -if (pulse & 01) { - if ((sb == 000) && (lp15_sta & (STA_ERR | STA_DON))) /* LPSF */ - dat = IOT_SKP | dat; - else if ((sb == 020) || (sb == 040)) { /* LPP1, LPPM */ - sim_activate (&lp15_unit, lp15_unit.wait); /* activate */ - header = M[(M[LPT_CA] + 1) & AMASK]; /* get first word */ - M[LPT_CA] = (M[LPT_CA] + 2) & DMASK; - lp15_mode = header & 1; /* mode */ - if (sb == 040) lp15_lc = 1; /* line count */ - else lp15_lc = (header >> 9) & 0377; - if (lp15_lc == 0) lp15_lc = 256; - lp15_bp = 0; } /* reset buf ptr */ - else if (sb == 060) lp15_ie = 0; /* LPDI */ - } -if ((pulse & 02) && (sb == 040)) dat = dat | lp15_updsta (0); /* LPOS, LPRS */ -if ((pulse & 04) && (sb == 040)) lp15_ie = 1; /* LPEI */ -lp15_updsta (0); /* update status */ -return dat; -} - -int32 lp15_66 (int32 pulse, int32 dat) -{ -if (pulse == 021) lp15_sta = lp15_sta & ~STA_DON; /* LPCD */ -if (pulse == 041) lp15_sta = 0; /* LPCF */ -lp15_updsta (0); /* update status */ -return dat; -} - -/* Unit service */ - -t_stat lp15_svc (UNIT *uptr) -{ -int32 i, ccnt, more, w0, w1; -char c[5]; -static const char *ctrl[040] = { - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, "\n", "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n", - "\f", "\r", NULL, NULL, - "\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", NULL, NULL, NULL, - NULL, NULL, NULL, "\r", NULL, NULL, NULL, NULL }; - -if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */ - lp15_updsta (STA_DON | STA_ALM); /* set done, err */ - return IORETURN (lp15_stopioe, SCPE_UNATT); } - -for (more = 1; more != 0; ) { /* loop until ctrl */ - w0 = M[(M[LPT_CA] + 1) & AMASK]; /* get first word */ - w1 = M[(M[LPT_CA] + 2) & AMASK]; /* get second word */ - M[LPT_CA] = (M[LPT_CA] + 2) & DMASK; /* advance mem addr */ - if (lp15_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; } - for (i = 0; i < ccnt; i++) { /* loop through */ - if ((c[i] <= 037) && ctrl[c[i]]) { /* control char? */ - fwrite (lp15_buf, 1, lp15_bp, uptr->fileref); - fputs (ctrl[c[i]], uptr->fileref); - if (ferror (uptr->fileref)) { /* error? */ - perror ("LPT I/O error"); - clearerr (uptr->fileref); - lp15_bp = 0; - lp15_updsta (STA_DON | STA_ALM); - return SCPE_IOERR; } - uptr->pos = ftell (uptr->fileref); - lp15_bp = more = 0; } - else { - if (lp15_bp < LP15_BSIZE) lp15_buf[lp15_bp++] = c[i]; - else lp15_sta = lp15_sta | STA_OVF; } } } - -lp15_lc = lp15_lc - 1; /* decr line count */ -if (lp15_lc) sim_activate (&lp15_unit, uptr->wait); /* more to do? */ -else lp15_updsta (STA_DON); /* no, set done */ -return SCPE_OK; -} - -/* Update status */ - -int32 lp15_updsta (int32 new) -{ -lp15_sta = (lp15_sta | new) & ~(STA_CLR | STA_ERR | STA_BUSY); -if (lp15_sta & STA_EFLGS) lp15_sta = lp15_sta | STA_ERR; /* update errors */ -if (sim_is_active (&lp15_unit)) lp15_sta = lp15_sta | STA_BUSY; -if (lp15_ie && (lp15_sta & STA_DON)) SET_INT (LPT); -else CLR_INT (LPT); /* update int */ -return lp15_sta; -} - -/* Reset routine */ - -t_stat lp15_reset (DEVICE *dptr) -{ -lp15_mode = lp15_lc = lp15_bp = 0; /* clear controls */ -sim_cancel (&lp15_unit); /* deactivate unit */ -lp15_sta = 0; /* clear status */ -lp15_ie = 1; /* enable interrupts */ -lp15_updsta (0); /* update status */ -return SCPE_OK; -} - -/* IORS routine */ - -int32 lp15_iors (void) -{ -return ((lp15_sta & STA_DON)? IOS_LPT: 0); -} - -#endif diff --git a/PDP18B/pdp18b_mt.c b/PDP18B/pdp18b_mt.c deleted file mode 100644 index 0796035d..00000000 --- a/PDP18B/pdp18b_mt.c +++ /dev/null @@ -1,476 +0,0 @@ -/* pdp18b_mt.c: 18b PDP magnetic tape simulator - - 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. - - mt (PDP-9) TC59 magtape - (PDP-15) TC59D magtape - - 25-Apr-03 RMS Revised for extended file support - 28-Mar-03 RMS Added multiformat support - 04-Mar-03 RMS Fixed bug in MTTR - 01-Mar-03 RMS Fixed bug in interrupt handling - Revised for magtape library - 02-Feb-03 RMS Revised IOT decoding - 30-Oct-02 RMS Revised BOT handling, added error record handling - 05-Oct-02 RMS Added DIB, device number support - Revamped error recovery - 28-Aug-02 RMS Added end of medium support - 30-May-02 RMS Widened POS to 32b - 22-Apr-02 RMS Added maximum record length test - 06-Jan-02 RMS Revised enabled/disable support - 29-Nov-01 RMS Added read only unit support - 25-Nov-01 RMS Revised interrupt structure - Changed UST, POS, FLG to arrays - 26-Apr-01 RMS Added device enable/disable support - 15-Feb-01 RMS Fixed 3-cycle data break sequence - 04-Oct-98 RMS V2.4 magtape format - 22-Jan-97 RMS V2.3 magtape format - 29-Jun-96 RMS Added unit enable/disable support - - Magnetic tapes are represented as a series of variable records - of the form: - - 32b byte count - byte 0 - byte 1 - : - byte n-2 - byte n-1 - 32 byte count - - If the byte count is odd, the record is padded with an extra byte - of junk. File marks are represented by a byte count of 0. -*/ - -#include "pdp18b_defs.h" -#include "sim_tape.h" - -#define MT_NUMDR 8 /* #drives */ -#define USTAT u3 /* unit status */ -#define MT_MAXFR (1 << 16) /* max record length */ -#define MT_WC 032 /* word count */ -#define MT_CA 033 /* current addr */ -#define WC_SIZE (1 << 12) /* max word count */ -#define WC_MASK (WC_SIZE - 1) - -/* Command/unit - mt_cu */ - -#define CU_V_UNIT 15 /* unit */ -#define CU_M_UNIT 07 -#define CU_PARITY 0040000 /* parity select */ -#define CU_DUMP 0020000 /* dump mode */ -#define CU_ERASE 0010000 /* ext rec gap */ -#define CU_V_CMD 9 /* command */ -#define CU_M_CMD 07 -#define FN_NOP 00 -#define FN_REWIND 01 -#define FN_READ 02 -#define FN_CMPARE 03 -#define FN_WRITE 04 -#define FN_WREOF 05 -#define FN_SPACEF 06 -#define FN_SPACER 07 -#define CU_IE 0000400 /* interrupt enable */ -#define CU_V_TYPE 6 /* drive type */ -#define CU_M_TYPE 03 -#define TY_9TK 3 -#define GET_UNIT(x) (((x) >> CU_V_UNIT) & CU_M_UNIT) -#define GET_CMD(x) (((x) >> CU_V_CMD) & CU_M_CMD) -#define GET_TYPE(x) (((x) >> CU_V_TYPE) & CU_M_TYPE) -#define PACKED(x) (((x) & CU_DUMP) || (GET_TYPE (x) != TY_9TK)) - -/* Status - stored in mt_sta or (*) uptr->USTAT */ - -#define STA_ERR 0400000 /* error */ -#define STA_REW 0200000 /* *rewinding */ -#define STA_BOT 0100000 /* *start of tape */ -#define STA_ILL 0040000 /* illegal cmd */ -#define STA_PAR 0020000 /* parity error */ -#define STA_EOF 0010000 /* *end of file */ -#define STA_EOT 0004000 /* *end of tape */ -#define STA_CPE 0002000 /* compare error */ -#define STA_RLE 0001000 /* rec lnt error */ -#define STA_DLT 0000400 /* data late */ -#define STA_BAD 0000200 /* bad tape */ -#define STA_DON 0000100 /* done */ - -#define STA_CLR 0000077 /* always clear */ -#define STA_DYN (STA_REW | STA_BOT | STA_EOF | STA_EOT) - /* kept in USTAT */ - -extern int32 M[]; -extern int32 int_hwre[API_HLVL+1]; -extern UNIT cpu_unit; - -int32 mt_cu = 0; /* command/unit */ -int32 mt_sta = 0; /* status register */ -int32 mt_time = 10; /* record latency */ -int32 mt_stopioe = 1; /* stop on error */ -int32 mt_log = 0; -uint8 *mtxb = NULL; /* transfer buffer */ - -DEVICE mt_dev; -int32 mt (int32 pulse, int32 dat); -int32 mt_iors (void); -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); -int32 mt_updcsta (UNIT *uptr, int32 val); -t_stat mt_map_err (UNIT *uptr, t_stat st); -UNIT *mt_busy (void); - -/* 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 = { DEV_MT, 1, &mt_iors, { &mt } }; - -UNIT mt_unit[] = { - { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) }, - { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) }, - { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) }, - { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) }, - { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) }, - { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) }, - { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) }, - { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) } }; - -REG mt_reg[] = { - { ORDATA (STA, mt_sta, 18) }, - { ORDATA (CMD, mt_cu, 18) }, - { ORDATA (WC, M[MT_WC], 18) }, - { ORDATA (CA, M[MT_CA], 18) }, - { FLDATA (INT, int_hwre[API_MTA], INT_V_MTA) }, - { FLDATA (STOP_IOE, mt_stopioe, 0) }, - { DRDATA (TIME, mt_time, 24), PV_LEFT }, - { URDATA (UST, mt_unit[0].USTAT, 8, 16, 0, MT_NUMDR, 0) }, - { URDATA (POS, mt_unit[0].pos, 10, T_ADDR_W, 0, - MT_NUMDR, PV_LEFT | REG_RO) }, - { FLDATA (LOG, mt_log, 0), REG_HIDDEN }, - { ORDATA (DEVNO, mt_dib.dev, 6), REG_HRO }, - { NULL } }; - -MTAB mt_mod[] = { - { MTUF_WLK, 0, "write enabled", "WRITEENABLED", NULL }, - { MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL }, - { MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT", - &sim_tape_set_fmt, &sim_tape_show_fmt, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", - &set_devno, &show_devno, NULL }, - { 0 } }; - -DEVICE mt_dev = { - "MT", mt_unit, mt_reg, mt_mod, - MT_NUMDR, 10, 31, 1, 8, 8, - NULL, NULL, &mt_reset, - NULL, &mt_attach, &mt_detach, - &mt_dib, DEV_DISABLE }; - -/* IOT routine */ - -int32 mt (int32 pulse, int32 dat) -{ -int32 f, sb; -UNIT *uptr; - -uptr = mt_dev.units + GET_UNIT (mt_cu); /* get unit */ -mt_updcsta (uptr, 0); /* update status */ -sb = pulse & 060; /* subop */ -if (pulse & 01) { - if ((sb == 000) && (uptr->flags & UNIT_ATT) && /* MTTR */ - !sim_is_active (uptr)) - dat = IOT_SKP | dat; - else if ((sb == 020) && !mt_busy ()) /* MTCR */ - dat = IOT_SKP | dat; - else if ((sb == 040) && (mt_sta & (STA_ERR | STA_DON))) /* MTSF */ - dat = IOT_SKP | dat; - } -if ((pulse & 06) && mt_log) - printf ("[MT%d: IOT=%o, AC=%o, sta=%o]\n", - GET_UNIT (mt_cu), 0707300 + pulse, dat, mt_sta); -if (pulse & 02) { - if (sb == 000) dat = dat | (mt_cu & 0777700); /* MTRC */ - else if (sb == 020) { /* MTAF, MTLC */ - if (!mt_busy ()) mt_cu = mt_sta = 0; /* if not busy, clr */ - mt_sta = mt_sta & ~(STA_ERR | STA_DON); } /* clear flags */ - else if (sb == 040) dat = dat | mt_sta; /* MTRS */ - } -if (pulse & 04) { - if (sb == 000) { /* MTGO */ - f = GET_CMD (mt_cu); /* get function */ - if (mt_busy () || - sim_is_active (uptr) || - (f == FN_NOP) || - (((f == FN_SPACER) || (f == FN_REWIND)) && (uptr->USTAT & STA_BOT)) || - (((f == FN_WRITE) || (f == FN_WREOF)) && sim_tape_wrp (uptr)) || - ((uptr->flags & UNIT_ATT) == 0)) - mt_sta = mt_sta | STA_ILL | STA_ERR; /* set illegal op */ - 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 */ - if (sb == 020) /* MTCM, MTLC */ - mt_cu = (mt_cu & 0770700) | (dat & 0777700); /* load status */ - } -mt_updcsta (mt_dev.units + GET_UNIT (mt_cu), 0); /* update status */ -return dat; -} - -/* Unit service - - If rewind done, reposition to start of tape, set status - else, do operation, set done, interrupt -*/ - -t_stat mt_svc (UNIT *uptr) -{ -int32 c, c1, c2, c3, f, i, p, u; -int32 wc, xma; -t_mtrlnt tbc, cbc; -t_stat st, r = SCPE_OK; - -u = uptr - mt_dev.units; /* get unit number */ -f = GET_CMD (mt_cu); /* get command */ -wc = WC_SIZE - (M[MT_WC] & WC_MASK); /* word count is 12b */ - -if (uptr->USTAT & STA_REW) { /* rewind? */ - sim_tape_rewind (uptr); /* rewind tape */ - if (uptr->flags & UNIT_ATT) uptr->USTAT = STA_BOT; - else uptr->USTAT = 0; - if (u == GET_UNIT (mt_cu)) mt_updcsta (uptr, STA_DON); - if (mt_log) printf ("[MT%d: rewind complete, sta=%o]\n", u, mt_sta); - return SCPE_OK; } - -if ((uptr->flags & UNIT_ATT) == 0) { /* if not attached */ - mt_updcsta (uptr, STA_ILL); /* illegal operation */ - return IORETURN (mt_stopioe, SCPE_UNATT); } - -switch (f) { /* case on function */ - -/* Unit service, continued */ - -case FN_READ: /* read */ -case FN_CMPARE: /* read/compare */ - st = sim_tape_rdrecf (uptr, mtxb, &tbc, MT_MAXFR); /* read rec */ - if (st == MTSE_RECE) mt_sta = mt_sta | STA_PAR | STA_ERR; /* rec in err? */ - else if (st != MTSE_OK) { /* other error? */ - mt_sta = mt_sta | STA_RLE | STA_ERR; /* set RLE flag */ - r = mt_map_err (uptr, st); /* map error */ - break; } - cbc = PACKED (mt_cu)? wc * 3: wc * 2; /* expected bc */ - if (tbc != cbc) mt_sta = mt_sta | STA_RLE | STA_ERR; /* wrong size? */ - if (tbc < cbc) { /* record small? */ - cbc = tbc; /* use smaller */ - wc = PACKED (mt_cu)? ((tbc + 2) / 3): ((tbc + 1) / 2); } - for (i = p = 0; i < wc; i++) { /* copy buffer */ - M[MT_WC] = (M[MT_WC] + 1) & DMASK; /* inc WC, CA */ - M[MT_CA] = (M[MT_CA] + 1) & DMASK; - xma = M[MT_CA] & AMASK; - if (PACKED (mt_cu)) { /* packed? */ - c1 = mtxb[p++] & 077; - c2 = mtxb[p++] & 077; - c3 = mtxb[p++] & 077; - c = (c1 << 12) | (c2 << 6) | c3; } - else { - c1 = mtxb[p++]; - c2 = mtxb[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)? DMASK: 0177777)))) { - mt_updcsta (uptr, STA_CPE); - break; } } - break; - -case FN_WRITE: /* write */ - tbc = PACKED (mt_cu)? wc * 3: wc * 2; - xma = M[MT_CA] & AMASK; /* get mem addr */ - for (i = p = 0; i < wc; i++) { /* copy buf to tape */ - xma = (xma + 1) & AMASK; /* incr mem addr */ - if (PACKED (mt_cu)) { /* packed? */ - mtxb[p++] = (M[xma] >> 12) & 077; - mtxb[p++] = (M[xma] >> 6) & 077; - mtxb[p++] = M[xma] & 077; } - else { - mtxb[p++] = (M[xma] >> 8) & 0377; - mtxb[p++] = M[xma] & 0377; } } - if (st = sim_tape_wrrecf (uptr, mtxb, tbc)) /* write rec, err? */ - r = mt_map_err (uptr, st); /* map error */ - else { - M[MT_CA] = (M[MT_CA] + wc) & DMASK; /* advance mem addr */ - M[MT_WC] = 0; } /* clear word cnt */ - mt_cu = mt_cu & ~CU_ERASE; /* clear erase flag */ - break; - -/* Unit service, continued */ - -case FN_WREOF: - if (st = sim_tape_wrtmk (uptr)) /* write tmk, err? */ - r = mt_map_err (uptr, st); /* map error */ - else uptr->USTAT = STA_EOF; - mt_cu = mt_cu & ~CU_ERASE; /* clear erase flag */ - break; - -case FN_SPACEF: /* space forward */ - do { - M[MT_WC] = (M[MT_WC] + 1) & DMASK; /* inc WC */ - if (st = sim_tape_sprecf (uptr, &tbc)) { /* space rec fwd, err? */ - r = mt_map_err (uptr, st); /* map error */ - break; } - } - while (M[MT_WC] != 0); - break; - -case FN_SPACER: /* space reverse */ - do { - M[MT_WC] = (M[MT_WC] + 1) & DMASK; /* inc WC */ - if (st = sim_tape_sprecr (uptr, &tbc)) { /* space rec rev, err? */ - r = mt_map_err (uptr, st); /* map error */ - break; } - } - while (M[MT_WC] != 0); - break; } /* end case */ - -mt_updcsta (uptr, STA_DON); /* set done */ -if (mt_log) printf ("MT%d: fnc=%d done, ma=%o, wc=%o, sta=%o]\n", - u, f, M[MT_CA], M[MT_WC], mt_sta); -return r; -} - -/* Update controller status */ - -int32 mt_updcsta (UNIT *uptr, int32 news) -{ -mt_sta = (mt_sta & ~(STA_DYN | STA_CLR)) | - (uptr->USTAT & STA_DYN) | news; -if ((mt_sta & (STA_ERR | STA_DON)) && (mt_cu & CU_IE)) - SET_INT (MTA); -else CLR_INT (MTA); /* int request */ -return mt_sta; -} - -/* Test if controller busy */ - -UNIT *mt_busy (void) -{ -int32 u; -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 NULL; -} - -/* Map tape error status */ - -t_stat mt_map_err (UNIT *uptr, t_stat st) -{ -switch (st) { -case MTSE_FMT: /* illegal fmt */ -case MTSE_UNATT: /* not attached */ - mt_sta = mt_sta | STA_ILL | STA_ERR; -case MTSE_OK: /* no error */ - return SCPE_IERR; -case MTSE_TMK: /* end of file */ - uptr->USTAT = uptr->USTAT | STA_EOF; /* set EOF */ - mt_sta = mt_sta | STA_ERR; - break; -case MTSE_IOERR: /* IO error */ - mt_sta = mt_sta | STA_PAR | STA_ERR; /* set par err */ - if (mt_stopioe) return SCPE_IOERR; - break; -case MTSE_INVRL: /* invalid rec lnt */ - mt_sta = mt_sta | STA_PAR | STA_ERR; /* set par err */ - return SCPE_MTRLNT; -case MTSE_RECE: /* record in error */ - mt_sta = mt_sta | STA_PAR | STA_ERR; /* set par err */ - break; -case MTSE_EOM: /* end of medium */ - mt_sta = mt_sta | STA_BAD | STA_ERR; /* set end tape */ - break; -case MTSE_BOT: /* reverse into BOT */ - uptr->USTAT = uptr->USTAT | STA_BOT; /* set status */ - mt_sta = mt_sta | STA_ERR; - break; -case MTSE_WRP: /* write protect */ - mt_sta = mt_sta | STA_ILL | STA_ERR; /* illegal operation */ - break; } -return SCPE_OK; -} - -/* Reset routine */ - -t_stat mt_reset (DEVICE *dptr) -{ -int32 u; -UNIT *uptr; - -mt_cu = mt_sta = 0; -for (u = 0; u < MT_NUMDR; u++) { /* loop thru units */ - uptr = mt_dev.units + u; - sim_tape_reset (uptr); /* reset tape */ - sim_cancel (uptr); /* cancel activity */ - if (uptr->flags & UNIT_ATT) uptr->USTAT = STA_BOT; - else uptr->USTAT = 0; } -mt_updcsta (&mt_unit[0], 0); /* update status */ -if (mtxb == NULL) mtxb = calloc (MT_MAXFR, sizeof (uint8)); -if (mtxb == NULL) return SCPE_MEM; -return SCPE_OK; -} - -/* IORS routine */ - -int32 mt_iors (void) -{ -return (mt_sta & (STA_ERR | STA_DON))? IOS_MTA: 0; -} - -/* Attach routine */ - -t_stat mt_attach (UNIT *uptr, char *cptr) -{ -t_stat r; - -r = sim_tape_attach (uptr, cptr); -if (r != SCPE_OK) return r; -uptr->USTAT = STA_BOT; -mt_updcsta (mt_dev.units + GET_UNIT (mt_cu), 0); /* update status */ -return r; -} - -/* Detach routine */ - -t_stat mt_detach (UNIT* uptr) -{ -if (!sim_is_active (uptr)) uptr->USTAT = 0; -mt_updcsta (mt_dev.units + GET_UNIT (mt_cu), 0); /* update status */ -return sim_tape_detach (uptr); -} diff --git a/PDP18B/pdp18b_rb.c b/PDP18B/pdp18b_rb.c deleted file mode 100644 index e3423225..00000000 --- a/PDP18B/pdp18b_rb.c +++ /dev/null @@ -1,273 +0,0 @@ -/* pdp18b_rb.c: RB09 fixed head disk simulator - - 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. - - rb RB09 fixed head disk - - The RB09 is a head-per-track disk. It uses the single cycle data break - facility. To minimize overhead, the entire RB09 is buffered in memory. - - Two timing parameters are provided: - - rb_time Interword timing. Must be non-zero. - rb_burst Burst mode. If 0, DMA occurs cycle by cycle; otherwise, - DMA occurs in a burst. -*/ - -#include "pdp18b_defs.h" -#include - -/* Constants */ - -#define RB_NUMWD 64 /* words/sector */ -#define RB_NUMSC 80 /* sectors/track */ -#define RB_NUMTR 200 /* tracks/disk */ -#define RB_WLKTR 10 /* tracks/wlock switch */ -#define RB_SIZE (RB_NUMTR * RB_NUMSC * RB_NUMWD) /* words/drive */ - -/* Function/status register */ - -#define RBS_ERR 0400000 /* error */ -#define RBS_PAR 0200000 /* parity error */ -#define RBS_ILA 0100000 /* ill addr error */ -#define RBS_TIM 0040000 /* timing transfer */ -#define RBS_NRY 0020000 /* not ready error */ -#define RBS_DON 0010000 /* done */ -#define RBS_IE 0004000 /* int enable */ -#define RBS_BSY 0002000 /* busy */ -#define RBS_WR 0001000 /* read/write */ -#define RBS_XOR (RBS_IE|RBS_BSY|RBS_WR) /* set by XOR */ -#define RBS_MBZ 0000777 /* always clear */ -#define RBS_EFLGS (RBS_PAR|RBS_ILA|RBS_TIM|RBS_NRY) /* error flags */ - -/* BCD disk address */ - -#define RBA_V_TR 8 -#define RBA_M_TR 0x1FF -#define RBA_V_SC 0 -#define RBA_M_SC 0xFF -#define RBA_GETTR(x) (((x) >> RBA_V_TR) & RBA_M_TR) -#define RBA_GETSC(x) (((x) >> RBA_V_SC) & RBA_M_SC) - -#define GET_POS(x) ((int) fmod (sim_gtime () / ((double) (x)), \ - ((double) (RB_NUMSC * RB_NUMWD)))) - -extern int32 M[]; -extern int32 int_hwre[API_HLVL+1]; -extern UNIT cpu_unit; - -int32 rb_sta = 0; /* status register */ -int32 rb_da = 0; /* disk address */ -int32 rb_ma = 0; /* current addr */ -int32 rb_wc = 0; /* word count */ -int32 rb_wlk = 0; /* write lock */ -int32 rb_time = 10; /* inter-word time */ -int32 rb_burst = 1; /* burst mode flag */ -int32 rb_stopioe = 1; /* stop on error */ - -DEVICE rb_dev; -int32 rb71 (int32 pulse, int32 AC); -t_stat rb_svc (UNIT *uptr); -t_stat rb_reset (DEVICE *dptr); -int32 rb_updsta (int32 new); -int32 rb_make_da (int32 dat); -int32 rb_make_bcd (int32 dat); -int32 rb_set_da (int32 dat, int32 old); -int32 rb_set_bcd (int32 dat); - -/* RB data structures - - rb_dev RF device descriptor - rb_unit RF unit descriptor - rb_reg RF register list -*/ - -DIB rb_dib = { DEV_RB, 1, NULL, { &rb71 } }; - -UNIT rb_unit = - { UDATA (&rb_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+UNIT_MUSTBUF, - RB_SIZE) }; - -REG rb_reg[] = { - { ORDATA (STA, rb_sta, 18) }, - { ORDATA (DA, rb_da, 20) }, - { ORDATA (WC, rb_wc, 16) }, - { ORDATA (MA, rb_ma, ADDRSIZE) }, - { FLDATA (INT, int_hwre[API_RB], INT_V_RB) }, - { ORDATA (WLK, rb_wlk, RB_NUMTR / RB_WLKTR) }, - { DRDATA (TIME, rb_time, 24), PV_LEFT + REG_NZ }, - { FLDATA (BURST, rb_burst, 0) }, - { FLDATA (STOP_IOE, rb_stopioe, 0) }, - { ORDATA (DEVNO, rb_dib.dev, 6), REG_HRO }, - { NULL } }; - -MTAB rb_mod[] = { - { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", &set_devno, &show_devno }, - { 0 } }; - -DEVICE rb_dev = { - "RB", &rb_unit, rb_reg, rb_mod, - 1, 8, 21, 1, 8, 18, - NULL, NULL, &rb_reset, - NULL, NULL, NULL, - &rb_dib, DEV_DIS | DEV_DISABLE }; - -/* IOT routines */ - -int32 rb71 (int32 pulse, int32 AC) -{ -int32 tow, t, sb = pulse & 060; - -if (pulse & 001) { - if (sb == 000) rb_sta = rb_sta & /* DBCF */ - ~(RBS_ERR | RBS_EFLGS | RBS_DON); - if ((sb == 020) && (rb_sta & (RBS_ERR | RBS_DON))) - AC = AC | IOT_SKP; /* DBSF */ - if (sb == 040) rb_sta = 0; /* DBCS */ - } -if (pulse & 002) { - if (sb == 000) AC = AC | rb_make_da (rb_da); /* DBRD */ - if (sb == 020) AC = AC | rb_sta; /* DBRS */ - if (sb == 040) rb_ma = AC & AMASK; /* DBLM */ - } -if (pulse & 004) { - if (sb == 000) rb_da = rb_set_da (AC, rb_da); /* DBLD */ - if (sb == 020) rb_wc = AC & 0177777; /* DBLW */ - if (sb == 040) { /* DBLS */ - rb_sta = (rb_sta & RBS_XOR) ^ (AC & ~RBS_MBZ); - if (rb_sta & RBS_BSY) { /* busy set? */ - if (!sim_is_active (&rb_unit)) { /* schedule */ - tow = rb_da % (RB_NUMSC * RB_NUMWD); - t = tow - GET_POS (rb_time); - if (t < 0) t = t + (RB_NUMSC * RB_NUMWD); - sim_activate (&rb_unit, t * rb_time); } } - else sim_cancel (&rb_unit); } /* no, stop */ - } -rb_updsta (0); /* update status */ -return AC; -} - -int32 rb_make_da (int32 da) -{ -int32 t = da / (RB_NUMSC * RB_NUMWD); /* bin track */ -int32 s = (da % (RB_NUMSC * RB_NUMWD)) / RB_NUMWD; /* bin sector */ -int32 bcd_t = rb_make_bcd (t); /* bcd track */ -int32 bcd_s = rb_make_bcd (s); /* bcd sector */ -return (bcd_t << RBA_V_TR) | (bcd_s << RBA_V_SC); -} - -int32 rb_set_da (int32 bcda, int32 old_da) -{ -int32 bcd_t = RBA_GETTR (bcda); /* bcd track */ -int32 bcd_s = RBA_GETSC (bcda); /* bcd sector */ -int32 t = rb_set_bcd (bcd_t); /* bin track */ -int32 s = rb_set_bcd (bcd_s); /* bin sector */ - -if ((t >= RB_NUMTR) || (t < 0) || /* invalid? */ - (s >= RB_NUMSC) || (s < 0)) { - rb_updsta (RBS_ILA); /* error */ - return old_da; } /* don't change */ -else return (((t * RB_NUMSC) + s) * RB_NUMWD); /* new da */ -} - -int32 rb_make_bcd (int32 bin) -{ -int32 d, i, r; - -for (r = i = 0; bin != 0; bin = bin / 10) { /* while nz */ - d = bin % 10; /* dec digit */ - r = r | (d << i); /* insert bcd */ - i = i + 4; } -return r; -} - -int32 rb_set_bcd (int32 bcd) -{ -int32 d, i, r; - -for (r = 0, i = 1; bcd != 0; bcd = bcd >> 4) { /* while nz */ - d = bcd & 0xF; /* bcd digit */ - if (d >= 10) return -1; /* invalid? */ - r = r + (d * i); /* insert bin */ - i = i * 10; } -return r; -} - -/* Unit service - disk is buffered in memory */ - -t_stat rb_svc (UNIT *uptr) -{ -int32 t, sw; - -if ((uptr->flags & UNIT_BUF) == 0) { /* not buf? abort */ - rb_updsta (RBS_NRY | RBS_DON); /* set nxd, done */ - return IORETURN (rb_stopioe, SCPE_UNATT); } - -do { if (rb_sta & RBS_WR) { /* write? */ - t = rb_da / (RB_NUMSC * RB_NUMWD); /* track */ - sw = t / RB_WLKTR; /* switch */ - if ((rb_wlk >> sw) & 1) { /* write locked? */ - rb_updsta (RBS_ILA | RBS_DON); - break; } - else { - *(((int32 *) uptr->filebuf) + rb_da) = M[rb_ma]; - if (((t_addr) rb_da) >= uptr->hwmark) uptr->hwmark = rb_da + 1; } } - else if (MEM_ADDR_OK (rb_ma)) /* read, valid addr? */ - M[rb_ma] = *(((int32 *) uptr->filebuf) + rb_da); - rb_wc = (rb_wc + 1) & 0177777; /* incr word count */ - rb_ma = (rb_ma + 1) & AMASK; /* incr mem addr */ - rb_da = rb_da + 1; /* incr disk addr */ - if (rb_da > RB_SIZE) rb_da = 0; /* disk wraparound? */ - } -while ((rb_wc != 0) && (rb_burst != 0)); /* brk if wc, no brst */ - -if ((rb_wc != 0) && ((rb_sta & RBS_ERR) == 0)) /* more to do? */ - sim_activate (&rb_unit, rb_time); /* sched next */ -else rb_updsta (RBS_DON); /* set done */ -return SCPE_OK; -} - -/* Update status */ - -int32 rb_updsta (int32 new) -{ -rb_sta = (rb_sta | new) & ~(RBS_ERR | RBS_MBZ); /* clear err, mbz */ -if (rb_sta & RBS_EFLGS) rb_sta = rb_sta | RBS_ERR; /* error? */ -if (rb_sta & RBS_DON) rb_sta = rb_sta & ~RBS_BSY; /* done? clear busy */ -if ((rb_sta & (RBS_ERR | RBS_DON)) && (rb_sta & RBS_IE)) - SET_INT (RB); /* set or clr intr */ -else CLR_INT (RB); -return rb_sta; -} - -/* Reset routine */ - -t_stat rb_reset (DEVICE *dptr) -{ -rb_sta = rb_da = 0; -rb_wc = rb_ma = 0; -rb_updsta (0); -sim_cancel (&rb_unit); -return SCPE_OK; -} diff --git a/PDP18B/pdp18b_rf.c b/PDP18B/pdp18b_rf.c deleted file mode 100644 index 86c2e60c..00000000 --- a/PDP18B/pdp18b_rf.c +++ /dev/null @@ -1,332 +0,0 @@ -/* pdp18b_rf.c: fixed head disk simulator - - 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. - - rf (PDP-9) RF09/RF09 - (PDP-15) RF15/RS09 - - 26-Jul-03 RMS Fixed bug in set size routine - 14-Mar-03 RMS Fixed variable platter interaction with save/restore - 03-Mar-03 RMS Fixed autosizing - 12-Feb-03 RMS Removed 8 platter sizing hack - 05-Feb-03 RMS Fixed decode bugs, added variable and autosizing - 05-Oct-02 RMS Added DIB, dev number support - 06-Jan-02 RMS Revised enable/disable support - 25-Nov-01 RMS Revised interrupt structure - 24-Nov-01 RMS Changed WLK to array - 26-Apr-01 RMS Added device enable/disable support - 15-Feb-01 RMS Fixed 3 cycle data break sequencing - 30-Nov-99 RMS Added non-zero requirement to rf_time - 14-Apr-99 RMS Changed t_addr to unsigned - - The RFxx is a head-per-track disk. It uses the multicycle data break - facility. To minimize overhead, the entire RFxx is buffered in memory. - - Two timing parameters are provided: - - rf_time Interword timing. Must be non-zero. - rf_burst Burst mode. If 0, DMA occurs cycle by cycle; otherwise, - DMA occurs in a burst. -*/ - -#include "pdp18b_defs.h" -#include - -#define UNIT_V_AUTO (UNIT_V_UF + 0) /* autosize */ -#define UNIT_V_PLAT (UNIT_V_UF + 1) /* #platters - 1 */ -#define UNIT_M_PLAT 07 -#define UNIT_PLAT (UNIT_M_PLAT << UNIT_V_PLAT) -#define UNIT_GETP(x) ((((x) >> UNIT_V_PLAT) & UNIT_M_PLAT) + 1) -#define UNIT_AUTO (1 << UNIT_V_AUTO) -#define UNIT_PLAT (UNIT_M_PLAT << UNIT_V_PLAT) - -/* Constants */ - -#define RF_NUMWD 2048 /* words/track */ -#define RF_NUMTR 128 /* tracks/disk */ -#define RF_DKSIZE (RF_NUMTR * RF_NUMWD) /* words/disk */ -#define RF_NUMDK 8 /* disks/controller */ -#define RF_WMASK (RF_NUMWD - 1) /* word mask */ -#define RF_WC 036 /* word count */ -#define RF_CA 037 /* current addr */ - -/* Function/status register */ - -#define RFS_ERR 0400000 /* error */ -#define RFS_HDW 0200000 /* hardware error */ -#define RFS_APE 0100000 /* addr parity error */ -#define RFS_MXF 0040000 /* missed transfer */ -#define RFS_WCE 0020000 /* write check error */ -#define RFS_DPE 0010000 /* data parity error */ -#define RFS_WLO 0004000 /* write lock error */ -#define RFS_NED 0002000 /* non-existent disk */ -#define RFS_DCH 0001000 /* data chan timing */ -#define RFS_PGE 0000400 /* programming error */ -#define RFS_DON 0000200 /* transfer complete */ -#define RFS_V_FNC 1 /* function */ -#define RFS_M_FNC 03 -#define RFS_FNC (RFS_M_FNC << RFS_V_FNC) -#define FN_NOP 0 -#define FN_READ 1 -#define FN_WRITE 2 -#define FN_WCHK 3 -#define RFS_IE 0000001 /* interrupt enable */ - -#define RFS_CLR 0000170 /* always clear */ -#define RFS_EFLGS (RFS_HDW | RFS_APE | RFS_MXF | RFS_WCE | \ - RFS_DPE | RFS_WLO | RFS_NED ) /* error flags */ -#define GET_FNC(x) (((x) >> RFS_V_FNC) & RFS_M_FNC) -#define GET_POS(x) ((int) fmod (sim_gtime () / ((double) (x)), \ - ((double) RF_NUMWD))) -#define RF_BUSY (sim_is_active (&rf_unit)) - -extern int32 M[]; -extern int32 int_hwre[API_HLVL+1]; -extern UNIT cpu_unit; - -int32 rf_sta = 0; /* status register */ -int32 rf_da = 0; /* disk address */ -int32 rf_dbuf = 0; /* data buffer */ -int32 rf_wlk[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; /* write lock */ -int32 rf_time = 10; /* inter-word time */ -int32 rf_burst = 1; /* burst mode flag */ -int32 rf_stopioe = 1; /* stop on error */ - -DEVICE rf_dev; -int32 rf70 (int32 pulse, int32 dat); -int32 rf72 (int32 pulse, int32 dat); -int32 rf_iors (void); -t_stat rf_svc (UNIT *uptr); -t_stat rf_reset (DEVICE *dptr); -int32 rf_updsta (int32 new); -t_stat rf_attach (UNIT *uptr, char *cptr); -t_stat rf_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); - -/* RF data structures - - rf_dev RF device descriptor - rf_unit RF unit descriptor - rf_reg RF register list -*/ - -DIB rf_dib = { DEV_RF, 3, &rf_iors, { &rf70, NULL, &rf72 } }; - -UNIT rf_unit = - { UDATA (&rf_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+UNIT_MUSTBUF+UNIT_AUTO, - RF_DKSIZE) }; - -REG rf_reg[] = { - { ORDATA (STA, rf_sta, 18) }, - { ORDATA (DA, rf_da, 22) }, - { ORDATA (WC, M[RF_WC], 18) }, - { ORDATA (CA, M[RF_CA], 18) }, - { ORDATA (BUF, rf_dbuf, 18) }, - { FLDATA (INT, int_hwre[API_RF], INT_V_RF) }, - { BRDATA (WLK, rf_wlk, 8, 16, RF_NUMDK) }, - { DRDATA (TIME, rf_time, 24), PV_LEFT + REG_NZ }, - { FLDATA (BURST, rf_burst, 0) }, - { FLDATA (STOP_IOE, rf_stopioe, 0) }, - { DRDATA (CAPAC, rf_unit.capac, 31), PV_LEFT + REG_HRO }, - { ORDATA (DEVNO, rf_dib.dev, 6), REG_HRO }, - { NULL } }; - -MTAB rf_mod[] = { - { UNIT_PLAT, (0 << UNIT_V_PLAT), NULL, "1P", &rf_set_size }, - { UNIT_PLAT, (1 << UNIT_V_PLAT), NULL, "2P", &rf_set_size }, - { UNIT_PLAT, (2 << UNIT_V_PLAT), NULL, "3P", &rf_set_size }, - { UNIT_PLAT, (3 << UNIT_V_PLAT), NULL, "4P", &rf_set_size }, - { UNIT_PLAT, (4 << UNIT_V_PLAT), NULL, "5P", &rf_set_size }, - { UNIT_PLAT, (5 << UNIT_V_PLAT), NULL, "6P", &rf_set_size }, - { UNIT_PLAT, (6 << UNIT_V_PLAT), NULL, "7P", &rf_set_size }, - { UNIT_PLAT, (7 << UNIT_V_PLAT), NULL, "8P", &rf_set_size }, - { UNIT_AUTO, UNIT_AUTO, "autosize", "AUTOSIZE", NULL }, - { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", &set_devno, &show_devno }, - { 0 } }; - -DEVICE rf_dev = { - "RF", &rf_unit, rf_reg, rf_mod, - 1, 8, 21, 1, 8, 18, - NULL, NULL, &rf_reset, - NULL, &rf_attach, NULL, - &rf_dib, DEV_DISABLE }; - -/* IOT routines */ - -int32 rf70 (int32 pulse, int32 dat) -{ -int32 t, sb; - -sb = pulse & 060; /* subopcode */ -if (pulse & 01) { - if ((sb == 000) && (rf_sta & (RFS_ERR | RFS_DON))) - dat = IOT_SKP | dat; /* DSSF */ - else if (sb == 020) rf_reset (&rf_dev); /* DSCC */ - else if (sb == 040) { /* DSCF */ - if (RF_BUSY) rf_sta = rf_sta | RFS_PGE; /* busy inhibits */ - else rf_sta = rf_sta & ~(RFS_FNC | RFS_IE); } /* clear func */ - } -if (pulse & 02) { - if (RF_BUSY) rf_sta = rf_sta | RFS_PGE; /* busy sets PGE */ - else if (sb == 000) dat = dat | rf_dbuf; /* DRBR */ - else if (sb == 020) /* DRAL */ - dat = dat | (rf_da & DMASK); - else if (sb == 040) /* DSFX */ - rf_sta = rf_sta ^ (dat & (RFS_FNC | RFS_IE)); /* xor func */ - else if (sb == 060) /* DRAH */ - dat = dat | (rf_da >> 18) | ((rf_sta & RFS_NED)? 010: 0); - } -if (pulse & 04) { - if (RF_BUSY) rf_sta = rf_sta | RFS_PGE; /* busy sets PGE */ - else if (sb == 000) rf_dbuf = dat & DMASK; /* DLBR */ - else if (sb == 020) /* DLAL */ - rf_da = (rf_da & ~DMASK) | (dat & DMASK); - else if (sb == 040) { /* DSCN */ - rf_sta = rf_sta & ~RFS_DON; /* clear done */ - 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 */ - else if (sb == 060) { /* DLAH */ - rf_da = (rf_da & DMASK) | ((dat & 07) << 18); - if ((uint32) rf_da >= rf_unit.capac) /* for sizing */ - rf_updsta (RFS_NED); } - } -rf_updsta (0); /* update status */ -return dat; -} - -int32 rf72 (int32 pulse, int32 dat) -{ -int32 sb = pulse & 060; - -if (pulse & 02) { - if (sb == 000) dat = dat | GET_POS (rf_time) | /* DLOK */ - (sim_is_active (&rf_unit)? 0400000: 0); - else if (sb == 040) { /* DSCD */ - if (RF_BUSY) rf_sta = rf_sta | RFS_PGE; /* busy inhibits */ - else rf_sta = 0; - rf_updsta (0); } - else if (sb == 060) { /* DSRS */ - if (RF_BUSY) rf_sta = rf_sta | RFS_PGE; /* busy sets PGE */ - dat = dat | rf_updsta (0); } - } -return dat; -} - -/* Unit service - assumes the entire disk is buffered */ - -t_stat rf_svc (UNIT *uptr) -{ -int32 f, pa, d, t; - -if ((uptr->flags & UNIT_BUF) == 0) { /* not buf? abort */ - rf_updsta (RFS_NED | RFS_DON); /* set nxd, done */ - return IORETURN (rf_stopioe, SCPE_UNATT); } - -f = GET_FNC (rf_sta); /* get function */ -do { if ((uint32) rf_da >= uptr->capac) { /* disk overflow? */ - rf_updsta (RFS_NED); /* nx disk error */ - break; } - M[RF_WC] = (M[RF_WC] + 1) & DMASK; /* incr word count */ - pa = M[RF_CA] = (M[RF_CA] + 1) & AMASK; /* incr mem addr */ - if ((f == FN_READ) && MEM_ADDR_OK (pa)) /* read? */ - 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; } - 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 (((uint32) rf_da) >= uptr->hwmark) uptr->hwmark = rf_da + 1; } } - rf_da = rf_da + 1; /* incr disk addr */ - } -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? */ - sim_activate (&rf_unit, rf_time); /* sched next */ -else rf_updsta (RFS_DON); -return SCPE_OK; -} - -/* Update status */ - -int32 rf_updsta (int32 new) -{ -rf_sta = (rf_sta | new) & ~(RFS_ERR | RFS_CLR); -if (rf_sta & RFS_EFLGS) rf_sta = rf_sta | RFS_ERR; -if ((rf_sta & (RFS_ERR | RFS_DON)) && (rf_sta & RFS_IE)) - SET_INT (RF); -else CLR_INT (RF); -return rf_sta; -} - -/* Reset routine */ - -t_stat rf_reset (DEVICE *dptr) -{ -rf_sta = rf_da = rf_dbuf = 0; -rf_updsta (0); -sim_cancel (&rf_unit); -return SCPE_OK; -} - -/* IORS routine */ - -int32 rf_iors (void) -{ -return ((rf_sta & (RFS_ERR | RFS_DON))? IOS_RF: 0); -} - -/* Attach routine */ - -t_stat rf_attach (UNIT *uptr, char *cptr) -{ -uint32 p, sz; -uint32 ds_bytes = RF_DKSIZE * sizeof (int32); - -if ((uptr->flags & UNIT_AUTO) && (sz = sim_fsize (cptr))) { - p = (sz + ds_bytes - 1) / ds_bytes; - if (p >= RF_NUMDK) p = RF_NUMDK - 1; - uptr->flags = (uptr->flags & ~UNIT_PLAT) | - (p << UNIT_V_PLAT); } -uptr->capac = UNIT_GETP (uptr->flags) * RF_DKSIZE; -return attach_unit (uptr, cptr); -} - -/* Change disk size */ - -t_stat rf_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -if (val < 0) return SCPE_IERR; -if (uptr->flags & UNIT_ATT) return SCPE_ALATT; -uptr->capac = UNIT_GETP (val) * RF_DKSIZE; -uptr->flags = uptr->flags & ~UNIT_AUTO; -return SCPE_OK; -} diff --git a/PDP18B/pdp18b_rp.c b/PDP18B/pdp18b_rp.c deleted file mode 100644 index b4d739c9..00000000 --- a/PDP18B/pdp18b_rp.c +++ /dev/null @@ -1,461 +0,0 @@ -/* pdp18b_rp.c: RP15/RP02 disk pack simulator - - 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. - - rp RP15/RP02 disk pack - - 06-Feb-03 RMS Revised IOT decoding, fixed bug in initiation - 05-Oct-02 RMS Added DIB, device number support - 06-Jan-02 RMS Revised enable/disable support - 29-Nov-01 RMS Added read only unit support - 25-Nov-01 RMS Revised interrupt structure - Changed FLG to array - 26-Apr-01 RMS Added device enable/disable support - 14-Apr-99 RMS Changed t_addr to unsigned - 29-Jun-96 RMS Added unit enable/disable support -*/ - -#include "pdp18b_defs.h" - -/* Constants */ - -#define RP_NUMWD 256 /* words/sector */ -#define RP_NUMSC 10 /* sectors/surface */ -#define RP_NUMSF 20 /* surfaces/cylinder */ -#define RP_NUMCY 203 /* cylinders/drive */ -#define RP_NUMDR 8 /* drives/controller */ -#define RP_SIZE (RP_NUMCY * RP_NUMSF * RP_NUMSC * RP_NUMWD) /* words/drive */ - -/* Unit specific flags */ - -#define UNIT_V_WLK (UNIT_V_UF + 0) /* hwre write lock */ -#define UNIT_WLK (1u << UNIT_V_WLK) -#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */ - -/* Parameters in the unit descriptor */ - -#define CYL u3 /* current cylinder */ -#define FUNC u4 /* function */ - -/* Status register A */ - -#define STA_V_UNIT 15 /* unit select */ -#define STA_M_UNIT 07 -#define STA_V_FUNC 12 /* function */ -#define STA_M_FUNC 07 -#define FN_IDLE 0 -#define FN_READ 1 -#define FN_WRITE 2 -#define FN_RECAL 3 -#define FN_SEEK 4 -#define FN_RDALL 5 -#define FN_WRALL 6 -#define FN_WRCHK 7 -#define FN_2ND 010 /* second state flag */ -#define STA_IED 0004000 /* int enable done */ -#define STA_IEA 0002000 /* int enable attn */ -#define STA_GO 0001000 /* go */ -#define STA_WPE 0000400 /* write lock error */ -#define STA_NXC 0000200 /* nx cyl error */ -#define STA_NXF 0000100 /* nx surface error */ -#define STA_NXS 0000040 /* nx sector error */ -#define STA_HNF 0000020 /* hdr not found */ -#define STA_SUWP 0000010 /* sel unit wrt lock */ -#define STA_SUSI 0000004 /* sel unit seek inc */ -#define STA_DON 0000002 /* done */ -#define STA_ERR 0000001 /* error */ - -#define STA_RW 0777000 /* read/write */ -#define STA_EFLGS (STA_WPE | STA_NXC | STA_NXF | STA_NXS | \ - STA_HNF | STA_SUSI) /* error flags */ -#define STA_DYN (STA_SUWP | STA_SUSI) /* per unit status */ -#define GET_UNIT(x) (((x) >> STA_V_UNIT) & STA_M_UNIT) -#define GET_FUNC(x) (((x) >> STA_V_FUNC) & STA_M_FUNC) - -/* Status register B */ - -#define STB_V_ATT0 17 /* unit 0 attention */ -#define STB_ATTN 0776000 /* attention flags */ -#define STB_SUFU 0001000 /* sel unit unsafe */ -#define STB_PGE 0000400 /* programming error */ -#define STB_EOP 0000200 /* end of pack */ -#define STB_TME 0000100 /* timing error */ -#define STB_FME 0000040 /* format error */ -#define STB_WCE 0000020 /* write check error */ -#define STB_WPE 0000010 /* word parity error */ -#define STB_LON 0000004 /* long parity error */ -#define STB_SUSU 0000002 /* sel unit seeking */ -#define STB_SUNR 0000001 /* sel unit not rdy */ - -#define STB_EFLGS (STB_SUFU | STB_PGE | STB_EOP | STB_TME | STB_FME | \ - STB_WCE | STB_WPE | STB_LON ) /* error flags */ -#define STB_DYN (STB_SUFU | STB_SUSU | STB_SUNR) /* per unit */ - -/* Disk address */ - -#define DA_V_SECT 0 /* sector */ -#define DA_M_SECT 017 -#define DA_V_SURF 5 -#define DA_M_SURF 037 -#define DA_V_CYL 10 /* cylinder */ -#define DA_M_CYL 0377 -#define GET_SECT(x) (((x) >> DA_V_SECT) & DA_M_SECT) -#define GET_SURF(x) (((x) >> DA_V_SURF) & DA_M_SURF) -#define GET_CYL(x) (((x) >> DA_V_CYL) & DA_M_CYL) -#define GET_DA(x) ((((GET_CYL (x) * RP_NUMSF) + GET_SURF (x)) * \ - RP_NUMSC) + GET_SECT (x)) - -#define RP_MIN 2 -#define MAX(x,y) (((x) > (y))? (x): (y)) - -extern int32 M[]; -extern int32 int_hwre[API_HLVL+1], nexm; -extern UNIT cpu_unit; - -int32 rp_sta = 0; /* status A */ -int32 rp_stb = 0; /* status B */ -int32 rp_ma = 0; /* memory address */ -int32 rp_da = 0; /* disk address */ -int32 rp_wc = 0; /* word count */ -int32 rp_busy = 0; /* busy */ -int32 rp_stopioe = 1; /* stop on error */ -int32 rp_swait = 10; /* seek time */ -int32 rp_rwait = 10; /* rotate time */ - -DEVICE rp_dev; -int32 rp63 (int32 pulse, int32 dat); -int32 rp64 (int32 pulse, int32 dat); -int32 rp_iors (void); -t_stat rp_svc (UNIT *uptr); -void rp_updsta (int32 newa, int32 newb); -t_stat rp_reset (DEVICE *dptr); -t_stat rp_attach (UNIT *uptr, char *cptr); -t_stat rp_detach (UNIT *uptr); - -/* RP15 data structures - - rp_dev RP device descriptor - rp_unit RP unit list - rp_reg RP register list - rp_mod RP modifier list -*/ - -DIB rp_dib = { DEV_RP, 2, &rp_iors, { &rp63, &rp64 } }; - -UNIT rp_unit[] = { - { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, RP_SIZE) }, - { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, RP_SIZE) }, - { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, RP_SIZE) }, - { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, RP_SIZE) }, - { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, RP_SIZE) }, - { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, RP_SIZE) }, - { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, RP_SIZE) }, - { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, RP_SIZE) } }; - -REG rp_reg[] = { - { ORDATA (STA, rp_sta, 18) }, - { ORDATA (STB, rp_stb, 18) }, - { ORDATA (DA, rp_da, 18) }, - { ORDATA (MA, rp_ma, 18) }, - { ORDATA (WC, rp_wc, 18) }, - { FLDATA (INT, int_hwre[API_RP], INT_V_RP) }, - { FLDATA (BUSY, rp_busy, 0) }, - { FLDATA (STOP_IOE, rp_stopioe, 0) }, - { DRDATA (STIME, rp_swait, 24), PV_LEFT }, - { DRDATA (RTIME, rp_rwait, 24), PV_LEFT }, - { ORDATA (DEVNO, rp_dib.dev, 6), REG_HRO }, - { NULL } }; - -MTAB rp_mod[] = { - { UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL }, - { UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL }, - { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", &set_devno, &show_devno }, - { 0 } }; - -DEVICE rp_dev = { - "RP", rp_unit, rp_reg, rp_mod, - RP_NUMDR, 8, 24, 1, 8, 18, - NULL, NULL, &rp_reset, - NULL, &rp_attach, &rp_detach, - &rp_dib, DEV_DISABLE }; - -/* IOT routines */ - -int32 rp63 (int32 pulse, int32 dat) -{ -int32 sb = pulse & 060; /* subopcode */ - -rp_updsta (0, 0); -if (pulse & 01) { - if ((sb == 000) && /* DPSF */ - ((rp_sta & (STA_DON | STA_ERR)) || (rp_stb & STB_ATTN))) - dat = IOT_SKP | dat; - else if ((sb == 020) && (rp_stb & STB_ATTN)) /* DPSA */ - dat = IOT_SKP | dat; - else if ((sb == 040) && (rp_sta & STA_DON)) /* DPSJ */ - dat = IOT_SKP | dat; - else if ((sb == 060) && (rp_sta & STA_ERR)) /* DPSE */ - dat = IOT_SKP | dat; - } -if (pulse & 02) { - if (sb == 000) dat = dat | rp_sta; /* DPOSA */ - else if (sb == 020) dat = dat | rp_stb; /* DPOSB */ - } -if (pulse & 04) { - if (rp_busy) { /* busy? */ - rp_updsta (0, STB_PGE); - return dat; } - else if (sb == 000) { /* DPLA */ - rp_da = dat & DMASK; - if (GET_SECT (rp_da) >= RP_NUMSC) rp_updsta (STA_NXS, 0); - if (GET_SURF (rp_da) >= RP_NUMSF) rp_updsta (STA_NXF, 0); - if (GET_CYL (rp_da) >= RP_NUMCY) rp_updsta (STA_NXC, 0); } - else if (sb == 020) { /* 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); - rp_updsta (0, 0); } - else if (sb == 040) rp_ma = dat & DMASK; /* DPCA */ - else if (sb == 060) rp_wc = dat & DMASK; /* DPWC */ - } -return dat; -} - -/* IOT 64 */ - -int32 rp64 (int32 pulse, int32 dat) -{ -int32 u, f, c, sb; -UNIT *uptr; - -sb = pulse & 060; -if (pulse & 01) { - if (sb == 020) dat = IOT_SKP | dat; /* DPSN */ - } -if (pulse & 02) { - if (sb == 000) dat = dat | rp_unit[GET_UNIT (rp_sta)].CYL; /* DPOU */ - else if (sb == 020) dat = dat | rp_da; /* DPOA */ - else if (sb == 040) dat = dat | rp_ma; /* DPOC */ - else if (sb == 060) dat = dat | rp_wc; /* DPOW */ - } -if (pulse & 04) { - if (rp_busy) { /* busy? */ - rp_updsta (0, STB_PGE); - return dat; } - if (sb == 000) rp_sta = rp_sta & ~STA_RW; /* DPCF */ - else if (sb == 020) rp_sta = rp_sta & (dat | ~STA_RW); /* DPLZ */ - else if (sb == 040) rp_sta = rp_sta | (dat & STA_RW); /* DPLO */ - else if (sb == 060) /* DPLF */ - rp_sta = (rp_sta & ~STA_RW) | (dat & STA_RW); - rp_sta = rp_sta & ~STA_DON; /* clear done */ - u = GET_UNIT (rp_sta); /* get unit num */ - uptr = rp_dev.units + u; /* select unit */ - if ((rp_sta & STA_GO) && !sim_is_active (uptr)) { - f = uptr->FUNC = GET_FUNC (rp_sta); /* get function */ - 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))); - 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)); } } - } -rp_updsta (0, 0); -return dat; -} - -/* Unit service - - If function = idle, clear busy - If seek or recal initial state, clear attention line, compute seek time, - put on cylinder, set second state - If unit not attached, give error - If seek or recal second state, set attention line, compute errors - Else complete data transfer command - - The unit control block contains the function and cylinder for - the current command. -*/ - -static int32 fill[RP_NUMWD] = { 0 }; -t_stat rp_svc (UNIT *uptr) -{ -int32 f, u, comp, cyl, sect, surf; -int32 err, pa, da, wc, awc, i; - -u = uptr - rp_dev.units; /* get drv number */ -f = uptr->FUNC; /* get function */ -if (f == FN_IDLE) { /* idle? */ - rp_busy = 0; /* clear busy */ - return SCPE_OK; } - -if ((f == FN_SEEK) || (f == FN_RECAL)) { /* seek or recal? */ - rp_busy = 0; /* not busy */ - cyl = (f == FN_SEEK)? GET_CYL (rp_da): 0; /* get cylinder */ - sim_activate (uptr, MAX (RP_MIN, abs (cyl - uptr->CYL) * rp_swait)); - uptr->CYL = cyl; /* on cylinder */ - uptr->FUNC = FN_SEEK | FN_2ND; /* set second state */ - rp_updsta (0, 0); /* update status */ - return SCPE_OK; } - -if (f == (FN_SEEK | FN_2ND)) { /* seek done? */ - rp_updsta (0, rp_stb | (1 << (STB_V_ATT0 - u))); /* set attention */ - return SCPE_OK; } - -if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */ - rp_updsta (STA_DON, STB_SUFU); /* done, unsafe */ - return IORETURN (rp_stopioe, SCPE_UNATT); } - -if ((f == FN_WRITE) && (uptr->flags & UNIT_WPRT)) { /* write locked? */ - rp_updsta (STA_DON | STA_WPE, 0); /* error */ - return SCPE_OK; } - -if (GET_SECT (rp_da) >= RP_NUMSC) rp_updsta (STA_NXS, 0); -if (GET_SURF (rp_da) >= RP_NUMSF) rp_updsta (STA_NXF, 0); -if (GET_CYL (rp_da) >= RP_NUMCY) rp_updsta (STA_NXC, 0); -if (rp_sta & (STA_NXS | STA_NXF | STA_NXC)) { /* or bad disk addr? */ - rp_updsta (STA_DON, STB_SUFU); /* done, unsafe */ - return SCPE_OK; } - -pa = rp_ma & AMASK; /* get mem addr */ -da = GET_DA (rp_da) * RP_NUMWD; /* get disk addr */ -wc = 01000000 - rp_wc; /* get true wc */ -if (((uint32) (pa + wc)) > MEMSIZE) { /* memory overrun? */ - nexm = 1; /* set nexm flag */ - wc = MEMSIZE - pa; } /* limit xfer */ -if ((da + wc) > RP_SIZE) { /* disk overrun? */ - rp_updsta (0, STB_EOP); /* error */ - wc = RP_SIZE - da; } /* limit xfer */ - -err = fseek (uptr->fileref, da * sizeof (int), SEEK_SET); - -if ((f == FN_READ) && (err == 0)) { /* read? */ - awc = fxread (&M[pa], sizeof (int32), wc, uptr->fileref); - for ( ; awc < wc; awc++) M[pa + awc] = 0; - err = ferror (uptr->fileref); } - -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); } } - -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); } - err = ferror (uptr->fileref); } - -rp_wc = (rp_wc + wc) & DMASK; /* final word count */ -rp_ma = (rp_ma + wc) & DMASK; /* final mem addr */ -da = (da + wc + (RP_NUMWD - 1)) / RP_NUMWD; /* final sector num */ -cyl = da / (RP_NUMSC * RP_NUMSF); /* get cyl */ -if (cyl >= RP_NUMCY) cyl = RP_NUMCY - 1; -surf = (da % (RP_NUMSC * RP_NUMSF)) / RP_NUMSC; /* get surface */ -sect = (da % (RP_NUMSC * RP_NUMSF)) % RP_NUMSC; /* get sector */ -rp_da = (cyl << DA_V_CYL) | (surf << DA_V_SURF) | (sect << DA_V_SECT); -rp_busy = 0; /* clear busy */ -rp_updsta (STA_DON, 0); /* set done */ - -if (err != 0) { /* error? */ - perror ("RP I/O error"); - clearerr (uptr->fileref); - return IORETURN (rp_stopioe, SCPE_IOERR); } -return SCPE_OK; -} - -/* Update status */ - -void rp_updsta (int32 newa, int32 newb) -{ -int32 f; -UNIT *uptr; - -uptr = rp_dev.units + GET_UNIT (rp_sta); -rp_sta = (rp_sta & ~(STA_DYN | STA_ERR)) | newa; -rp_stb = (rp_stb & ~STB_DYN) | newb; -if (uptr->flags & UNIT_WPRT) rp_sta = rp_sta | STA_SUWP; -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; } -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)) || - ((rp_stb & STB_ATTN) && (rp_sta & STA_IEA))) SET_INT (RP); -else CLR_INT (RP); -return; -} - -/* Reset routine */ - -t_stat rp_reset (DEVICE *dptr) -{ -int32 i; -UNIT *uptr; - -rp_sta = rp_stb = rp_da = rp_wc = rp_ma = rp_busy = 0; -CLR_INT (RP); -for (i = 0; i < RP_NUMDR; i++) { - uptr = rp_dev.units + i; - sim_cancel (uptr); - uptr->CYL = uptr->FUNC = 0; } -return SCPE_OK; -} - -/* IORS routine */ - -int32 rp_iors (void) -{ -return ((rp_sta & (STA_ERR | STA_DON)) || (rp_stb & STB_ATTN))? IOS_RP: 0; -} - -/* Attach unit */ - -t_stat rp_attach (UNIT *uptr, char *cptr) -{ -t_stat reason; - -reason = attach_unit (uptr, cptr); -rp_updsta (0, 0); -return reason; -} - -/* Detach unit */ - -t_stat rp_detach (UNIT *uptr) -{ -t_stat reason; - -reason = detach_unit (uptr); -rp_updsta (0, 0); -return reason; -} diff --git a/PDP18B/pdp18b_stddev.c b/PDP18B/pdp18b_stddev.c deleted file mode 100644 index dc36133b..00000000 --- a/PDP18B/pdp18b_stddev.c +++ /dev/null @@ -1,975 +0,0 @@ -/* pdp18b_stddev.c: 18b PDP's standard devices - - 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. - - ptr paper tape reader - ptp paper tape punch - tti keyboard - tto teleprinter - clk clock - - 26-Jul-03 RMS Increased PTP, TTO timeouts for PDP-15 operating systems - Added hardware read-in mode support for PDP-7/9/15 - 25-Apr-03 RMS Revised for extended file support - 14-Mar-03 RMS Clean up flags on detach - 01-Mar-03 RMS Added SET/SHOW CLK FREQ support, SET TTI CTRL-C support - 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) - 30-May-02 RMS Widened POS to 32b - 29-Nov-01 RMS Added read only unit support - 25-Nov-01 RMS Revised interrupt structure - 17-Sep-01 RMS Removed multiconsole support - 07-Sep-01 RMS Added terminal multiplexor support - 17-Jul-01 RMS Moved function prototype - 10-Jun-01 RMS Cleaned up IOT decoding to reflect hardware - 27-May-01 RMS Added multiconsole support - 10-Mar-01 RMS Added funny format loader support - 05-Mar-01 RMS Added clock calibration support - 22-Dec-00 RMS Added PDP-9/15 half duplex support - 30-Nov-00 RMS Fixed PDP-4/7 bootstrap loader for 4K systems - 30-Oct-00 RMS Standardized register naming - 06-Jan-97 RMS Fixed PDP-4 console input - 16-Dec-96 RMS Fixed bug in binary ptr service -*/ - -#include "pdp18b_defs.h" -#include - -#define UNIT_V_RASCII (UNIT_V_UF + 0) /* reader ASCII */ -#define UNIT_RASCII (1 << UNIT_V_RASCII) -#define UNIT_V_PASCII (UNIT_V_UF + 0) /* punch ASCII */ -#define UNIT_PASCII (1 << UNIT_V_PASCII) - -extern int32 M[]; -extern int32 int_hwre[API_HLVL+1], PC, ASW; -extern int32 sim_switches; -extern UNIT cpu_unit; - -int32 clk_state = 0; -int32 ptr_err = 0, ptr_stopioe = 0, ptr_state = 0; -int32 ptp_err = 0, ptp_stopioe = 0; -int32 tti_state = 0; -int32 tto_state = 0; -int32 clk_tps = 60; /* ticks/second */ -int32 tmxr_poll = 16000; /* term mux poll */ - -int32 ptr (int32 pulse, int32 dat); -int32 ptp (int32 pulse, int32 dat); -int32 tti (int32 pulse, int32 dat); -int32 tto (int32 pulse, int32 dat); -int32 clk_iors (void); -int32 ptr_iors (void); -int32 ptp_iors (void); -int32 tti_iors (void); -int32 tto_iors (void); -t_stat clk_svc (UNIT *uptr); -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 clk_reset (DEVICE *dptr); -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_attach (UNIT *uptr, char *cptr); -t_stat ptp_attach (UNIT *uptr, char *cptr); -t_stat ptr_detach (UNIT *uptr); -t_stat ptp_detach (UNIT *uptr); -t_stat ptr_boot (int32 unitno, DEVICE *dptr); -t_stat tty_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat tti_set_ctrlc (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat clk_set_freq (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat clk_show_freq (FILE *st, UNIT *uptr, int32 val, void *desc); - -extern int32 upd_iors (void); - -/* CLK data structures - - clk_dev CLK device descriptor - clk_unit CLK unit - clk_reg CLK register list -*/ - -DIB clk_dib = { 0, 0, &clk_iors, { NULL } }; - -UNIT clk_unit = { UDATA (&clk_svc, 0, 0), 16000 }; - -REG clk_reg[] = { - { FLDATA (INT, int_hwre[API_CLK], INT_V_CLK) }, - { FLDATA (DONE, int_hwre[API_CLK], INT_V_CLK) }, - { FLDATA (ENABLE, clk_state, 0) }, - { DRDATA (TIME, clk_unit.wait, 24), REG_NZ + PV_LEFT }, - { DRDATA (TPS, clk_tps, 8), PV_LEFT + REG_HRO }, - { NULL } }; - -MTAB clk_mod[] = { - { MTAB_XTD|MTAB_VDV, 50, NULL, "50HZ", - &clk_set_freq, NULL, NULL }, - { MTAB_XTD|MTAB_VDV, 60, NULL, "60HZ", - &clk_set_freq, NULL, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "FREQUENCY", NULL, - NULL, &clk_show_freq, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "DEVNO", NULL, NULL, &show_devno }, - { 0 } }; - -DEVICE clk_dev = { - "CLK", &clk_unit, clk_reg, clk_mod, - 1, 0, 0, 0, 0, 0, - NULL, NULL, &clk_reset, - NULL, NULL, NULL, - &clk_dib, 0 }; - -/* PTR data structures - - ptr_dev PTR device descriptor - ptr_unit PTR unit - ptr_reg PTR register list -*/ - -DIB ptr_dib = { DEV_PTR, 1, &ptr_iors, { &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, 18) }, - { FLDATA (INT, int_hwre[API_PTR], INT_V_PTR) }, - { FLDATA (DONE, int_hwre[API_PTR], INT_V_PTR) }, -#if defined (IOS_PTRERR) - { FLDATA (ERR, ptr_err, 0) }, -#endif - { ORDATA (STATE, ptr_state, 5), REG_HRO }, - { DRDATA (POS, ptr_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, ptr_unit.wait, 24), PV_LEFT }, - { FLDATA (STOP_IOE, ptr_stopioe, 0) }, - { NULL } }; - -MTAB ptr_mod[] = { - { MTAB_XTD|MTAB_VDV, 0, "DEVNO", NULL, NULL, &show_devno }, - { 0 } }; - -DEVICE ptr_dev = { - "PTR", &ptr_unit, ptr_reg, ptr_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &ptr_reset, - &ptr_boot, &ptr_attach, &ptr_detach, - &ptr_dib, 0 }; - -/* PTP data structures - - ptp_dev PTP device descriptor - ptp_unit PTP unit - ptp_reg PTP register list -*/ - -DIB ptp_dib = { DEV_PTP, 1, &ptp_iors, { &ptp } }; - -UNIT ptp_unit = { - UDATA (&ptp_svc, UNIT_SEQ+UNIT_ATTABLE, 0), 1000 }; - -REG ptp_reg[] = { - { ORDATA (BUF, ptp_unit.buf, 8) }, - { FLDATA (INT, int_hwre[API_PTP], INT_V_PTP) }, - { FLDATA (DONE, int_hwre[API_PTP], INT_V_PTP) }, -#if defined (IOS_PTPERR) - { FLDATA (ERR, ptp_err, 0) }, -#endif - { DRDATA (POS, ptp_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, ptp_unit.wait, 24), PV_LEFT }, - { FLDATA (STOP_IOE, ptp_stopioe, 0) }, - { NULL } }; - -MTAB ptp_mod[] = { - { MTAB_XTD|MTAB_VDV, 0, "DEVNO", NULL, NULL, &show_devno }, - { 0 } }; - -DEVICE ptp_dev = { - "PTP", &ptp_unit, ptp_reg, ptp_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &ptp_reset, - NULL, &ptp_attach, &ptp_detach, - &ptp_dib, 0 }; - -/* TTI data structures - - tti_dev TTI device descriptor - tti_unit TTI unit - tti_reg TTI register list - tti_trans ASCII to Baudot table -*/ - -#if defined (KSR28) -#define TTI_WIDTH 5 -#define TTI_FIGURES (1 << TTI_WIDTH) -#define TTI_2ND (1 << (TTI_WIDTH + 1)) -#define TTI_BOTH (1 << (TTI_WIDTH + 2)) -#define BAUDOT_LETTERS 033 -#define BAUDOT_FIGURES 037 - -static const int32 tti_trans[128] = { - 000,000,000,000,000,000,000,064, /* bell */ - 000,000,0210,000,000,0202,000,000, /* lf, cr */ - 000,000,000,000,000,000,000,000, - 000,000,000,000,000,000,000,000, - 0204,066,061,045,062,000,053,072, /* space - ' */ - 076,051,000,000,046,070,047,067, /* ( - / */ - 055,075,071,060,052,041,065,074, /* 0 - 7 */ - 054,043,056,057,000,000,000,063, /* 8 - ? */ - 000,030,023,016,022,020,026,013, /* @ - G */ - 005,014,032,036,011,007,006,003, /* H - O */ - 015,035,012,024,001,034,017,031, /* P - W */ - 027,025,021,000,000,000,000,000, /* X - _ */ - 000,030,023,016,022,020,026,013, /* ` - g */ - 005,014,032,036,011,007,006,003, /* h - o */ - 015,035,012,024,001,034,017,031, /* p - w */ - 027,025,021,000,000,000,000,000 }; /* x - DEL */ -#else - -#define TTI_WIDTH 8 -#endif - -#define TTI_MASK ((1 << TTI_WIDTH) - 1) -#define UNIT_V_8B (UNIT_V_UF + 0) /* 8B */ -#define UNIT_V_KSR (UNIT_V_UF + 1) /* KSR33 */ -#define UNIT_V_HDX (UNIT_V_UF + 2) /* half duplex */ -#define UNIT_8B (1 << UNIT_V_8B) -#define UNIT_KSR (1 << UNIT_V_KSR) -#define UNIT_HDX (1 << UNIT_V_HDX) - -DIB tti_dib = { DEV_TTI, 1, &tti_iors, { &tti } }; - -#if defined (PDP4) || defined (PDP7) -UNIT tti_unit = { UDATA (&tti_svc, UNIT_KSR, 0), KBD_POLL_WAIT }; -#else -UNIT tti_unit = { UDATA (&tti_svc, UNIT_KSR+UNIT_HDX, 0), KBD_POLL_WAIT }; -#endif - -REG tti_reg[] = { - { ORDATA (BUF, tti_unit.buf, TTI_WIDTH) }, - { FLDATA (INT, int_hwre[API_TTI], INT_V_TTI) }, - { FLDATA (DONE, int_hwre[API_TTI], INT_V_TTI) }, -#if defined (KSR28) - { ORDATA (TTI_STATE, tti_state, (TTI_WIDTH + 3)), REG_HRO }, -#endif - { DRDATA (POS, tti_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, tti_unit.wait, 24), REG_NZ + PV_LEFT }, - { NULL } }; - -MTAB tti_mod[] = { -#if !defined (KSR28) - { UNIT_KSR+UNIT_8B, UNIT_KSR, "KSR", "KSR", &tty_set_mode }, - { UNIT_KSR+UNIT_8B, 0 , "7b" , "7B" , &tty_set_mode }, - { UNIT_KSR+UNIT_8B, UNIT_8B , "8b" , "8B" , &tty_set_mode }, - { UNIT_HDX, 0 , "full duplex", "FDX", NULL }, - { UNIT_HDX, UNIT_HDX, "half duplex", "HDX", NULL }, - { MTAB_XTD|MTAB_VDV|MTAB_VUN, 0, NULL, "CTRL-C", &tti_set_ctrlc, NULL, NULL }, -#endif - { MTAB_XTD|MTAB_VDV, 0, "DEVNO", NULL, NULL, &show_devno, NULL }, - { 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 - tto_trans Baudot to ASCII table -*/ - -#if defined (KSR28) -#define TTO_WIDTH 5 -#define TTO_FIGURES (1 << TTO_WIDTH) - -static const char tto_trans[64] = { - 0 ,'T',015,'O',' ','H','N','M', - 012,'L','R','G','I','P','C','V', - 'E','Z','D','B','S','Y','F','X', - 'A','W','J', 0 ,'U','Q','K', 0, - 0 ,'5','\r','9',' ','#',',','.', - 012,')','4','&','8','0',':',';', - '3','"','$','?','\a','6','!','/', - '-','2','\'',0 ,'7','1','(', 0 }; -#else - -#define TTO_WIDTH 8 -#endif - -#define TTO_MASK ((1 << TTO_WIDTH) - 1) - -DIB tto_dib = { DEV_TTO, 1, &tto_iors, { &tto } }; - -UNIT tto_unit = { UDATA (&tto_svc, UNIT_KSR, 0), 1000 }; - -REG tto_reg[] = { - { ORDATA (BUF, tto_unit.buf, TTO_WIDTH) }, - { FLDATA (INT, int_hwre[API_TTO], INT_V_TTO) }, - { FLDATA (DONE, int_hwre[API_TTO], INT_V_TTO) }, -#if defined (KSR28) - { FLDATA (TTO_STATE, tto_state, 0), REG_HRO }, -#endif - { DRDATA (POS, tto_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, tto_unit.wait, 24), PV_LEFT }, - { NULL } }; - -MTAB tto_mod[] = { -#if !defined (KSR28) - { UNIT_KSR+UNIT_8B, UNIT_KSR, "KSR", "KSR", &tty_set_mode }, - { UNIT_KSR+UNIT_8B, 0 , "7b" , "7B" , &tty_set_mode }, - { UNIT_KSR+UNIT_8B, UNIT_8B , "8b" , "8B" , &tty_set_mode }, -#endif - { MTAB_XTD|MTAB_VDV, 0, "DEVNO", NULL, NULL, &show_devno }, - { 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 }; - -/* Clock: IOT routine */ - -int32 clk (int32 pulse, int32 dat) -{ -if (pulse & 001) { /* CLSF */ - if (TST_INT (CLK)) dat = dat | 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)); } - else clk_reset (&clk_dev); } /* CLOF */ -return dat; -} - -/* Unit service */ - -t_stat clk_svc (UNIT *uptr) -{ -int32 t; - -if (clk_state) { /* clock on? */ - M[7] = (M[7] + 1) & DMASK; /* incr counter */ - if (M[7] == 0) SET_INT (CLK); /* ovrflo? set flag */ - t = sim_rtc_calb (clk_tps); /* calibrate clock */ - sim_activate (&clk_unit, t); /* reactivate unit */ - tmxr_poll = t; } /* set mux poll */ -return SCPE_OK; -} - -/* IORS service */ - -int32 clk_iors (void) -{ -return (TST_INT (CLK)? IOS_CLK: 0); -} - -/* Reset routine */ - -t_stat clk_reset (DEVICE *dptr) -{ -CLR_INT (CLK); /* clear flag */ -clk_state = 0; /* clock off */ -sim_cancel (&clk_unit); /* stop clock */ -tmxr_poll = clk_unit.wait; /* set mux poll */ -return SCPE_OK; -} - -/* Set frequency */ - -t_stat clk_set_freq (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -if (cptr) return SCPE_ARG; -if ((val != 50) && (val != 60)) return SCPE_IERR; -clk_tps = val; -return SCPE_OK; -} - -/* Show frequency */ - -t_stat clk_show_freq (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -fprintf (st, (clk_tps == 50)? "50Hz": "60Hz"); -return SCPE_OK; -} - -/* Paper tape reader: IOT routine */ - -int32 ptr (int32 pulse, int32 dat) -{ -if (pulse & 001) { /* RSF */ - if (TST_INT (PTR)) dat = dat | IOT_SKP; } -if (pulse & 002) { /* RRB, RCF */ - CLR_INT (PTR); /* clear done */ - dat = dat | ptr_unit.buf; } /* return buffer */ -if (pulse & 004) { /* RSA, RSB */ - ptr_state = (pulse & 040)? 18: 0; /* set mode */ - CLR_INT (PTR); /* clear done */ - ptr_unit.buf = 0; /* clear buffer */ - sim_activate (&ptr_unit, ptr_unit.wait); } -return dat; -} - -/* Unit service */ - -t_stat ptr_svc (UNIT *uptr) -{ -int32 temp; - -if ((ptr_unit.flags & UNIT_ATT) == 0) { /* attached? */ -#if defined (IOS_PTRERR) - SET_INT (PTR); /* if err, set int */ - ptr_err = 1; -#endif - return IORETURN (ptr_stopioe, SCPE_UNATT); } -if ((temp = getc (ptr_unit.fileref)) == EOF) { /* end of file? */ -#if defined (IOS_PTRERR) - SET_INT (PTR); /* if err, set done */ - ptr_err = 1; -#endif - 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; } -if (ptr_state == 0) { /* ASCII */ - if (ptr_unit.flags & UNIT_RASCII) { /* want parity? */ - ptr_unit.buf = temp = temp & 0177; /* parity off */ - while (temp = temp & (temp - 1)) - ptr_unit.buf = ptr_unit.buf ^ 0200; /* count bits */ - ptr_unit.buf = ptr_unit.buf ^ 0200; } /* set even parity */ - else ptr_unit.buf = temp & 0377; } -else if (temp & 0200) { /* binary */ - ptr_state = ptr_state - 6; - ptr_unit.buf = ptr_unit.buf | ((temp & 077) << ptr_state); } -if (ptr_state == 0) SET_INT (PTR); /* if done, set flag */ -else sim_activate (&ptr_unit, ptr_unit.wait); /* else restart */ -ptr_unit.pos = ptr_unit.pos + 1; -return SCPE_OK; -} - -/* Reset routine */ - -t_stat ptr_reset (DEVICE *dptr) -{ -ptr_state = 0; /* clear state */ -ptr_unit.buf = 0; -CLR_INT (PTR); /* clear flag */ -ptr_err = (ptr_unit.flags & UNIT_ATT)? 0: 1; -sim_cancel (&ptr_unit); /* deactivate unit */ -return SCPE_OK; -} - -/* IORS service */ - -int32 ptr_iors (void) -{ -return ((TST_INT (PTR)? IOS_PTR: 0) -#if defined (IOS_PTRERR) - | (ptr_err? IOS_PTRERR: 0) -#endif - ); -} - -/* Attach routine */ - -t_stat ptr_attach (UNIT *uptr, char *cptr) -{ -t_stat reason; - -reason = attach_unit (uptr, cptr); -ptr_err = (ptr_unit.flags & UNIT_ATT)? 0: 1; -ptr_unit.flags = ptr_unit.flags & ~UNIT_RASCII; -if (sim_switches & SWMASK ('A')) - ptr_unit.flags = ptr_unit.flags | UNIT_RASCII; -return reason; -} - -/* Detach routine */ - -t_stat ptr_detach (UNIT *uptr) -{ -ptr_err = 1; -ptr_unit.flags = ptr_unit.flags & ~UNIT_RASCII; -return detach_unit (uptr); -} - -/* Hardware RIM loader routines, PDP-7/9/15 */ - -int32 ptr_getw (FILE *fileref, int32 *hi) -{ -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++; } } -while (st < 3); -if (hi != NULL) *hi = bits; -return word; -} - -t_stat ptr_rim_load (FILE *fileref, int32 origin) -{ -int32 bits, val; - -for (;;) { /* word loop */ - if ((val = ptr_getw (fileref, &bits)) < 0) return SCPE_FMT; - if (bits & 1) { /* end of tape? */ - if ((val & 0760000) == OP_JMP) { - PC = ((origin - 1) & 060000) | (val & 017777); - return SCPE_OK; } - else if (val == OP_HLT) return STOP_HALT; - break; } - else if (MEM_ADDR_OK (origin)) M[origin++] = val; } -return SCPE_FMT; -} - -#if defined (PDP4) || defined (PDP7) - -/* Bootstrap routine, PDP-4 and PDP-7 - - In a 4K system, the boostrap resides at 7762-7776. - In an 8K or greater system, the bootstrap resides at 17762-17776. - Because the program is so small, simple masking can be - used to remove addr<5> for a 4K system. */ - -#define BOOT_START 017577 -#define BOOT_FPC 017577 /* funny format loader */ -#define BOOT_RPC 017770 /* RIM loader */ -#define BOOT_LEN (sizeof (boot_rom) / sizeof (int)) - -static const int32 boot_rom[] = { - 0700144, /* rsb */ - 0117762, /* ff, jsb r1b */ - 0057666, /* dac done 1 */ - 0117762, /* jms r1b */ - 0057667, /* dac done 2 */ - 0117762, /* jms r1b */ - 0040007, /* dac conend */ - 0057731, /* dac conbeg */ - 0440007, /* isz conend */ - 0117762, /* blk, jms r1b */ - 0057673, /* dac cai */ - 0741100, /* spa */ - 0617665, /* jmp done */ - 0117762, /* jms r1b */ - 0057777, /* dac tem1 */ - 0317673, /* add cai */ - 0057775, /* dac cks */ - 0117713, /* jms r1a */ - 0140010, /* dzm word */ - 0457777, /* cont, isz tem1 */ - 0617632, /* jmp cont1 */ - 0217775, /* lac cks */ - 0740001, /* cma */ - 0740200, /* sza */ - 0740040, /* hlt */ - 0700144, /* rsb */ - 0617610, /* jmp blk */ - 0117713, /* cont1, jms r1a */ - 0057762, /* dac tem2 */ - 0117713, /* jms r1a */ - 0742010, /* rtl */ - 0742010, /* rtl */ - 0742010, /* rtl */ - 0742010, /* rtl */ - 0317762, /* add tem2 */ - 0057762, /* dac tem2 */ - 0117713, /* jms r1a */ - 0742020, /* rtr */ - 0317726, /* add cdsp */ - 0057713, /* dac r1a */ - 0517701, /* and ccma */ - 0740020, /* rar */ - 0317762, /* add tem2 */ - 0437713, /* xct i r1a */ - 0617622, /* jmp cont */ - 0617672, /* dsptch, jmp code0 */ - 0617670, /* jmp code1 */ - 0617700, /* jmp code2 */ - 0617706, /* jmp code3 */ - 0417711, /* xct code4 */ - 0617732, /* jmp const */ - 0740000, /* nop */ - 0740000, /* nop */ - 0740000, /* nop */ - 0200007, /* done, lac conend */ - 0740040, /* xx */ - 0740040, /* xx */ - 0517727, /* code1, and imsk */ - 0337762, /* add i tem2 */ - 0300010, /* code0, add word */ - 0740040, /* cai, xx */ - 0750001, /* clc */ - 0357673, /* tad cai */ - 0057673, /* dac cai */ - 0617621, /* jmp cont-1 */ - 0711101, /* code2, spa cla */ - 0740001, /* ccma, cma */ - 0277762, /* xor i tem2 */ - 0300010, /* add word */ - 0040010, /* code2a, dac word */ - 0617622, /* jmp cont */ - 0057711, /* code3, dac code4 */ - 0217673, /* lac cai */ - 0357701, /* tad ccma */ - 0740040, /* code4, xx */ - 0617622, /* jmp cont */ - 0000000, /* r1a, 0 */ - 0700101, /* rsf */ - 0617714, /* jmp .-1 */ - 0700112, /* rrb */ - 0700104, /* rsa */ - 0057730, /* dac tem */ - 0317775, /* add cks */ - 0057775, /* dac cks */ - 0217730, /* lac tem */ - 0744000, /* cll */ - 0637713, /* jmp i r1a */ - 0017654, /* cdsp, dsptch */ - 0760000, /* imsk, 760000 */ - 0000000, /* tem, 0 */ - 0000000, /* conbeg, 0 */ - 0300010, /* const, add word */ - 0060007, /* dac i conend */ - 0217731, /* lac conbeg */ - 0040010, /* dac index */ - 0220007, /* lac i conend */ - 0560010, /* con1, sad i index */ - 0617752, /* jmp find */ - 0560010, /* sad i index */ - 0617752, /* jmp find */ - 0560010, /* sad i index */ - 0617752, /* jmp find */ - 0560010, /* sad i index */ - 0617752, /* jmp find */ - 0560010, /* sad i index */ - 0617752, /* jmp find */ - 0617737, /* jmp con1 */ - 0200010, /* find, lac index */ - 0540007, /* sad conend */ - 0440007, /* isz conend */ - 0617704, /* jmp code2a */ - 0000000, - 0000000, - 0000000, - 0000000, - 0000000, /* r1b, 0 */ - 0700101, /* rsf */ - 0617763, /* jmp .-1 */ - 0700112, /* rrb */ - 0700144, /* rsb */ - 0637762, /* jmp i r1b */ - 0700144, /* go, rsb */ - 0117762, /* g, jms r1b */ - 0057775, /* dac cks */ - 0417775, /* xct cks */ - 0117762, /* jms r1b */ - 0000000, /* cks, 0 */ - 0617771 /* jmp g */ -}; - -t_stat ptr_boot (int32 unitno, DEVICE *dptr) -{ -int32 i, mask, wd; -extern int32 sim_switches; - -#if defined (PDP7) -if (sim_switches & SWMASK ('H')) /* hardware RIM load? */ - return ptr_rim_load (ptr_unit.fileref, ASW); -#endif -if (ptr_dib.dev != DEV_PTR) return STOP_NONSTD; /* non-std addr? */ -if (MEMSIZE < 8192) mask = 0767777; /* 4k? */ -else mask = 0777777; -for (i = 0; i < BOOT_LEN; i++) { - wd = boot_rom[i]; - if ((wd >= 0040000) && (wd < 0640000)) wd = wd & mask; - M[(BOOT_START & mask) + i] = wd; } -PC = ((sim_switches & SWMASK ('F'))? BOOT_FPC: BOOT_RPC) & mask; -return SCPE_OK; -} - -#else - -/* PDP-9 and PDP-15 have built-in hardware RIM loaders */ - -t_stat ptr_boot (int32 unitno, DEVICE *dptr) -{ -return ptr_rim_load (ptr_unit.fileref, ASW); -} - -#endif - -/* Paper tape punch: IOT routine */ - -int32 ptp (int32 pulse, int32 dat) -{ -if (pulse & 001) { /* PSF */ - if (TST_INT (PTP)) dat = dat | IOT_SKP; } -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 */ - (dat & 077) | 0200: dat & 0377; /* bin or alpha */ - sim_activate (&ptp_unit, ptp_unit.wait); } /* activate unit */ -return dat; -} - -/* Unit service */ - -t_stat ptp_svc (UNIT *uptr) -{ -SET_INT (PTP); /* set done flag */ -if ((ptp_unit.flags & UNIT_ATT) == 0) { /* not attached? */ - ptp_err = 1; /* set error */ - return IORETURN (ptp_stopioe, SCPE_UNATT); } -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 */ -if (putc (ptp_unit.buf, ptp_unit.fileref) == EOF) { /* I/O error? */ - ptp_err = 1; /* set error */ - perror ("PTP I/O error"); - clearerr (ptp_unit.fileref); - return SCPE_IOERR; } -ptp_unit.pos = ptp_unit.pos + 1; -return SCPE_OK; -} - -/* IORS service */ - -int32 ptp_iors (void) -{ -return ((TST_INT (PTP)? IOS_PTP: 0) -#if defined (IOS_PTPERR) - | (ptp_err? IOS_PTPERR: 0) -#endif - ); -} - -/* Reset routine */ - -t_stat ptp_reset (DEVICE *dptr) -{ -ptp_unit.buf = 0; -CLR_INT (PTP); /* clear flag */ -ptp_err = (ptp_unit.flags & UNIT_ATT)? 0: 1; -sim_cancel (&ptp_unit); /* deactivate unit */ -return SCPE_OK; -} - -/* Attach routine */ - -t_stat ptp_attach (UNIT *uptr, char *cptr) -{ -t_stat reason; - -reason = attach_unit (uptr, cptr); -ptp_err = (ptp_unit.flags & UNIT_ATT)? 0: 1; -ptp_unit.flags = ptp_unit.flags & ~UNIT_PASCII; -if (sim_switches & SWMASK ('A')) - ptp_unit.flags = ptp_unit.flags | UNIT_PASCII; -return reason; -} - -/* Detach routine */ - -t_stat ptp_detach (UNIT *uptr) -{ -ptp_err = 1; -ptp_unit.flags = ptp_unit.flags & ~UNIT_PASCII; -return detach_unit (uptr); -} - -/* Terminal input: IOT routine */ - -int32 tti (int32 pulse, int32 dat) -{ -if (pulse & 001) { /* KSF */ - if (TST_INT (TTI)) dat = dat | IOT_SKP; } -if (pulse & 002) { /* KRB */ - CLR_INT (TTI); /* clear flag */ - dat = dat | tti_unit.buf & TTI_MASK; } /* return buffer */ -if (pulse & 004) { /* IORS */ - dat = dat | upd_iors (); } -return dat; -} - -/* Unit service */ - -t_stat tti_svc (UNIT *uptr) -{ -#if defined (KSR28) /* Baudot... */ -int32 c; - -sim_activate (&tti_unit, tti_unit.wait); /* continue poll */ -if (tti_state & TTI_2ND) { /* char waiting? */ - tti_unit.buf = tti_state & TTI_MASK; /* return char */ - tti_state = tti_state & ~TTI_2ND; } /* not waiting */ -else { if ((c = sim_poll_kbd ()) < SCPE_KFLAG) return c; - c = tti_trans[c & 0177]; /* translate char */ - 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 /* ASCII... */ -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 (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) && out && /* half duplex and */ - (!(tto_unit.flags & UNIT_KSR) || /* 7b/8b or */ - ((out >= 007) && (out <= 0137)))) { /* in range? */ - sim_putchar (out); /* echo */ - tto_unit.pos = tto_unit.pos + 1; } -tti_unit.buf = c; /* got char */ - -#endif -tti_unit.pos = tti_unit.pos + 1; -SET_INT (TTI); /* set flag */ -return SCPE_OK; -} - -/* IORS service */ - -int32 tti_iors (void) -{ -return (TST_INT (TTI)? IOS_TTI: 0); -} - -/* Reset routine */ - -t_stat tti_reset (DEVICE *dptr) -{ -tti_unit.buf = 0; /* clear buffer */ -tti_state = 0; /* clear state */ -CLR_INT (TTI); /* clear flag */ -sim_activate (&tti_unit, tti_unit.wait); /* activate unit */ -return SCPE_OK; -} - -/* Set control-C */ - -t_stat tti_set_ctrlc (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -if (cptr) return SCPE_ARG; -uptr->buf = (uptr->flags & UNIT_KSR)? 0203: 0003; -uptr->pos = uptr->pos + 1; -SET_INT (TTI); -return SCPE_OK; -} - -/* Terminal output: IOT routine */ - -int32 tto (int32 pulse, int32 dat) -{ -if (pulse & 001) { /* TSF */ - if (TST_INT (TTO)) dat = dat | IOT_SKP; } -if (pulse & 002) CLR_INT (TTO); /* clear flag */ -if (pulse & 004) { /* load buffer */ - sim_activate (&tto_unit, tto_unit.wait); /* activate unit */ - tto_unit.buf = dat & TTO_MASK; } /* load buffer */ -return dat; -} - -/* Unit service */ - -t_stat tto_svc (UNIT *uptr) -{ -int32 c; -t_stat r; - -SET_INT (TTO); /* set flag */ -#if defined (KSR28) /* Baudot... */ -if (tto_unit.buf == BAUDOT_FIGURES) { /* set figures? */ - tto_state = TTO_FIGURES; - return SCPE_OK; } -if (tto_unit.buf == BAUDOT_LETTERS) { /* set letters? */ - tto_state = 0; - return SCPE_OK; } -c = tto_trans[tto_unit.buf + tto_state]; /* translate */ -#else -if (tto_unit.flags & UNIT_KSR) { /* KSR? */ - c = tto_unit.buf & 0177; - if (islower (c)) c = toupper (c); - if ((c < 007) || (c > 0137)) return SCPE_OK; } -else c = tto_unit.buf & ((tto_unit.flags & UNIT_8B)? 0377: 0177); -#endif -if ((r = sim_putchar (c)) != SCPE_OK) return r; -tto_unit.pos = tto_unit.pos + 1; -return SCPE_OK; -} - -/* IORS service */ - -int32 tto_iors (void) -{ -return (TST_INT (TTO)? IOS_TTO: 0); -} - -/* Reset routine */ - -t_stat tto_reset (DEVICE *dptr) -{ -tto_unit.buf = 0; /* clear buffer */ -tto_state = 0; /* clear state */ -CLR_INT (TTO); /* clear flag */ -sim_cancel (&tto_unit); /* deactivate unit */ -return SCPE_OK; -} - -/* Set mode */ - -t_stat tty_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -tti_unit.flags = (tti_unit.flags & ~(UNIT_KSR | UNIT_8B)) | val; -tto_unit.flags = (tto_unit.flags & ~(UNIT_KSR | UNIT_8B)) | val; -return SCPE_OK; -} diff --git a/PDP18B/pdp18b_sys.c b/PDP18B/pdp18b_sys.c deleted file mode 100644 index 583de1b0..00000000 --- a/PDP18B/pdp18b_sys.c +++ /dev/null @@ -1,1119 +0,0 @@ -/* pdp18b_sys.c: 18b PDP's simulator interface - - 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. - - 30-Jul-03 RMS Fixed FPM class mask - 18-Jul-03 RMS Added FP15 support - 02-Mar-03 RMS Split loaders apart for greater flexibility - 09-Feb-03 RMS Fixed bug in FMTASC (found by Hans Pufal) - 31-Jan-03 RMS Added support for RB09 - 05-Oct-02 RMS Added variable device number support - 25-Jul-02 RMS Added PDP-4 DECtape support - 10-Feb-02 RMS Added PDP-7 DECtape IOT's - 03-Feb-02 RMS Fixed typo (found by Robert Alan Byer) - 17-Sep-01 RMS Removed multiconsole support - 27-May-01 RMS Added second Teletype support - 18-May-01 RMS Added PDP-9,-15 API IOT's - 12-May-01 RMS Fixed bug in RIM loaders - 14-Mar-01 RMS Added extension detection of RIM format tapes - 21-Jan-01 RMS Added DECtape support - 30-Nov-00 RMS Added PDP-9,-15 RIM/BIN loader format - 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 "pdp18b_defs.h" -#include - -extern DEVICE cpu_dev; -#if defined (PDP15) -extern DEVICE fpp_dev; -#endif -extern DEVICE ptr_dev, ptp_dev; -extern DEVICE tti_dev, tto_dev; -extern UNIT tti_unit, tto_unit; -extern DEVICE clk_dev; -#if defined (TYPE62) -extern DEVICE lp62_dev; -#endif -#if defined (TYPE647) -extern DEVICE lp647_dev; -#endif -#if defined (LP09) -extern DEVICE lp09_dev; -#endif -#if defined (LP15) -extern DEVICE lp15_dev; -#endif -extern DEVICE dt_dev; -#if defined (DRM) -extern DEVICE drm_dev; -#endif -#if defined (RB) -extern DEVICE rb_dev; -#endif -#if defined (RF) -extern DEVICE rf_dev; -#endif -#if defined (RP) -extern DEVICE rp_dev; -#endif -#if defined (MTA) -extern DEVICE mt_dev; -#endif -#if defined (TTY1) -extern DEVICE tti1_dev, tto1_dev; -extern UNIT tti1_unit, tto1_unit; -#endif -extern UNIT cpu_unit; -extern REG cpu_reg[]; -extern int32 M[]; -extern int32 memm; -extern int32 PC; - -/* 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 -*/ - -#if defined (PDP4) -char sim_name[] = "PDP-4"; -#elif defined (PDP7) -char sim_name[] = "PDP-7"; -#elif defined (PDP9) -char sim_name[] = "PDP-9"; -#elif defined (PDP15) -char sim_name[] = "PDP-15"; -#endif - -REG *sim_PC = &cpu_reg[0]; - -int32 sim_emax = 2; - -DEVICE *sim_devices[] = { - &cpu_dev, -#if defined (PDP15) - &fpp_dev, -#endif - &ptr_dev, - &ptp_dev, - &tti_dev, - &tto_dev, - &clk_dev, -#if defined (TYPE62) - &lp62_dev, -#endif -#if defined (TYPE647) - &lp647_dev, -#endif -#if defined (LP09) - &lp09_dev, -#endif -#if defined (LP15) - &lp15_dev, -#endif -#if defined (DRM) - &drm_dev, -#endif -#if defined (RB) - &rb_dev, -#endif -#if defined (RF) - &rf_dev, -#endif -#if defined (RP) - &rp_dev, -#endif - &dt_dev, -#if defined (MTA) - &mt_dev, -#endif -#if defined (TTY1) - &tti1_dev, &tto1_dev, -#endif - NULL }; - -const char *sim_stop_messages[] = { - "Unknown error", - "Undefined instruction", - "HALT instruction", - "Breakpoint", - "Nested XCT's", - "Invalid API interrupt", - "Non-standard device number", - "Memory management error", - "FP15 instruction disabled" }; - -/* Binary loaders */ - -int32 getword (FILE *fileref, int32 *hi) -{ -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++; } } -while (st < 3); -if (hi != NULL) *hi = bits; -return word; -} - -/* PDP-4/PDP-7 RIM format loader - - Tape format - dac addr - data - : - dac addr - data - jmp addr or hlt -*/ - -t_stat rim_load_47 (FILE *fileref, char *cptr) -{ -int32 origin, val; - -if (*cptr != 0) return SCPE_2MARG; -origin = 0200; -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; } - else if ((val & 0760000) == OP_JMP) { /* JMP? */ - 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 */ -} - -/* PDP-9/15 RIM format loader - - Tape format (read in address specified externally) - data - : - data - word to execute (bit 1 of last character set) -*/ - -t_stat rim_load_915 (FILE *fileref, char *cptr) -{ -int32 bits, origin, val; -char gbuf[CBUFSIZE]; -t_stat r; - -if (*cptr != 0) { /* more input? */ - cptr = get_glyph (cptr, gbuf, 0); /* get origin */ - origin = get_uint (gbuf, 8, AMASK, &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) 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; -} - -/* PDP-9/15 BIN format loader - - BIN format (starts after RIM bootstrap) - block/ origin (>= 0) - count - checksum - data - : - data - block/ - : - endblock/ origin (< 0) -*/ - -t_stat bin_load_915 (FILE *fileref, char *cptr) -{ -int32 i, val, bits, origin, count, cksum; - -if (*cptr != 0) return SCPE_2MARG; /* no arguments */ -do { val = getword (fileref, & bits); } /* find end RIM */ -while ((val >= 0) && ((bits & 1) == 0)); -if (val < 0) rewind (fileref); /* no RIM? rewind */ -for (;;) { /* block loop */ - if ((val = getword (fileref, NULL)) < 0) return SCPE_FMT; - if (val & SIGN) { - if (val != DMASK) PC = val & 077777; - break; } - cksum = origin = val; /* save origin */ - if ((val = getword (fileref, NULL)) < 0) return SCPE_FMT; - cksum = cksum + val; /* add to cksum */ - count = (-val) & DMASK; /* save count */ - 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 ((cksum & DMASK) != 0) return SCPE_CSUM; } -return SCPE_OK; -} - -#if defined (PDP4) || defined (PDP7) - -/* PDP-4/PDP-7: RIM format only */ - -t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag) -{ -if (flag != 0) return SCPE_NOFNC; -return rim_load_47 (fileref, cptr); -} - -#else - -/* PDP-9/PDP-15: all formats */ - -t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag) -{ -extern int32 sim_switches; - -if (flag != 0) return SCPE_NOFNC; -if (sim_switches & SWMASK ('S')) /* PDP-4/7 format? */ - return rim_load_47 (fileref, cptr); -if ((sim_switches & SWMASK ('R')) || /* RIM format? */ - (match_ext (fnam, "RIM") && !(sim_switches & SWMASK ('B')))) - return rim_load_915 (fileref, cptr); -return bin_load_915 (fileref, cptr); /* must be BIN */ -} - -#endif - -/* Symbol tables */ - -#define I_V_FL 18 /* inst class */ -#define I_M_FL 017 /* class mask */ -#define I_V_DC 22 /* default count */ -#define I_V_NPN 0 /* no operand */ -#define I_V_NPI 1 /* no operand IOT */ -#define I_V_IOT 2 /* IOT */ -#define I_V_MRF 3 /* memory reference */ -#define I_V_OPR 4 /* OPR */ -#define I_V_LAW 5 /* LAW */ -#define I_V_XR 6 /* index */ -#define I_V_XR9 7 /* index literal */ -#define I_V_EST 8 /* EAE setup */ -#define I_V_ESH 9 /* EAE shift */ -#define I_V_EMD 10 /* EAE mul-div */ -#define I_V_FPM 11 /* FP15 mem ref */ -#define I_V_FPI 12 /* FP15 indirect */ -#define I_V_FPN 13 /* FP15 no operand */ -#define I_NPN (I_V_NPN << I_V_FL) -#define I_NPI (I_V_NPI << I_V_FL) -#define I_IOT (I_V_IOT << I_V_FL) -#define I_MRF (I_V_MRF << I_V_FL) -#define I_OPR (I_V_OPR << I_V_FL) -#define I_LAW (I_V_LAW << I_V_FL) -#define I_XR (I_V_XR << I_V_FL) -#define I_XR9 (I_V_XR9 << I_V_FL) -#define I_EST (I_V_EST << I_V_FL) -#define I_ESH (I_V_ESH << I_V_FL) -#define I_EMD (I_V_EMD << I_V_FL) -#define I_FPM (I_V_FPM << I_V_FL) -#define I_FPI (I_V_FPI << I_V_FL) -#define I_FPN (I_V_FPN << I_V_FL) -#define MD(x) ((I_EMD) + ((x) << I_V_DC)) - -static const int32 masks[] = { - 0777777, 0777767, 0770000, 0760000, - 0763730, 0760000, 0777000, 0777000, - 0740700, 0760700, 0777700, 0777777, - 0777777, 0777777 }; - -static const char *opcode[] = { - "CAL", "DAC", "JMS", "DZM", /* mem refs */ - "LAC", "XOR", "ADD", "TAD", - "XCT", "ISZ", "AND", "SAD", - "JMP", - -#if defined (PDP9) || defined (PDP15) /* mem ref ind */ - "CAL*", "DAC*", "JMS*", "DZM*", /* normal */ - "LAC*", "XOR*", "ADD*", "TAD*", - "XCT*", "ISZ*", "AND*", "SAD*", - "JMP*", -#else - "CAL I", "DAC I", "JMS I", "DZM I", /* decode only */ - "LAC I", "XOR I", "ADD I", "TAD I", - "XCT I", "ISZ I", "AND I", "SAD I", - "JMP I", -#endif - - "LAW", /* LAW */ - - "LACQ", "LACS", "ABS", "GSM", "LMQ", /* EAE */ - "MUL", "MULS", "DIV", "DIVS", - "IDIV", "IDIVS", "FRDIV", "FRDIVS", - "NORM", "NORMS", - "MUY", "LLK MUY", "DVI", "LLK DVI", - "NMI", "NMIS", "LRS", "LRSS", - "LLS", "LLSS", "ALS", "ALSS", - "EAE-setup", "EAE", /* setup, general */ - - "CLSF", "IOF", "ION", "CLOF", "CLON", /* standard IO devs */ - "RSF", "RRB", "RCF", "RSA", "RSB", - "PSF", "PCF", "PSA", "PSB", "PLS", - "KSF", "KRB", "KCF", "IORS", "IOOS", - "TSF", "TCF", "TPC", "TLS", -#if defined (TYPE62) /* Type 62 */ - "LPSF", "LPCF", "LPLD", "LPSE", - "LSSF", "LSCF", "LSPR", -#endif -#if defined (TYPE647) /* Type 647 */ - "LPSF", "LPCB", "LPCD", "LPCD", "LPCD", - "LPL2", "LPLD", "LPL1", - "LPEF", "LPCF", "LPCF", "LPCF", "LPCF", - "LPPB", "LPLS", "LPPS", -#endif -#if defined (LP09) - "LSDF", "LSEF", "LSCF", "LPLD", - "LIOF", "LION", -#endif -#if defined (LP15) /* LP15 */ - "LPSF", "LPPM", "LPP1", "LPDI", - "LPRS", "LPOS", "LPEI", "LPCD", "LPCF", -#endif -#if defined (DRM) /* drum */ - "DRLR", "DRLW", "DRSS", "DRCS", - "DRSF", "DRSN", "DRCF", - "DRLCRD", "DRLCWR", "DRLBLK", "DRCONT", - "DRSF", "DRSOK", "DRCF", -#endif -#if defined (RB) /* RB09 */ - "DBCF", "DBRD", "DBLD", - "DBSF", "DBRS", "DBLW", - "DBCS", "DBLM", "DBLS", -#endif -#if defined (RF) /* RF09 */ - "DSSF", "DSCC", "DSCF", - "DRBR", "DRAL", "DSFX", "DRAH", - "DLBR", "DLAL", "DSCN", "DLAH", - "DLOK", "DSCD", "DSRS", - "DGHS", "DGSS", -#endif -#if defined (RP) - "DPSF", "DPSA", "DPSJ", "DPSE", - "DPRSA", "DPOSA", "DPRSB", "DPOSB", - "DPRM", "DPOM", - "DPLA", "DPCS", "DPCA", "DPWC", - "DPLM", "DPEM", "DPSN", - "DPRU", "DPOU", "DPRA", "DPOA", - "DPRC", "DPOC", "DPRW", "DPOW", - "DPCF", "DPLZ", "DPCN", "DPLO", "DPLF", -#endif -#if defined (MTA) /* TC59 */ - "MTTR", "MTCR", "MTSF", "MTRC", "MTAF", - "MTRS", "MTGO", "MTCM", "MTLC", -#endif -#if defined (TYPE550) /* Type 550 */ - "MMDF", "MMEF", "MMRD", "MMWR", - "MMBF", "MMRS", "MMLC", "MMSE", -#elif defined (TC02) /* TC02/TC15 */ - "DTCA", "DTRA", "DTXA", "DTLA", - "DTEF", "DTRB", "DTDF", -#endif -#if defined (TTY1) - "KSF1", "KRB1", - "TSF1", "TCF1", "TLS1", "TCF1!TLS1", -#endif -#if defined (PDP7) - "ITON", "TTS", "SKP7", "CAF", - "SEM", "EEM", "EMIR", "LEM", -#endif -#if defined (PDP9) - "SKP7", "SEM", "EEM", "LEM", - "LPDI", "LPEI", -#endif -#if defined (PDP15) - "SPCO", "SKP15", "RES", - "SBA", "DBA", "EBA", - "ORMM", "RDMM", "LDMM", "MPLR", - "ENB", "INH", "MPRC", "IPFH", - "AAS", "PAX", "PAL", "AAC", - "PXA", "AXS", "PXL", "PLA", - "PLX", "CLAC","CLX", "CLLR", "AXR", - - "FPT", /* FP15 */ - "ISB", "ESB", /* mem ref */ - "FSB", "URFSB", "UNFSB", "UUFSB", - "DSB", "URDSB", "UNDSB", "UUDSB", - "IRS", "ERS", - "FRS", "URFRS", "UNFRS", "UUFRS", - "DRS", "URDRS", "UNDRS", "UUDRS", - "IMP", "EMP", - "FMP", "URFMP", "UNFMP", "UUFMP", - "DMP", "URDMP", "UNDMP", "UUDMP", - "IDV", "EDV", - "FDV", "URFDV", "UNFDV", "UUFDV", - "DDV", "URDDV", "UNDDV", "UUDDV", - "IRD", "ERD", - "FRD", "URFRD", "UNFRD", "UUFRD", - "DRD", "URDRD", "UNDRD", "UUDRD", - "ILD", "ELD", - "FLD", "UNFLD", "DLD", "UNDLD", - "IST", "EST", - "FST", "URFST", "UNFST", "UUFST", - "DST", "UNDST", - "ILF", "UNILF", "ELF", "UNELF", - "FLX", "URFLX", "DLX", "URDLX", - "ILQ", "ELQ", - "FLQ", "UNFLQ", "DLQ", "UNDLQ", - "LJE", "SJE", - "IAD", "EAD", - "FAD", "URFAD", "UNFAD", "UUFAD", - "DAD", "URDAD", "UNDAD", "UUDAD", - "BZA", "BMA", "BLE", "BPA", - "BRU", "BNA", "BAC", - "ISB*", "ESB*", /* indirect */ - "FSB*", "URFSB*", "UNFSB*", "UUFSB*", - "DSB*", "URDSB*", "UNDSB*", "UUDSB*", - "IRS*", "ERS*", - "FRS*", "URFRS*", "UNFRS*", "UUFRS*", - "DRS*", "URDRS*", "UNDRS*", "UUDRS*", - "IMP*", "EMP*", - "FMP*", "URFMP*", "UNFMP*", "UUFMP*", - "DMP*", "URDMP*", "UNDMP*", "UUDMP*", - "IDV*", "EDV*", - "FDV*", "URFDV*", "UNFDV*", "UUFDV*", - "DDV*", "URDDV*", "UNDDV*", "UUDDV*", - "IRD*", "ERD", - "FRD*", "URFRD*", "UNFRD*", "UUFRD*", - "DRD*", "URDRD*", "UNDRD*", "UUDRD*", - "ILD*", "ELD", - "FLD*", "UNFLD*", "DLD*", "UNDLD*", - "IST*", "EST", - "FST*", "URFST*", "UNFST*", "UUFST*", - "DST*", "UNDST*", - "ILF*", "UNILF*", "ELF*", "UNELF*", - "FLX*", "URFLX*", "DLX*", "URDLX*", - "ILQ*", "ELQ*", - "FLQ*", "UNFLQ*", "DLQ*", "UNDLQ*", - "LJE*", "SJE*", - "IAD*", "EAD*", - "FAD*", "URFAD*", "UNFAD*", "UUFAD*", - "DAD*", "URDAD*", "UNDAD*", "UUDAD*", - - "FLA", "UNFLA", "FXA", "URFXA", /* no operand */ - "SWQ", "UNSWQ", "FZR", - "FAB", "FNG", "FCM", "FNM", -#endif -#if defined (PDP9) || defined (PDP15) - "MPSK", "MPSNE", "MPCV", "MPEU", - "MPLD", "MPCNE", "PFSF", - "TTS", "CAF", "DBK", "DBR", - "SPI", "RPL", "ISA", -#endif - "IOT", /* general */ - - "NOP", "STL", "RCL", "RCR", - "CLC", "LAS", "GLK", - "OPR", "SMA", "SZA", "SZA SMA", - "SNL", "SNL SMA", "SNL SZA", "SNL SZA SMA", - "SKP", "SPA", "SNA", "SNA SPA", - "SZL", "SZL SPA", "SZL SNA", "SZL SZA SPA", - "RAL", "SMA RAL", "SZA RAL", "SZA SMA RAL", - "SNL RAL", "SNL SMA RAL", "SNL SZA RAL", "SNL SZA SMA RAL", - "SKP RAL", "SPA RAL", "SNA RAL", "SNA SPA RAL", - "SZL RAL", "SZL SPA RAL", "SZL SNA RAL", "SZL SZA SPA RAL", - "RAR", "SMA RAR", "SZA RAR", "SZA SMA RAR", - "SNL RAR", "SNL SMA RAR", "SNL SZA RAR", "SNL SZA SMA RAR", - "SKP RAR", "SPA RAR", "SNA RAR", "SNA SPA RAR", - "SZL RAR", "SZL SPA RAR", "SZL SNA RAR", "SZL SZA SPA RAR", -#if defined (PDP15) - "IAC", "SMA IAC", "SZA IAC", "SZA SMA IAC", - "SNL IAC", "SNL SMA IAC", "SNL SZA IAC", "SNL SZA SMA IAC", - "SKP IAC", "SPA IAC", "SNA IAC", "SNA SPA IAC", - "SZL IAC", "SZL SPA IAC", "SZL SNA IAC", "SZL SZA SPA IAC", -#else - "RAL RAR", "SMA RAL RAR", "SZA RAL RAR", "SZA SMA RAL RAR", - "SNL RAL RAR", "SNL SMA RAL RAR", "SNL SZA RAL RAR", "SNL SZA SMA RAL RAR", - "SKP RAL RAR", "SPA RAL RAR", "SNA RAL RAR", "SNA SPA RAL RAR", - "SZL RAL RAR", "SZL SPA RAL RAR", "SZL SNA RAL RAR", "SZL SZA SPA RAL RAR", -#endif - "RTWO", "SMA RTWO", "SZA RTWO", "SZA SMA RTWO", - "SNL RTWO", "SNL SMA RTWO", "SNL SZA RTWO", "SNL SZA SMA RTWO", - "SKP RTWO", "SPA RTWO", "SNA RTWO", "SNA SPA RTWO", - "SZL RTWO", "SZL SPA RTWO", "SZL SNA RTWO", "SZL SZA SPA RTWO", - "RTL", "SMA RTL", "SZA RTL", "SZA SMA RTL", - "SNL RTL", "SNL SMA RTL", "SNL SZA RTL", "SNL SZA SMA RTL", - "SKP RTL", "SPA RTL", "SNA RTL", "SNA SPA RTL", - "SZL RTL", "SZL SPA RTL", "SZL SNA RTL", "SZL SZA SPA RTL", - "RTR", "SMA RTR", "SZA RTR", "SZA SMA RTR", - "SNL RTR", "SNL SMA RTR", "SNL SZA RTR", "SNL SZA SMA RTR", - "SKP RTR", "SPA RTR", "SNA RTR", "SNA SPA RTR", - "SZL RTR", "SZL SPA RTR", "SZL SNA RTR", "SZL SZA SPA RTR", -#if defined (PDP15) - "BSW", "SMA BSW", "SZA BSW", "SZA SMA BSW", - "SNL BSW", "SNL SMA BSW", "SNL SZA BSW", "SNL SZA SMA BSW", - "SKP BSW", "SPA BSW", "SNA BSW", "SNA SPA BSW", - "SZL BSW", "SZL SPA BSW", "SZL SNA BSW", "SZL SZA SPA BSW", -#else - "RTL RTR", "SMA RTL RTR", "SZA RTL RTR", "SZA SMA RTL RTR", - "SNL RTL RTR", "SNL SMA RTL RTR", "SNL SZA RTL RTR", "SNL SZA SMA RTL RTR", - "SKP RTL RTR", "SPA RTL RTR", "SNA RTL RTR", "SNA SPA RTL RTR", - "SZL RTL RTR", "SZL SPA RTL RTR", "SZL SNA RTL RTR", "SZL SZA SPA RTL RTR", -#endif - - "LLK", "CLQ", "LSN", "OACQ", "ECLA", /* encode only masks */ - "CMQ", "OMQ", "OSC", - "CLA", "CLL", "CML", "CMA", - "OAS", "HLT", - NULL }; - -static const int32 opc_val[] = { - 0000000+I_MRF, 0040000+I_MRF, 0100000+I_MRF, 0140000+I_MRF, - 0200000+I_MRF, 0240000+I_MRF, 0300000+I_MRF, 0340000+I_MRF, - 0400000+I_MRF, 0440000+I_MRF, 0500000+I_MRF, 0540000+I_MRF, - 0600000+I_MRF, - 0020000+I_MRF, 0060000+I_MRF, 0120000+I_MRF, 0160000+I_MRF, - 0220000+I_MRF, 0260000+I_MRF, 0320000+I_MRF, 0360000+I_MRF, - 0420000+I_MRF, 0460000+I_MRF, 0520000+I_MRF, 0560000+I_MRF, - 0620000+I_MRF, - - 0760000+I_LAW, - - 0641002+I_NPN, 0641001+I_NPN, 0644000+I_NPN, 0664000+I_NPN, 0652000+I_NPN, - 0653100+MD(022), 0657100+MD(022), 0640300+MD(023), 0644300+MD(023), - 0653300+MD(023), 0657300+MD(023), 0650300+MD(023), 0654300+MD(023), - 0640400+MD(044), 0660400+MD(044), - 0640100+I_ESH, 0660100+I_ESH, 0640300+I_ESH, 0660300+I_ESH, - 0640400+I_ESH, 0660400+I_ESH, 0640500+I_ESH, 0660500+I_ESH, - 0640600+I_ESH, 0660600+I_ESH, 0640700+I_ESH, 0660700+I_ESH, - 0640000+I_EST, 0640000+I_IOT, - - 0700001+I_NPI, 0700002+I_NPI, 0700042+I_NPI, 0700004+I_NPI, 0700044+I_NPI, - 0700101+I_NPI, 0700112+I_NPN, 0700102+I_NPI, 0700104+I_NPI, 0700144+I_NPI, - 0700201+I_NPI, 0700202+I_NPI, 0700204+I_NPI, 0700244+I_NPI, 0700206+I_NPI, - 0700301+I_NPI, 0700312+I_NPN, 0700302+I_NPI, 0700314+I_NPN, 0700304+I_NPI, - 0700401+I_NPI, 0700402+I_NPI, 0700404+I_NPI, 0700406+I_NPI, -#if defined (TYPE62) - 0706501+I_NPI, 0706502+I_NPI, 0706542+I_NPI, 0706506+I_NPI, - 0706601+I_NPI, 0706602+I_NPI, 0706606+I_NPI, -#endif -#if defined (TYPE647) - 0706501+I_NPI, 0706502+I_NPI, 0706522+I_NPI, 0706542+I_NPI, 0706562+I_NPI, - 0706526+I_NPI, 0706546+I_NPI, 0706566+I_NPI, - 0706601+I_NPI, 0706602+I_NPI, 0706622+I_NPI, 0706642+I_NPI, 0706662+I_NPI, - 0706606+I_NPI, 0706626+I_NPI, 0706646+I_NPI, -#endif -#if defined (LP09) - 0706601+I_NPI, 0706621+I_NPI, 0706602+I_NPI, 0706622+I_NPI, - 0706604+I_NPI, 0706644+I_NPI, -#endif -#if defined (LP15) - 0706501+I_NPI, 0706521+I_NPI, 0706541+I_NPI, 0706561+I_NPI, - 0706552+I_NPN, 0706542+I_NPI, 0706544+I_NPI, 0706621+I_NPI, 0706641+I_NPI, -#endif -#if defined (DRM) - 0706006+I_NPI, 0706046+I_NPI, 0706106+I_NPI, 0706204+I_NPI, - 0706101+I_NPI, 0706201+I_NPI, 0706102+I_NPI, - 0706006+I_NPI, 0706046+I_NPI, 0706106+I_NPI, 0706204+I_NPI, - 0706101+I_NPI, 0706201+I_NPI, 0706102+I_NPI, -#endif -#if defined (RB) - 0707101+I_NPI, 0707112+I_NPN, 0707104+I_NPI, - 0707121+I_NPI, 0707132+I_NPN, 0707124+I_NPI, - 0707141+I_NPI, 0707142+I_NPI, 0707144+I_NPI, -#endif -#if defined (RF) - 0707001+I_NPI, 0707021+I_NPI, 0707041+I_NPI, - 0707002+I_NPI, 0707022+I_NPI, 0707042+I_NPI, 0707062+I_NPI, - 0707004+I_NPI, 0707024+I_NPI, 0707044+I_NPI, 0707064+I_NPI, - 0707202+I_NPI, 0707242+I_NPI, 0707262+I_NPI, - 0707204+I_NPI, 0707224+I_NPI, -#endif -#if defined (RP) - 0706301+I_NPI, 0706321+I_NPI, 0706341+I_NPI, 0706361+I_NPI, - 0706312+I_NPN, 0706302+I_NPI, 0706332+I_NPN, 0706322+I_NPI, - 0706342+I_NPN, 0706352+I_NPI, - 0706304+I_NPI, 0706324+I_NPI, 0706344+I_NPI, 0706364+I_NPI, - 0706411+I_NPN, 0706401+I_NPI, 0706421+I_NPI, - 0706412+I_NPN, 0706402+I_NPI, 0706432+I_NPN, 0706422+I_NPI, - 0706452+I_NPN, 0706442+I_NPI, 0706472+I_NPN, 0706462+I_NPI, - 0706404+I_NPI, 0706424+I_NPI, 0706454+I_NPN, 0706444+I_NPI, 0706464+I_NPI, -#endif -#if defined (MTA) - 0707301+I_NPI, 0707321+I_NPI, 0707341+I_NPI, 0707312+I_NPN, 0707322+I_NPI, - 0707352+I_NPN, 0707304+I_NPI, 0707324+I_NPI, 0707326+I_NPI, -#endif -#if defined (TYPE550) /* Type 550 */ - 0707501+I_NPI, 0707541+I_NPI, 0707512+I_NPN, 0707504+I_NPI, - 0707601+I_NPI, 0707612+I_NPN, 0707604+I_NPI, 0707644+I_NPI, -#elif defined (TC02) /* TC02/TC15 */ - 0707541+I_NPI, 0707552+I_NPN, 0707544+I_NPI, 0707545+I_NPI, - 0707561+I_NPI, 0707572+I_NPN, 0707601+I_NPI, -#endif -#if defined (TTY1) - 0704101+I_NPI, 0704112+I_NPN, - 0704001+I_NPI, 0704002+I_NPI, 0704004+I_NPI, 0704006+I_NPI, -#endif -#if defined (PDP7) - 0703201+I_NPI, 0703301+I_NPI, 0703341+I_NPI, 0703302+I_NPI, - 0707701+I_NPI, 0707702+I_NPI, 0707742+I_NPI, 0707704+I_NPI, -#endif -#if defined (PDP9) - 0703341+I_NPI, 0707701+I_NPI, 0707702+I_NPI, 0707704+I_NPI, - 0706504+I_NPI, 0706604+I_NPI, -#endif -#if defined (PDP15) - 0703341+I_NPI, 0707741+I_NPI, 0707742+I_NPI, - 0707761+I_NPI, 0707762+I_NPI, 0707764+I_NPI, - 0700022+I_NPI, 0700032+I_NPN, 0700024+I_NPI, 0701724+I_NPI, - 0705521+I_NPI, 0705522+I_NPI, 0701722+I_NPI, 0701764+I_NPI, - 0720000+I_XR9, 0721000+I_XR, 0722000+I_XR, 0723000+I_XR9, - 0724000+I_XR, 0725000+I_XR9, 0726000+I_XR, 0730000+I_XR, - 0731000+I_XR, 0734000+I_XR, 0735000+I_XR, 0736000+I_XR, 0737000+I_XR9, - - 0710314+I_FPN, - 0710400+I_FPM, 0710500+I_FPM, - 0710440+I_FPM, 0710450+I_FPM, 0710460+I_FPM, 0710470+I_FPM, - 0710540+I_FPM, 0710550+I_FPM, 0710560+I_FPM, 0710570+I_FPM, - 0711000+I_FPM, 0711100+I_FPM, - 0711040+I_FPM, 0711050+I_FPM, 0711060+I_FPM, 0711070+I_FPM, - 0711140+I_FPM, 0711150+I_FPM, 0711160+I_FPM, 0711170+I_FPM, - 0711400+I_FPM, 0711500+I_FPM, - 0711440+I_FPM, 0711450+I_FPM, 0711460+I_FPM, 0711470+I_FPM, - 0711540+I_FPM, 0711550+I_FPM, 0711560+I_FPM, 0711570+I_FPM, - 0712000+I_FPM, 0712100+I_FPM, - 0712040+I_FPM, 0712050+I_FPM, 0712060+I_FPM, 0712070+I_FPM, - 0712140+I_FPM, 0712150+I_FPM, 0712160+I_FPM, 0712170+I_FPM, - 0712400+I_FPM, 0712500+I_FPM, - 0712440+I_FPM, 0712450+I_FPM, 0712460+I_FPM, 0712470+I_FPM, - 0712540+I_FPM, 0712550+I_FPM, 0712560+I_FPM, 0712570+I_FPM, - 0713000+I_FPM, 0713100+I_FPM, - 0713050+I_FPM, 0713070+I_FPM, 0713150+I_FPM, 0713170+I_FPM, - 0713600+I_FPM, 0713700+I_FPM, - 0713640+I_FPM, 0713650+I_FPM, 0713660+I_FPM, 0713670+I_FPM, - 0713750+I_FPM, 0713770+I_FPM, - 0714010+I_FPM, 0714030+I_FPM, 0714110+I_FPM, 0714130+I_FPM, - 0714460+I_FPM, 0714470+I_FPM, 0714560+I_FPM, 0714570+I_FPM, - 0715000+I_FPM, 0715100+I_FPM, - 0715050+I_FPM, 0715070+I_FPM, 0715150+I_FPM, 0715170+I_FPM, - 0715400+I_FPM, 0715600+I_FPM, - 0716000+I_FPM, 0716100+I_FPM, - 0716040+I_FPM, 0716050+I_FPM, 0716060+I_FPM, 0716070+I_FPM, - 0716140+I_FPM, 0716150+I_FPM, 0716160+I_FPM, 0716170+I_FPM, - 0716601+I_FPM, 0716602+I_FPM, 0716603+I_FPM, - 0716604+I_FPM, 0716606+I_FPM, 0716610+I_FPM, 0716620+I_FPM, - 0710400+I_FPI, 0710500+I_FPI, /* indirect */ - 0710440+I_FPI, 0710450+I_FPI, 0710460+I_FPI, 0710470+I_FPI, - 0710540+I_FPI, 0710550+I_FPI, 0710560+I_FPI, 0710570+I_FPI, - 0711000+I_FPI, 0711100+I_FPI, - 0711040+I_FPI, 0711050+I_FPI, 0711060+I_FPI, 0711070+I_FPI, - 0711140+I_FPI, 0711150+I_FPI, 0711160+I_FPI, 0711170+I_FPI, - 0711400+I_FPI, 0711500+I_FPI, - 0711440+I_FPI, 0711450+I_FPI, 0711460+I_FPI, 0711470+I_FPI, - 0711540+I_FPI, 0711550+I_FPI, 0711560+I_FPI, 0711570+I_FPI, - 0712000+I_FPI, 0712100+I_FPI, - 0712040+I_FPI, 0712050+I_FPI, 0712060+I_FPI, 0712070+I_FPI, - 0712140+I_FPI, 0712150+I_FPI, 0712160+I_FPI, 0712170+I_FPI, - 0712400+I_FPI, 0712500+I_FPI, - 0712440+I_FPI, 0712450+I_FPI, 0712460+I_FPI, 0712470+I_FPI, - 0712540+I_FPI, 0712550+I_FPI, 0712560+I_FPI, 0712570+I_FPI, - 0713000+I_FPI, 0713100+I_FPI, - 0713050+I_FPI, 0713070+I_FPI, 0713150+I_FPI, 0713170+I_FPI, - 0713600+I_FPI, 0713700+I_FPI, - 0713640+I_FPI, 0713650+I_FPI, 0713660+I_FPI, 0713670+I_FPI, - 0713750+I_FPI, 0713770+I_FPI, - 0714010+I_FPI, 0714030+I_FPI, 0714110+I_FPI, 0714130+I_FPI, - 0714460+I_FPI, 0714470+I_FPI, 0714560+I_FPI, 0714570+I_FPI, - 0715000+I_FPI, 0715100+I_FPI, - 0715050+I_FPI, 0715070+I_FPI, 0715150+I_FPI, 0715170+I_FPI, - 0715400+I_FPI, 0715600+I_FPI, - 0716000+I_FPI, 0716100+I_FPI, - 0716040+I_FPI, 0716050+I_FPI, 0716060+I_FPI, 0716070+I_FPI, - 0716140+I_FPI, 0716150+I_FPI, 0716160+I_FPI, 0716170+I_FPI, - 0714210+I_FPN, 0714230+I_FPN, 0714660+I_FPN, 0714670+I_FPN, - 0715250+I_FPN, 0715270+I_FPN, 0711200+I_FPN, - 0713271+I_FPN, 0713272+I_FPN, 0713273+I_FPN, 0713250+I_FPN, -#endif -#if defined (PDP9) || defined (PDP15) - 0701701+I_NPI, 0701741+I_NPI, 0701702+I_NPI, 0701742+I_NPI, - 0701704+I_NPI, 0701744+I_NPI, 0703201+I_NPI, - 0703301+I_NPI, 0703302+I_NPI, 0703304+I_NPI, 0703344+I_NPI, - 0705501+I_NPI, 0705512+I_NPN, 0705504+I_NPI, -#endif - 0700000+I_IOT, - - 0740000+I_NPN, 0744002+I_NPN, 0744010+I_NPN, 0744020+I_NPN, - 0750001+I_NPN, 0750004+I_NPN, 0750010+I_NPN, - 0740000+I_OPR, 0740100+I_OPR, 0740200+I_OPR, 0740300+I_OPR, - 0740400+I_OPR, 0740500+I_OPR, 0740600+I_OPR, 0740700+I_OPR, - 0741000+I_OPR, 0741100+I_OPR, 0741200+I_OPR, 0741300+I_OPR, - 0741400+I_OPR, 0741500+I_OPR, 0741600+I_OPR, 0741700+I_OPR, - 0740010+I_OPR, 0740110+I_OPR, 0740210+I_OPR, 0740310+I_OPR, - 0740410+I_OPR, 0740510+I_OPR, 0740610+I_OPR, 0740710+I_OPR, - 0741010+I_OPR, 0741110+I_OPR, 0741210+I_OPR, 0741310+I_OPR, - 0741410+I_OPR, 0741510+I_OPR, 0741610+I_OPR, 0741710+I_OPR, - 0740020+I_OPR, 0740120+I_OPR, 0740220+I_OPR, 0740320+I_OPR, - 0740420+I_OPR, 0740520+I_OPR, 0740620+I_OPR, 0740720+I_OPR, - 0741020+I_OPR, 0741120+I_OPR, 0741220+I_OPR, 0741320+I_OPR, - 0741420+I_OPR, 0741520+I_OPR, 0741620+I_OPR, 0741720+I_OPR, - 0740030+I_OPR, 0740130+I_OPR, 0740230+I_OPR, 0740330+I_OPR, - 0740430+I_OPR, 0740530+I_OPR, 0740630+I_OPR, 0740730+I_OPR, - 0741030+I_OPR, 0741130+I_OPR, 0741230+I_OPR, 0741330+I_OPR, - 0741430+I_OPR, 0741530+I_OPR, 0741630+I_OPR, 0741730+I_OPR, - 0742000+I_OPR, 0742100+I_OPR, 0742200+I_OPR, 0742300+I_OPR, - 0742400+I_OPR, 0742500+I_OPR, 0742600+I_OPR, 0742700+I_OPR, - 0743000+I_OPR, 0743100+I_OPR, 0743200+I_OPR, 0743300+I_OPR, - 0743400+I_OPR, 0743500+I_OPR, 0743600+I_OPR, 0743700+I_OPR, - 0742010+I_OPR, 0742110+I_OPR, 0742210+I_OPR, 0742310+I_OPR, - 0742410+I_OPR, 0742510+I_OPR, 0742610+I_OPR, 0742710+I_OPR, - 0743010+I_OPR, 0743110+I_OPR, 0743210+I_OPR, 0743310+I_OPR, - 0743410+I_OPR, 0743510+I_OPR, 0743610+I_OPR, 0743710+I_OPR, - 0742020+I_OPR, 0742120+I_OPR, 0742220+I_OPR, 0742320+I_OPR, - 0742420+I_OPR, 0742520+I_OPR, 0742620+I_OPR, 0742720+I_OPR, - 0743020+I_OPR, 0743120+I_OPR, 0743220+I_OPR, 0743320+I_OPR, - 0743420+I_OPR, 0743520+I_OPR, 0743620+I_OPR, 0743720+I_OPR, - 0742030+I_OPR, 0742130+I_OPR, 0742230+I_OPR, 0742330+I_OPR, - 0742430+I_OPR, 0742530+I_OPR, 0742630+I_OPR, 0742730+I_OPR, - 0743030+I_OPR, 0743130+I_OPR, 0743230+I_OPR, 0743330+I_OPR, - 0743430+I_OPR, 0743530+I_OPR, 0743630+I_OPR, 0743730+I_OPR, - - 0660000+I_EST, 0650000+I_EST, 0644000+I_EST, 0642000+I_EST, 0641000+I_EST, - 0640004+I_EST, 0640002+I_EST, 0640001+I_EST, - 0750000+I_OPR, 0744000+I_OPR, 0740002+I_OPR, 0740001+I_OPR, - 0740004+I_OPR, 0740040+I_OPR, - -1 }; - -/* Operate or EAE 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) (((x) >= 040)? (x): ((x) + 0100)) - -t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, - UNIT *uptr, int32 sw) -{ -int32 cflag, i, j, k, 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 defined (PDP15) -if (sw & SWMASK ('P')) { /* packed ASCII? */ - i = val[1]; - fprintf (of, FMTASC ((inst >> 11) & 0177)); - fprintf (of, FMTASC ((inst >> 4) & 0177)); - fprintf (of, FMTASC (((inst << 3) | (i >> 15)) & 0177)); - fprintf (of, FMTASC ((i >> 8) & 0177)); - fprintf (of, FMTASC ((i >> 1) & 0177)); - return -1; } -#endif -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_XR: /* index no opers */ - 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; - case I_V_IOT: /* IOT or EAE */ - fprintf (of, "%s %-o", opcode[i], inst & 037777); - break; - case I_V_MRF: /* mem ref */ -#if defined (PDP15) - if (memm) { - disp = inst & B_DAMASK; - ma = (addr & (AMASK & ~B_DAMASK)) | disp; } - else { - disp = inst & P_DAMASK; - ma = (addr & (AMASK & ~P_DAMASK)) | disp; } - fprintf (of, "%s %-o", opcode[i], (cflag? ma & AMASK: disp)); - if (!memm && (inst & I_IDX)) fprintf (of, ",X"); -#else - disp = inst & B_DAMASK; - ma = (addr & (AMASK & ~B_DAMASK)) | disp; - fprintf (of, "%s %-o", opcode[i], (cflag? ma & AMASK: 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; - case I_V_LAW: /* LAW */ - 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; - case I_V_EST: /* EAE setup */ - 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; - 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; - case I_V_FPM: case I_V_FPI: /* FP15 mem ref */ - fprintf (of, "%s", opcode[i]); - if (val[1] & SIGN) fputc ('*', of); - fprintf (of, " %-o", val[1] & ~SIGN); - return -1; - case I_V_FPN: /* FP15 no operand */ - fprintf (of, "%s", opcode[i]); - return -1; } /* 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 = 0; -if (*cptr == '+') { - *sign = 1; - 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, damask, epcmask; -t_stat r, sta = SCPE_OK; -char gbuf[CBUFSIZE]; - -cflag = (uptr == NULL) || (uptr == &cpu_unit); -while (isspace (*cptr)) cptr++; -for (i = 1; (i < 5) && (cptr[i] != 0); i++) - if (cptr[i] == 0) for (j = i + 1; j <= 5; 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++)) { /* sixbit string? */ - if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */ - val[0] = (((t_value) cptr[0] & 077) << 12) | - (((t_value) cptr[1] & 077) << 6) | - ((t_value) cptr[2] & 077); - return SCPE_OK; } -#if defined (PDP15) -if ((sw & SWMASK ('P')) || ((*cptr == '#') && cptr++)) { /* packed string? */ - if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */ - val[0] = (((t_value) cptr[0] & 0177) << 11) | - (((t_value) cptr[1] & 0177) << 4) | - (((t_value) cptr[2] & 0170) >> 3); - val[1] = (((t_value) cptr[2] & 0007) << 15) | - (((t_value) cptr[3] & 0177) << 8) | - (((t_value) cptr[4] & 0177) << 1); - return -1; } -#endif - -/* 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_XR: /* index */ - break; -case I_V_XR9: /* index literal */ - cptr = get_glyph (cptr, gbuf, 0); /* get next field */ - 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; - val[0] = val[0] | ((sign >= 0)? d: (01000 - d)); - break; -case I_V_LAW: /* law */ - cptr = get_glyph (cptr, gbuf, 0); /* get next field */ - d = get_uint (gbuf, 8, 017777, &r); - if (r != SCPE_OK) return SCPE_ARG; - val[0] = val[0] | d; - break; -case I_V_MRF: /* mem ref */ -#if defined (PDP15) - if (memm) damask = B_DAMASK; - else damask = P_DAMASK; - cptr = get_glyph (cptr, gbuf, ','); /* get glyph */ -#else - damask = B_DAMASK; - cptr = get_glyph (cptr, gbuf, 0); /* get next field */ -#endif -#if defined (PDP4) || defined (PDP7) - if (strcmp (gbuf, "I") == 0) { /* indirect? */ - val[0] = val[0] | I_IND; - cptr = get_glyph (cptr, gbuf, 0); } -#endif - epcmask = AMASK & ~damask; /* get ePC */ - d = get_uint (gbuf, 8, AMASK, &r); /* get addr */ - if (r != SCPE_OK) return SCPE_ARG; - if (d <= damask) val[0] = val[0] | d; /* fit in 12/13b? */ - else if (cflag && (((addr ^ d) & epcmask) == 0)) - val[0] = val[0] | (d & damask); /* 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] | I_IDX; } } -#endif - break; -case I_V_EMD: /* or'able */ - val[0] = val[0] | ((opc_val[i] >> I_V_DC) & 077); /* default shift */ -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) && - (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; } } - break; -case I_V_FPM: /* FP15 mem ref */ - cptr = get_glyph (cptr, gbuf, 0); /* get next field */ - val[1] = get_uint (gbuf, 8, AMASK, &r); /* get addr */ - if (r != SCPE_OK) return SCPE_ARG; - sta = -1; - break; -case I_V_FPI: /* FP15 ind mem ref */ - cptr = get_glyph (cptr, gbuf, 0); /* get next field */ - val[1] = get_uint (gbuf, 8, AMASK, &r) | SIGN; /* get @addr */ - if (r != SCPE_OK) return SCPE_ARG; - sta = -1; - break; -case I_V_FPN: /* FP15 no operand */ - val[1] = 0; - sta = -1; - break; } /* end case */ -if (*cptr != 0) return SCPE_ARG; /* junk at end? */ -return sta; -} diff --git a/PDP18B/pdp18b_tt1.c b/PDP18B/pdp18b_tt1.c deleted file mode 100644 index 9229bc3d..00000000 --- a/PDP18B/pdp18b_tt1.c +++ /dev/null @@ -1,312 +0,0 @@ -/* pdp18b_tt1.c: 18b PDP's second Teletype - - 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. - - tti1 keyboard - tto1 teleprinter - - 09-May-03 RMS Added network device flag - 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 - 30-May-02 RMS Widened POS to 32b - 06-Jan-02 RMS Added enable/disable support - 30-Dec-01 RMS Added show statistics, set disconnect - 30-Nov-01 RMS Added extended SET/SHOW support - 25-Nov-01 RMS Revised interrupt structure - 19-Sep-01 RMS Fixed typo - 17-Sep-01 RMS Changed to use terminal multiplexor library - 07-Sep-01 RMS Moved function prototypes - 10-Jun-01 RMS Cleaned up IOT decoding to reflect hardware -*/ - -#include "pdp18b_defs.h" -#include "sim_sock.h" -#include "sim_tmxr.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) - -extern int32 int_hwre[API_HLVL+1], dev_enb; -extern int32 tmxr_poll; /* calibrated poll */ -TMLN tt1_ldsc = { 0 }; /* line descriptors */ -TMXR tt_desc = { 1, 0, 0, &tt1_ldsc }; /* mux descriptor */ - -DEVICE tti1_dev, tto1_dev; -int32 tti1 (int32 pulse, int32 dat); -int32 tto1 (int32 pulse, int32 dat); -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 tti1_attach (UNIT *uptr, char *cptr); -t_stat tti1_detach (UNIT *uptr); -t_stat tti1_summ (FILE *st, UNIT *uptr, int32 val, void *desc); -t_stat tti1_show (FILE *st, UNIT *uptr, int32 val, void *desc); -void tt1_enbdis (int32 dis); -t_stat tt1_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc); - -/* TTI1 data structures - - tti1_dev TTI1 device descriptor - tti1_unit TTI1 unit - tto1_mod TTI1 modifier list - tti1_reg TTI1 register list -*/ - -DIB tti1_dib = { DEV_TTI1, 1, NULL, { &tti1 } }; - -UNIT tti1_unit = { UDATA (&tti1_svc, UNIT_ATTABLE+UNIT_KSR, 0), KBD_POLL_WAIT }; - -REG tti1_reg[] = { - { ORDATA (BUF, tti1_unit.buf, 8) }, - { FLDATA (INT, int_hwre[API_TTI1], INT_V_TTI1) }, - { FLDATA (DONE, int_hwre[API_TTI1], INT_V_TTI1) }, - { DRDATA (POS, tt1_ldsc.rxcnt, 32), PV_LEFT }, - { DRDATA (TIME, tti1_unit.wait, 24), REG_NZ + PV_LEFT }, - { ORDATA (DEVNO, tti1_dib.dev, 6), REG_HRO }, - { NULL } }; - -MTAB tti1_mod[] = { - { UNIT_KSR+UNIT_8B, UNIT_KSR, "KSR", "KSR", &tt1_set_mode }, - { UNIT_KSR+UNIT_8B, 0 , "7b" , "7B" , &tt1_set_mode }, - { UNIT_KSR+UNIT_8B, UNIT_8B , "8b" , "8B" , &tt1_set_mode }, - { UNIT_ATT, UNIT_ATT, "summary", NULL, NULL, &tti1_summ }, - { MTAB_XTD | MTAB_VDV, 0, NULL, "DISCONNECT", - &tmxr_dscln, NULL, &tt_desc }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "CONNECTIONS", NULL, - NULL, &tti1_show, NULL }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "STATISTICS", NULL, - NULL, &tti1_show, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", &set_devno, &show_devno }, - { 0 } }; - -DEVICE tti1_dev = { - "TTI1", &tti1_unit, tti1_reg, tti1_mod, - 1, 10, 31, 1, 8, 8, - &tmxr_ex, &tmxr_dep, &tti1_reset, - NULL, &tti1_attach, &tti1_detach, - &tti1_dib, DEV_NET | DEV_DISABLE }; - -/* TTO1 data structures - - tto1_dev TTO1 device descriptor - tto1_unit TTO1 unit - tto1_mod TTO1 modifier list - tto1_reg TTO1 register list -*/ - -DIB tto1_dib = { DEV_TTO1, 1, NULL, { &tto1 } }; - -UNIT tto1_unit = { UDATA (&tto1_svc, UNIT_KSR, 0), SERIAL_OUT_WAIT }; - -REG tto1_reg[] = { - { ORDATA (BUF, tto1_unit.buf, 8) }, - { FLDATA (INT, int_hwre[API_TTO1], INT_V_TTO1) }, - { FLDATA (DONE, int_hwre[API_TTO1], INT_V_TTO1) }, - { DRDATA (POS, tt1_ldsc.txcnt, 32), PV_LEFT }, - { DRDATA (TIME, tto1_unit.wait, 24), PV_LEFT }, - { ORDATA (DEVNO, tto1_dib.dev, 6), REG_HRO }, - { NULL } }; - -MTAB tto1_mod[] = { - { UNIT_KSR+UNIT_8B, UNIT_KSR, "KSR", "KSR", &tt1_set_mode }, - { UNIT_KSR+UNIT_8B, 0 , "7b" , "7B" , &tt1_set_mode }, - { UNIT_KSR+UNIT_8B, UNIT_8B , "8b" , "8B" , &tt1_set_mode }, - { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", &set_devno, &show_devno }, - { 0 } }; - -DEVICE tto1_dev = { - "TTO1", &tto1_unit, tto1_reg, tto1_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &tto1_reset, - NULL, NULL, NULL, - &tto1_dib, DEV_DISABLE }; - -/* Terminal input: IOT routine */ - -int32 tti1 (int32 pulse, int32 dat) -{ -if (pulse & 001) { /* KSF1 */ - if (TST_INT (TTI1)) dat = dat | IOT_SKP; } -if (pulse & 002) { /* KRB1 */ - CLR_INT (TTI1); /* clear flag */ - dat= dat | tti1_unit.buf; } /* return buffer */ -return dat; -} - -/* Unit service */ - -t_stat tti1_svc (UNIT *uptr) -{ -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 (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 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? */ - newln = tmxr_poll_conn (&tt_desc); /* poll connect */ - if (newln >= 0) { /* got one? */ - sim_activate (&tti1_unit, tti1_unit.wait); - tt1_ldsc.rcve = 1; } /* rcv enabled */ - sim_activate (uptr, tmxr_poll); } /* sched poll */ -return SCPE_OK; -} - -/* Reset routine */ - -t_stat tti1_reset (DEVICE *dptr) -{ -tt1_enbdis (dptr->flags & DEV_DIS); /* sync enables */ -tti1_unit.buf = 0; /* clear buffer */ -CLR_INT (TTI1); /* clear flag */ -if (tt1_ldsc.conn) { /* if conn, */ - sim_activate (&tti1_unit, tti1_unit.wait); /* activate, */ - tt1_ldsc.rcve = 1; } /* enable */ -else if (tti1_unit.flags & UNIT_ATT) /* if attached, */ - sim_activate (&tti1_unit, tmxr_poll); /* activate */ -else sim_cancel (&tti1_unit); /* else stop */ -return SCPE_OK; -} - -/* Terminal output: IOT routine */ - -int32 tto1 (int32 pulse, int32 dat) -{ -if (pulse & 001) { /* TSF */ - if (TST_INT (TTO1)) dat = dat | IOT_SKP; } -if (pulse & 002) CLR_INT (TTO1); /* clear flag */ -if (pulse & 004) { /* load buffer */ - sim_activate (&tto1_unit, tto1_unit.wait); /* activate unit */ - tto1_unit.buf = dat & 0377; } /* load buffer */ -return dat; -} - -/* Unit service */ - -t_stat tto1_svc (UNIT *uptr) -{ -int32 c; - -SET_INT (TTO1); /* set flag */ -c = tto1_unit.buf & 0177; -if (tt1_ldsc.conn) { /* connected? */ - if (tt1_ldsc.xmte) { /* tx enabled? */ - if (tto1_unit.flags & UNIT_KSR) { /* KSR? */ - c = c & 0177; - if (islower (c)) c = toupper (c); - if ((c < 007) || (c > 0137)) c = 0; } - else c = c & ((tto1_unit.flags & UNIT_8B)? 0377: 0177); - if (c) tmxr_putc_ln (&tt1_ldsc, c); /* output char */ - tmxr_poll_tx (&tt_desc); } /* poll xmt */ - else { - tmxr_poll_tx (&tt_desc); /* poll xmt */ - sim_activate (&tto1_unit, tmxr_poll); /* wait */ - return SCPE_OK; } } -return SCPE_OK; -} - -/* Reset routine */ - -t_stat tto1_reset (DEVICE *dptr) -{ -tt1_enbdis (dptr->flags & DEV_DIS); /* sync enables */ -tto1_unit.buf = 0; /* clear buffer */ -CLR_INT (TTO1); /* clear flag */ -sim_cancel (&tto1_unit); /* deactivate unit */ -return SCPE_OK; -} - -/* Attach routine */ - -t_stat tti1_attach (UNIT *uptr, char *cptr) -{ -t_stat r; - -r = tmxr_attach (&tt_desc, uptr, cptr); /* attach */ -if (r != SCPE_OK) return r; /* error */ -sim_activate (uptr, tmxr_poll); /* start poll */ -return SCPE_OK; -} - -/* Detach routine */ - -t_stat tti1_detach (UNIT *uptr) -{ -t_stat r; - -r = tmxr_detach (&tt_desc, uptr); /* detach */ -tt1_ldsc.rcve = 0; /* disable rcv */ -sim_cancel (uptr); /* stop poll */ -return r; -} - -/* Show summary processor */ - -t_stat tti1_summ (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -if (tt1_ldsc.conn) fprintf (st, "connected"); -else fprintf (st, "disconnected"); -return SCPE_OK; -} - -/* SHOW CONN/STAT processor */ - -t_stat tti1_show (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -if (val) tmxr_fconns (st, &tt1_ldsc, -1); -else tmxr_fstats (st, &tt1_ldsc, -1); -return SCPE_OK; -} - -/* Enable/disable device */ - -void tt1_enbdis (int32 dis) -{ -if (dis) { - tti1_dev.flags = tto1_dev.flags | DEV_DIS; - tto1_dev.flags = tto1_dev.flags | DEV_DIS; } -else { tti1_dev.flags = tti1_dev.flags & ~DEV_DIS; - tto1_dev.flags = tto1_dev.flags & ~DEV_DIS; } -return; -} - -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; -} diff --git a/PDP8/pdp8_clk.c b/PDP8/pdp8_clk.c deleted file mode 100644 index 462de909..00000000 --- a/PDP8/pdp8_clk.c +++ /dev/null @@ -1,166 +0,0 @@ -/* pdp8_clk.c: PDP-8 real-time clock simulator - - 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. - - clk real time clock - - 01-Mar-03 RMS Aded SET/SHOW CLK FREQ support - 04-Oct-02 RMS Added DIB, device number support - 30-Dec-01 RMS Removed for generalized timers - 05-Sep-01 RMS Added terminal multiplexor support - 17-Jul-01 RMS Moved function prototype - 05-Mar-01 RMS Added clock calibration support - - Note: includes the IOT's for both the PDP-8/E and PDP-8/A clocks -*/ - -#include "pdp8_defs.h" - -extern int32 int_req, int_enable, dev_done, stop_inst; - -int32 clk_tps = 60; /* ticks/second */ -int32 tmxr_poll = 16000; /* term mux poll */ - -int32 clk (int32 IR, int32 AC); -t_stat clk_svc (UNIT *uptr); -t_stat clk_reset (DEVICE *dptr); -t_stat clk_set_freq (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat clk_show_freq (FILE *st, UNIT *uptr, int32 val, void *desc); - -/* CLK data structures - - clk_dev CLK device descriptor - clk_unit CLK unit descriptor - clk_reg CLK register list -*/ - -DIB clk_dib = { DEV_CLK, 1, { &clk } }; - -UNIT clk_unit = { UDATA (&clk_svc, 0, 0), 16000 }; - -REG clk_reg[] = { - { FLDATA (DONE, dev_done, INT_V_CLK) }, - { FLDATA (ENABLE, int_enable, INT_V_CLK) }, - { FLDATA (INT, int_req, INT_V_CLK) }, - { DRDATA (TIME, clk_unit.wait, 24), REG_NZ + PV_LEFT }, - { DRDATA (TPS, clk_tps, 8), PV_LEFT + REG_HRO }, - { NULL } }; - -MTAB clk_mod[] = { - { MTAB_XTD|MTAB_VDV, 50, NULL, "50HZ", - &clk_set_freq, NULL, NULL }, - { MTAB_XTD|MTAB_VDV, 60, NULL, "60HZ", - &clk_set_freq, NULL, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "FREQUENCY", NULL, - NULL, &clk_show_freq, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "DEVNO", NULL, NULL, &show_dev }, - { 0 } }; - -DEVICE clk_dev = { - "CLK", &clk_unit, clk_reg, clk_mod, - 1, 0, 0, 0, 0, 0, - NULL, NULL, &clk_reset, - NULL, NULL, NULL, - &clk_dib, 0 }; - -/* IOT routine - - IOT's 6131-6133 are the PDP-8/E clock - IOT's 6135-6137 are the PDP-8/A clock -*/ - -int32 clk (int32 IR, int32 AC) -{ -switch (IR & 07) { /* decode IR<9:11> */ -case 1: /* CLEI */ - int_enable = int_enable | INT_CLK; /* enable clk ints */ - int_req = INT_UPDATE; /* update interrupts */ - return AC; -case 2: /* CLDI */ - int_enable = int_enable & ~INT_CLK; /* disable clk ints */ - int_req = int_req & ~INT_CLK; /* update interrupts */ - 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; } - return AC; -case 5: /* CLLE */ - if (AC & 1) int_enable = int_enable | INT_CLK; /* test AC<11> */ - else int_enable = int_enable & ~INT_CLK; - int_req = INT_UPDATE; /* update interrupts */ - return AC; -case 6: /* CLCL */ - dev_done = dev_done & ~INT_CLK; /* clear flag */ - int_req = int_req & ~INT_CLK; /* clear int req */ - return AC; -case 7: /* CLSK */ - return (dev_done & INT_CLK)? IOT_SKP + AC: AC; -default: - return (stop_inst << IOT_V_REASON) + AC; } /* end switch */ -} - -/* Unit service */ - -t_stat clk_svc (UNIT *uptr) -{ -int32 t; - -dev_done = dev_done | INT_CLK; /* set done */ -int_req = INT_UPDATE; /* update interrupts */ -t = sim_rtcn_calb (clk_tps, TMR_CLK); /* calibrate clock */ -sim_activate (&clk_unit, t); /* reactivate unit */ -tmxr_poll = t; /* set mux poll */ -return SCPE_OK; -} - -/* Reset routine */ - -t_stat clk_reset (DEVICE *dptr) -{ -dev_done = dev_done & ~INT_CLK; /* clear done, int */ -int_req = int_req & ~INT_CLK; -int_enable = int_enable & ~INT_CLK; /* clear enable */ -sim_activate (&clk_unit, clk_unit.wait); /* activate unit */ -return SCPE_OK; -} - -/* Set frequency */ - -t_stat clk_set_freq (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -if (cptr) return SCPE_ARG; -if ((val != 50) && (val != 60)) return SCPE_IERR; -clk_tps = val; -return SCPE_OK; -} - -/* Show frequency */ - -t_stat clk_show_freq (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -fprintf (st, (clk_tps == 50)? "50Hz": "60Hz"); -return SCPE_OK; -} diff --git a/PDP8/pdp8_cpu.c b/PDP8/pdp8_cpu.c deleted file mode 100644 index dbada524..00000000 --- a/PDP8/pdp8_cpu.c +++ /dev/null @@ -1,1145 +0,0 @@ -/* pdp8_cpu.c: PDP-8 CPU simulator - - 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. - - cpu central processor - - 12-Mar-03 RMS Added logical name support - 04-Oct-02 RMS Revamped device dispatching, added device number support - 06-Jan-02 RMS Added device enable/disable routines - 30-Dec-01 RMS Added old PC queue - 16-Dec-01 RMS Fixed bugs in EAE - 07-Dec-01 RMS Revised to use new breakpoint package - 30-Nov-01 RMS Added RL8A, extended SET/SHOW support - 16-Sep-01 RMS Fixed bug in reset routine, added KL8A support - 10-Aug-01 RMS Removed register from declarations - 17-Jul-01 RMS Moved function prototype - 07-Jun-01 RMS Fixed bug in JMS to non-existent memory - 25-Apr-01 RMS Added device enable/disable support - 18-Mar-01 RMS Added DF32 support - 05-Mar-01 RMS Added clock calibration support - 15-Feb-01 RMS Added DECtape support - 14-Apr-99 RMS Changed t_addr to unsigned - - The register state for the PDP-8 is: - - AC<0:11> accumulator - MQ<0:11> multiplier-quotient - L link flag - PC<0:11> program counter - IF<0:2> instruction field - IB<0:2> instruction buffer - DF<0:2> data field - UF user flag - UB user buffer - SF<0:6> interrupt save field - - The PDP-8 has three instruction formats: memory reference, I/O transfer, - and operate. The memory reference format is: - - 0 1 2 3 4 5 6 7 8 9 10 11 - +--+--+--+--+--+--+--+--+--+--+--+--+ - | op |in|zr| page offset | memory reference - +--+--+--+--+--+--+--+--+--+--+--+--+ - - <0:2> mnemonic action - - 000 AND AC = AC & M[MA] - 001 TAD L'AC = AC + M[MA] - 010 DCA M[MA] = AC, AC = 0 - 011 ISZ M[MA] = M[MA] + 1, skip if M[MA] == 0 - 100 JMS M[MA] = PC, PC = MA + 1 - 101 JMP PC = MA - - <3:4> mode action - 00 page zero MA = IF'0'IR<5:11> - 01 current page MA = IF'PC<0:4>'IR<5:11> - 10 indirect page zero MA = xF'M[IF'0'IR<5:11>] - 11 indirect current page MA = xF'M[IF'PC<0:4>'IR<5:11>] - - where x is D for AND, TAD, ISZ, DCA, and I for JMS, JMP. - - Memory reference instructions can access an address space of 32K words. - The address space is divided into eight 4K word fields; each field is - divided into thirty-two 128 word pages. An instruction can directly - address, via its 7b offset, locations 0-127 on page zero or on the current - page. All 32k words can be accessed via indirect addressing and the - instruction and data field registers. If an indirect address is in - locations 0010-0017 of any field, the indirect address is incremented - and rewritten to memory before use. -*/ - -/* The I/O transfer format is as follows: - - 0 1 2 3 4 5 6 7 8 9 10 11 - +--+--+--+--+--+--+--+--+--+--+--+--+ - | op | device | pulse | I/O transfer - +--+--+--+--+--+--+--+--+--+--+--+--+ - - The IO transfer instruction sends the the specified pulse to the - specified I/O device. The I/O device may take data from the AC, - return data to the AC, initiate or cancel operations, or skip on - status. - - The operate format is as follows: - - +--+--+--+--+--+--+--+--+--+--+--+--+ - | 1| 1| 1| 0| | | | | | | | | operate group 1 - +--+--+--+--+--+--+--+--+--+--+--+--+ - | | | | | | | | - | | | | | | | +--- increment AC 3 - | | | | | | +--- rotate 1 or 2 4 - | | | | | +--- rotate left 4 - | | | | +--- rotate right 4 - | | | +--- complement L 2 - | | +--- complement AC 2 - | +--- clear L 1 - +-- clear AC 1 - - +--+--+--+--+--+--+--+--+--+--+--+--+ - | 1| 1| 1| 1| | | | | | | | 0| operate group 2 - +--+--+--+--+--+--+--+--+--+--+--+--+ - | | | | | | | - | | | | | | +--- halt 3 - | | | | | +--- or switch register 3 - | | | | +--- reverse skip sense 1 - | | | +--- skip on L != 0 1 - | | +--- skip on AC == 0 1 - | +--- skip on AC < 0 1 - +-- clear AC 2 - - +--+--+--+--+--+--+--+--+--+--+--+--+ - | 1| 1| 1| 1| | | | | | | | 1| operate group 3 - +--+--+--+--+--+--+--+--+--+--+--+--+ - | | | | \______/ - | | | | | - | | +--|-----+--- EAE command 3 - | | +--- AC -> MQ, 0 -> AC 2 - | +--- MQ v AC --> AC 2 - +-- clear AC 1 - - The operate instruction can be microprogrammed to perform operations - on the AC, MQ, and link. -*/ - -/* This routine is the instruction decode routine for the PDP-8. - 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 - I/O error in I/O simulator - - 2. Interrupts. Interrupts are maintained by three parallel variables: - - dev_done device done flags - int_enable interrupt enable flags - int_req interrupt requests - - In addition, int_req contains the interrupt enable flag, the - CIF not pending flag, and the ION not pending flag. If all - three of these flags are set, and at least one interrupt request - is set, then an interrupt occurs. - - 3. Non-existent memory. On the PDP-8, 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 outside the current field (indirect writes) need - be checked against actual memory size. - - 3. Adding I/O devices. These modules must be modified: - - pdp8_defs.h add device number and interrupt definitions - pdp8_sys.c add sim_devices table entry -*/ - -#include "pdp8_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_NOEAE (UNIT_V_UF) /* EAE absent */ -#define UNIT_NOEAE (1 << UNIT_V_NOEAE) -#define UNIT_V_MSIZE (UNIT_V_UF+1) /* dummy mask */ -#define UNIT_MSIZE (1 << UNIT_V_MSIZE) - -uint16 M[MAXMEMSIZE] = { 0 }; /* main memory */ -int32 saved_LAC = 0; /* saved L'AC */ -int32 saved_MQ = 0; /* saved MQ */ -int32 saved_PC = 0; /* saved IF'PC */ -int32 saved_DF = 0; /* saved Data Field */ -int32 IB = 0; /* Instruction Buffer */ -int32 SF = 0; /* Save Field */ -int32 emode = 0; /* EAE mode */ -int32 gtf = 0; /* EAE gtf flag */ -int32 SC = 0; /* EAE shift count */ -int32 UB = 0; /* User mode Buffer */ -int32 UF = 0; /* User mode Flag */ -int32 OSR = 0; /* Switch Register */ -int16 pcq[PCQ_SIZE] = { 0 }; /* PC queue */ -int32 pcq_p = 0; /* PC queue ptr */ -REG *pcq_r = NULL; /* PC queue reg ptr */ -int32 dev_done = 0; /* dev done flags */ -int32 int_enable = INT_INIT_ENABLE; /* intr enables */ -int32 int_req = 0; /* intr requests */ -int32 stop_inst = 0; /* trap on ill inst */ -int32 (*dev_tab[DEV_MAX])(int32 IR, int32 dat); /* device dispatch */ - -extern int32 sim_interval; -extern int32 sim_int_char; -extern int32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */ -extern DEVICE *sim_devices[]; -extern FILE *sim_log; -extern UNIT clk_unit, ttix_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_bool build_dev_tab (void); - -/* CPU data structures - - cpu_dev CPU device descriptor - cpu_unit CPU unit descriptor - 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, saved_PC, 15) }, - { ORDATA (AC, saved_LAC, 12) }, - { FLDATA (L, saved_LAC, 12) }, - { ORDATA (MQ, saved_MQ, 12) }, - { ORDATA (SR, OSR, 12) }, - { GRDATA (IF, saved_PC, 8, 3, 12) }, - { GRDATA (DF, saved_DF, 8, 3, 12) }, - { GRDATA (IB, IB, 8, 3, 12) }, - { ORDATA (SF, SF, 7) }, - { FLDATA (UB, UB, 0) }, - { FLDATA (UF, UF, 0) }, - { ORDATA (SC, SC, 5) }, - { FLDATA (GTF, gtf, 0) }, - { FLDATA (EMODE, emode, 0) }, - { FLDATA (ION, int_req, INT_V_ION) }, - { FLDATA (ION_DELAY, int_req, INT_V_NO_ION_PENDING) }, - { FLDATA (CIF_DELAY, int_req, INT_V_NO_CIF_PENDING) }, - { FLDATA (PWR_INT, int_req, INT_V_PWR) }, - { FLDATA (UF_INT, int_req, INT_V_UF) }, - { ORDATA (INT, int_req, INT_V_ION+1), REG_RO }, - { ORDATA (DONE, dev_done, INT_V_DIRECT), REG_RO }, - { ORDATA (ENABLE, int_enable, INT_V_DIRECT), REG_RO }, - { BRDATA (PCQ, pcq, 8, 15, PCQ_SIZE), REG_RO+REG_CIRC }, - { ORDATA (PCQP, pcq_p, 6), REG_HRO }, - { FLDATA (STOP_INST, stop_inst, 0) }, - { ORDATA (WRU, sim_int_char, 8) }, - { NULL } }; - -MTAB cpu_mod[] = { - { UNIT_NOEAE, UNIT_NOEAE, "no EAE", "NOEAE", NULL }, - { UNIT_NOEAE, 0, "EAE", "EAE", 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 }, - { 0 } }; - -DEVICE cpu_dev = { - "CPU", &cpu_unit, cpu_reg, cpu_mod, - 1, 8, 15, 1, 8, 12, - &cpu_ex, &cpu_dep, &cpu_reset, - NULL, NULL, NULL, - NULL, 0 }; - -t_stat sim_instr (void) -{ -int32 IR, MB, IF, DF, LAC, MQ; -uint32 PC, MA; -int32 device, pulse, temp, iot_data; -t_stat reason; - -/* Restore register state */ - -if (build_dev_tab ()) return SCPE_STOP; /* build dev_tab */ -PC = saved_PC & 007777; /* load local copies */ -IF = saved_PC & 070000; -DF = saved_DF & 070000; -LAC = saved_LAC & 017777; -MQ = saved_MQ & 07777; -int_req = INT_UPDATE; -reason = 0; -sim_rtcn_init (clk_unit.wait, TMR_CLK); /* init clk calib */ -sim_rtcn_init (ttix_unit.wait, TMR_TTX); /* init ttx calib */ - -/* Main instruction fetch/decode loop */ - -while (reason == 0) { /* loop until halted */ -if (sim_interval <= 0) { /* check clock queue */ - if (reason = sim_process_event ()) break; } - -if (int_req > INT_PENDING) { /* interrupt? */ - int_req = int_req & ~INT_ION; /* interrupts off */ - SF = (UF << 6) | (IF >> 9) | (DF >> 12); /* form save field */ - IF = IB = DF = UF = UB = 0; /* clear mem ext */ - PCQ_ENTRY; /* save old PC */ - M[0] = PC; /* save PC in 0 */ - PC = 1; } /* fetch next from 1 */ - -MA = IF | PC; /* form PC */ -if (sim_brk_summ && sim_brk_test (MA, SWMASK ('E'))) { /* breakpoint? */ - reason = STOP_IBKPT; /* stop simulation */ - break; } - -IR = M[MA]; /* fetch instruction */ -PC = (PC + 1) & 07777; /* increment PC */ -int_req = int_req | INT_NO_ION_PENDING; /* clear ION delay */ -sim_interval = sim_interval - 1; - -/* Instruction decoding. - - The opcode (IR<0:2>), indirect flag (IR<3>), and page flag (IR<4>) - are decoded together. This produces 32 decode points, four per - major opcode. For IOT, the extra decode points are not useful; - for OPR, only the group flag (IR<3>) is used. - - The following macros define the address calculations for data and - jump calculations. Data calculations return a full 15b extended - address, jump calculations a 12b field-relative address. - - Autoindex calculations always occur within the same field as the - instruction fetch. The field must exist; otherwise, the instruction - fetched would be 0000, and indirect addressing could not occur. - - Note that MA contains IF'PC. -*/ - -#define ZERO_PAGE MA = IF | (IR & 0177) -#define CURR_PAGE MA = (MA & 077600) | (IR & 0177) -#define INDIRECT if ((MA & 07770) != 00010) MA = DF | M[MA]; \ - else MA = DF | (M[MA] = (M[MA] + 1) & 07777) - -#define ZERO_PAGE_J MA = IR & 0177 -#define CURR_PAGE_J MA = (MA & 007600) | (IR & 0177) -#define INDIRECT_J if ((MA & 07770) != 00010) MA = M[MA]; \ - else MA = (M[MA] = (M[MA] + 1) & 07777) -#define CHANGE_FIELD IF = IB; UF = UB; \ - int_req = int_req | INT_NO_CIF_PENDING - -switch ((IR >> 7) & 037) { /* decode IR<0:4> */ - -/* Opcode 0, AND */ - -case 000: /* AND, dir, zero */ - ZERO_PAGE; - LAC = LAC & (M[MA] | 010000); - break; -case 001: /* AND, dir, curr */ - CURR_PAGE; - LAC = LAC & (M[MA] | 010000); - break; -case 002: /* AND, indir, zero */ - ZERO_PAGE; - INDIRECT; - LAC = LAC & (M[MA] | 010000); - break; -case 003: /* AND, indir, curr */ - CURR_PAGE; - INDIRECT; - LAC = LAC & (M[MA] | 010000); - break; - -/* Opcode 1, TAD */ - -case 004: /* TAD, dir, zero */ - ZERO_PAGE; - LAC = (LAC + M[MA]) & 017777; - break; -case 005: /* TAD, dir, curr */ - CURR_PAGE; - LAC = (LAC + M[MA]) & 017777; - break; -case 006: /* TAD, indir, zero */ - ZERO_PAGE; - INDIRECT; - LAC = (LAC + M[MA]) & 017777; - break; -case 007: /* TAD, indir, curr */ - CURR_PAGE; - INDIRECT; - LAC = (LAC + M[MA]) & 017777; - break; - -/* Opcode 2, ISZ */ - -case 010: /* ISZ, dir, zero */ - ZERO_PAGE; - M[MA] = MB = (M[MA] + 1) & 07777; /* field must exist */ - if (MB == 0) PC = (PC + 1) & 07777; - break; -case 011: /* ISZ, dir, curr */ - CURR_PAGE; - M[MA] = MB = (M[MA] + 1) & 07777; /* field must exist */ - if (MB == 0) PC = (PC + 1) & 07777; - break; -case 012: /* ISZ, indir, zero */ - ZERO_PAGE; - INDIRECT; - MB = (M[MA] + 1) & 07777; - if (MEM_ADDR_OK (MA)) M[MA] = MB; - if (MB == 0) PC = (PC + 1) & 07777; - break; -case 013: /* ISZ, indir, curr */ - CURR_PAGE; - INDIRECT; - MB = (M[MA] + 1) & 07777; - if (MEM_ADDR_OK (MA)) M[MA] = MB; - if (MB == 0) PC = (PC + 1) & 07777; - break; - -/* Opcode 3, DCA */ - -case 014: /* DCA, dir, zero */ - ZERO_PAGE; - M[MA] = LAC & 07777; - LAC = LAC & 010000; - break; -case 015: /* DCA, dir, curr */ - CURR_PAGE; - M[MA] = LAC & 07777; - LAC = LAC & 010000; - break; -case 016: /* DCA, indir, zero */ - ZERO_PAGE; - INDIRECT; - if (MEM_ADDR_OK (MA)) M[MA] = LAC & 07777; - LAC = LAC & 010000; - break; -case 017: /* DCA, indir, curr */ - CURR_PAGE; - INDIRECT; - if (MEM_ADDR_OK (MA)) M[MA] = LAC & 07777; - LAC = LAC & 010000; - break; - -/* Opcode 4, JMS */ - -case 020: /* JMS, dir, zero */ - ZERO_PAGE_J; - CHANGE_FIELD; - MA = IF | MA; - PCQ_ENTRY; - if (MEM_ADDR_OK (MA)) M[MA] = PC; - PC = (MA + 1) & 07777; - break; -case 021: /* JMS, dir, curr */ - CURR_PAGE_J; - CHANGE_FIELD; - MA = IF | MA; - PCQ_ENTRY; - if (MEM_ADDR_OK (MA)) M[MA] = PC; - PC = (MA + 1) & 07777; - break; -case 022: /* JMS, indir, zero */ - ZERO_PAGE; - INDIRECT_J; - CHANGE_FIELD; - MA = IF | MA; - PCQ_ENTRY; - if (MEM_ADDR_OK (MA)) M[MA] = PC; - PC = (MA + 1) & 07777; - break; -case 023: /* JMS, indir, curr */ - CURR_PAGE; - INDIRECT_J; - CHANGE_FIELD; - MA = IF | MA; - PCQ_ENTRY; - if (MEM_ADDR_OK (MA)) M[MA] = PC; - PC = (MA + 1) & 07777; - break; - -/* Opcode 5, JMP */ - -case 024: /* JMP, dir, zero */ - ZERO_PAGE_J; - CHANGE_FIELD; - PCQ_ENTRY; - PC = MA; - break; -case 025: /* JMP, dir, curr */ - CURR_PAGE_J; - CHANGE_FIELD; - PCQ_ENTRY; - PC = MA; - break; -case 026: /* JMP, indir, zero */ - ZERO_PAGE; - INDIRECT_J; - CHANGE_FIELD; - PCQ_ENTRY; - PC = MA; - break; -case 027: /* JMP, indir, curr */ - CURR_PAGE; - INDIRECT_J; - CHANGE_FIELD; - PCQ_ENTRY; - PC = MA; - break; - -/* Opcode 7, OPR group 1 */ - -case 034:case 035: /* OPR, group 1 */ - switch ((IR >> 4) & 017) { /* decode IR<4:7> */ - case 0: /* nop */ - break; - case 1: /* CML */ - LAC = LAC ^ 010000; - break; - case 2: /* CMA */ - LAC = LAC ^ 07777; - break; - case 3: /* CMA CML */ - LAC = LAC ^ 017777; - break; - case 4: /* CLL */ - LAC = LAC & 07777; - break; - case 5: /* CLL CML = STL */ - LAC = LAC | 010000; - break; - case 6: /* CLL CMA */ - LAC = (LAC ^ 07777) & 07777; - break; - case 7: /* CLL CMA CML */ - LAC = (LAC ^ 07777) | 010000; - break; - case 010: /* CLA */ - LAC = LAC & 010000; - break; - case 011: /* CLA CML */ - LAC = (LAC & 010000) ^ 010000; - break; - case 012: /* CLA CMA = STA */ - LAC = LAC | 07777; - break; - case 013: /* CLA CMA CML */ - LAC = (LAC | 07777) ^ 010000; - break; - case 014: /* CLA CLL */ - LAC = 0; - break; - case 015: /* CLA CLL CML */ - LAC = 010000; - break; - case 016: /* CLA CLL CMA */ - LAC = 07777; - break; - case 017: /* CLA CLL CMA CML */ - 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; - case 1: /* BSW */ - LAC = (LAC & 010000) | ((LAC >> 6) & 077) | ((LAC & 077) << 6); - break; - case 2: /* RAL */ - LAC = ((LAC << 1) | (LAC >> 12)) & 017777; - break; - case 3: /* RTL */ - LAC = ((LAC << 2) | (LAC >> 11)) & 017777; - break; - case 4: /* RAR */ - LAC = ((LAC >> 1) | (LAC << 12)) & 017777; - break; - case 5: /* RTR */ - LAC = ((LAC >> 2) | (LAC << 11)) & 017777; - break; - case 6: /* RAL RAR - undef */ - LAC = LAC & (IR | 010000); /* uses AND path */ - break; - case 7: /* RTL RTR - undef */ - 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 */ - 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 */ - -/* OPR group 3 standard - - MQA!MQL exchanges AC and MQ, as follows: - - temp = MQ; - MQ = LAC & 07777; - LAC = LAC & 010000 | temp; -*/ - - temp = MQ; /* group 3 */ - if (IR & 0200) LAC = LAC & 010000; /* CLA */ - if (IR & 0020) { /* MQL */ - 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; } - -/* OPR group 3 EAE - - The EAE operates in two modes: - - Mode A, PDP-8/I compatible - Mode B, extended capability - - Mode B provides eight additional subfunctions; in addition, some - of the Mode A functions operate differently in Mode B. - - The mode switch instructions are decoded explicitly and cannot be - microprogrammed with other EAE functions (SWAB performs an MQL as - part of standard group 3 decoding). If mode switching is decoded, - all other EAE timing is suppressed. -*/ - - if (IR == 07431) { /* SWAB */ - emode = 1; /* set mode flag */ - break; } - if (IR == 07447) { /* SWBA */ - emode = gtf = 0; /* clear mode, gtf */ - break; } - -/* If not switching modes, the EAE operation is determined by the mode - and IR<6,8:10>: - - <6:10> mode A mode B comments - - 0x000 NOP NOP - 0x001 SCL ACS - 0x010 MUY MUY if mode B, next = address - 0x011 DVI DVI if mode B, next = address - 0x100 NMI NMI if mode B, clear AC if - result = 4000'0000 - 0x101 SHL SHL if mode A, extra shift - 0x110 ASR ASR if mode A, extra shift - 0x111 LSR LSR if mode A, extra shift - 1x000 SCA SCA - 1x001 SCA + SCL DAD - 1x010 SCA + MUY DST - 1x011 SCA + DVI SWBA NOP if not detected earlier - 1x100 SCA + NMI DPSZ - 1x101 SCA + SHL DPIC must be combined with MQA!MQL - 1x110 SCA + ASR DCM must be combined with MQA!MQL - 1x111 SCA + LSR SAM - - EAE instructions which fetch memory operands use the CPU's DEFER - state to read the first word; if the address operand is in locations - x0010 - x0017, it is autoincremented. -*/ - -/* EAE continued */ - - 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; - case 000: /* mode A, B: NOP */ - 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 001: /* mode B: ACS */ - if (emode) { - SC = LAC & 037; - LAC = LAC & 010000; } - else { /* mode A: SCL */ - SC = (~M[IF | PC]) & 037; - 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 002: /* 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 */ - case 003: /* 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; - case 024: /* mode B: DPSZ */ - if (emode) { - if (((LAC | MQ) & 07777) == 0) PC = (PC + 1) & 07777; - break; } - LAC = LAC | SC; /* mode A: SCA then */ - case 004: /* 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; - 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 */ - 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; - -/* 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 */ - 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; - 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 */ - 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 */ - 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; } - 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 */ - -/* 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 */ - -/* 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 */ - 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 case IOT */ - } /* end switch opcode */ -} /* end while */ - -/* Simulation halted */ - -saved_PC = IF | (PC & 07777); /* save copies */ -saved_DF = DF & 070000; -saved_LAC = LAC & 017777; -saved_MQ = MQ & 07777; -pcq_r->qptr = pcq_p; /* update pc q ptr */ -return reason; -} /* end sim_instr */ - -/* Reset routine */ - -t_stat cpu_reset (DEVICE *dptr) -{ -int_req = (int_req & ~INT_ION) | INT_NO_CIF_PENDING; -saved_DF = IB = saved_PC & 070000; -UF = UB = gtf = emode = 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] & 07777; -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 & 07777; -return SCPE_OK; -} - -/* Memory size change */ - -t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -int32 mc = 0; -uint32 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; -} - -/* 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, 8, DEV_MAX - 1, &r); /* get new */ -if ((r != SCPE_OK) || (newdev == dibp->dev)) return r; -dibp->dev = 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) return SCPE_IERR; -fprintf (st, "devno=%02o", dibp->dev); -if (dibp->num > 1) fprintf (st, "-%2o", dibp->dev + dibp->num - 1); -return SCPE_OK; -} - -/* CPU device handler - should never get here! */ - -int32 bad_dev (int32 IR, int32 AC) -{ -return (SCPE_IERR << IOT_V_REASON) | AC; /* broken! */ -} - -/* Build device dispatch table */ - -t_bool build_dev_tab (void) -{ -DEVICE *dptr; -DIB *dibp; -uint32 i, j; -static const uint8 std_dev[] = - { 000, 010, 020, 021, 022, 023, 024, 025, 026, 027 }; - -for (i = 0; i < DEV_MAX; i++) dev_tab[i] = NULL; /* clr table */ -for (i = 0; i < ((uint32) sizeof (std_dev)); i++) /* std entries */ - dev_tab[std_dev[i]] = &bad_dev; -for (i = 0; (dptr = sim_devices[i]) != NULL; i++) { /* add devices */ - dibp = (DIB *) dptr->ctxt; /* get DIB */ - if (dibp && !(dptr->flags & DEV_DIS)) { /* enabled? */ - for (j = 0; j < dibp->num; j++) { /* loop thru disp */ - if (dibp->dsp[j]) { /* any dispatch? */ - if (dev_tab[dibp->dev + j]) { /* already filled? */ - printf ("%s device number conflict at %02o\n", - sim_dname (dptr), dibp->dev + j); - if (sim_log) fprintf (sim_log, - "%s device number conflict at %02o\n", - sim_dname (dptr), dibp->dev + j); - return TRUE; } - dev_tab[dibp->dev + j] = dibp->dsp[j]; /* fill */ - } /* end if dsp */ - } /* end for j */ - } /* end if enb */ - } /* end for i */ -return FALSE; -} diff --git a/PDP8/pdp8_defs.h b/PDP8/pdp8_defs.h deleted file mode 100644 index 74c9fed7..00000000 --- a/PDP8/pdp8_defs.h +++ /dev/null @@ -1,188 +0,0 @@ -/* pdp8_defs.h: PDP-8 simulator definitions - - 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. - - 04-Oct-02 RMS Added variable device number support - 20-Jan-02 RMS Fixed bug in TTx interrupt enable initialization - 25-Nov-01 RMS Added RL8A support - 16-Sep-01 RMS Added multiple KL support - 18-Mar-01 RMS Added DF32 support - 15-Feb-01 RMS Added DECtape support - 14-Apr-99 RMS Changed t_addr to unsigned - 19-Mar-95 RMS Added dynamic memory size - 02-May-94 RMS Added non-existent memory handling - - The author gratefully acknowledges the help of Max Burnet, Richie Lary, - and Bill Haygood in resolving questions about the PDP-8 -*/ - -#include "sim_defs.h" /* simulator defns */ - -/* Simulator stop codes */ - -#define STOP_RSRV 1 /* must be 1 */ -#define STOP_HALT 2 /* HALT */ -#define STOP_IBKPT 3 /* breakpoint */ -#define STOP_NOTSTD 4 /* non-std devno */ - -/* Memory */ - -#define MAXMEMSIZE 32768 /* max memory size */ -#define MEMSIZE (cpu_unit.capac) /* actual memory size */ -#define ADDRMASK (MAXMEMSIZE - 1) /* address mask */ -#define MEM_ADDR_OK(x) (((uint32) (x)) < MEMSIZE) - -/* IOT subroutine return codes */ - -#define IOT_V_SKP 12 /* skip */ -#define IOT_V_REASON 13 /* reason */ -#define IOT_SKP (1 << IOT_V_SKP) -#define IOT_REASON (1 << IOT_V_REASON) -#define IORETURN(f,v) ((f)? (v): SCPE_OK) /* stop on error */ - -/* Timers */ - -#define TMR_CLK 0 /* timer 0 = clock */ -#define TMR_TTX 1 /* timer 1 = TTx */ - -/* Device information block */ - -#define DEV_MAXBLK 8 /* max dev block */ -#define DEV_MAX 64 /* total devices */ - -struct pdp8_dib { - uint32 dev; /* base dev number */ - uint32 num; /* number of slots */ - int32 (*dsp[DEV_MAXBLK])(int32 IR, int32 dat); -}; - -typedef struct pdp8_dib DIB; - -/* Standard device numbers */ - -#define DEV_PTR 001 /* paper tape reader */ -#define DEV_PTP 002 /* paper tape punch */ -#define DEV_TTI 003 /* console input */ -#define DEV_TTO 004 /* console output */ -#define DEV_CLK 013 /* clock */ -#define DEV_KJ8 040 /* extra terminals */ -#define DEV_DF 060 /* DF32 */ -#define DEV_RF 060 /* RF08 */ -#define DEV_RL 060 /* RL8A */ -#define DEV_LPT 066 /* line printer */ -#define DEV_MT 070 /* TM8E */ -#define DEV_RK 074 /* RK8E */ -#define DEV_RX 075 /* RX8E/RX28 */ -#define DEV_DTA 076 /* TC08 */ - -/* Interrupt flags - - The interrupt flags consist of three groups: - - 1. Devices with individual interrupt enables. These record - their interrupt requests in device_done and their enables - in device_enable, and must occupy the low bit positions. - - 2. Devices without interrupt enables. These record their - interrupt requests directly in int_req, and must occupy - the middle bit positions. - - 3. Overhead. These exist only in int_req and must occupy the - high bit positions. - - Because the PDP-8 does not have priority interrupts, the order - of devices within groups does not matter. - - Note: all extra KL input and output interrupts must be assigned - to contiguous bits. -*/ - -#define INT_V_START 0 /* enable start */ -#define INT_V_LPT (INT_V_START+0) /* line printer */ -#define INT_V_PTP (INT_V_START+1) /* tape punch */ -#define INT_V_PTR (INT_V_START+2) /* tape reader */ -#define INT_V_TTO (INT_V_START+3) /* terminal */ -#define INT_V_TTI (INT_V_START+4) /* keyboard */ -#define INT_V_CLK (INT_V_START+5) /* clock */ -#define INT_V_TTO1 (INT_V_START+6) /* tto1 */ -#define INT_V_TTO2 (INT_V_START+7) /* tto2 */ -#define INT_V_TTO3 (INT_V_START+8) /* tto3 */ -#define INT_V_TTO4 (INT_V_START+9) /* tto4 */ -#define INT_V_TTI1 (INT_V_START+10) /* tti1 */ -#define INT_V_TTI2 (INT_V_START+11) /* tti2 */ -#define INT_V_TTI3 (INT_V_START+12) /* tti3 */ -#define INT_V_TTI4 (INT_V_START+13) /* tti4 */ -#define INT_V_DIRECT (INT_V_START+14) /* direct start */ -#define INT_V_RX (INT_V_DIRECT+0) /* RX8E */ -#define INT_V_RK (INT_V_DIRECT+1) /* RK8E */ -#define INT_V_RF (INT_V_DIRECT+2) /* RF08 */ -#define INT_V_DF (INT_V_DIRECT+3) /* DF32 */ -#define INT_V_MT (INT_V_DIRECT+4) /* TM8E */ -#define INT_V_DTA (INT_V_DIRECT+5) /* TC08 */ -#define INT_V_RL (INT_V_DIRECT+6) /* RL8A */ -#define INT_V_PWR (INT_V_DIRECT+7) /* power int */ -#define INT_V_UF (INT_V_DIRECT+8) /* user int */ -#define INT_V_OVHD (INT_V_DIRECT+9) /* overhead start */ -#define INT_V_NO_ION_PENDING (INT_V_OVHD+0) /* ion pending */ -#define INT_V_NO_CIF_PENDING (INT_V_OVHD+1) /* cif pending */ -#define INT_V_ION (INT_V_OVHD+2) /* interrupts on */ - -#define INT_LPT (1 << INT_V_LPT) -#define INT_PTP (1 << INT_V_PTP) -#define INT_PTR (1 << INT_V_PTR) -#define INT_TTO (1 << INT_V_TTO) -#define INT_TTI (1 << INT_V_TTI) -#define INT_CLK (1 << INT_V_CLK) -#define INT_TTO1 (1 << INT_V_TTO1) -#define INT_TTO2 (1 << INT_V_TTO2) -#define INT_TTO3 (1 << INT_V_TTO3) -#define INT_TTO4 (1 << INT_V_TTO4) -#define INT_TTI1 (1 << INT_V_TTI1) -#define INT_TTI2 (1 << INT_V_TTI2) -#define INT_TTI3 (1 << INT_V_TTI3) -#define INT_TTI4 (1 << INT_V_TTI4) -#define INT_RX (1 << INT_V_RX) -#define INT_RK (1 << INT_V_RK) -#define INT_RF (1 << INT_V_RF) -#define INT_DF (1 << INT_V_DF) -#define INT_MT (1 << INT_V_MT) -#define INT_DTA (1 << INT_V_DTA) -#define INT_RL (1 << INT_V_RL) -#define INT_PWR (1 << INT_V_PWR) -#define INT_UF (1 << INT_V_UF) -#define INT_NO_ION_PENDING (1 << INT_V_NO_ION_PENDING) -#define INT_NO_CIF_PENDING (1 << INT_V_NO_CIF_PENDING) -#define INT_ION (1 << INT_V_ION) -#define INT_DEV_ENABLE ((1 << INT_V_DIRECT) - 1) /* devices w/enables */ -#define INT_ALL ((1 << INT_V_OVHD) - 1) /* all interrupts */ -#define INT_INIT_ENABLE (INT_TTI+INT_TTO+INT_PTR+INT_PTP+INT_LPT) | \ - (INT_TTI1+INT_TTI2+INT_TTI3+INT_TTI4) | \ - (INT_TTO1+INT_TTO2+INT_TTO3+INT_TTO4) -#define INT_PENDING (INT_ION+INT_NO_CIF_PENDING+INT_NO_ION_PENDING) -#define INT_UPDATE ((int_req & ~INT_DEV_ENABLE) | (dev_done & int_enable)) - -/* Function prototypes */ - -t_stat set_dev (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat show_dev (FILE *st, UNIT *uptr, int32 val, void *desc); diff --git a/PDP8/pdp8_df.c b/PDP8/pdp8_df.c deleted file mode 100644 index 3e28847c..00000000 --- a/PDP8/pdp8_df.c +++ /dev/null @@ -1,347 +0,0 @@ -/* pdp8_df.c: DF32 fixed head disk simulator - - 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. - - df DF32 fixed head disk - - 26-Jul-03 RMS Fixed bug in set size routine - 14-Mar-03 RMS Fixed variable platter interaction with save/restore - 03-Mar-03 RMS Fixed autosizing - 02-Feb-03 RMS Added variable platter and autosizing support - 04-Oct-02 RMS Added DIBs, device number support - 28-Nov-01 RMS Added RL8A support - 25-Apr-01 RMS Added device enable/disable support - - The DF32 is a head-per-track disk. It uses the three cycle data break - facility. To minimize overhead, the entire DF32 is buffered in memory. - - Two timing parameters are provided: - - df_time Interword timing, must be non-zero - df_burst Burst mode, if 0, DMA occurs cycle by cycle; otherwise, - DMA occurs in a burst -*/ - -#include "pdp8_defs.h" -#include - -#define UNIT_V_AUTO (UNIT_V_UF + 0) /* autosize */ -#define UNIT_V_PLAT (UNIT_V_UF + 1) /* #platters - 1 */ -#define UNIT_M_PLAT 03 -#define UNIT_PLAT (UNIT_M_PLAT << UNIT_V_PLAT) -#define UNIT_GETP(x) ((((x) >> UNIT_V_PLAT) & UNIT_M_PLAT) + 1) -#define UNIT_AUTO (1 << UNIT_V_AUTO) -#define UNIT_PLAT (UNIT_M_PLAT << UNIT_V_PLAT) - -/* Constants */ - -#define DF_NUMWD 2048 /* words/track */ -#define DF_NUMTR 16 /* tracks/disk */ -#define DF_DKSIZE (DF_NUMTR * DF_NUMWD) /* words/disk */ -#define DF_NUMDK 4 /* disks/controller */ -#define DF_WC 07750 /* word count */ -#define DF_MA 07751 /* mem address */ -#define DF_WMASK (DF_NUMWD - 1) /* word mask */ - -/* Parameters in the unit descriptor */ - -#define FUNC u4 /* function */ -#define DF_READ 2 /* read */ -#define DF_WRITE 4 /* write */ - -/* Status register */ - -#define DFS_PCA 04000 /* photocell status */ -#define DFS_DEX 03700 /* disk addr extension */ -#define DFS_MEX 00070 /* mem addr extension */ -#define DFS_DRL 00004 /* data late error */ -#define DFS_WLS 00002 /* write lock error */ -#define DFS_NXD 00002 /* non-existent disk */ -#define DFS_PER 00001 /* parity error */ -#define DFS_ERR (DFS_DRL | DFS_WLS | DFS_PER) -#define DFS_V_DEX 6 -#define DFS_V_MEX 3 - -#define GET_MEX(x) (((x) & DFS_MEX) << (12 - DFS_V_MEX)) -#define GET_DEX(x) (((x) & DFS_DEX) << (12 - DFS_V_DEX)) -#define GET_POS(x) ((int) fmod (sim_gtime() / ((double) (x)), \ - ((double) DF_NUMWD))) -#define UPDATE_PCELL if (GET_POS (df_time) < 6) df_sta = df_sta | DFS_PCA; \ - else df_sta = df_sta & ~DFS_PCA - -extern uint16 M[]; -extern int32 int_req, stop_inst; -extern UNIT cpu_unit; - -int32 df_sta = 0; /* status register */ -int32 df_da = 0; /* disk address */ -int32 df_done = 0; /* done flag */ -int32 df_wlk = 0; /* write lock */ -int32 df_time = 10; /* inter-word time */ -int32 df_burst = 1; /* burst mode flag */ -int32 df_stopioe = 1; /* stop on error */ - -DEVICE df_dev; -int32 df60 (int32 IR, int32 AC); -int32 df61 (int32 IR, int32 AC); -int32 df62 (int32 IR, int32 AC); -t_stat df_svc (UNIT *uptr); -t_stat pcell_svc (UNIT *uptr); -t_stat df_reset (DEVICE *dptr); -t_stat df_boot (int32 unitno, DEVICE *dptr); -t_stat df_attach (UNIT *uptr, char *cptr); -t_stat df_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); - -/* DF32 data structures - - df_dev RF device descriptor - df_unit RF unit descriptor - pcell_unit photocell timing unit (orphan) - df_reg RF register list -*/ - -DIB df_dib = { DEV_DF, 3, { &df60, &df61, &df62 } }; - -UNIT df_unit = - { UDATA (&df_svc, UNIT_FIX+UNIT_ATTABLE+ - UNIT_BUFABLE+UNIT_MUSTBUF, DF_DKSIZE) }; - -REG df_reg[] = { - { ORDATA (STA, df_sta, 12) }, - { ORDATA (DA, df_da, 12) }, - { ORDATA (WC, M[DF_WC], 12) }, - { ORDATA (MA, M[DF_MA], 12) }, - { FLDATA (DONE, df_done, 0) }, - { FLDATA (INT, int_req, INT_V_DF) }, - { ORDATA (WLS, df_wlk, 8) }, - { DRDATA (TIME, df_time, 24), REG_NZ + PV_LEFT }, - { FLDATA (BURST, df_burst, 0) }, - { FLDATA (STOP_IOE, df_stopioe, 0) }, - { DRDATA (CAPAC, df_unit.capac, 18), REG_HRO }, - { ORDATA (DEVNUM, df_dib.dev, 6), REG_HRO }, - { NULL } }; - -MTAB df_mod[] = { - { UNIT_PLAT, (0 << UNIT_V_PLAT), NULL, "1P", &df_set_size }, - { UNIT_PLAT, (1 << UNIT_V_PLAT), NULL, "2P", &df_set_size }, - { UNIT_PLAT, (2 << UNIT_V_PLAT), NULL, "3P", &df_set_size }, - { UNIT_PLAT, (3 << UNIT_V_PLAT), NULL, "4P", &df_set_size }, - { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", - &set_dev, &show_dev, NULL }, - { 0 } }; - -DEVICE df_dev = { - "DF", &df_unit, df_reg, df_mod, - 1, 8, 17, 1, 8, 12, - NULL, NULL, &df_reset, - &df_boot, &df_attach, NULL, - &df_dib, DEV_DISABLE }; - -/* IOT routines */ - -int32 df60 (int32 IR, int32 AC) -{ -int32 t; -int32 pulse = IR & 07; - -UPDATE_PCELL; /* update photocell */ -if (pulse & 1) { /* DCMA */ - df_da = 0; /* clear disk addr */ - df_done = 0; /* clear done */ - df_sta = df_sta & ~DFS_ERR; /* clear errors */ - int_req = int_req & ~INT_DF; } /* clear int req */ -if (pulse & 6) { /* DMAR, DMAW */ - df_da = df_da | AC; /* disk addr |= AC */ - df_unit.FUNC = pulse & ~1; /* save function */ - t = (df_da & DF_WMASK) - GET_POS (df_time); /* delta to new loc */ - if (t < 0) t = t + DF_NUMWD; /* wrap around? */ - sim_activate (&df_unit, t * df_time); /* schedule op */ - AC = 0; } /* clear AC */ -return AC; -} - -/* Based on the hardware implementation. DEAL and DEAC work as follows: - - 6615 pulse 1 = clear df_sta - pulse 4 = df_sta = df_sta | AC - AC = AC | old_df_sta - 6616 pulse 2 = clear AC, skip if address confirmed - pulse 4 = df_sta = df_sta | AC = 0 (nop) - AC = AC | old_df_sta -*/ - -int32 df61 (int32 IR, int32 AC) -{ -int32 old_df_sta = df_sta; -int32 pulse = IR & 07; - -UPDATE_PCELL; /* update photocell */ -if (pulse & 1) /* DCEA */ - df_sta = df_sta & ~(DFS_DEX | DFS_MEX); /* clear dex, mex */ -if (pulse & 2) /* DSAC */ - AC = ((df_da & DF_WMASK) == GET_POS (df_time))? IOT_SKP: 0; -if (pulse & 4) { - df_sta = df_sta | (AC & (DFS_DEX | DFS_MEX)); /* DEAL */ - AC = AC | old_df_sta; } /* DEAC */ -return AC; -} - -int32 df62 (int32 IR, int32 AC) -{ -int32 pulse = IR & 07; - -UPDATE_PCELL; /* update photocell */ -if (pulse & 1) { /* DFSE */ - if ((df_sta & DFS_ERR) == 0) AC = AC | IOT_SKP; } -if (pulse & 2) { /* DFSC */ - if (pulse & 4) AC = AC & ~07777; /* for DMAC */ - else if (df_done) AC = AC | IOT_SKP; } -if (pulse & 4) AC = AC | df_da; /* DMAC */ -return AC; -} - -/* Unit service - - Note that for reads and writes, memory addresses wrap around in the - current field. This code assumes the entire disk is buffered. -*/ - -t_stat df_svc (UNIT *uptr) -{ -int32 pa, t, mex; -uint32 da; - -UPDATE_PCELL; /* update photocell */ -if ((uptr->flags & UNIT_BUF) == 0) { /* not buf? abort */ - df_done = 1; - int_req = int_req | INT_DF; /* update int req */ - return IORETURN (df_stopioe, SCPE_UNATT); } - -mex = GET_MEX (df_sta); -da = GET_DEX (df_sta) | df_da; /* form disk addr */ -do { if (da >= uptr->capac) { /* nx disk addr? */ - df_sta = df_sta | DFS_NXD; - break; } - 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) { /* 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 */ - -if ((M[DF_WC] != 0) && ((df_sta & DFS_ERR) == 0)) /* more to do? */ - sim_activate (&df_unit, df_time); /* sched next */ -else { if (uptr->FUNC != DF_READ) da = (da - 1) & 0377777; - df_done = 1; /* done */ - int_req = int_req | INT_DF; } /* update int req */ -df_sta = (df_sta & ~DFS_DEX) | ((da >> (12 - DFS_V_DEX)) & DFS_DEX); -df_da = da & 07777; /* separate disk addr */ -return SCPE_OK; -} - -/* Reset routine */ - -t_stat df_reset (DEVICE *dptr) -{ -df_sta = df_da = 0; -df_done = 1; -int_req = int_req & ~INT_DF; /* clear interrupt */ -sim_cancel (&df_unit); -return SCPE_OK; -} - -/* Bootstrap routine */ - -#define OS8_START 07750 -#define OS8_LEN (sizeof (os8_rom) / sizeof (int16)) -#define DM4_START 00200 -#define DM4_LEN (sizeof (dm4_rom) / sizeof (int16)) - -static const uint16 os8_rom[] = { - 07600, /* 7750, CLA CLL ; also word count */ - 06603, /* 7751, DMAR ; also address */ - 06622, /* 7752, DFSC ; done? */ - 05352, /* 7753, JMP .-1 ; no */ - 05752 /* 7754, JMP @.-2 ; enter boot */ -}; - -static const uint16 dm4_rom[] = { - 00200, 07600, /* 0200, CLA CLL */ - 00201, 06603, /* 0201, DMAR ; read */ - 00202, 06622, /* 0202, DFSC ; done? */ - 00203, 05202, /* 0203, JMP .-1 ; no */ - 00204, 05600, /* 0204, JMP @.-4 ; enter boot */ - 07750, 07576, /* 7750, 7576 ; word count */ - 07751, 07576 /* 7751, 7576 ; address */ -}; - -t_stat df_boot (int32 unitno, DEVICE *dptr) -{ -int32 i; -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]; - saved_PC = DM4_START; } -else { for (i = 0; i < OS8_LEN; i++) - M[OS8_START + i] = os8_rom[i]; - saved_PC = OS8_START; } -return SCPE_OK; -} - -/* Attach routine */ - -t_stat df_attach (UNIT *uptr, char *cptr) -{ -uint32 p, sz; -uint32 ds_bytes = DF_DKSIZE * sizeof (int16); - -if ((uptr->flags & UNIT_AUTO) && (sz = sim_fsize (cptr))) { - p = (sz + ds_bytes - 1) / ds_bytes; - if (p >= DF_NUMDK) p = DF_NUMDK - 1; - uptr->flags = (uptr->flags & ~UNIT_PLAT) | - (p << UNIT_V_PLAT); } -uptr->capac = UNIT_GETP (uptr->flags) * DF_DKSIZE; -return attach_unit (uptr, cptr); -} - -/* Change disk size */ - -t_stat df_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -if (val < 0) return SCPE_IERR; -if (uptr->flags & UNIT_ATT) return SCPE_ALATT; -uptr->capac = UNIT_GETP (val) * DF_DKSIZE; -uptr->flags = uptr->flags & ~UNIT_AUTO; -return SCPE_OK; -} diff --git a/PDP8/pdp8_doc.txt b/PDP8/pdp8_doc.txt deleted file mode 100644 index 08f8a218..00000000 --- a/PDP8/pdp8_doc.txt +++ /dev/null @@ -1,758 +0,0 @@ -To: Users -From: Bob Supnik -Subj: PDP-8 Simulator Usage -Date: 1-Feb-2003 - - COPYRIGHT NOTICE - -The following copyright notice applies to both the SIMH source and binary: - - 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"), - 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-8 simulator. - - -1. Simulator Files - -sim/ sim_defs.h - sim_rev.h - sim_sock.h - sim_tape.h - sim_tmxr.h - scp.c - scp_tty.c - sim_sock.c - sim_tape.c - sim_tmxr.c - -sim/pdp8/ pdp8_defs.h - pdp8_cpu.c - pdp8_df.c - pdp8_dt.c - pdp8_lp.c - pdp8_mt.c - pdp8_pt.c - pdp8_rf.c - pdp8_rk.c - pdp8_rl.c - pdp8_rx.c - pdp8_sys.c - pdp8_tt.c - pdp8_ttx.c - -2. PDP-8 Features - -The PDP-8 simulator is configured as follows: - -device simulates -name(s) - -CPU PDP-8/E CPU with 4KW-32KW of memory -- KE8E extended arithmetic element (EAE) -- KM8E memory management and timeshare control -PTR,PTP PC8E paper tape reader/punch -TTI,TTO KL8E console terminal -TTIX,TTOX KL8JA additional terminals -LPT LE8E line printer -CLK DK8E line frequency clock (also PDP-8/A compatible) -RK RK8E/RK05 cartridge disk controller with four drives -RF RF08/RS08 fixed head disk controller with 1-4 platters, or -DF DF32/DS32 fixed head disk controller with 1-4 platters -RL RL8A/RL01 cartridge disk controller with four drives -RX RX8E/RX01, RX28/RX02 floppy disk controller with two drives -DT TC08/TU56 DECtape controller with eight drives -MT TM8E/TU10 magnetic tape controller with eight drives - -Most devices can be disabled or enabled, by the commands: - - SET DISABLED - SET ENABLED - -The simulator allows most device numbers to be changed, by the command: - - SET DEV= - -The PDP-8 can support only one of the set {DF32, RF08, RL8A} using the -default device numbers, since they all use device numbers 60-61. The -default is the RF08. To change the disk at device numbers 60-61: - - sim> SET RF DISABLED disable RF08 - sim> SET DF ENABLED, or enable DF32 - sim> SET RL ENABLED enable RL8A - -Alternately, the device conflict can be eliminated by changing device -numbers: - - sim> SET RL DEV=50 - sim> SET RL ENA - -However, devices can only be BOOTed with their default device numbers. - -The PDP-8 simulator implements one unique stop condition: if an undefined -instruction (unimplemented IOT or OPR) is decoded, and register STOP_INST -is set, the simulator halts. - -The PDP-8 loader supports both RIM format and BIN format tapes. If the file -extension is .RIM, or the -r switch is specified with LOAD, the file is -assumed to be RIM format; if the file extension is not .RIM, or if the -b -switch is specified, the file is assumed to be BIN format. - -2.1 CPU - -The only CPU options are the presence of the EAE and the size of main -memory; the memory extension and time-share control is always included, -even if memory size is 4K. - - SET CPU EAE enable EAE - SET CPU NOEAE disable EAE - 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 - -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 32K. - -CPU registers include the visible state of the processor as well as the -control registers for the interrupt system. - - name size comments - - PC 15 program counter, including IF as high 3 bits - AC 12 accumulator - MQ 12 multiplier-quotient - L 1 link - SR 12 front panel switches - IF 3 instruction field - DF 3 data field - IB 3 instruction field buffer - SF 7 save field - UF 1 user mode flag - UB 1 user mode buffer - SC 5 EAE shift counter - GTF 1 EAE greater than flag - EMODE 1 EAE mode (0 = A, 1 = B) - ION 1 interrupt enable - ION_DELAY 1 interrupt enable delay for ION - CIF_DELAY 1 interrupt enable delay for CIF - PWR_INT 1 power fail interrupt - UF_INT 1 user mode violation interrupt - INT 15 interrupt pending flags - DONE 15 device done flags - ENABLE 15 device interrupt enable flags - PCQ[0:63] 15 PC prior to last JMP, JMS, or interrupt; - most recent PC change first - STOP_INST 1 stop on undefined instruction - WRU 8 interrupt character - -2.2 Programmed I/O Devices - -2.2.1 PC8E 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 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 - ENABLE 1 interrupt enable flag - INT 1 interrupt pending 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 PC8E 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 bewritten. 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 - ENABLE 1 interrupt enable flag - INT 1 interrupt pending 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 KL8E Terminal Input (TTI) - -The terminal interfaces (TTI, TTO) 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 interface changes both. The default mode is KSR. - -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 - ENABLE 1 interrupt enable flag - INT 1 interrupt pending flag - POS 32 number of characters input - TIME 24 keyboard polling interval - -If the simulator is compiled under Windows Visual C++, typing ^C to the -terminal input causes a fatal run-time error. Use the following command -to simulate typing ^C: - - SET TTI CTRL-C - -2.2.4 KL8E 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 - ENABLE 1 interrupt enable flag - INT 1 interrupt pending flag - POS 32 number of characters output - TIME 24 time from I/O initiation to interrupt - -2.2.5 LE8E 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 read or written. Thus, -by changing POS, the user can backspace or advance the printer. - -The line printer implements these registers: - - name size comments - - BUF 8 last data item processed - ERR 1 error status flag - DONE 1 device done flag - ENABLE 1 interrupt enable flag - INT 1 interrupt pending flag - POS 32 position in the output file - TIME 24 time from I/O initiation to interrupt - -Error handling is as follows: - - error STOP_IOE processed as - - not attached 1 report error and stop - 0 set error flag - - OS I/O error x report error and stop - -2.2.6 DK8E Line-Frequency Clock (CLK) - -The real-time clock (CLK) frequency can be adjusted as follows: - - SET CLK 60HZ set frequency to 60Hz - SET CLK 50HZ set frequency to 50Hz - -The default is 60Hz. - -The clock implements these registers: - - name size comments - - DONE 1 device done flag - ENABLE 1 interrupt enable flag - INT 1 interrupt pending flag - TIME 24 clock interval - -The real-time clock autocalibrates; the clock interval is adjusted up or -down so that the clock tracks actual elapsed time. - -2.2.7 KL8JA Additional Terminals (TTIX, TTOX) - -The additional terminals consist of two independent devices, TTIX and -TTOX. The entire set is modelled as a terminal multiplexor, with TTIX -as the master unit. The additional terminals perform input and output -through Telnet sessions connected to a user-specified port. The ATTACH -command specifies the port to be used: - - ATTACH TTIX set up listening port - -where port is a decimal number between 1 and 65535 that is not being used -for other TCP/IP activities. - -The additional terminals can be set to one of three modes: UC, 7B, or -8B. In KSR 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. - -Once TTIX 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 TTIX DISCONNECT command, -or a DETACH TTIX command. - -The SHOW TTIX CONNECTIONS command displays the current connections to the -extra terminals. The SHOW TTIX STATISTICS command displays statistics for -active connections. The SET TTIX DISCONNECT=linenumber disconnects the -specified line. - -The input device (TTIX) implements these registers: - - name size comments - - BUF[0:3] 8 input buffer, lines 0-3 - DONE 4 device done flags (line 0 rightmost) - ENABLE 4 interrupt enable flag - INT 4 interrupt pending flag - TIME 24 initial polling interval - TPS 10 polls per second after calibration - -The output device (TTOX) implements these registers: - - name size comments - - BUF[0:3] 8 last data item processed, lines 0-3 - DONE 4 device done flag (line 0 rightmost) - ENABLE 4 interrupt enable flag - INT 4 interrupt pending flag - TIME[0:3] 24 time from I/O initiation to interrupt, - lines 0-3 - -The additional terminals do not support save and restore. All open -connections are lost when the simulator shuts down or TTIX is detached. - -2.3 Moving Head Disks - -2.3.1 RK8E Cartridge Disk (RK) - -RK8E options include the ability to make units write enabled or write locked: - - SET RKn LOCKED set unit n write locked - SET RKn WRITEENABLED set unit n write enabled - -Units can also be set ONLINE or OFFLINE. The RK8E supports the BOOT command. - -The RK8E implements these registers: - - name size comments - - RKSTA 12 status - RKCMD 12 disk command - RKDA 12 disk address - RKMA 12 current memory address - BUSY 1 control busy flag - INT 1 interrupt pending flag - STIME 24 seek time, per cylinder - RTIME 24 rotational delay - 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 - -2.3.2 RL8A Cartridge Disk (RL) - -RL8A options include the ability to make units write enabled or write locked: - - SET RLn LOCKED set unit n write locked - SET RLn WRITEENABLED set unit n write enabled - -Units can also be set ONLINE or OFFILE. The RL8A supports the BOOT command. - -The RL8A implements these registers: - - name size comments - - RLCSA 12 control/status A - RLCSB 12 control/status B - RLMA 12 memory address - RLWC 12 word count - RLSA 6 sector address - RLER 12 error flags - RLSI 16 silo top word - RLSI1 16 silo second word - RLSI2 16 silo third word - RLSIL 1 silo read left/right flag - INT 1 interrupt request - DONE 1 done flag - ERR 1 composite error flag - STIME 1 seek time, per cylinder - RTIME 1 rotational delay - 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 - -2.4 RX8E/RX01, RX28/RX02 Floppy Disk (RX) - -The RX can be configured as an RX8E with two RX01 drives, or an RX28 with -two RX02 drives: - - SET RX RX8E set controller to RX8E/RX01 - SET RX RX28 set controller to RX28/RX02 - -The controller is set to the RX8E by default. The RX28 is not backwards- -compatible with the RX8E and will not work with the standard OS/8 V3D floppy -disk driver. - -RX8E options include the ability to set units write enabled or write locked: - - SET RXn LOCKED set unit n write locked - SET RXn WRITEENABLED set unit n write enabled - -RX28 options include, in addition, the ability to set the unit density to -single density, double density, or autosized; autosizing is the default: - - SET RXn SINGLE set unit n single density - SET RXn DOUBLE set unit n double density - SET RXn AUTOSIZE set unit n autosize - -The RX8E and RX28 support the BOOT command. - -The RX8E and RX28 implement these registers: - - name size comments - - RXCS 12 status - RXDB 12 data buffer - RXES 12 error status - RXTA 8 current track - RXSA 8 current sector - STAPTR 4 controller state - BUFPTR 8 buffer pointer - INT 1 interrupt pending flag - DONE 1 device done flag - ENABLE 1 interrupt enable flag - TR 1 transfer ready flag - ERR 1 error flag - CTIME 24 command completion time - STIME 24 seek time, per track - XTIME 24 transfer ready delay - STOP_IOE 1 stop on I/O error - SBUF[0:255] 8 sector buffer array - -Error handling is as follows: - - error STOP_IOE processed as - - not attached 1 report error and stop - 0 disk not ready - -RX01 and RX02 data files are buffered in memory; therefore, end of file -and OS I/O errors cannot occur. - -2.5 Fixed Head Disks - -Either the RF08 or the DF32 can be present in a configuration, but -not both, with default device addressing. - -2.5.1 RF08/RS08 Fixed Head Disk (RF) - -RF08 options include the ability to set the number of platters to a -fixed value between 1 and 4, or to autosize the number of platters -from the attached file: - - SET RF 1P one platter (256K) - SET RF 2P two platters (512K) - SET RF 3P three platters (768K) - SET RF 4P four platters (1024K) - SET RF AUTOSIZE autosized on attach - -The default is one platter. - -The RF08 implements these registers: - - name size comments - - STA 12 status - DA 20 current disk address - MA 12 memory address (in memory) - WC 12 word count (in memory) - WLK 32 write lock switches - INT 1 interrupt pending flag - DONE 1 device done flag - TIME 24 rotational delay, per word - BURST 1 burst flag - STOP_IOE 1 stop on I/O error - -The RF08 supports the BOOT command. The default bootstrap is for OS/8. To -bootstrap the 4K Disk Monitor, use the BOOT -D RF command. - -The RF08 is a three-cycle data break device. If BURST = 0, word transfers -are scheduled individually; if BURST = 1, the entire transfer occurs in -a single data break. - -Error handling is as follows: - - error STOP_IOE processed as - - not attached 1 report error and stop - 0 disk not ready - -RF08 data files are buffered in memory; therefore, end of file and OS -I/O errors cannot occur. - -2.5.2 DF32/DS32 Fixed Head Disk (RF) - -DF32 options include the ability to set the number of platters to a -fixed value between 1 and 4, or to autosize the number of platters -from the attached file: - - SET DF 1P one platter (32K) - SET DF 2P two platters (64K) - SET DF 3P three platters (98K) - SET DF 4P four platters (128K) - SET DF AUTOSIZE autosized on attach - -The default is one platter. - -The DF32 implements these registers: - - name size comments - - STA 12 status, disk and memory address extension - DA 12 low order disk address - MA 12 memory address (in memory) - WC 12 word count (in memory) - WLK 16 write lock switches - INT 1 interrupt pending flag - DONE 1 device done flag - TIME 24 rotational delay, per word - BURST 1 burst flag - STOP_IOE 1 stop on I/O error - -The DF32 supports the BOOT command. The default bootstrap is for OS/8. To -bootstrap the 4K Disk Monitor, use the BOOT -D DF command. - -The DF32 is a three-cycle data break device. If BURST = 0, word transfers -are scheduled individually; if BURST = 1, the entire transfer occurs in -a single data break. - -Error handling is as follows: - - error STOP_IOE processed as - - not attached 1 report error and stop - 0 disk not ready - -DF32 data files are buffered in memory; therefore, end of file and OS -I/O errors cannot occur. - -2.6 TC08/TU56 DECtape (DT) - -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 LOCKED set unit n write locked - SET DTn WRITEENABLED set unit n write enabled - -Units can also be set ONLINE or OFFLINE. The TC08 supports the BOOT command. - -The TC08 supports 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 - INT 1 interrupt pending flag - ENB 1 interrupt enable flag - DTF 1 DECtape flag - ERF 1 error flag - CA 12 current address (memory location 7754) - WC 12 word count (memory location 7755) - 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] 31 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.7 TM8E Magnetic Tape (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 controller implements these registers: - - name size comments - - CMD 12 command - FNC 12 function - CA 12 memory address - WC 12 word count - DB 12 data buffer - STA 12 main status - STA2 6 secondary status - DONE 1 device done flag - INT 1 interrupt pending flag - STOP_IOE 1 stop on I/O error - TIME 24 record delay - UST[0:7] 24 unit status, units 0-7 - POS[0:7] 32 position, units 0-7 - -Error handling is as follows: - - error processed as - - not attached tape not ready; if STOP_IOE, stop - - end of file bad tape - - OS I/O error parity error; if STOP_IOE, stop - -2.8 Symbolic Display and Input - -The PDP-8 simulator implements symbolic display and input. Display is -controlled by command line switches: - - -a display as ASCII character - -c display as (sixbit) character string - -t display as (TSS/8 sixbit) 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 - # or -t two character TSS/8 sixbit string - alphabetic instruction mnemonic - numeric octal number - -Instruction input uses standard PDP-8 assembler syntax. There are four -instruction classes: memory reference, IOT, field change, and operate. - -Memory reference instructions have the format - - memref {I} {C/Z} address - -where I signifies indirect, C a current page reference, and Z a zero page -reference. The address is an octal number in the range 0 - 07777; if C or -Z is specified, the address is a page offset in the range 0 - 177. Normally, -C is not needed; the simulator figures out from the address what mode to use. -However, when referencing memory outside the CPU (eg, disks), there is no -valid PC, and C must be used to specify current page addressing. - -IOT instructions consist of single mnemonics, eg, KRB, TLS. IOT instructions -may be or'd together - - iot iot iot... - -The simulator does not check the legality of the proposed combination. IOT's -for which there is no opcode may be specified as IOT n, where n is an octal -number in the range 0 - 0777. - -Field change instructions (CIF, CDF) have the format - - fldchg field - -where field is an octal number in the range 0 - 7. Field change instructions -may be or'd together. - -Operate instructions have the format - - opr opr opr... - -The simulator does not check the legality of the proposed combination. EAE -mode A and B mnemonics may be specified regardless of the EAE mode. The -operands for MUY and DVI must be deposited explicitly. diff --git a/PDP8/pdp8_dt.c b/PDP8/pdp8_dt.c deleted file mode 100644 index f2c62316..00000000 --- a/PDP8/pdp8_dt.c +++ /dev/null @@ -1,1174 +0,0 @@ -/* pdp8_dt.c: PDP-8 DECtape simulator - - 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. - - dt TC08/TU56 DECtape - - 25-Apr-03 RMS Revised for extended file support - 14-Mar-03 RMS Fixed sizing interaction with save/restore - 17-Oct-02 RMS Fixed bug in end of reel logic - 04-Oct-02 RMS Added DIB, device number support - 12-Sep-02 RMS Added support for 16b format - 30-May-02 RMS Widened POS to 32b - 06-Jan-02 RMS Changed enable/disable support - 30-Nov-01 RMS Added read only unit, extended SET/SHOW support - 24-Nov-01 RMS Changed POS, STATT, LASTT, FLG to arrays - 29-Aug-01 RMS Added casts to PDP-18b packup routine - 17-Jul-01 RMS Moved function prototype - 11-May-01 RMS Fixed bug in reset - 25-Apr-01 RMS Added device enable/disable support - 18-Apr-01 RMS Changed to rewind tape before boot - 19-Mar-01 RMS Changed bootstrap to support 4k disk monitor - 15-Mar-01 RMS Added 129th word to PDP-8 format - - PDP-8 DECtapes are represented in memory by fixed length buffer of 16b 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 18/36bb DECtape file is read in, it is converted to 12b 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). - - 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. -*/ - -#include "pdp8_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 07754 /* word count */ -#define DT_CA 07755 /* 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 */ - -/* 16b, 18b, 36b DECtape constants */ - -#define D18_WSIZE 6 /* word size in lines */ -#define D18_BSIZE 384 /* block size in 12b */ -#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 D18_NBSIZE ((D18_BSIZE * D8_WSIZE) / D18_WSIZE) -#define D18_FILSIZ (D18_NBSIZE * D18_TSIZE * sizeof (int32)) -#define D11_FILSIZ (D18_NBSIZE * D18_TSIZE * sizeof (int16)) - -/* 12b DECtape constants */ - -#define D8_WSIZE 4 /* word size in lines */ -#define D8_BSIZE 129 /* block size in 12b */ -#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_FILSIZ (D8_CAPAC * sizeof (int16)) - -/* This controller */ - -#define DT_CAPAC D8_CAPAC /* default */ -#define DT_WSIZE D8_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 9 /* unit select */ -#define DTA_M_UNIT 07 -#define DTA_UNIT (DTA_M_UNIT << DTA_V_UNIT) -#define DTA_V_MOT 7 /* motion */ -#define DTA_M_MOT 03 -#define DTA_V_MODE 6 /* mode */ -#define DTA_V_FNC 3 /* function */ -#define DTA_M_FNC 07 -#define FNC_MOVE 00 /* move */ -#define FNC_SRCH 01 /* search */ -#define FNC_READ 02 /* read */ -#define FNC_RALL 03 /* read all */ -#define FNC_WRIT 04 /* write */ -#define FNC_WALL 05 /* write all */ -#define FNC_WMRK 06 /* write timing */ -#define DTA_V_ENB 2 /* int enable */ -#define DTA_V_CERF 1 /* clr error flag */ -#define DTA_V_CDTF 0 /* clr DECtape flag */ -#define DTA_FWDRV (1u << (DTA_V_MOT + 1)) -#define DTA_STSTP (1u << DTA_V_MOT) -#define DTA_MODE (1u << DTA_V_MODE) -#define DTA_ENB (1u << DTA_V_ENB) -#define DTA_CERF (1u << DTA_V_CERF) -#define DTA_CDTF (1u << DTA_V_CDTF) -#define DTA_RW (07777 & ~(DTA_CERF | DTA_CDTF)) - -#define DTA_GETUNIT(x) (((x) >> DTA_V_UNIT) & DTA_M_UNIT) -#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_ERF 11 /* error flag */ -#define DTB_V_MRK 10 /* mark trk err */ -#define DTB_V_END 9 /* end zone err */ -#define DTB_V_SEL 8 /* select err */ -#define DTB_V_PAR 7 /* parity err */ -#define DTB_V_TIM 6 /* timing err */ -#define DTB_V_MEX 3 /* memory extension */ -#define DTB_M_MEX 07 -#define DTB_MEX (DTB_M_MEX << DTB_V_MEX) -#define DTB_V_DTF 0 /* DECtape flag */ -#define DTB_ERF (1u << DTB_V_ERF) -#define DTB_MRK (1u << DTB_V_MRK) -#define DTB_END (1u << DTB_V_END) -#define DTB_SEL (1u << DTB_V_SEL) -#define DTB_PAR (1u << DTB_V_PAR) -#define DTB_TIM (1u << DTB_V_TIM) -#define DTB_DTF (1u << DTB_V_DTF) -#define DTB_ALLERR (DTB_ERF | DTB_MRK | DTB_END | DTB_SEL | \ - DTB_PAR | DTB_TIM) -#define DTB_GETMEX(x) (((x) & DTB_MEX) << (12 - DTB_V_MEX)) - -/* 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 DT_UPDINT if ((dtsa & DTA_ENB) && (dtsb & (DTB_ERF | DTB_DTF))) \ - int_req = int_req | INT_DTA; \ - else int_req = int_req & ~INT_DTA; -#define ABS(x) (((x) < 0)? (-(x)): (x)) - -extern uint16 M[]; -extern int32 int_req; -extern UNIT cpu_unit; -extern int32 sim_switches; - -int32 dtsa = 0; /* status A */ -int32 dtsb = 0; /* status B */ -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; /* debug */ -int32 dt_logblk = 0; - -DEVICE dt_dev; -int32 dt76 (int32 IR, int32 AC); -int32 dt77 (int32 IR, int32 AC); -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); -t_stat dt_boot (int32 unitno, DEVICE *dptr); -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, int32 dir); -extern int32 sim_is_running; - -/* DT data structures - - dt_dev DT device descriptor - dt_unit DT unit list - dt_reg DT register list - dt_mod DT modifier list -*/ - -DIB dt_dib = { DEV_DTA, 2, { &dt76, &dt77 } }; - -UNIT dt_unit[] = { - { UDATA (&dt_svc, UNIT_8FMT+UNIT_FIX+UNIT_ATTABLE+ - UNIT_DISABLE+UNIT_ROABLE, DT_CAPAC) }, - { UDATA (&dt_svc, UNIT_8FMT+UNIT_FIX+UNIT_ATTABLE+ - UNIT_DISABLE+UNIT_ROABLE, DT_CAPAC) }, - { UDATA (&dt_svc, UNIT_8FMT+UNIT_FIX+UNIT_ATTABLE+ - UNIT_DISABLE+UNIT_ROABLE, DT_CAPAC) }, - { UDATA (&dt_svc, UNIT_8FMT+UNIT_FIX+UNIT_ATTABLE+ - UNIT_DISABLE+UNIT_ROABLE, DT_CAPAC) }, - { UDATA (&dt_svc, UNIT_8FMT+UNIT_FIX+UNIT_ATTABLE+ - UNIT_DISABLE+UNIT_ROABLE, DT_CAPAC) }, - { UDATA (&dt_svc, UNIT_8FMT+UNIT_FIX+UNIT_ATTABLE+ - UNIT_DISABLE+UNIT_ROABLE, DT_CAPAC) }, - { UDATA (&dt_svc, UNIT_8FMT+UNIT_FIX+UNIT_ATTABLE+ - UNIT_DISABLE+UNIT_ROABLE, DT_CAPAC) }, - { UDATA (&dt_svc, UNIT_8FMT+UNIT_FIX+UNIT_ATTABLE+ - UNIT_DISABLE+UNIT_ROABLE, DT_CAPAC) } }; - -REG dt_reg[] = { - { ORDATA (DTSA, dtsa, 12) }, - { ORDATA (DTSB, dtsb, 12) }, - { FLDATA (INT, int_req, INT_V_DTA) }, - { FLDATA (ENB, dtsa, DTA_V_ENB) }, - { FLDATA (DTF, dtsb, DTB_V_DTF) }, - { FLDATA (ERF, dtsb, DTB_V_ERF) }, - { ORDATA (WC, M[DT_WC], 18) }, - { ORDATA (CA, M[DT_CA], 18) }, - { 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, T_ADDR_W, 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) }, - { ORDATA (DEVNUM, dt_dib.dev, 6), 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 }, - { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", - &set_dev, &show_dev, NULL }, - { 0 } }; - -DEVICE dt_dev = { - "DT", dt_unit, dt_reg, dt_mod, - DT_NUMDR, 8, 24, 1, 8, 12, - NULL, NULL, &dt_reset, - &dt_boot, &dt_attach, &dt_detach, - &dt_dib, DEV_DISABLE }; - -/* IOT routines */ - -int32 dt76 (int32 IR, int32 AC) -{ -int32 pulse = IR & 07; -int32 old_dtsa = dtsa, fnc; -UNIT *uptr; - -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 ((old_dtsa ^ dtsa) & DTA_UNIT) dt_deselect (old_dtsa); - uptr = dt_dev.units + DTA_GETUNIT (dtsa); /* get unit */ - fnc = DTA_GETFNC (dtsa); /* get fnc */ - if (((uptr->flags) & UNIT_DIS) || /* disabled? */ - (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 */ - else dt_newsa (dtsa); - DT_UPDINT; } -return AC; -} - -int32 dt77 (int32 IR, int32 AC) -{ -int32 pulse = IR & 07; - -if ((pulse & 01) && (dtsb & (DTB_ERF |DTB_DTF))) /* DTSF */ - AC = IOT_SKP | AC; -if (pulse & 02) AC = AC | dtsb; /* DTRB */ -if (pulse & 04) { /* DTLB */ - dtsb = (dtsb & ~DTB_MEX) | (AC & DTB_MEX); - AC = AC & ~07777; } /* clear AC */ -return AC; -} - -/* Unit deselect */ - -void dt_deselect (int32 oldf) -{ -int32 old_unit = DTA_GETUNIT (oldf); -UNIT *uptr = dt_dev.units + old_unit; -int32 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, old units */ -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, relpos, 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_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; } - if (dir) newpos = DT_BLK2LN (((relpos >= (DTU_LPERB (uptr) - DT_HTLIN))? - blk + 1: blk), uptr) - DT_HTLIN - DT_WSIZE; - else newpos = DT_BLK2LN (((relpos < DT_HTLIN)? - blk: blk + 1), uptr) + DT_HTLIN + (DT_WSIZE - 1); - break; -default: - dt_seterr (uptr, DTB_SEL); /* bad state */ - return; } -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); -int16 *bptr = uptr->filebuf; -int32 unum = uptr - dt_dev.units; -int32 blk, wrd, ma, relpos, dat; -uint32 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 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 */ - 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 */ - break; -case DTS_OFR: /* off reel */ - detach_unit (uptr); /* must be deselected */ - uptr->STATE = uptr->pos = 0; /* no visible action */ - break; - -/* Read has four subcases - - Start of block, not wc ovf - check that DTF is clear, otherwise normal - Normal - increment MA, WC, copy word from tape to memory - if read dir != write dir, bits must be scrambled - if wc overflow, next state is wc overflow - if end of block, possibly set DTF, next state is start of block - Wc ovf, not start of block - - if end of block, possibly set DTF, next state is start of block - Wc ovf, start of block - if end of block reached, timing error, - otherwise, continue to next word -*/ - -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 */ - 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? */ - 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; - 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; } - break; - -/* Write has four subcases - - Start of block, not wc ovf - check that DTF is clear, set block direction - Normal - increment MA, WC, copy word from memory to tape - if wc overflow, next state is wc overflow - if end of block, possibly set DTF, next state is start of block - Wc ovf, not start of block - - copy 0 to tape - if end of block, possibly set DTF, next state is start of block - Wc ovf, start of block - schedule end zone -*/ - -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 */ - case 0: /* normal write */ - 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 */ - break; - case DTO_WCO | DTO_SOB: /* all done */ - dt_schedez (uptr, dir); /* sched end zone */ - break; } - break; - -/* Read all has two subcases - - Not word count overflow - increment MA, WC, copy word from tape to memory - Word count overflow - schedule end zone -*/ - -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; - case DTO_WCO: case DTO_WCO | DTO_SOB: /* all done */ - dt_schedez (uptr, dir); /* sched end zone */ - break; } /* end case substate */ - break; - -/* Write all has two subcases - - Not word count overflow - increment MA, WC, copy word from memory to tape - Word count overflow - schedule end zone -*/ - -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; } -/* /* 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; - case DTO_WCO: case DTO_WCO | DTO_SOB: /* all done */ - dt_schedez (uptr, dir); /* sched end zone */ - break; } /* end case substate */ - break; -default: - dt_seterr (uptr, DTB_SEL); /* impossible state */ - break; } -DT_UPDINT; /* update interrupts */ -return SCPE_OK; -} - -/* Reading the header is complicated, because 18b words are being parsed - out 12b at a time. The sequence of word numbers is directionally - sensitive - - Forward Reverse - Word Word Content Word Word Content - (abs) (rel) (abs) (rel) - - 137 8 rev csm'00 6 6 fwd csm'00 - 138 9 0000 5 5 0000 - 139 10 0000 4 4 0000 - 140 11 0000 3 3 0000 - 141 12 00'lo rev blk 2 2 00'lo fwd blk - 142 13 hi rev blk 1 1 hi fwd blk - 143 14 0000 0 0 0000 - 0 0 0000 143 14 0000 - 1 1 0000 142 13 0000 - 2 2 hi fwd blk 141 12 hi rev blk - 3 3 lo fwd blk'00 140 11 lo rev blk'00 - 4 4 0000 139 10 0000 - 5 5 0000 138 9 0000 - 6 6 0000 137 8 0000 - 7 7 00'fwd csm 136 7 00'rev csm -*/ - -int32 dt_gethdr (UNIT *uptr, int32 blk, int32 relpos, int32 dir) -{ -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))); - case 2: /* lo fwd blk */ - return dt_comobv ((blk & 077) << 6); - case 1: /* hi fwd blk */ - return dt_comobv (blk >> 6); - case 12: /* hi rev blk */ - return (blk >> 6) & 07777; - case 11: /* lo rev blk */ - return ((blk & 077) << 6); - default: /* others */ - return 077; } } -else { /* forward */ - switch (relpos / DT_WSIZE) { - case 8: /* rev csum */ - return (dt_csum (uptr, blk) << 6); - case 12: /* lo rev blk */ - return dt_comobv ((blk & 077) << 6); - case 13: /* hi rev blk */ - return dt_comobv (blk >> 6); - case 2: /* hi fwd blk */ - return ((blk >> 6) & 07777); - case 3: /* lo fwd blk */ - return ((blk & 077) << 6); - default: /* others */ - break; } } -return 0; -} - -/* 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 ^ 07777; /* compl obverse */ -dat = ((dat >> 9) & 07) | ((dat >> 3) & 070) | - ((dat & 070) << 3) | ((dat & 07) << 9); -return dat; -} - -/* Checksum routine */ - -int32 dt_csum (UNIT *uptr, int32 blk) -{ -int16 *bptr = uptr->filebuf; -int32 ba = blk * DTU_BSIZE (uptr); -int32 i, csum, wrd; - -csum = 077; /* init csum */ -for (i = 0; i < DTU_BSIZE (uptr); i++) { /* loop thru buf */ - wrd = bptr[ba + i] ^ 07777; /* get ~word */ - csum = csum ^ (wrd >> 6) ^ wrd; } -return (csum & 077); -} - -/* Reset routine */ - -t_stat dt_reset (DEVICE *dptr) -{ -int32 i, prev_mot; -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 (); } } -dtsa = dtsb = 0; /* clear status */ -DT_UPDINT; /* reset interrupt */ -return SCPE_OK; -} - -/* Bootstrap routine - - This is actually the 4K disk monitor bootstrap, which also - works with OS/8. The reverse is not true - the OS/8 bootstrap - doesn't work with the disk monitor. -*/ - -#define BOOT_START 0200 -#define BOOT_LEN (sizeof (boot_rom) / sizeof (int16)) - -static const uint16 boot_rom[] = { - 07600, /* 200, CLA CLL */ - 01216, /* TAD MVB ; move back */ - 04210, /* JMS DO ; action */ - 01217, /* TAD K7577 ; addr */ - 03620, /* DCA I CA */ - 01222, /* TAD RDF ; read fwd */ - 04210, /* JMS DO ; action */ - 05600, /* JMP I 200 ; enter boot */ - 00000, /* DO, 0 */ - 06766, /* DTCA!DTXA ; start tape */ - 03621, /* DCA I WC ; clear wc */ - 06771, /* DTSF ; wait */ - 05213, /* JMP .-1 */ - 05610, /* JMP I DO */ - 00600, /* MVB, 0600 */ - 07577, /* K7577, 7757 */ - 07755, /* CA, 7755 */ - 07754, /* WC, 7754 */ - 00220 /* RF, 0220 */ -}; - -t_stat dt_boot (int32 unitno, DEVICE *dptr) -{ -int32 i; -extern int32 saved_PC; - -if (unitno) return SCPE_ARG; /* only unit 0 */ -if (dt_dib.dev != DEV_DTA) return STOP_NOTSTD; /* only std devno */ -dt_unit[unitno].pos = DT_EZLIN; -for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i]; -saved_PC = BOOT_START; -return SCPE_OK; -} - -/* Attach routine - - Determine 12b, 16b, or 18b/36b format - Allocate buffer - If 16b or 18b, read 16b or 18b format and convert to 12b in buffer - If 12b, read data into buffer -*/ - -t_stat dt_attach (UNIT *uptr, char *cptr) -{ -uint32 pdp18b[D18_NBSIZE]; -uint16 pdp11b[D18_NBSIZE], *bptr; -int32 i, k; -int32 u = uptr - dt_dev.units; -t_stat r; -uint32 ba, sz; - -r = attach_unit (uptr, cptr); /* attach */ -if (r != SCPE_OK) return r; /* fail? */ -if ((sim_switches & SIM_SW_REST) == 0) { /* not from rest? */ - uptr->flags = (uptr->flags | UNIT_8FMT) & ~UNIT_11FMT; - if (sim_switches & SWMASK ('T')) /* att 18b? */ - uptr->flags = uptr->flags & ~UNIT_8FMT; - else if (sim_switches & SWMASK ('S')) /* att 16b? */ - uptr->flags = (uptr->flags | UNIT_11FMT) & ~UNIT_8FMT; - else if (!(sim_switches & SWMASK ('R')) && /* autosize? */ - (sz = sim_fsize (cptr))) { - if (sz == D11_FILSIZ) - uptr->flags = (uptr->flags | UNIT_11FMT) & ~UNIT_8FMT; - else if (sz > D8_FILSIZ) - uptr->flags = uptr->flags & ~UNIT_8FMT; } } -uptr->capac = DTU_CAPAC (uptr); /* set capacity */ -uptr->filebuf = calloc (uptr->capac, sizeof (int16)); -if (uptr->filebuf == NULL) { /* can't alloc? */ - detach_unit (uptr); - return SCPE_MEM; } -bptr = uptr->filebuf; /* file buffer */ -printf ("%s%d: ", sim_dname (&dt_dev), u); -if (uptr->flags & UNIT_8FMT) printf ("12b format"); -else if (uptr->flags & UNIT_11FMT) printf ("16b format"); -else printf ("18b/36b format"); -printf (", buffering file in memory\n"); -if (uptr->flags & UNIT_8FMT) /* 12b? */ - uptr->hwmark = fxread (uptr->filebuf, sizeof (int16), - uptr->capac, uptr->fileref); -else { /* 16b/18b */ - for (ba = 0; ba < uptr->capac; ) { /* loop thru file */ - if (uptr->flags & UNIT_11FMT) { - k = fxread (pdp11b, sizeof (int16), D18_NBSIZE, uptr->fileref); - for (i = 0; i < k; i++) pdp18b[i] = pdp11b[i]; } - else k = fxread (pdp18b, sizeof (int32), D18_NBSIZE, uptr->fileref); - if (k == 0) break; - for ( ; k < D18_NBSIZE; k++) pdp18b[k] = 0; - for (k = 0; k < D18_NBSIZE; k = k + 2) { /* loop thru blk */ - bptr[ba] = (pdp18b[k] >> 6) & 07777; - bptr[ba + 1] = ((pdp18b[k] & 077) << 6) | - ((pdp18b[k + 1] >> 12) & 077); - bptr[ba + 2] = pdp18b[k + 1] & 07777; - ba = ba + 3; } /* end blk loop */ - } /* end file loop */ - uptr->hwmark = ba; } /* end else */ -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, write buffer to file - If 16b or 18b, convert 12b buffer to 16b or 18b and write to file - Deallocate buffer -*/ - -t_stat dt_detach (UNIT* uptr) -{ -uint32 pdp18b[D18_NBSIZE]; -uint16 pdp11b[D18_NBSIZE], *bptr; -int32 i, k; -int32 u = uptr - dt_dev.units; -uint32 ba; - -if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; -if (sim_is_active (uptr)) { - sim_cancel (uptr); - if ((u == 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 ("%s%d: writing buffer to file\n", sim_dname (&dt_dev), u); - rewind (uptr->fileref); /* start of file */ - if (uptr->flags & UNIT_8FMT) /* PDP8? */ - fxwrite (uptr->filebuf, sizeof (int16), /* write file */ - uptr->hwmark, uptr->fileref); - else { /* 16b/18b */ - for (ba = 0; ba < uptr->hwmark; ) { /* loop thru buf */ - for (k = 0; k < D18_NBSIZE; k = k + 2) { - pdp18b[k] = ((uint32) (bptr[ba] & 07777) << 6) | - ((uint32) (bptr[ba + 1] >> 6) & 077); - pdp18b[k + 1] = ((uint32) (bptr[ba + 1] & 077) << 12) | - ((uint32) (bptr[ba + 2] & 07777)); - ba = ba + 3; } /* end loop blk */ - if (uptr->flags & UNIT_11FMT) { /* 16b? */ - for (i = 0; i < D18_NBSIZE; i++) pdp11b[i] = pdp18b[i]; - fxwrite (pdp11b, sizeof (int16), - D18_NBSIZE, uptr->fileref); } - else fxwrite (pdp18b, sizeof (int32), - D18_NBSIZE, uptr->fileref); - } /* end loop buf */ - } /* end else */ - 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/PDP8/pdp8_lp.c b/PDP8/pdp8_lp.c deleted file mode 100644 index 48bda59f..00000000 --- a/PDP8/pdp8_lp.c +++ /dev/null @@ -1,165 +0,0 @@ -/* pdp8_lp.c: PDP-8 line printer simulator - - 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. - - lpt LP8E line printer - - 25-Apr-03 RMS Revised for extended file support - 04-Oct-02 RMS Added DIB, enable/disable, device number support - 30-May-02 RMS Widened POS to 32b -*/ - -#include "pdp8_defs.h" - -extern int32 int_req, int_enable, dev_done, stop_inst; - -int32 lpt_err = 0; /* error flag */ -int32 lpt_stopioe = 0; /* stop on error */ - -DEVICE lpt_dev; -int32 lpt (int32 IR, int32 AC); -t_stat lpt_svc (UNIT *uptr); -t_stat lpt_reset (DEVICE *dptr); -t_stat lpt_attach (UNIT *uptr, char *cptr); -t_stat lpt_detach (UNIT *uptr); - -/* LPT data structures - - lpt_dev LPT device descriptor - lpt_unit LPT unit descriptor - lpt_reg LPT register list -*/ - -DIB lpt_dib = { DEV_LPT, 1, { &lpt } }; - -UNIT lpt_unit = { - UDATA (&lpt_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT }; - -REG lpt_reg[] = { - { ORDATA (BUF, lpt_unit.buf, 8) }, - { FLDATA (ERR, lpt_err, 0) }, - { FLDATA (DONE, dev_done, INT_V_LPT) }, - { FLDATA (ENABLE, int_enable, INT_V_LPT) }, - { FLDATA (INT, int_req, INT_V_LPT) }, - { DRDATA (POS, lpt_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, lpt_unit.wait, 24), PV_LEFT }, - { FLDATA (STOP_IOE, lpt_stopioe, 0) }, - { ORDATA (DEVNUM, lpt_dib.dev, 6), REG_HRO }, - { NULL } }; - -MTAB lpt_mod[] = { - { 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, 8, 8, - NULL, NULL, &lpt_reset, - NULL, &lpt_attach, &lpt_detach, - &lpt_dib, DEV_DISABLE }; - -/* IOT routine */ - -int32 lpt (int32 IR, int32 AC) -{ -switch (IR & 07) { /* decode IR<9:11> */ -case 1: /* PSKF */ - return (dev_done & INT_LPT)? IOT_SKP + AC: AC; -case 2: /* PCLF */ - dev_done = dev_done & ~INT_LPT; /* clear flag */ - int_req = int_req & ~INT_LPT; /* clear int req */ - return AC; -case 3: /* PSKE */ - return (lpt_err)? IOT_SKP + AC: AC; -case 6: /* PCLF!PSTB */ - dev_done = dev_done & ~INT_LPT; /* clear flag */ - int_req = int_req & ~INT_LPT; /* clear int req */ -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; } - return (lpt_svc (&lpt_unit) << IOT_V_REASON) + AC; -case 5: /* PSIE */ - int_enable = int_enable | INT_LPT; /* set enable */ - int_req = INT_UPDATE; /* update interrupts */ - return AC; -case 7: /* PCIE */ - int_enable = int_enable & ~INT_LPT; /* clear enable */ - int_req = int_req & ~INT_LPT; /* clear int req */ - return AC; -default: - return (stop_inst << IOT_V_REASON) + AC; } /* end switch */ -} - -/* Unit service */ - -t_stat lpt_svc (UNIT *uptr) -{ -dev_done = dev_done | INT_LPT; /* set done */ -int_req = INT_UPDATE; /* update interrupts */ -if ((lpt_unit.flags & UNIT_ATT) == 0) { - lpt_err = 1; - return IORETURN (lpt_stopioe, SCPE_UNATT); } -if (putc (lpt_unit.buf, lpt_unit.fileref) == EOF) { - perror ("LPT I/O error"); - clearerr (lpt_unit.fileref); - return SCPE_IOERR; } -lpt_unit.pos = lpt_unit.pos + 1; -return SCPE_OK; -} - -/* Reset routine */ - -t_stat lpt_reset (DEVICE *dptr) -{ -lpt_unit.buf = 0; -dev_done = dev_done & ~INT_LPT; /* clear done, int */ -int_req = int_req & ~INT_LPT; -int_enable = int_enable | INT_LPT; /* set enable */ -lpt_err = (lpt_unit.flags & UNIT_ATT) == 0; -sim_cancel (&lpt_unit); /* deactivate unit */ -return SCPE_OK; -} - -/* Attach routine */ - -t_stat lpt_attach (UNIT *uptr, char *cptr) -{ -t_stat reason; - -reason = attach_unit (uptr, cptr); -lpt_err = (lpt_unit.flags & UNIT_ATT) == 0; -return reason; -} - -/* Detach routine */ - -t_stat lpt_detach (UNIT *uptr) -{ -lpt_err = 1; -return detach_unit (uptr); -} diff --git a/PDP8/pdp8_mt.c b/PDP8/pdp8_mt.c deleted file mode 100644 index 315105b8..00000000 --- a/PDP8/pdp8_mt.c +++ /dev/null @@ -1,582 +0,0 @@ -/* pdp8_mt.c: PDP-8 magnetic tape simulator - - 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. - - mt TM8E/TU10 magtape - - 25-Apr-03 RMS Revised for extended file support - 29-Mar-03 RMS Added multiformat support - 04-Mar-03 RMS Fixed bug in SKTR - 01-Mar-03 RMS Fixed interrupt handling - Revised for magtape library - 30-Oct-02 RMS Revised BOT handling, added error record handling - 04-Oct-02 RMS Added DIBs, device number support - 30-Aug-02 RMS Revamped error handling - 28-Aug-02 RMS Added end of medium support - 30-May-02 RMS Widened POS to 32b - 22-Apr-02 RMS Added maximum record length test - 06-Jan-02 RMS Changed enable/disable support - 30-Nov-01 RMS Added read only unit, extended SET/SHOW support - 24-Nov-01 RMS Changed UST, POS, FLG to arrays - 25-Apr-01 RMS Added device enable/disable support - 04-Oct-98 RMS V2.4 magtape format - 22-Jan-97 RMS V2.3 magtape format - 01-Jan-96 RMS Rewritten from TM8-E Maintenance Manual - - Magnetic tapes are represented as a series of variable records - of the form: - - 32b byte count - byte 0 - byte 1 - : - byte n-2 - byte n-1 - 32b byte count - - If the byte count is odd, the record is padded with an extra byte - of junk. File marks are represented by a byte count of 0. -*/ - -#include "pdp8_defs.h" -#include "sim_tape.h" - -#define MT_NUMDR 8 /* #drives */ -#define USTAT u3 /* unit status */ -#define MT_MAXFR (1 << 16) /* max record lnt */ -#define WC_SIZE (1 << 12) /* max word count */ -#define WC_MASK (WC_SIZE - 1) - -/* Command/unit - mt_cu */ - -#define CU_V_UNIT 9 /* unit */ -#define CU_M_UNIT 07 -#define CU_PARITY 00400 /* parity select */ -#define CU_IEE 00200 /* error int enable */ -#define CU_IED 00100 /* done int enable */ -#define CU_V_EMA 3 /* ext mem address */ -#define CU_M_EMA 07 -#define CU_EMA (CU_M_EMA << CU_V_EMA) -#define CU_DTY 00002 /* drive type */ -#define CU_UNPAK 00001 /* 6b vs 8b mode */ -#define GET_UNIT(x) (((x) >> CU_V_UNIT) & CU_M_UNIT) -#define GET_EMA(x) (((x) & CU_EMA) << (12 - CU_V_EMA)) - -/* Function - mt_fn */ - -#define FN_V_FNC 9 /* function */ -#define FN_M_FNC 07 -#define FN_UNLOAD 00 -#define FN_REWIND 01 -#define FN_READ 02 -#define FN_CMPARE 03 -#define FN_WRITE 04 -#define FN_WREOF 05 -#define FN_SPACEF 06 -#define FN_SPACER 07 -#define FN_ERASE 00400 /* erase */ -#define FN_CRC 00200 /* read CRC */ -#define FN_GO 00100 /* go */ -#define FN_INC 00040 /* incr mode */ -#define FN_RMASK 07700 /* readable bits */ -#define GET_FNC(x) (((x) >> FN_V_FNC) & FN_M_FNC) - -/* Status - stored in mt_sta or (*) uptr->USTAT */ - -#define STA_ERR (04000 << 12) /* error */ -#define STA_REW (02000 << 12) /* *rewinding */ -#define STA_BOT (01000 << 12) /* *start of tape */ -#define STA_REM (00400 << 12) /* *offline */ -#define STA_PAR (00200 << 12) /* parity error */ -#define STA_EOF (00100 << 12) /* *end of file */ -#define STA_RLE (00040 << 12) /* rec lnt error */ -#define STA_DLT (00020 << 12) /* data late */ -#define STA_EOT (00010 << 12) /* *end of tape */ -#define STA_WLK (00004 << 12) /* *write locked */ -#define STA_CPE (00002 << 12) /* compare error */ -#define STA_ILL (00001 << 12) /* illegal */ -#define STA_9TK 00040 /* 9 track */ -/* #define STA_BAD 00020 /* bad tape?? */ -#define STA_INC 00010 /* increment error */ -#define STA_LAT 00004 /* lateral par error */ -#define STA_CRC 00002 /* CRC error */ -#define STA_LON 00001 /* long par error */ - -#define STA_CLR (FN_RMASK | 00020) /* always clear */ -#define STA_DYN (STA_REW | STA_BOT | STA_REM | STA_EOF | \ - STA_EOT | STA_WLK) /* kept in USTAT */ - -extern uint16 M[]; -extern int32 int_req, stop_inst; -extern UNIT cpu_unit; - -int32 mt_cu = 0; /* command/unit */ -int32 mt_fn = 0; /* function */ -int32 mt_ca = 0; /* current address */ -int32 mt_wc = 0; /* word count */ -int32 mt_sta = 0; /* status register */ -int32 mt_db = 0; /* data buffer */ -int32 mt_done = 0; /* mag tape flag */ -int32 mt_time = 10; /* record latency */ -int32 mt_stopioe = 1; /* stop on error */ -uint8 *mtxb = NULL; /* transfer buffer */ - -DEVICE mt_dev; -int32 mt70 (int32 IR, int32 AC); -int32 mt71 (int32 IR, int32 AC); -int32 mt72 (int32 IR, int32 AC); -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); -int32 mt_updcsta (UNIT *uptr); -int32 mt_ixma (int32 xma); -t_stat mt_map_err (UNIT *uptr, t_stat st); -t_stat mt_vlock (UNIT *uptr, int32 val, char *cptr, void *desc); -UNIT *mt_busy (void); -void mt_set_done (void); - -/* 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 = { DEV_MT, 3, { &mt70, &mt71, &mt72 } }; - -UNIT mt_unit[] = { - { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) }, - { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) }, - { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) }, - { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) }, - { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) }, - { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) }, - { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) }, - { UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) } }; - -REG mt_reg[] = { - { ORDATA (CMD, mt_cu, 12) }, - { ORDATA (FNC, mt_fn, 12) }, - { ORDATA (CA, mt_ca, 12) }, - { ORDATA (WC, mt_wc, 12) }, - { ORDATA (DB, mt_db, 12) }, - { GRDATA (STA, mt_sta, 8, 12, 12) }, - { ORDATA (STA2, mt_sta, 6) }, - { FLDATA (DONE, mt_done, 0) }, - { FLDATA (INT, int_req, INT_V_MT) }, - { FLDATA (STOP_IOE, mt_stopioe, 0) }, - { DRDATA (TIME, mt_time, 24), PV_LEFT }, - { URDATA (UST, mt_unit[0].USTAT, 8, 16, 0, MT_NUMDR, 0) }, - { URDATA (POS, mt_unit[0].pos, 10, T_ADDR_W, 0, - MT_NUMDR, PV_LEFT | REG_RO) }, - { FLDATA (DEVNUM, mt_dib.dev, 6), REG_HRO }, - { NULL } }; - -MTAB mt_mod[] = { - { MTUF_WLK, 0, "write enabled", "WRITEENABLED", &mt_vlock }, - { MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", &mt_vlock }, - { MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT", - &sim_tape_set_fmt, &sim_tape_show_fmt, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", - &set_dev, &show_dev, NULL }, - { 0 } }; - -DEVICE mt_dev = { - "MT", mt_unit, mt_reg, mt_mod, - MT_NUMDR, 10, 31, 1, 8, 8, - NULL, NULL, &mt_reset, - NULL, &mt_attach, &mt_detach, - &mt_dib, DEV_DISABLE }; - -/* IOT routines */ - -int32 mt70 (int32 IR, int32 AC) -{ -int32 f; -UNIT *uptr; - -uptr = mt_dev.units + GET_UNIT (mt_cu); /* get unit */ -switch (IR & 07) { /* decode IR<9:11> */ -case 1: /* LWCR */ - mt_wc = AC; /* load word count */ - return 0; -case 2: /* CWCR */ - mt_wc = 0; /* clear word count */ - return AC; -case 3: /* LCAR */ - mt_ca = AC; /* load mem address */ - return 0; -case 4: /* CCAR */ - mt_ca = 0; /* clear mem address */ - return AC; -case 5: /* LCMR */ - if (mt_busy ()) mt_sta = mt_sta | STA_ILL | STA_ERR; /* busy? illegal op */ - mt_cu = AC; /* load command reg */ - mt_updcsta (mt_dev.units + GET_UNIT (mt_cu)); - return 0; -case 6: /* LFGR */ - if (mt_busy ()) mt_sta = mt_sta | STA_ILL | STA_ERR; /* busy? illegal op */ - mt_fn = AC; /* load function */ - if ((mt_fn & FN_GO) == 0) { /* go set? */ - mt_updcsta (uptr); /* update status */ - return 0; } - f = GET_FNC (mt_fn); /* get function */ - if (((uptr->flags & UNIT_ATT) == 0) || - sim_is_active (uptr) || - (((f == FN_WRITE) || (f == FN_WREOF)) && sim_tape_wrp (uptr)) - || (((f == FN_SPACER) || (f == FN_REWIND)) && sim_tape_bot (uptr))) { - mt_sta = mt_sta | STA_ILL | STA_ERR; /* 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 */ - else if (f == FN_REWIND) { /* rewind */ - 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 */ - return 0; -case 7: /* LDBR */ - if (mt_busy ()) mt_sta = mt_sta | STA_ILL | STA_ERR; /* busy? illegal op */ - mt_db = AC; /* load buffer */ - mt_set_done (); /* set done */ - mt_updcsta (uptr); /* update status */ - return 0; } /* end switch */ -return (stop_inst << IOT_V_REASON) + AC; /* ill inst */ -} - -/* IOTs, continued */ - -int32 mt71 (int32 IR, int32 AC) -{ -UNIT *uptr; - -uptr = mt_dev.units + GET_UNIT (mt_cu); -switch (IR & 07) { /* decode IR<9:11> */ -case 1: /* RWCR */ - return mt_wc; /* read word count */ -case 2: /* CLT */ - mt_reset (&mt_dev); /* reset everything */ - return AC; -case 3: /* RCAR */ - return mt_ca; /* read mem address */ -case 4: /* RMSR */ - return ((mt_updcsta (uptr) >> 12) & 07777); /* read status */ -case 5: /* RCMR */ - return mt_cu; /* read command */ -case 6: /* RFSR */ - return (((mt_fn & FN_RMASK) | (mt_updcsta (uptr) & ~FN_RMASK)) - & 07777); /* read function */ -case 7: /* RDBR */ - return mt_db; } /* read data buffer */ -return (stop_inst << IOT_V_REASON) + AC; /* ill inst */ -} - -int32 mt72 (int32 IR, int32 AC) -{ -UNIT *uptr; - -uptr = mt_dev.units + GET_UNIT (mt_cu); /* get unit */ -switch (IR & 07) { /* decode IR<9:11> */ -case 1: /* SKEF */ - return (mt_sta & STA_ERR)? IOT_SKP + AC: AC; -case 2: /* SKCB */ - return (!mt_busy ())? IOT_SKP + AC: AC; -case 3: /* SKJD */ - return mt_done? IOT_SKP + AC: AC; -case 4: /* SKTR */ - return (!sim_is_active (uptr) && - (uptr->flags & UNIT_ATT))? IOT_SKP + AC: AC; -case 5: /* CLF */ - if (!sim_is_active (uptr)) mt_reset (&mt_dev); /* if TUR, zap */ - 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 */ -} - -/* Unit service - - If rewind done, reposition to start of tape, set status - else, do operation, set done, interrupt -*/ - -t_stat mt_svc (UNIT *uptr) -{ -int32 f, i, p, u, wc, xma; -t_mtrlnt tbc, cbc; -uint16 c, c1, c2; -t_stat st, r = SCPE_OK; - -u = uptr - mt_dev.units; /* get unit number */ -f = GET_FNC (mt_fn); /* get command */ -xma = GET_EMA (mt_cu) + mt_ca; /* get mem addr */ -wc = WC_SIZE - mt_wc; /* get wc */ - -if (uptr->USTAT & STA_REW) { /* rewind? */ - sim_tape_rewind (uptr); /* update position */ - if (uptr->flags & UNIT_ATT) /* still on line? */ - 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 */ - return SCPE_OK; } - -if ((uptr->flags & UNIT_ATT) == 0) { /* if not attached */ - uptr->USTAT = STA_REM; /* unit off line */ - mt_sta = mt_sta | STA_ILL | STA_ERR; /* illegal operation */ - mt_set_done (); /* set done */ - mt_updcsta (uptr); /* update status */ - return IORETURN (mt_stopioe, SCPE_UNATT); } - -switch (f) { /* case on function */ - -/* Unit service, continued */ - -case FN_READ: /* read */ -case FN_CMPARE: /* read/compare */ - st = sim_tape_rdrecf (uptr, mtxb, &tbc, MT_MAXFR); /* read rec */ - if (st == MTSE_RECE) mt_sta = mt_sta | STA_PAR | STA_ERR; /* rec in err? */ - else if (st != MTSE_OK) { /* other error? */ - r = mt_map_err (uptr, st); /* map error */ - mt_sta = mt_sta | STA_RLE | STA_ERR; /* err, eof/eom, tmk */ - break; } - cbc = (mt_cu & CU_UNPAK)? wc: wc * 2; /* expected bc */ - if (tbc != cbc) mt_sta = mt_sta | STA_RLE | STA_ERR; /* wrong size? */ - if (tbc < cbc) { /* record small? */ - cbc = tbc; /* use smaller */ - wc = (mt_cu & CU_UNPAK)? cbc: (cbc + 1) / 2; } - for (i = p = 0; i < wc; i++) { /* copy buffer */ - xma = mt_ixma (xma); /* increment xma */ - mt_wc = (mt_wc + 1) & 07777; /* incr word cnt */ - if (mt_cu & CU_UNPAK) c = mtxb[p++]; - else { - c1 = mtxb[p++] & 077; - c2 = mtxb[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 | STA_ERR; - break; } } - break; - -case FN_WRITE: /* write */ - tbc = (mt_cu & CU_UNPAK)? wc: wc * 2; - for (i = p = 0; i < wc; i++) { /* copy buf to tape */ - xma = mt_ixma (xma); /* incr mem addr */ - if (mt_cu & CU_UNPAK) mtxb[p++] = M[xma] & 0377; - else { - mtxb[p++] = (M[xma] >> 6) & 077; - mtxb[p++] = M[xma] & 077; } } - if (st = sim_tape_wrrecf (uptr, mtxb, tbc)) { /* write rec, err? */ - r = mt_map_err (uptr, st); /* map error */ - xma = GET_EMA (mt_cu) + mt_ca; } /* restore xma */ - else mt_wc = 0; /* ok, clear wc */ - break; - -/* Unit service, continued */ - -case FN_WREOF: - if (st = sim_tape_wrtmk (uptr)) /* write tmk, err? */ - r = mt_map_err (uptr, st); /* map error */ - break; - -case FN_SPACEF: /* space forward */ - do { - mt_wc = (mt_wc + 1) & 07777; /* incr wc */ - if (st = sim_tape_sprecf (uptr, &tbc)) { /* space rec fwd, err? */ - r = mt_map_err (uptr, st); /* map error */ - break; } /* stop */ - } - while (mt_wc != 0); - break; - -case FN_SPACER: /* space reverse */ - do { - mt_wc = (mt_wc + 1) & 07777; /* incr wc */ - if (st = sim_tape_sprecr (uptr, &tbc)) { /* space rec rev, err? */ - r = mt_map_err (uptr, st); /* map error */ - break; } /* stop */ - } - while (mt_wc != 0); - break; } /* end case */ - -mt_cu = (mt_cu & ~CU_EMA) | ((xma >> (12 - CU_V_EMA)) & CU_EMA); -mt_ca = xma & 07777; /* update mem addr */ -mt_set_done (); /* set done */ -mt_updcsta (uptr); /* update status */ -return r; -} - -/* Update controller status */ - -int32 mt_updcsta (UNIT *uptr) -{ -mt_sta = (mt_sta & ~(STA_DYN | STA_CLR)) | (uptr->USTAT & STA_DYN); -if (((mt_sta & STA_ERR) && (mt_cu & CU_IEE)) || - (mt_done && (mt_cu & CU_IED))) int_req = int_req | INT_MT; -else int_req = int_req & ~INT_MT; -return mt_sta; -} - -/* Test if controller busy */ - -UNIT *mt_busy (void) -{ -int32 u; -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 NULL; -} - -/* Increment extended memory address */ - -int32 mt_ixma (int32 xma) /* incr extended ma */ -{ -int32 v; - -v = ((xma + 1) & 07777) | (xma & 070000); /* wrapped incr */ -if (mt_fn & FN_INC) { /* increment mode? */ - if (xma == 077777) mt_sta = mt_sta | STA_INC | STA_ERR; /* at limit? error */ - else v = xma + 1; } /* else 15b incr */ -return v; -} - -/* Set done */ - -void mt_set_done (void) -{ -mt_done = 1; /* set done */ -mt_fn = mt_fn & ~(FN_CRC | FN_GO | FN_INC); /* clear func<4:6> */ -return; -} - -/* Map tape error status */ - -t_stat mt_map_err (UNIT *uptr, t_stat st) -{ -switch (st) { -case MTSE_FMT: /* illegal fmt */ -case MTSE_UNATT: /* unattached */ - mt_sta = mt_sta | STA_ILL | STA_ERR; -case MTSE_OK: /* no error */ - return SCPE_IERR; /* never get here! */ -case MTSE_TMK: /* end of file */ - uptr->USTAT = uptr->USTAT | STA_EOF; /* set EOF */ - mt_sta = mt_sta | STA_ERR; - break; -case MTSE_IOERR: /* IO error */ - mt_sta = mt_sta | STA_PAR | STA_ERR; /* set par err */ - if (mt_stopioe) return SCPE_IOERR; - break; -case MTSE_INVRL: /* invalid rec lnt */ - mt_sta = mt_sta | STA_PAR | STA_ERR; /* set par err */ - return SCPE_MTRLNT; -case MTSE_RECE: /* record in error */ -case MTSE_EOM: /* end of medium */ - mt_sta = mt_sta | STA_PAR | STA_ERR; /* set par err */ - break; -case MTSE_BOT: /* reverse into BOT */ - uptr->USTAT = uptr->USTAT | STA_BOT; /* set status */ - mt_sta = mt_sta | STA_ERR; - break; -case MTSE_WRP: /* write protect */ - mt_sta = mt_sta | STA_ILL | STA_ERR; /* illegal operation */ - break; } -return SCPE_OK; -} - -/* Reset routine */ - -t_stat mt_reset (DEVICE *dptr) -{ -int32 u; -UNIT *uptr; - -mt_cu = mt_fn = mt_wc = mt_ca = mt_db = mt_sta = mt_done = 0; -int_req = int_req & ~INT_MT; /* clear interrupt */ -for (u = 0; u < MT_NUMDR; u++) { /* loop thru units */ - uptr = mt_dev.units + u; - sim_cancel (uptr); /* cancel activity */ - sim_tape_reset (uptr); /* reset tape */ - if (uptr->flags & UNIT_ATT) uptr->USTAT = - (sim_tape_bot (uptr)? STA_BOT: 0) | - (sim_tape_wrp (uptr)? STA_WLK: 0); - else uptr->USTAT = STA_REM; } -if (mtxb == NULL) mtxb = calloc (MT_MAXFR, sizeof (uint8)); -if (mtxb == NULL) return SCPE_MEM; -return SCPE_OK; -} - -/* Attach routine */ - -t_stat mt_attach (UNIT *uptr, char *cptr) -{ -t_stat r; -int32 u = uptr - mt_dev.units; /* get unit number */ - -r = sim_tape_attach (uptr, cptr); -if (r != SCPE_OK) return r; -uptr->USTAT = STA_BOT | (sim_tape_wrp (uptr)? STA_WLK: 0); -if (u == GET_UNIT (mt_cu)) mt_updcsta (uptr); -return r; -} - -/* Detach routine */ - -t_stat mt_detach (UNIT* uptr) -{ -int32 u = uptr - mt_dev.units; /* get unit number */ - -if (!sim_is_active (uptr)) uptr->USTAT = STA_REM; -if (u == GET_UNIT (mt_cu)) mt_updcsta (uptr); -return sim_tape_detach (uptr); -} - -/* Write lock/enable routine */ - -t_stat mt_vlock (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -int32 u = uptr - mt_dev.units; /* get unit number */ - -if ((uptr->flags & UNIT_ATT) && (val || sim_tape_wrp (uptr))) - uptr->USTAT = uptr->USTAT | STA_WLK; -else uptr->USTAT = uptr->USTAT & ~STA_WLK; -if (u == GET_UNIT (mt_cu)) mt_updcsta (uptr); -return SCPE_OK; -} diff --git a/PDP8/pdp8_pt.c b/PDP8/pdp8_pt.c deleted file mode 100644 index 92a39858..00000000 --- a/PDP8/pdp8_pt.c +++ /dev/null @@ -1,266 +0,0 @@ -/* pdp8_pt.c: PDP-8 paper tape reader/punch simulator - - 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. - - ptr,ptp PC8E paper tape reader/punch - - 25-Apr-03 RMS Revised for extended file support - 04-Oct-02 RMS Added DIBs - 30-May-02 RMS Widened POS to 32b - 30-Nov-01 RMS Added read only unit support - 30-Mar-98 RMS Added RIM loader as PTR bootstrap -*/ - -#include "pdp8_defs.h" - -extern int32 int_req, int_enable, dev_done, stop_inst; - -int32 ptr_stopioe = 0, ptp_stopioe = 0; /* stop on error */ - -int32 ptr (int32 IR, int32 AC); -int32 ptp (int32 IR, int32 AC); -t_stat ptr_svc (UNIT *uptr); -t_stat ptp_svc (UNIT *uptr); -t_stat ptr_reset (DEVICE *dptr); -t_stat ptp_reset (DEVICE *dptr); -t_stat ptr_boot (int32 unitno, DEVICE *dptr); - -/* PTR data structures - - ptr_dev PTR device descriptor - ptr_unit PTR unit descriptor - ptr_reg PTR register list -*/ - -DIB ptr_dib = { DEV_PTR, 1, { &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, 8) }, - { FLDATA (DONE, dev_done, INT_V_PTR) }, - { FLDATA (ENABLE, int_enable, INT_V_PTR) }, - { FLDATA (INT, int_req, INT_V_PTR) }, - { DRDATA (POS, ptr_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, ptr_unit.wait, 24), PV_LEFT }, - { FLDATA (STOP_IOE, ptr_stopioe, 0) }, - { NULL } }; - -MTAB ptr_mod[] = { - { MTAB_XTD|MTAB_VDV, 0, "DEVNO", NULL, NULL, &show_dev }, - { 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, 0 }; - -/* PTP data structures - - ptp_dev PTP device descriptor - ptp_unit PTP unit descriptor - ptp_reg PTP register list -*/ - -DIB ptp_dib = { DEV_PTP, 1, { &ptp } }; - -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, dev_done, INT_V_PTP) }, - { FLDATA (ENABLE, int_enable, INT_V_PTP) }, - { FLDATA (INT, int_req, INT_V_PTP) }, - { DRDATA (POS, ptp_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, ptp_unit.wait, 24), PV_LEFT }, - { FLDATA (STOP_IOE, ptp_stopioe, 0) }, - { NULL } }; - -MTAB ptp_mod[] = { - { MTAB_XTD|MTAB_VDV, 0, "DEVNO", NULL, NULL, &show_dev }, - { 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, 0 }; - -/* Paper tape reader: IOT routine */ - -int32 ptr (int32 IR, int32 AC) -{ -switch (IR & 07) { /* decode IR<9:11> */ -case 0: /* RPE */ - int_enable = int_enable | (INT_PTR+INT_PTP); /* set enable */ - int_req = INT_UPDATE; /* update interrupts */ - return AC; -case 1: /* RSF */ - return (dev_done & INT_PTR)? IOT_SKP + AC: AC; -case 6: /* RFC!RRB */ - sim_activate (&ptr_unit, ptr_unit.wait); -case 2: /* RRB */ - dev_done = dev_done & ~INT_PTR; /* clear flag */ - int_req = int_req & ~INT_PTR; /* clear int req */ - return (AC | ptr_unit.buf); /* or data to AC */ -case 4: /* RFC */ - sim_activate (&ptr_unit, ptr_unit.wait); - dev_done = dev_done & ~INT_PTR; /* clear flag */ - int_req = int_req & ~INT_PTR; /* clear int req */ - return AC; -default: - return (stop_inst << IOT_V_REASON) + AC; } /* end switch */ -} - -/* 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) { - 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; } -dev_done = dev_done | INT_PTR; /* set done */ -int_req = INT_UPDATE; /* update interrupts */ -ptr_unit.buf = temp & 0377; -ptr_unit.pos = ptr_unit.pos + 1; -return SCPE_OK; -} - -/* Reset routine */ - -t_stat ptr_reset (DEVICE *dptr) -{ -ptr_unit.buf = 0; -dev_done = dev_done & ~INT_PTR; /* clear done, int */ -int_req = int_req & ~INT_PTR; -int_enable = int_enable | INT_PTR; /* set enable */ -sim_cancel (&ptr_unit); /* deactivate unit */ -return SCPE_OK; -} - -/* Paper tape punch: IOT routine */ - -int32 ptp (int32 IR, int32 AC) -{ -switch (IR & 07) { /* decode IR<9:11> */ -case 0: /* PCE */ - int_enable = int_enable & ~(INT_PTR+INT_PTP); /* clear enables */ - int_req = INT_UPDATE; /* update interrupts */ - return AC; -case 1: /* PSF */ - return (dev_done & INT_PTP)? IOT_SKP + AC: AC; -case 2: /* PCF */ - dev_done = dev_done & ~INT_PTP; /* clear flag */ - int_req = int_req & ~INT_PTP; /* clear int req */ - return AC; -case 6: /* PLS */ - dev_done = dev_done & ~INT_PTP; /* clear flag */ - int_req = int_req & ~INT_PTP; /* clear int req */ -case 4: /* PPC */ - ptp_unit.buf = AC & 0377; /* load punch buf */ - sim_activate (&ptp_unit, ptp_unit.wait); /* activate unit */ - return AC; -default: - return (stop_inst << IOT_V_REASON) + AC; } /* end switch */ -} - -/* Unit service */ - -t_stat ptp_svc (UNIT *uptr) -{ -dev_done = dev_done | INT_PTP; /* set done */ -int_req = INT_UPDATE; /* update interrupts */ -if ((ptp_unit.flags & UNIT_ATT) == 0) /* attached? */ - return IORETURN (ptp_stopioe, SCPE_UNATT); -if (putc (ptp_unit.buf, ptp_unit.fileref) == EOF) { - 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; -dev_done = dev_done & ~INT_PTP; /* clear done, int */ -int_req = int_req & ~INT_PTP; -int_enable = int_enable | INT_PTP; /* set enable */ -sim_cancel (&ptp_unit); /* deactivate unit */ -return SCPE_OK; -} - -/* Bootstrap routine */ - -#define BOOT_START 07756 -#define BOOT_LEN (sizeof (boot_rom) / sizeof (int16)) - -static const uint16 boot_rom[] = { - 06014, /* 7756, RFC */ - 06011, /* 7757, LOOP, RSF */ - 05357, /* JMP .-1 */ - 06016, /* RFC RRB */ - 07106, /* CLL RTL*/ - 07006, /* RTL */ - 07510, /* SPA*/ - 05374, /* JMP 7774 */ - 07006, /* RTL */ - 06011, /* RSF */ - 05367, /* JMP .-1 */ - 06016, /* RFC RRB */ - 07420, /* SNL */ - 03776, /* DCA I 7776 */ - 03376, /* 7774, DCA 7776 */ - 05357, /* JMP 7757 */ - 00000, /* 7776, 0 */ - 05301 /* 7777, JMP 7701 */ -}; - -t_stat ptr_boot (int32 unitno, DEVICE *dptr) -{ -int32 i; -extern int32 saved_PC; -extern uint16 M[]; - -if (ptr_dib.dev != DEV_PTR) return STOP_NOTSTD; /* only std devno */ -for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i]; -saved_PC = BOOT_START; -return SCPE_OK; -} diff --git a/PDP8/pdp8_rf.c b/PDP8/pdp8_rf.c deleted file mode 100644 index c8441147..00000000 --- a/PDP8/pdp8_rf.c +++ /dev/null @@ -1,400 +0,0 @@ -/* pdp8_rf.c: RF08 fixed head disk simulator - - 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. - - rf RF08 fixed head disk - - 26-Jul-03 RMS Fixed bug in set size routine - 14-Mar-03 RMS Fixed variable platter interaction with save/restore - 03-Mar-03 RMS Fixed autosizing - 02-Feb-03 RMS Added variable platter and autosizing support - 04-Oct-02 RMS Added DIB, device number support - 28-Nov-01 RMS Added RL8A support - 25-Apr-01 RMS Added device enable/disable support - 19-Mar-01 RMS Added disk monitor bootstrap, fixed IOT decoding - 15-Feb-01 RMS Fixed 3 cycle data break sequence - 14-Apr-99 RMS Changed t_addr to unsigned - 30-Mar-98 RMS Fixed bug in RF bootstrap - - The RF08 is a head-per-track disk. It uses the three cycle data break - facility. To minimize overhead, the entire RF08 is buffered in memory. - - Two timing parameters are provided: - - rf_time Interword timing, must be non-zero - rf_burst Burst mode, if 0, DMA occurs cycle by cycle; otherwise, - DMA occurs in a burst -*/ - -#include "pdp8_defs.h" -#include - -#define UNIT_V_AUTO (UNIT_V_UF + 0) /* autosize */ -#define UNIT_V_PLAT (UNIT_V_UF + 1) /* #platters - 1 */ -#define UNIT_M_PLAT 03 -#define UNIT_GETP(x) ((((x) >> UNIT_V_PLAT) & UNIT_M_PLAT) + 1) -#define UNIT_AUTO (1 << UNIT_V_AUTO) -#define UNIT_PLAT (UNIT_M_PLAT << UNIT_V_PLAT) - -/* Constants */ - -#define RF_NUMWD 2048 /* words/track */ -#define RF_NUMTR 128 /* tracks/disk */ -#define RF_DKSIZE (RF_NUMTR * RF_NUMWD) /* words/disk */ -#define RF_NUMDK 4 /* disks/controller */ -#define RF_WC 07750 /* word count */ -#define RF_MA 07751 /* mem address */ -#define RF_WMASK (RF_NUMWD - 1) /* word mask */ - -/* Parameters in the unit descriptor */ - -#define FUNC u4 /* function */ -#define RF_READ 2 /* read */ -#define RF_WRITE 4 /* write */ - -/* Status register */ - -#define RFS_PCA 04000 /* photocell status */ -#define RFS_DRE 02000 /* data req enable */ -#define RFS_WLS 01000 /* write lock status */ -#define RFS_EIE 00400 /* error int enable */ -#define RFS_PIE 00200 /* photocell int enb */ -#define RFS_CIE 00100 /* done int enable */ -#define RFS_MEX 00070 /* memory extension */ -#define RFS_DRL 00004 /* data late error */ -#define RFS_NXD 00002 /* non-existent disk */ -#define RFS_PER 00001 /* parity error */ -#define RFS_ERR (RFS_WLS + RFS_DRL + RFS_NXD + RFS_PER) -#define RFS_V_MEX 3 - -#define GET_MEX(x) (((x) & RFS_MEX) << (12 - RFS_V_MEX)) -#define GET_POS(x) ((int) fmod (sim_gtime() / ((double) (x)), \ - ((double) RF_NUMWD))) -#define UPDATE_PCELL if (GET_POS(rf_time) < 6) rf_sta = rf_sta | RFS_PCA; \ - else rf_sta = rf_sta & ~RFS_PCA -#define RF_INT_UPDATE if ((rf_done && (rf_sta & RFS_CIE)) || \ - ((rf_sta & RFS_ERR) && (rf_sta & RFS_EIE)) || \ - ((rf_sta & RFS_PCA) && (rf_sta & RFS_PIE))) \ - int_req = int_req | INT_RF; \ - else int_req = int_req & ~INT_RF - -extern uint16 M[]; -extern int32 int_req, stop_inst; -extern UNIT cpu_unit; - -int32 rf_sta = 0; /* status register */ -int32 rf_da = 0; /* disk address */ -int32 rf_done = 0; /* done flag */ -int32 rf_wlk = 0; /* write lock */ -int32 rf_time = 10; /* inter-word time */ -int32 rf_burst = 1; /* burst mode flag */ -int32 rf_stopioe = 1; /* stop on error */ - -DEVICE rf_dev; -int32 rf60 (int32 IR, int32 AC); -int32 rf61 (int32 IR, int32 AC); -int32 rf62 (int32 IR, int32 AC); -int32 rf64 (int32 IR, int32 AC); -t_stat rf_svc (UNIT *uptr); -t_stat pcell_svc (UNIT *uptr); -t_stat rf_reset (DEVICE *dptr); -t_stat rf_boot (int32 unitno, DEVICE *dptr); -t_stat rf_attach (UNIT *uptr, char *cptr); -t_stat rf_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); - -/* RF08 data structures - - rf_dev RF device descriptor - rf_unit RF unit descriptor - pcell_unit photocell timing unit (orphan) - rf_reg RF register list -*/ - -DIB rf_dib = { DEV_RF, 5, { &rf60, &rf61, &rf62, NULL, &rf64 } }; - -UNIT rf_unit = - { UDATA (&rf_svc, UNIT_FIX+UNIT_ATTABLE+ - UNIT_BUFABLE+UNIT_MUSTBUF, RF_DKSIZE) }; - -UNIT pcell_unit = { UDATA (&pcell_svc, 0, 0) }; - -REG rf_reg[] = { - { ORDATA (STA, rf_sta, 12) }, - { ORDATA (DA, rf_da, 20) }, - { ORDATA (WC, M[RF_WC], 12) }, - { ORDATA (MA, M[RF_MA], 12) }, - { FLDATA (DONE, rf_done, 0) }, - { FLDATA (INT, int_req, INT_V_RF) }, - { ORDATA (WLK, rf_wlk, 32) }, - { DRDATA (TIME, rf_time, 24), REG_NZ + PV_LEFT }, - { FLDATA (BURST, rf_burst, 0) }, - { FLDATA (STOP_IOE, rf_stopioe, 0) }, - { DRDATA (CAPAC, rf_unit.capac, 21), REG_HRO }, - { ORDATA (DEVNUM, rf_dib.dev, 6), REG_HRO }, - { NULL } }; - -MTAB rf_mod[] = { - { UNIT_PLAT, (0 << UNIT_V_PLAT), NULL, "1P", &rf_set_size }, - { UNIT_PLAT, (1 << UNIT_V_PLAT), NULL, "2P", &rf_set_size }, - { UNIT_PLAT, (2 << UNIT_V_PLAT), NULL, "3P", &rf_set_size }, - { UNIT_PLAT, (3 << UNIT_V_PLAT), NULL, "4P", &rf_set_size }, - { UNIT_AUTO, UNIT_AUTO, "autosize", "AUTOSIZE", NULL }, - { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", - &set_dev, &show_dev, NULL }, - { 0 } }; - -DEVICE rf_dev = { - "RF", &rf_unit, rf_reg, rf_mod, - 1, 8, 20, 1, 8, 12, - NULL, NULL, &rf_reset, - &rf_boot, &rf_attach, NULL, - &rf_dib, DEV_DISABLE | DEV_DIS }; - -/* IOT routines */ - -int32 rf60 (int32 IR, int32 AC) -{ -int32 t; -int32 pulse = IR & 07; - -UPDATE_PCELL; /* update photocell */ -if (pulse & 1) { /* DCMA */ - rf_da = rf_da & ~07777; /* clear DAR<8:19> */ - rf_done = 0; /* clear done */ - rf_sta = rf_sta & ~RFS_ERR; /* clear errors */ - RF_INT_UPDATE; } /* update int req */ -if (pulse & 6) { /* DMAR, DMAW */ - rf_da = rf_da | AC; /* DAR<8:19> |= AC */ - rf_unit.FUNC = pulse & ~1; /* save function */ - t = (rf_da & RF_WMASK) - GET_POS (rf_time); /* delta to new loc */ - if (t < 0) t = t + RF_NUMWD; /* wrap around? */ - sim_activate (&rf_unit, t * rf_time); /* schedule op */ - AC = 0; } /* clear AC */ -return AC; -} - -int32 rf61 (int32 IR, int32 AC) -{ -int32 pulse = IR & 07; - -UPDATE_PCELL; /* update photocell */ -switch (pulse) { /* decode IR<9:11> */ -case 1: /* DCIM */ - rf_sta = rf_sta & 07007; /* clear STA<3:8> */ - int_req = int_req & ~INT_RF; /* clear int req */ - sim_cancel (&pcell_unit); /* cancel photocell */ - return AC; -case 2: /* DSAC */ - return ((rf_da & RF_WMASK) == GET_POS (rf_time))? IOT_SKP: 0; -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); - else sim_cancel (&pcell_unit); - RF_INT_UPDATE; /* update int req */ - return 0; /* clear AC */ -case 6: /* DIMA */ - return rf_sta; } /* AC <- STA<0:11> */ -return AC; -} - -/* IOT's, continued */ - -int32 rf62 (int32 IR, int32 AC) -{ -int32 pulse = IR & 07; - -UPDATE_PCELL; /* update photocell */ -if (pulse & 1) { /* DFSE */ - if (rf_sta & RFS_ERR) AC = AC | IOT_SKP; } -if (pulse & 2) { /* DFSC */ - if (pulse & 4) AC = AC & ~07777; /* for DMAC */ - else if (rf_done) AC = AC | IOT_SKP; } -if (pulse & 4) AC = AC | (rf_da & 07777); /* DMAC */ -return AC; -} - -int32 rf64 (int32 IR, int32 AC) -{ -int32 pulse = IR & 07; - -UPDATE_PCELL; /* update photocell */ -switch (pulse) { /* decode IR<9:11> */ -case 1: /* DCXA */ - rf_da = rf_da & 07777; /* clear DAR<0:7> */ - break; -case 3: /* DXAL */ - rf_da = rf_da & 07777; /* clear DAR<0:7> */ -case 2: /* DXAL w/o clear */ - rf_da = rf_da | ((AC & 0377) << 12); /* DAR<0:7> |= AC */ - AC = AC & ~07777; /* clear AC */ - break; -case 5: /* DXAC */ - AC = AC & ~07777; /* clear AC */ -case 4: /* DXAC w/o clear */ - AC = AC | ((rf_da >> 12) & 0377); /* AC |= DAR<0:7> */ - break; -default: - AC = (stop_inst << IOT_V_REASON) + AC; - break; } /* end switch */ -if ((uint32) rf_da >= rf_unit.capac) rf_sta = rf_sta | RFS_NXD; -else rf_sta = rf_sta & ~RFS_NXD; -RF_INT_UPDATE; -return AC; -} - -/* Unit service - - Note that for reads and writes, memory addresses wrap around in the - current field. This code assumes the entire disk is buffered. -*/ - -t_stat rf_svc (UNIT *uptr) -{ -int32 pa, t, mex; - -UPDATE_PCELL; /* update photocell */ -if ((uptr->flags & UNIT_BUF) == 0) { /* not buf? abort */ - rf_sta = rf_sta | RFS_NXD; - rf_done = 1; - RF_INT_UPDATE; /* update int req */ - return IORETURN (rf_stopioe, SCPE_UNATT); } - -mex = GET_MEX (rf_sta); -do { if ((uint32) rf_da >= rf_unit.capac) { /* disk overflow? */ - rf_sta = rf_sta | RFS_NXD; - break; } - 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) { /* 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 (((uint32) 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 */ - -if ((M[RF_WC] != 0) && ((rf_sta & RFS_ERR) == 0)) /* more to do? */ - sim_activate (&rf_unit, rf_time); /* sched next */ -else { rf_done = 1; /* done */ - RF_INT_UPDATE; } /* update int req */ -return SCPE_OK; -} - -/* Photocell unit service */ - -t_stat pcell_svc (UNIT *uptr) -{ -rf_sta = rf_sta | RFS_PCA; /* set photocell */ -if (rf_sta & RFS_PIE) { /* int enable? */ - sim_activate (&pcell_unit, RF_NUMWD * rf_time); - int_req = int_req | INT_RF; } -return SCPE_OK; -} - -/* Reset routine */ - -t_stat rf_reset (DEVICE *dptr) -{ -rf_sta = rf_da = 0; -rf_done = 1; -int_req = int_req & ~INT_RF; /* clear interrupt */ -sim_cancel (&rf_unit); -sim_cancel (&pcell_unit); -return SCPE_OK; -} - -/* Bootstrap routine */ - -#define OS8_START 07750 -#define OS8_LEN (sizeof (os8_rom) / sizeof (int16)) -#define DM4_START 00200 -#define DM4_LEN (sizeof (dm4_rom) / sizeof (int16)) - -static const uint16 os8_rom[] = { - 07600, /* 7750, CLA CLL ; also word count */ - 06603, /* 7751, DMAR ; also address */ - 06622, /* 7752, DFSC ; done? */ - 05352, /* 7753, JMP .-1 ; no */ - 05752 /* 7754, JMP @.-2 ; enter boot */ -}; - -static const uint16 dm4_rom[] = { - 00200, 07600, /* 0200, CLA CLL */ - 00201, 06603, /* 0201, DMAR ; read */ - 00202, 06622, /* 0202, DFSC ; done? */ - 00203, 05202, /* 0203, JMP .-1 ; no */ - 00204, 05600, /* 0204, JMP @.-4 ; enter boot */ - 07750, 07576, /* 7750, 7576 ; word count */ - 07751, 07576 /* 7751, 7576 ; address */ -}; - -t_stat rf_boot (int32 unitno, DEVICE *dptr) -{ -int32 i; -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]; - saved_PC = DM4_START; } -else { for (i = 0; i < OS8_LEN; i++) - M[OS8_START + i] = os8_rom[i]; - saved_PC = OS8_START; } -return SCPE_OK; -} - -/* Attach routine */ - -t_stat rf_attach (UNIT *uptr, char *cptr) -{ -uint32 sz, p; -uint32 ds_bytes = RF_DKSIZE * sizeof (int16); - -if ((uptr->flags & UNIT_AUTO) && (sz = sim_fsize (cptr))) { - p = (sz + ds_bytes - 1) / ds_bytes; - if (p >= RF_NUMDK) p = RF_NUMDK - 1; - uptr->flags = (uptr->flags & ~UNIT_PLAT) | - (p << UNIT_V_PLAT); } -uptr->capac = UNIT_GETP (uptr->flags) * RF_DKSIZE; -return attach_unit (uptr, cptr); -} - -/* Change disk size */ - -t_stat rf_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -if (val < 0) return SCPE_IERR; -if (uptr->flags & UNIT_ATT) return SCPE_ALATT; -uptr->capac = UNIT_GETP (val) * RF_DKSIZE; -uptr->flags = uptr->flags & ~UNIT_AUTO; -return SCPE_OK; -} diff --git a/PDP8/pdp8_rk.c b/PDP8/pdp8_rk.c deleted file mode 100644 index 7273430e..00000000 --- a/PDP8/pdp8_rk.c +++ /dev/null @@ -1,410 +0,0 @@ -/* pdp8_rk.c: RK8E cartridge disk simulator - - 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. - - rk RK8E/RK05 cartridge disk - - 25-Apr-03 RMS Revised for extended file support - 04-Oct-02 RMS Added DIB, device number support - 06-Jan-02 RMS Changed enable/disable support - 30-Nov-01 RMS Added read only unit, extended SET/SHOW support - 24-Nov-01 RMS Converted FLG to array, made register names consistent - 25-Apr-01 RMS Added device enable/disable support - 29-Jun-96 RMS Added unit enable/disable support -*/ - -#include "pdp8_defs.h" - -/* Constants */ - -#define RK_NUMSC 16 /* sectors/surface */ -#define RK_NUMSF 2 /* surfaces/cylinder */ -#define RK_NUMCY 203 /* cylinders/drive */ -#define RK_NUMWD 256 /* words/sector */ -#define RK_SIZE (RK_NUMCY * RK_NUMSF * RK_NUMSC * RK_NUMWD) /* words/drive */ -#define RK_NUMDR 4 /* drives/controller */ -#define RK_M_NUMDR 03 - -/* Flags in the unit flags word */ - -#define UNIT_V_HWLK (UNIT_V_UF + 0) /* hwre write lock */ -#define UNIT_V_SWLK (UNIT_V_UF + 1) /* swre write lock */ -#define UNIT_HWLK (1 << UNIT_V_HWLK) -#define UNIT_SWLK (1 << UNIT_V_SWLK) -#define UNIT_WPRT (UNIT_HWLK|UNIT_SWLK|UNIT_RO) /* write protect */ - -/* Parameters in the unit descriptor */ - -#define CYL u3 /* current cylinder */ -#define FUNC u4 /* function */ - -/* Status register */ - -#define RKS_DONE 04000 /* transfer done */ -#define RKS_HMOV 02000 /* heads moving */ -#define RKS_SKFL 00400 /* drive seek fail */ -#define RKS_NRDY 00200 /* drive not ready */ -#define RKS_BUSY 00100 /* control busy error */ -#define RKS_TMO 00040 /* timeout error */ -#define RKS_WLK 00020 /* write lock error */ -#define RKS_CRC 00010 /* CRC error */ -#define RKS_DLT 00004 /* data late error */ -#define RKS_STAT 00002 /* drive status error */ -#define RKS_CYL 00001 /* cyl address error */ -#define RKS_ERR (RKS_BUSY+RKS_TMO+RKS_WLK+RKS_CRC+RKS_DLT+RKS_STAT+RKS_CYL) - -/* Command register */ - -#define RKC_M_FUNC 07 /* function */ -#define RKC_READ 0 -#define RKC_RALL 1 -#define RKC_WLK 2 -#define RKC_SEEK 3 -#define RKC_WRITE 4 -#define RKC_WALL 5 -#define RKC_V_FUNC 9 -#define RKC_IE 00400 /* interrupt enable */ -#define RKC_SKDN 00200 /* int on seek done */ -#define RKC_HALF 00100 /* 128W sector */ -#define RKC_MEX 00070 /* memory extension */ -#define RKC_V_MEX 3 -#define RKC_M_DRV 03 /* drive select */ -#define RKC_V_DRV 1 -#define RKC_CYHI 00001 /* high cylinder addr */ - -#define GET_FUNC(x) (((x) >> RKC_V_FUNC) & RKC_M_FUNC) -#define GET_DRIVE(x) (((x) >> RKC_V_DRV) & RKC_M_DRV) -#define GET_MEX(x) (((x) & RKC_MEX) << (12 - RKC_V_MEX)) - -/* Disk address */ - -#define RKD_V_SECT 0 /* sector */ -#define RKD_M_SECT 017 -#define RKD_V_SUR 4 /* surface */ -#define RKD_M_SUR 01 -#define RKD_V_CYL 5 /* cylinder */ -#define RKD_M_CYL 0177 -#define GET_CYL(x,y) ((((x) & RKC_CYHI) << (12-RKD_V_CYL)) | \ - (((y) >> RKD_V_CYL) & RKD_M_CYL)) -#define GET_DA(x,y) ((((x) & RKC_CYHI) << 12) | y) - -/* Reset commands */ - -#define RKX_CLS 0 /* clear status */ -#define RKX_CLC 1 /* clear control */ -#define RKX_CLD 2 /* clear drive */ -#define RKX_CLSA 3 /* clear status alt */ - -#define RK_INT_UPDATE \ - if (((rk_sta & (RKS_DONE + RKS_ERR)) != 0) && \ - ((rk_cmd & RKC_IE) != 0)) int_req = int_req | INT_RK; \ - else int_req = int_req & ~INT_RK -#define RK_MIN 10 -#define MAX(x,y) (((x) > (y))? (x): (y)) - -extern uint16 M[]; -extern int32 int_req, stop_inst; -extern UNIT cpu_unit; - -int32 rk_busy = 0; /* controller busy */ -int32 rk_sta = 0; /* status register */ -int32 rk_cmd = 0; /* command register */ -int32 rk_da = 0; /* disk address */ -int32 rk_ma = 0; /* memory address */ -int32 rk_swait = 10, rk_rwait = 10; /* seek, rotate wait */ -int32 rk_stopioe = 1; /* stop on error */ - -DEVICE rk_dev; -int32 rk (int32 IR, int32 AC); -t_stat rk_svc (UNIT *uptr); -t_stat rk_reset (DEVICE *dptr); -t_stat rk_boot (int32 unitno, DEVICE *dptr); -void rk_go (int32 function, int32 cylinder); - -/* RK-8E data structures - - rk_dev RK device descriptor - rk_unit RK unit list - rk_reg RK register list - rk_mod RK modifiers list -*/ - -DIB rk_dib = { DEV_RK, 1, { &rk } }; - -UNIT rk_unit[] = { - { UDATA (&rk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE, RK_SIZE) }, - { UDATA (&rk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE, RK_SIZE) }, - { UDATA (&rk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE, RK_SIZE) }, - { UDATA (&rk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE, RK_SIZE) } }; - -REG rk_reg[] = { - { ORDATA (RKSTA, rk_sta, 12) }, - { ORDATA (RKCMD, rk_cmd, 12) }, - { ORDATA (RKDA, rk_da, 12) }, - { ORDATA (RKMA, rk_ma, 12) }, - { FLDATA (BUSY, rk_busy, 0) }, - { FLDATA (INT, int_req, INT_V_RK) }, - { DRDATA (STIME, rk_swait, 24), PV_LEFT }, - { DRDATA (RTIME, rk_rwait, 24), PV_LEFT }, - { FLDATA (STOP_IOE, rk_stopioe, 0) }, - { ORDATA (DEVNUM, rk_dib.dev, 6), REG_HRO }, - { NULL } }; - -MTAB rk_mod[] = { - { UNIT_HWLK, 0, "write enabled", "WRITEENABLED", NULL }, - { UNIT_HWLK, UNIT_HWLK, "write locked", "LOCKED", NULL }, - { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", - &set_dev, &show_dev, NULL }, - { 0 } }; - -DEVICE rk_dev = { - "RK", rk_unit, rk_reg, rk_mod, - RK_NUMDR, 8, 24, 1, 8, 12, - NULL, NULL, &rk_reset, - &rk_boot, NULL, NULL, - &rk_dib, DEV_DISABLE }; - -/* IOT routine */ - -int32 rk (int32 IR, int32 AC) -{ -int32 i; -UNIT *uptr; - -switch (IR & 07) { /* decode IR<9:11> */ -case 0: /* unused */ - return (stop_inst << IOT_V_REASON) + AC; -case 1: /* DSKP */ - return (rk_sta & (RKS_DONE + RKS_ERR))? /* skip on done, err */ - IOT_SKP + AC: AC; -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; - case RKX_CLSA: /* clear status alt */ - 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; - 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 */ - 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)); } - break; -case 4: /* DLCA */ - if (rk_busy != 0) rk_sta = rk_sta | RKS_BUSY; - else rk_ma = AC; /* load curr addr */ - break; -case 5: /* DRST */ - uptr = rk_dev.units + GET_DRIVE (rk_cmd); /* selected unit */ - rk_sta = rk_sta & ~(RKS_HMOV + RKS_NRDY); /* clear dynamic */ - if ((uptr->flags & UNIT_ATT) == 0) rk_sta = rk_sta | RKS_NRDY; - if (sim_is_active (uptr)) rk_sta = rk_sta | RKS_HMOV; - 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 */ - break; -case 7: /* DMAN */ - break; } /* end case pulse */ -RK_INT_UPDATE; /* update int req */ -return 0; /* clear AC */ -} - -/* Initiate new function - - Called with function, cylinder, to allow recalibrate as well as - load and go to be processed by this routine. - - Assumes that the controller is idle, and that updating of interrupt - request will be done by the caller. -*/ - -void rk_go (int32 func, int32 cyl) -{ -int32 t; -UNIT *uptr; - -if (func == RKC_RALL) func = RKC_READ; /* all? use standard */ -if (func == RKC_WALL) func = RKC_WRITE; -uptr = rk_dev.units + GET_DRIVE (rk_cmd); /* selected unit */ -if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */ - rk_sta = rk_sta | RKS_DONE | RKS_NRDY | RKS_STAT; - return; } -if (sim_is_active (uptr) || (cyl >= RK_NUMCY)) { /* busy or bad cyl? */ - rk_sta = rk_sta | RKS_DONE | RKS_STAT; - return; } -if ((func == RKC_WRITE) && (uptr->flags & UNIT_WPRT)) { - rk_sta = rk_sta | RKS_DONE | RKS_WLK; /* write and locked? */ - return; } -if (func == RKC_WLK) { /* write lock? */ - uptr->flags = uptr->flags | UNIT_SWLK; - rk_sta = rk_sta | RKS_DONE; - return; } -t = abs (cyl - uptr->CYL) * rk_swait; /* seek time */ -if (func == RKC_SEEK) { /* seek? */ - sim_activate (uptr, MAX (RK_MIN, t)); /* schedule */ - rk_sta = rk_sta | RKS_DONE; } /* set done */ -else { sim_activate (uptr, t + rk_rwait); /* schedule */ - rk_busy = 1; } /* set busy */ -uptr->FUNC = func; /* save func */ -uptr->CYL = cyl; /* put on cylinder */ -return; -} - -/* Unit service - - If seek, complete seek command - Else complete data transfer command - - The unit control block contains the function and cylinder address for - the current command. - - Note that memory addresses wrap around in the current field. -*/ - -static uint16 fill[RK_NUMWD/2] = { 0 }; -t_stat rk_svc (UNIT *uptr) -{ -int32 err, wc, wc1, awc, swc, pa, da; -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; } - return SCPE_OK; } - -if ((uptr->flags & UNIT_ATT) == 0) { /* not att? abort */ - rk_sta = rk_sta | RKS_DONE | RKS_NRDY | RKS_STAT; - rk_busy = 0; - RK_INT_UPDATE; - return IORETURN (rk_stopioe, SCPE_UNATT); } - -if ((uptr->FUNC == RKC_WRITE) && (uptr->flags & UNIT_WPRT)) { - rk_sta = rk_sta | RKS_DONE | RKS_WLK; /* write and locked? */ - rk_busy = 0; - RK_INT_UPDATE; - return SCPE_OK; } - -pa = GET_MEX (rk_cmd) | rk_ma; /* phys address */ -da = GET_DA (rk_cmd, rk_da) * RK_NUMWD * sizeof (int16);/* disk address */ -swc = wc = (rk_cmd & RKC_HALF)? RK_NUMWD / 2: RK_NUMWD; /* get transfer size */ -if ((wc1 = ((rk_ma + wc) - 010000)) > 0) wc = wc - wc1; /* if wrap, limit */ -err = fseek (uptr->fileref, da, SEEK_SET); /* locate sector */ - -if ((uptr->FUNC == RKC_READ) && (err == 0) && MEM_ADDR_OK (pa)) { /* read? */ - awc = fxread (&M[pa], sizeof (int16), wc, uptr->fileref); - 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); } } - -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); } - if ((rk_cmd & RKC_HALF) && (err == 0)) { /* fill half sector */ - 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 */ -rk_busy = 0; -RK_INT_UPDATE; - -if (err != 0) { - perror ("RK I/O error"); - clearerr (uptr->fileref); - return SCPE_IOERR; } -return SCPE_OK; -} - -/* Reset routine */ - -t_stat rk_reset (DEVICE *dptr) -{ -int32 i; -UNIT *uptr; - -rk_cmd = rk_ma = rk_da = rk_sta = rk_busy = 0; -int_req = int_req & ~INT_RK; /* clear interrupt */ -for (i = 0; i < RK_NUMDR; i++) { /* stop all units */ - uptr = rk_dev.units + i; - sim_cancel (uptr); - uptr->flags = uptr->flags & ~UNIT_SWLK; - uptr->CYL = uptr->FUNC = 0; } -return SCPE_OK; -} - -/* Bootstrap routine */ - -#define BOOT_START 023 -#define BOOT_UNIT 032 -#define BOOT_LEN (sizeof (boot_rom) / sizeof (int16)) - -static const uint16 boot_rom[] = { - 06007, /* 23, CAF */ - 06744, /* 24, DLCA ; addr = 0 */ - 01032, /* 25, TAD UNIT ; unit no */ - 06746, /* 26, DLDC ; command, unit */ - 06743, /* 27, DLAG ; disk addr, go */ - 01032, /* 30, TAD UNIT ; unit no, for OS */ - 05031, /* 31, JMP . */ - 00000 /* UNIT, 0 ; in bits <9:10> */ -}; - -t_stat rk_boot (int32 unitno, DEVICE *dptr) -{ -int32 i; -extern int32 saved_PC; - -if (rk_dib.dev != DEV_RK) return STOP_NOTSTD; /* only std devno */ -for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i]; -M[BOOT_UNIT] = (unitno & RK_M_NUMDR) << 1; -saved_PC = BOOT_START; -return SCPE_OK; -} diff --git a/PDP8/pdp8_rl.c b/PDP8/pdp8_rl.c deleted file mode 100644 index 69a91459..00000000 --- a/PDP8/pdp8_rl.c +++ /dev/null @@ -1,629 +0,0 @@ - /* pdp8_rl.c: RL8A cartridge disk simulator - - 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. - - rl RL8A cartridge disk - - 25-Apr-03 RMS Revised for extended file support - 04-Oct-02 RMS Added DIB, device number support - 06-Jan-02 RMS Changed enable/disable support - 30-Nov-01 RMS Cloned from RL11 - - The RL8A is a four drive cartridge disk subsystem. An RL01 drive - consists of 256 cylinders, each with 2 surfaces containing 40 sectors - of 256 bytes. An RL02 drive has 512 cylinders. - - The RL8A controller has several serious complications. - - Seeking is relative to the current disk address; this requires - keeping accurate track of the current cylinder. - - The RL8A will not switch heads or cross cylinders during transfers. - - The RL8A operates in 8b and 12b mode, like the RX8E; in 12b mode, it - packs 2 12b words into 3 bytes, creating a 170 "word" sector with - one wasted byte. Multi-sector transfers in 12b mode don't work. -*/ - -#include "pdp8_defs.h" - -/* Constants */ - -#define RL_NUMBY 256 /* 8b bytes/sector */ -#define RL_NUMSC 40 /* sectors/surface */ -#define RL_NUMSF 2 /* surfaces/cylinder */ -#define RL_NUMCY 256 /* cylinders/drive */ -#define RL_NUMDR 4 /* drives/controller */ -#define RL_MAXFR (1 << 12) /* max transfer */ -#define RL01_SIZE (RL_NUMCY*RL_NUMSF*RL_NUMSC*RL_NUMBY) /* words/drive */ -#define RL02_SIZE (RL01_SIZE * 2) /* words/drive */ -#define RL_BBMAP 014 /* sector for bblk map */ -#define RL_BBID 0123 /* ID for bblk map */ - -/* Flags in the unit flags word */ - -#define UNIT_V_WLK (UNIT_V_UF + 0) /* write lock */ -#define UNIT_V_RL02 (UNIT_V_UF + 1) /* RL01 vs RL02 */ -#define UNIT_V_AUTO (UNIT_V_UF + 2) /* autosize enable */ -#define UNIT_V_DUMMY (UNIT_V_UF + 3) /* dummy flag */ -#define UNIT_DUMMY (1u << UNIT_V_DUMMY) -#define UNIT_WLK (1u << UNIT_V_WLK) -#define UNIT_RL02 (1u << UNIT_V_RL02) -#define UNIT_AUTO (1u << UNIT_V_AUTO) -#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */ - -/* Parameters in the unit descriptor */ - -#define TRK u3 /* current cylinder */ -#define STAT u4 /* status */ - -/* RLDS, NI = not implemented, * = kept in STAT, ^ = kept in TRK */ - -#define RLDS_LOAD 0 /* no cartridge */ -#define RLDS_LOCK 5 /* lock on */ -#define RLDS_BHO 0000010 /* brushes home NI */ -#define RLDS_HDO 0000020 /* heads out NI */ -#define RLDS_CVO 0000040 /* cover open NI */ -#define RLDS_HD 0000100 /* head select ^ */ -#define RLDS_RL02 0000200 /* RL02 */ -#define RLDS_DSE 0000400 /* drv sel err NI */ -#define RLDS_VCK 0001000 /* vol check * */ -#define RLDS_WGE 0002000 /* wr gate err * */ -#define RLDS_SPE 0004000 /* spin err * */ -#define RLDS_STO 0010000 /* seek time out NI */ -#define RLDS_WLK 0020000 /* wr locked */ -#define RLDS_HCE 0040000 /* hd curr err NI */ -#define RLDS_WDE 0100000 /* wr data err NI */ -#define RLDS_ATT (RLDS_HDO+RLDS_BHO+RLDS_LOCK) /* att status */ -#define RLDS_UNATT (RLDS_CVO+RLDS_LOAD) /* unatt status */ -#define RLDS_ERR (RLDS_WDE+RLDS_HCE+RLDS_STO+RLDS_SPE+RLDS_WGE+ \ - RLDS_VCK+RLDS_DSE) /* errors bits */ - -/* RLCSA, seek = offset/rw = address (also uptr->TRK) */ - -#define RLCSA_DIR 04000 /* direction */ -#define RLCSA_HD 02000 /* head select */ -#define RLCSA_CYL 00777 /* cyl offset */ -#define GET_CYL(x) ((x) & RLCSA_CYL) -#define GET_TRK(x) ((((x) & RLCSA_CYL) * RL_NUMSF) + \ - (((x) & RLCSA_HD)? 1: 0)) -#define GET_DA(x) ((GET_TRK(x) * RL_NUMSC) + rlsa) - -/* RLCSB, function/unit select */ - -#define RLCSB_V_FUNC 0 /* function */ -#define RLCSB_M_FUNC 07 -#define RLCSB_MNT 0 -#define RLCSB_CLRD 1 -#define RLCSB_GSTA 2 -#define RLCSB_SEEK 3 -#define RLCSB_RHDR 4 -#define RLCSB_WRITE 5 -#define RLCSB_READ 6 -#define RLCSB_RNOHDR 7 -#define RLCSB_V_MEX 3 /* memory extension */ -#define RLCSB_M_MEX 07 -#define RLCSB_V_DRIVE 6 /* drive */ -#define RLCSB_M_DRIVE 03 -#define RLCSB_V_IE 8 /* int enable */ -#define RLCSB_IE (1u << RLCSB_V_IE) -#define RLCSB_8B 01000 /* 12b/8b */ -#define RCLS_MNT 02000 /* maint NI */ -#define RLCSB_RW 0001777 /* read/write */ -#define GET_FUNC(x) (((x) >> RLCSB_V_FUNC) & RLCSB_M_FUNC) -#define GET_MEX(x) (((x) >> RLCSB_V_MEX) & RLCSB_M_MEX) -#define GET_DRIVE(x) (((x) >> RLCSB_V_DRIVE) & RLCSB_M_DRIVE) - -/* RLSA, disk sector */ - -#define RLSA_V_SECT 6 /* sector */ -#define RLSA_M_SECT 077 -#define GET_SECT(x) (((x) >> RLSA_V_SECT) & RLSA_M_SECT) - -/* RLER, error register */ - -#define RLER_DRDY 00001 /* drive ready */ -#define RLER_DRE 00002 /* drive error */ -#define RLER_HDE 01000 /* header error */ -#define RLER_INCMP 02000 /* incomplete */ -#define RLER_ICRC 04000 /* CRC error */ -#define RLER_MASK 07003 - -/* RLSI, silo register, used only in read header */ - -#define RLSI_V_TRK 6 /* track */ - -extern uint16 M[]; -extern int32 int_req; -extern UNIT cpu_unit; - -uint8 *rlxb = NULL; /* xfer buffer */ -int32 rlcsa = 0; /* control/status A */ -int32 rlcsb = 0; /* control/status B */ -int32 rlma = 0; /* memory address */ -int32 rlwc = 0; /* word count */ -int32 rlsa = 0; /* sector address */ -int32 rler = 0; /* error register */ -int32 rlsi = 0, rlsi1 = 0, rlsi2 = 0; /* silo queue */ -int32 rl_lft = 0; /* silo left/right */ -int32 rl_done = 0; /* done flag */ -int32 rl_erf = 0; /* error flag */ -int32 rl_swait = 10; /* seek wait */ -int32 rl_rwait = 10; /* rotate wait */ -int32 rl_stopioe = 1; /* stop on error */ - -DEVICE rl_dev; -int32 rl60 (int32 IR, int32 AC); -int32 rl61 (int32 IR, int32 AC); -t_stat rl_svc (UNIT *uptr); -t_stat rl_reset (DEVICE *dptr); -void rl_set_done (int32 error); -t_stat rl_boot (int32 unitno, DEVICE *dptr); -t_stat rl_attach (UNIT *uptr, char *cptr); -t_stat rl_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat rl_set_bad (UNIT *uptr, int32 val, char *cptr, void *desc); - -/* RL8A data structures - - rl_dev RL device descriptor - rl_unit RL unit list - rl_reg RL register list - rl_mod RL modifier list -*/ - -DIB rl_dib = { DEV_RL, 2, { &rl60, &rl61 } }; - -UNIT rl_unit[] = { - { UDATA (&rl_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+ - UNIT_ROABLE, RL01_SIZE) }, - { UDATA (&rl_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+ - UNIT_ROABLE, RL01_SIZE) }, - { UDATA (&rl_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+ - UNIT_ROABLE, RL01_SIZE) }, - { UDATA (&rl_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+ - UNIT_ROABLE, RL01_SIZE) } }; - -REG rl_reg[] = { - { ORDATA (RLCSA, rlcsa, 12) }, - { ORDATA (RLCSB, rlcsb, 12) }, - { ORDATA (RLMA, rlma, 12) }, - { ORDATA (RLWC, rlwc, 12) }, - { ORDATA (RLSA, rlsa, 6) }, - { ORDATA (RLER, rler, 12) }, - { ORDATA (RLSI, rlsi, 16) }, - { ORDATA (RLSI1, rlsi1, 16) }, - { ORDATA (RLSI2, rlsi2, 16) }, - { FLDATA (RLSIL, rl_lft, 0) }, - { FLDATA (INT, int_req, INT_V_RL) }, - { FLDATA (DONE, rl_done, INT_V_RL) }, - { FLDATA (IE, rlcsb, RLCSB_V_IE) }, - { FLDATA (ERR, rl_erf, 0) }, - { DRDATA (STIME, rl_swait, 24), PV_LEFT }, - { DRDATA (RTIME, rl_rwait, 24), PV_LEFT }, - { URDATA (CAPAC, rl_unit[0].capac, 10, T_ADDR_W, 0, - RL_NUMDR, PV_LEFT + REG_HRO) }, - { FLDATA (STOP_IOE, rl_stopioe, 0) }, - { ORDATA (DEVNUM, rl_dib.dev, 6), REG_HRO }, - { NULL } }; - -MTAB rl_mod[] = { - { UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL }, - { UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL }, - { UNIT_DUMMY, 0, NULL, "BADBLOCK", &rl_set_bad }, - { (UNIT_RL02+UNIT_ATT), UNIT_ATT, "RL01", NULL, NULL }, - { (UNIT_RL02+UNIT_ATT), (UNIT_RL02+UNIT_ATT), "RL02", NULL, NULL }, - { (UNIT_AUTO+UNIT_RL02+UNIT_ATT), 0, "RL01", NULL, NULL }, - { (UNIT_AUTO+UNIT_RL02+UNIT_ATT), UNIT_RL02, "RL02", NULL, NULL }, - { (UNIT_AUTO+UNIT_ATT), UNIT_AUTO, "autosize", NULL, NULL }, - { UNIT_AUTO, UNIT_AUTO, NULL, "AUTOSIZE", NULL }, - { (UNIT_AUTO+UNIT_RL02), 0, NULL, "RL01", &rl_set_size }, - { (UNIT_AUTO+UNIT_RL02), UNIT_RL02, NULL, "RL02", &rl_set_size }, - { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", - &set_dev, &show_dev, NULL }, - { 0 } }; - -DEVICE rl_dev = { - "RL", rl_unit, rl_reg, rl_mod, - RL_NUMDR, 8, 24, 1, 8, 8, - NULL, NULL, &rl_reset, - &rl_boot, &rl_attach, NULL, - &rl_dib, DEV_DISABLE | DEV_DIS }; - -/* IOT 60 routine */ - -int32 rl60 (int32 IR, int32 AC) -{ -int32 curr, offs, newc, maxc; -UNIT *uptr; - -switch (IR & 07) { /* case IR<9:11> */ -case 0: /* RLDC */ - rl_reset (&rl_dev); /* reset device */ - break; -case 1: /* RLSD */ - if (rl_done) AC = IOT_SKP; /* skip if done */ - else AC = 0; - rl_done = 0; /* clear done */ - int_req = int_req & ~INT_RL; /* clear intr */ - return AC; -case 2: /* RLMA */ - rlma = AC; - break; -case 3: /* RLCA */ - rlcsa = AC; - break; -case 4: /* RLCB */ - rlcsb = AC; - rl_done = 0; /* clear done */ - rler = rl_erf = 0; /* clear errors */ - int_req = int_req & ~INT_RL; /* clear intr */ - rl_lft = 0; /* clear silo ptr */ - 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 */ - case RLCSB_MNT: /* mnt */ - 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; - default: /* data transfer */ - sim_activate (uptr, rl_swait); /* activate unit */ - break; } /* end switch func */ - break; -case 5: /* RLSA */ - rlsa = GET_SECT (AC); - break; -case 6: /* spare */ - return 0; -case 7: /* RLWC */ - rlwc = AC; - break; } /* end switch pulse */ -return 0; /* clear AC */ -} - -/* IOT 61 routine */ - -int32 rl61 (int32 pulse, int32 AC) -{ -int32 dat; -UNIT *uptr; - -switch (pulse) { /* case IR<9:11> */ -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; - else rler = rler & ~RLER_DRDY; - dat = rler & RLER_MASK; - break; -case 1: /* RRWC */ - dat = rlwc; - break; -case 2: /* RRCA */ - dat = rlcsa; - break; -case 3: /* RRCB */ - dat = rlcsb; - break; -case 4: /* RRSA */ - dat = (rlsa << RLSA_V_SECT) & 07777; - break; -case 5: /* RRSI */ - if (rl_lft) { /* silo left? */ - 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; -case 6: /* spare */ - return AC; -case 7: /* RLSE */ - if (rl_erf) dat = IOT_SKP | AC; /* skip if err */ - else dat = AC; - rl_erf = 0; - break; } /* end switch pulse */ -return dat; -} - -/* Service unit timeout - - If seek in progress, complete seek command - Else complete data transfer command - - The unit control block contains the function and cylinder for - the current command. -*/ - -t_stat rl_svc (UNIT *uptr) -{ -int32 err, wc, maxc; -int32 i, j, func, da, bc, wbc; -uint32 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); - if (uptr->flags & UNIT_RL02) rlsi = rlsi | RLDS_RL02; - if (uptr->flags & UNIT_WPRT) rlsi = rlsi | RLDS_WLK; - rlsi2 = rlsi1 = rlsi; - rl_set_done (0); /* done */ - return SCPE_OK; } - -if ((uptr->flags & UNIT_ATT) == 0) { /* attached? */ - uptr->STAT = uptr->STAT | RLDS_SPE; /* spin error */ - rl_set_done (RLER_INCMP); /* flag error */ - return IORETURN (rl_stopioe, SCPE_UNATT); } - -if ((func == RLCSB_WRITE) && (uptr->flags & UNIT_WPRT)) { - uptr->STAT = uptr->STAT | RLDS_WGE; /* write and locked */ - rl_set_done (RLER_DRE); /* flag error */ - return SCPE_OK; } - -if (func == RLCSB_SEEK) { /* seek? */ - rl_set_done (0); /* done */ - return SCPE_OK; } - -if (func == RLCSB_RHDR) { /* read header? */ - rlsi = (GET_TRK (uptr->TRK) << RLSI_V_TRK) | rlsa; - rlsi1 = rlsi2 = 0; - rl_set_done (0); /* done */ - return SCPE_OK; } - -if (((func != RLCSB_RNOHDR) && (GET_CYL (uptr->TRK) != GET_CYL (rlcsa))) - || (rlsa >= RL_NUMSC)) { /* bad cyl or sector? */ - rl_set_done (RLER_HDE | RLER_INCMP); /* flag error */ - return SCPE_OK; } - -ma = (GET_MEX (rlcsb) << 12) | rlma; /* get mem addr */ -da = GET_DA (rlcsa) * RL_NUMBY; /* get disk addr */ -wc = 010000 - rlwc; /* get true wc */ -if (rlcsb & RLCSB_8B) { /* 8b mode? */ - bc = wc; /* bytes to xfr */ - maxc = (RL_NUMSC - rlsa) * RL_NUMBY; /* max transfer */ - 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; } } - -err = fseek (uptr->fileref, da, SEEK_SET); - -if ((func >= RLCSB_READ) && (err == 0) && /* read (no hdr)? */ - MEM_ADDR_OK (ma)) { /* valid bank? */ - i = fxread (rlxb, sizeof (int8), bc, uptr->fileref); - err = ferror (uptr->fileref); - for ( ; i < bc; i++) rlxb[i] = 0; /* fill buffer */ - for (i = j = 0; i < wc; i++) { /* store buffer */ - if (rlcsb & RLCSB_8B) /* 8b mode? */ - M[ma] = rlxb[i] & 0377; /* store */ - else if (i & 1) { /* odd wd 12b? */ - M[ma] = ((rlxb[j + 1] >> 4) & 017) | - (((uint16) rlxb[j + 2]) << 4); - j = j + 3; } - else M[ma] = rlxb[j] | /* even wd 12b */ - ((((uint16) rlxb[j + 1]) & 017) << 8); - ma = (ma & 070000) + ((ma + 1) & 07777); - } /* end for */ - } /* end if wr */ - -if ((func == RLCSB_WRITE) && (err == 0)) { /* write? */ - for (i = j = 0; i < wc; i++) { /* fetch buffer */ - if (rlcsb & RLCSB_8B) /* 8b mode? */ - rlxb[i] = M[ma] & 0377; /* fetch */ - else if (i & 1) { /* odd wd 12b? */ - rlxb[j + 1] = rlxb[j + 1] | ((M[ma] & 017) << 4); - rlxb[j + 2] = ((M[ma] >> 4) & 0377); - j = j + 3; } - else { /* even wd 12b */ - rlxb[j] = M[ma] & 0377; - rlxb[j + 1] = (M[ma] >> 8) & 017; } - ma = (ma & 070000) + ((ma + 1) & 07777); - } /* end for */ - wbc = (bc + (RL_NUMBY - 1)) & ~(RL_NUMBY - 1); /* clr to */ - for (i = bc; i < wbc; i++) rlxb[i] = 0; /* end of blk */ - fxwrite (rlxb, sizeof (int8), wbc, uptr->fileref); - err = ferror (uptr->fileref); - } /* end write */ - -rlwc = (rlwc + wc) & 07777; /* final word count */ -if (rlwc != 0) rler = rler | RLER_INCMP; /* completed? */ -rlma = (rlma + wc) & 07777; /* final word addr */ -rlsa = rlsa + ((bc + (RL_NUMBY - 1)) / RL_NUMBY); -rl_set_done (0); - -if (err != 0) { /* error? */ - perror ("RL I/O error"); - clearerr (uptr->fileref); - return SCPE_IOERR; } -return SCPE_OK; -} - -/* Set done and possibly errors */ - -void rl_set_done (int32 status) -{ -rl_done = 1; -rler = rler | status; -if (rler) rl_erf = 1; -if (rlcsb & RLCSB_IE) int_req = int_req | INT_RL; -else int_req = int_req & ~INT_RL; -return; -} - -/* Device reset - - Note that the RL8A does NOT recalibrate its drives on RESET -*/ - -t_stat rl_reset (DEVICE *dptr) -{ -int32 i; -UNIT *uptr; - -rlcsa = rlcsb = rlsa = rler = 0; -rlma = rlwc = 0; -rlsi = rlsi1 = rlsi2 = 0; -rl_lft = 0; -rl_done = 0; -rl_erf = 0; -int_req = int_req & ~INT_RL; -for (i = 0; i < RL_NUMDR; i++) { - uptr = rl_dev.units + i; - sim_cancel (uptr); - uptr->STAT = 0; } -if (rlxb == NULL) rlxb = calloc (RL_MAXFR, sizeof (unsigned int8)); -if (rlxb == NULL) return SCPE_MEM; -return SCPE_OK; -} - -/* Attach routine */ - -t_stat rl_attach (UNIT *uptr, char *cptr) -{ -uint32 p; -t_stat r; - -uptr->capac = (uptr->flags & UNIT_RL02)? RL02_SIZE: RL01_SIZE; -r = attach_unit (uptr, cptr); /* attach unit */ -if (r != SCPE_OK) return r; /* error? */ -uptr->TRK = 0; /* cyl 0 */ -uptr->STAT = RLDS_VCK; /* new volume */ -if (fseek (uptr->fileref, 0, SEEK_END)) return SCPE_OK; /* seek to end */ -if ((p = ftell (uptr->fileref)) == 0) { /* new disk image? */ - if (uptr->flags & UNIT_RO) return SCPE_OK; - return rl_set_bad (uptr, 0, NULL, NULL); } -if ((uptr->flags & UNIT_AUTO) == 0) return r; /* autosize? */ -if (p > (RL01_SIZE * sizeof (int16))) { - uptr->flags = uptr->flags | UNIT_RL02; - uptr->capac = RL02_SIZE; } -else { uptr->flags = uptr->flags & ~UNIT_RL02; - uptr->capac = RL01_SIZE; } -return SCPE_OK; -} - -/* Set size routine */ - -t_stat rl_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -if (uptr->flags & UNIT_ATT) return SCPE_ALATT; -uptr->capac = (val & UNIT_RL02)? RL02_SIZE: RL01_SIZE; -return SCPE_OK; -} - -/* Factory bad block table creation routine - - This routine writes the OS/8 specific bad block map in track 0, sector 014 (RL_BBMAP): - - words 0 magic number = 0123 (RL_BBID) - words 1-n block numbers - : - words n+1 end of table = 0 - - Inputs: - uptr = pointer to unit - val = ignored - Outputs: - sta = status code -*/ - -t_stat rl_set_bad (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -int32 i, da = RL_BBMAP * RL_NUMBY; - -if ((uptr->flags & UNIT_ATT) == 0) return SCPE_UNATT; -if (uptr->flags & UNIT_RO) return SCPE_RO; -if (!get_yn ("Create bad block table? [N]", FALSE)) return SCPE_OK; -if (fseek (uptr->fileref, da, SEEK_SET)) return SCPE_IOERR; -rlxb[0] = RL_BBID; -for (i = 1; i < RL_NUMBY; i++) rlxb[i] = 0; -fxwrite (rlxb, sizeof (int8), RL_NUMBY, uptr->fileref); -if (ferror (uptr->fileref)) return SCPE_IOERR; -return SCPE_OK; -} - -/* Bootstrap */ - -#define BOOT_START 1 /* start */ -#define BOOT_UNIT 02006 /* unit number */ -#define BOOT_LEN (sizeof (boot_rom) / sizeof (int16)) - -static const uint16 boot_rom[] = { - 06600, /* BT, RLDC ; reset */ - 07201, /* 02, CLA IAC ; clr drv = 1 */ - 04027, /* 03, JMS GO ; do io */ - 01004, /* 04, TAD 4 ; rd hdr fnc */ - 04027, /* 05, JMS GO ; do io */ - 06615, /* 06, RRSI ; rd hdr lo */ - 07002, /* 07, BSW ; swap */ - 07012, /* 10, RTR ; lo cyl to L */ - 06615, /* 11, RRSI ; rd hdr hi */ - 00025, /* 12, AND 25 ; mask = 377 */ - 07004, /* 13, RTL ; get cyl */ - 06603, /* 14, RLCA ; set addr */ - 07325, /* 15, CLA STL IAC RAL ; seek = 3 */ - 04027, /* 16, JMS GO ; do io */ - 07332, /* 17, CLA STL RTR ; dir in = 2000 */ - 06605, /* 20, RLSA ; sector */ - 01026, /* 21, TAD (-200) ; one sector */ - 06607, /* 22, RLWC ; word cnt */ - 07327, /* 23, CLA STL IAC RTL ; read = 6*/ - 04027, /* 24, JMS GO ; do io */ - 00377, /* 25, JMP 377 ; start */ - 07600, /* 26, -200 ; word cnt */ - 00000, /* GO, 0 ; subr */ - 06604, /* 30, RLCB ; load fnc */ - 06601, /* 31, RLSD ; wait */ - 05031, /* 32, JMP .-1 ; */ - 06617, /* 33, RLSE ; error? */ - 05427, /* 34, JMP I GO ; no, ok */ - 05001 /* 35, JMP BT ; restart */ -}; - - -t_stat rl_boot (int32 unitno, DEVICE *dptr) -{ -int32 i; -extern int32 saved_PC; - -if (unitno) return SCPE_ARG; /* only unit 0 */ -if (rl_dib.dev != DEV_RL) return STOP_NOTSTD; /* only std devno */ -rl_unit[unitno].TRK = 0; -for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i]; -saved_PC = BOOT_START; -return SCPE_OK; -} diff --git a/PDP8/pdp8_rx.c b/PDP8/pdp8_rx.c deleted file mode 100644 index ba68fcdd..00000000 --- a/PDP8/pdp8_rx.c +++ /dev/null @@ -1,659 +0,0 @@ -/* pdp8_rx.c: RX8E/RX01, RX28/RX02 floppy disk simulator - - 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. - - rx RX8E/RX01, RX28/RX02 floppy disk - - 25-Apr-03 RMS Revised for extended file support - 14-Mar-03 RMS Fixed variable size interaction with save/restore - 03-Mar-03 RMS Fixed autosizing - 08-Oct-02 RMS Added DIB, device number support - Fixed reset to work with disabled device - 15-Sep-02 RMS Added RX28/RX02 support - 06-Jan-02 RMS Changed enable/disable support - 30-Nov-01 RMS Added read only unit, extended SET/SHOW support - 24-Nov-01 RMS Converted FLG to array - 17-Jul-01 RMS Fixed warning from VC++ 6 - 26-Apr-01 RMS Added device enable/disable support - 13-Apr-01 RMS Revised for register arrays - 14-Apr-99 RMS Changed t_addr to unsigned - 15-Aug-96 RMS Fixed bug in LCD - - An RX01 diskette consists of 77 tracks, each with 26 sectors of 128B. - An RX02 diskette consists of 77 tracks, each with 26 sectors of 128B - (single density) or 256B (double density). Tracks are numbered 0-76, - sectors 1-26. The RX8E (RX28) can store data in 8b mode or 12b mode. - In 8b mode, the controller reads or writes 128 bytes (128B or 256B) - per sector. In 12b mode, it reads or writes 64 (64 or 128) 12b words - per sector. The 12b words are bit packed into the first 96 (192) bytes - of the sector; the last 32 (64) bytes are zeroed on writes. -*/ - -#include "pdp8_defs.h" - -#define RX_NUMTR 77 /* tracks/disk */ -#define RX_M_TRACK 0377 -#define RX_NUMSC 26 /* sectors/track */ -#define RX_M_SECTOR 0177 /* cf Jones!! */ -#define RX_NUMBY 128 /* bytes/sector */ -#define RX2_NUMBY 256 -#define RX_NUMWD (RX_NUMBY / 2) /* words/sector */ -#define RX2_NUMWD (RX2_NUMBY / 2) -#define RX_SIZE (RX_NUMTR * RX_NUMSC * RX_NUMBY) /* bytes/disk */ -#define RX2_SIZE (RX_NUMTR * RX_NUMSC * RX2_NUMBY) -#define RX_NUMDR 2 /* drives/controller */ -#define RX_M_NUMDR 01 -#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */ -#define UNIT_V_DEN (UNIT_V_UF + 1) /* double density */ -#define UNIT_V_AUTO (UNIT_V_UF + 2) /* autosize */ -#define UNIT_WLK (1u << UNIT_V_WLK) -#define UNIT_DEN (1u << UNIT_V_DEN) -#define UNIT_AUTO (1u << UNIT_V_AUTO) -#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */ - -#define IDLE 0 /* idle state */ -#define CMD8 1 /* 8b cmd, ho next */ -#define RWDS 2 /* rw, sect next */ -#define RWDT 3 /* rw, track next */ -#define RWXFR 4 /* rw, transfer */ -#define FILL 5 /* fill buffer */ -#define EMPTY 6 /* empty buffer */ -#define SDCNF 7 /* set dens, conf next */ -#define SDXFR 8 /* set dens, transfer */ -#define CMD_COMPLETE 9 /* set done next */ -#define INIT_COMPLETE 10 /* init compl next */ - -#define RXCS_V_FUNC 1 /* function */ -#define RXCS_M_FUNC 7 -#define RXCS_FILL 0 /* fill buffer */ -#define RXCS_EMPTY 1 /* empty buffer */ -#define RXCS_WRITE 2 /* write sector */ -#define RXCS_READ 3 /* read sector */ -#define RXCS_SDEN 4 /* set density (RX28) */ -#define RXCS_RXES 5 /* read status */ -#define RXCS_WRDEL 6 /* write del data */ -#define RXCS_ECODE 7 /* read error code */ -#define RXCS_DRV 0020 /* drive */ -#define RXCS_MODE 0100 /* mode */ -#define RXCS_MAINT 0200 /* maintenance */ -#define RXCS_DEN 0400 /* density (RX28) */ -#define RXCS_GETFNC(x) (((x) >> RXCS_V_FUNC) & RXCS_M_FUNC) - -#define RXES_CRC 0001 /* CRC error NI */ -#define RXES_ID 0004 /* init done */ -#define RXES_RX02 0010 /* RX02 (RX28) */ -#define RXES_DERR 0020 /* density err (RX28) */ -#define RXES_DEN 0040 /* density (RX28) */ -#define RXES_DD 0100 /* deleted data */ -#define RXES_DRDY 0200 /* drive ready */ - -#define TRACK u3 /* current track */ -#define READ_RXDBR ((rx_csr & RXCS_MODE)? AC | (rx_dbr & 0377): rx_dbr) -#define CALC_DA(t,s,b) (((t) * RX_NUMSC) + ((s) - 1)) * b - -extern int32 int_req, int_enable, dev_done; - -int32 rx_28 = 0; /* controller type */ -int32 rx_tr = 0; /* xfer ready flag */ -int32 rx_err = 0; /* error flag */ -int32 rx_csr = 0; /* control/status */ -int32 rx_dbr = 0; /* data buffer */ -int32 rx_esr = 0; /* error status */ -int32 rx_ecode = 0; /* error code */ -int32 rx_track = 0; /* desired track */ -int32 rx_sector = 0; /* desired sector */ -int32 rx_state = IDLE; /* controller state */ -int32 rx_cwait = 100; /* command time */ -int32 rx_swait = 10; /* seek, per track */ -int32 rx_xwait = 1; /* tr set time */ -int32 rx_stopioe = 0; /* stop on error */ -uint8 rx_buf[RX2_NUMBY] = { 0 }; /* sector buffer */ -static int32 bptr = 0; /* buffer pointer */ - -DEVICE rx_dev; -int32 rx (int32 IR, int32 AC); -t_stat rx_svc (UNIT *uptr); -t_stat rx_reset (DEVICE *dptr); -t_stat rx_boot (int32 unitno, DEVICE *dptr); -t_stat rx_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat rx_attach (UNIT *uptr, char *cptr); -void rx_cmd (void); -void rx_done (int32 esr_flags, int32 new_ecode); -t_stat rx_settype (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat rx_showtype (FILE *st, UNIT *uptr, int32 val, void *desc); - -/* RX8E data structures - - rx_dev RX device descriptor - rx_unit RX unit list - rx_reg RX register list - rx_mod RX modifier list -*/ - -DIB rx_dib = { DEV_RX, 1, { &rx } }; - -UNIT rx_unit[] = { - { UDATA (&rx_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+UNIT_MUSTBUF+ - UNIT_ROABLE, RX_SIZE) }, - { UDATA (&rx_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+UNIT_MUSTBUF+ - UNIT_ROABLE, RX_SIZE) } }; - -REG rx_reg[] = { - { ORDATA (RXCS, rx_csr, 12) }, - { ORDATA (RXDB, rx_dbr, 12) }, - { ORDATA (RXES, rx_esr, 12) }, - { ORDATA (RXERR, rx_ecode, 8) }, - { ORDATA (RXTA, rx_track, 8) }, - { ORDATA (RXSA, rx_sector, 8) }, - { DRDATA (STAPTR, rx_state, 4), REG_RO }, - { DRDATA (BUFPTR, bptr, 8) }, - { FLDATA (TR, rx_tr, 0) }, - { FLDATA (ERR, rx_err, 0) }, - { FLDATA (DONE, dev_done, INT_V_RX) }, - { FLDATA (ENABLE, int_enable, INT_V_RX) }, - { FLDATA (INT, int_req, INT_V_RX) }, - { DRDATA (CTIME, rx_cwait, 24), PV_LEFT }, - { DRDATA (STIME, rx_swait, 24), PV_LEFT }, - { DRDATA (XTIME, rx_xwait, 24), PV_LEFT }, - { FLDATA (STOP_IOE, rx_stopioe, 0) }, - { BRDATA (SBUF, rx_buf, 8, 8, RX2_NUMBY) }, - { FLDATA (RX28, rx_28, 0), REG_HRO }, - { URDATA (CAPAC, rx_unit[0].capac, 10, T_ADDR_W, 0, - RX_NUMDR, REG_HRO | PV_LEFT) }, - { ORDATA (DEVNUM, rx_dib.dev, 6), REG_HRO }, - { NULL } }; - -MTAB rx_mod[] = { - { UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL }, - { UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL }, - { MTAB_XTD | MTAB_VDV, 1, NULL, "RX28", - &rx_settype, NULL, NULL }, - { MTAB_XTD | MTAB_VDV, 0, NULL, "RX8E", - &rx_settype, NULL, NULL }, - { MTAB_XTD | MTAB_VDV, 0, "TYPE", NULL, - NULL, &rx_showtype, NULL }, - { (UNIT_DEN+UNIT_ATT), UNIT_ATT, "single density", NULL, NULL }, - { (UNIT_DEN+UNIT_ATT), (UNIT_DEN+UNIT_ATT), "double density", NULL, NULL }, - { (UNIT_AUTO+UNIT_DEN+UNIT_ATT), 0, "single density", NULL, NULL }, - { (UNIT_AUTO+UNIT_DEN+UNIT_ATT), UNIT_DEN, "double density", NULL, NULL }, - { (UNIT_AUTO+UNIT_ATT), UNIT_AUTO, "autosize", NULL, NULL }, - { UNIT_AUTO, UNIT_AUTO, NULL, "AUTOSIZE", NULL }, - { (UNIT_AUTO+UNIT_DEN), 0, NULL, "SINGLE", &rx_set_size }, - { (UNIT_AUTO+UNIT_DEN), UNIT_DEN, NULL, "DOUBLE", &rx_set_size }, - { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", - &set_dev, &show_dev, NULL }, - { 0 } }; - -DEVICE rx_dev = { - "RX", rx_unit, rx_reg, rx_mod, - RX_NUMDR, 8, 20, 1, 8, 8, - NULL, NULL, &rx_reset, - &rx_boot, &rx_attach, NULL, - &rx_dib, DEV_DISABLE }; - -/* IOT routine */ - -int32 rx (int32 IR, int32 AC) -{ -int32 drv = ((rx_csr & RXCS_DRV)? 1: 0); /* get drive number */ - -switch (IR & 07) { /* decode IR<9:11> */ -case 0: /* unused */ - break; -case 1: /* LCD */ - if (rx_state != IDLE) return AC; /* ignore if busy */ - dev_done = dev_done & ~INT_RX; /* clear done, int */ - int_req = int_req & ~INT_RX; - 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 */ - 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 */ - case CMD8: /* waiting for cmd */ - 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; - default: /* default */ - return READ_RXDBR; } /* return data reg */ - break; -case 3: /* STR */ - if (rx_tr != 0) { - rx_tr = 0; - return IOT_SKP + AC; } - break; -case 4: /* SER */ - if (rx_err != 0) { - 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; } - break; -case 6: /* INTR */ - if (AC & 1) int_enable = int_enable | INT_RX; - else int_enable = int_enable & ~INT_RX; - int_req = INT_UPDATE; - break; -case 7: /* INIT */ - rx_reset (&rx_dev); /* reset device */ - break; } /* end case pulse */ -return AC; -} - -void rx_cmd (void) -{ -int32 drv = ((rx_csr & RXCS_DRV)? 1: 0); /* get drive number */ - -switch (RXCS_GETFNC (rx_csr)) { /* decode command */ -case RXCS_FILL: - rx_state = FILL; /* state = fill */ - rx_tr = 1; /* xfer is ready */ - break; -case RXCS_EMPTY: - rx_state = EMPTY; /* state = empty */ - sim_activate (&rx_unit[drv], rx_xwait); /* sched xfer */ - break; -case RXCS_READ: case RXCS_WRITE: case RXCS_WRDEL: - rx_state = RWDS; /* state = get sector */ - rx_tr = 1; /* xfer is ready */ - rx_esr = rx_esr & RXES_ID; /* clear errors */ - break; -case RXCS_SDEN: - if (rx_28) { /* RX28? */ - 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 */ - break; } /* end switch func */ -return; -} - -/* Unit service; the action to be taken depends on the transfer state: - - IDLE Should never get here - RWDS Save sector, set TR, set RWDT - RWDT Save track, set RWXFR - RWXFR Read/write buffer - FILL copy dbr to rx_buf[bptr], advance ptr - if bptr > max, finish command, else set tr - EMPTY if bptr > max, finish command, else - copy rx_buf[bptr] to dbr, advance ptr, set tr - CMD_COMPLETE copy requested data to dbr, finish command - INIT_COMPLETE read drive 0, track 1, sector 1 to buffer, finish command - - For RWDT and CMD_COMPLETE, the input argument is the selected drive; - otherwise, it is drive 0. -*/ - -t_stat rx_svc (UNIT *uptr) -{ -int32 i, func, byptr, bps, wps; -uint32 da; -#define PTR12(x) (((x) + (x) + (x)) >> 1) - -if (rx_28 && (uptr->flags & UNIT_DEN)) - bps = RX2_NUMBY; -else bps = RX_NUMBY; -wps = bps / 2; -func = RXCS_GETFNC (rx_csr); /* get function */ -switch (rx_state) { /* case on state */ - -case IDLE: /* idle */ - return SCPE_IERR; - -case EMPTY: /* empty buffer */ - if (rx_csr & RXCS_MODE) { /* 8b xfer? */ - if (bptr >= bps) { /* done? */ - rx_done (0, 0); /* set done */ - break; } /* and exit */ - rx_dbr = rx_buf[bptr]; } /* else get data */ - else { - byptr = PTR12 (bptr); /* 12b xfer */ - if (bptr >= wps) { /* done? */ - rx_done (0, 0); /* set done */ - break; } /* and exit */ - rx_dbr = (bptr & 1)? /* get data */ - ((rx_buf[byptr] & 017) << 8) | rx_buf[byptr + 1]: - (rx_buf[byptr] << 4) | ((rx_buf[byptr + 1] >> 4) & 017); } - bptr = bptr + 1; - rx_tr = 1; - break; - -case FILL: /* fill buffer */ - if (rx_csr & RXCS_MODE) { /* 8b xfer? */ - rx_buf[bptr] = rx_dbr; /* fill buffer */ - bptr = bptr + 1; - if (bptr < bps) rx_tr = 1; /* if more, set xfer */ - else rx_done (0, 0); } /* else done */ - else { - byptr = PTR12 (bptr); /* 12b xfer */ - if (bptr & 1) { /* odd or even? */ - rx_buf[byptr] = (rx_buf[byptr] & 0360) | ((rx_dbr >> 8) & 017); - rx_buf[byptr + 1] = rx_dbr & 0377; } - else { - rx_buf[byptr] = (rx_dbr >> 4) & 0377; - rx_buf[byptr + 1] = (rx_dbr & 017) << 4; } - bptr = bptr + 1; - if (bptr < wps) rx_tr = 1; /* if more, set xfer */ - else { - for (i = PTR12 (RX_NUMWD); i < RX_NUMBY; i++) - rx_buf[i] = 0; /* else fill sector */ - rx_done (0, 0); } } /* set done */ - break; - -case RWDS: /* wait for sector */ - rx_sector = rx_dbr & RX_M_SECTOR; /* save sector */ - rx_tr = 1; /* set xfer ready */ - rx_state = RWDT; /* advance state */ - return SCPE_OK; -case RWDT: /* wait for track */ - rx_track = rx_dbr & RX_M_TRACK; /* save track */ - rx_state = RWXFR; - sim_activate (uptr, /* sched done */ - rx_swait * abs (rx_track - uptr->TRACK)); - return SCPE_OK; -case RWXFR: /* transfer */ - if ((uptr->flags & UNIT_BUF) == 0) { /* not buffered? */ - 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; } - uptr->TRACK = rx_track; /* now on track */ - if ((rx_sector == 0) || (rx_sector > RX_NUMSC)) { /* bad sect? */ - rx_done (0, 0070); /* done, error */ - break; } - if (rx_28 && /* RX28? */ - (((uptr->flags & UNIT_DEN) != 0) ^ - ((rx_csr & RXCS_DEN) != 0))) { /* densities agree? */ - rx_done (RXES_DERR, 0240); /* no, error */ - break; } - da = CALC_DA (rx_track, rx_sector, bps); /* get disk address */ - if (func == RXCS_WRDEL) rx_esr = rx_esr | RXES_DD; /* del data? */ - if (func == RXCS_READ) { /* read? */ - for (i = 0; i < bps; i++) - rx_buf[i] = *(((int8 *) uptr->filebuf) + da + i); } - else { /* write */ - if (uptr->flags & UNIT_WPRT) { /* locked? */ - rx_done (0, 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 SDCNF: /* confirm set density */ - if ((rx_dbr & 0377) != 0111) { /* confirmed? */ - rx_done (0, 0250); /* no, error */ - break; } - rx_state = SDXFR; /* next state */ - sim_activate (uptr, rx_cwait * 100); /* schedule operation */ - break; -case SDXFR: /* erase disk */ - for (i = 0; i < (int32) uptr->capac; i++) - *(((int8 *) uptr->filebuf) + i) = 0; - uptr->hwmark = uptr->capac; - if (rx_csr & RXCS_DEN) uptr->flags = uptr->flags | UNIT_DEN; - else uptr->flags = uptr->flags & ~UNIT_DEN; - rx_done (0, 0); - 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 */ - else rx_done (0, 0); - break; - -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; } - da = CALC_DA (1, 1, bps); /* track 1, sector 1 */ - for (i = 0; i < bps; i++) /* read sector */ - 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 */ -return SCPE_OK; -} - -/* Command complete. Set done and put final value in interface register, - return to IDLE state. -*/ - -void rx_done (int32 esr_flags, int32 new_ecode) -{ -int32 drv = (rx_csr & RXCS_DRV)? 1: 0; - -rx_state = IDLE; /* now idle */ -dev_done = dev_done | INT_RX; /* set done */ -int_req = INT_UPDATE; /* update ints */ -rx_esr = (rx_esr | esr_flags) & ~(RXES_DRDY|RXES_RX02|RXES_DEN); -if (rx_28) rx_esr = rx_esr | RXES_RX02; /* update estat */ -if (rx_unit[drv].flags & UNIT_ATT) { /* update drv rdy */ - rx_esr = rx_esr | RXES_DRDY; - if (rx_unit[drv].flags & UNIT_DEN) /* update density */ - rx_esr = rx_esr | RXES_DEN; } -if (new_ecode > 0) rx_err = 1; /* test for error */ -if (new_ecode < 0) return; /* don't update? */ -rx_ecode = new_ecode; /* update ecode */ -rx_dbr = rx_esr; /* update RXDB */ -return; -} - -/* Reset routine. The RX is one of the few devices that schedules - an I/O transfer as part of its initialization */ - -t_stat rx_reset (DEVICE *dptr) -{ -rx_dbr = rx_csr = 0; /* 12b mode, drive 0 */ -rx_esr = rx_ecode = 0; /* clear error */ -rx_tr = rx_err = 0; /* clear flags */ -rx_track = rx_sector = 0; /* clear address */ -rx_state = IDLE; /* ctrl idle */ -dev_done = dev_done & ~INT_RX; /* clear done, int */ -int_req = int_req & ~INT_RX; -int_enable = int_enable & ~INT_RX; -sim_cancel (&rx_unit[1]); /* cancel drive 1 */ -if (dptr->flags & DEV_DIS) sim_cancel (&rx_unit[0]); /* disabled? */ -else if (rx_unit[0].flags & UNIT_BUF) { /* attached? */ - rx_state = INIT_COMPLETE; /* yes, sched init */ - sim_activate (&rx_unit[0], rx_swait * abs (1 - rx_unit[0].TRACK)); } -else rx_done (rx_esr | RXES_ID, 0010); /* no, error */ -return SCPE_OK; -} - -/* Attach routine */ - -t_stat rx_attach (UNIT *uptr, char *cptr) -{ -uint32 sz; - -if ((uptr->flags & UNIT_AUTO) && (sz = sim_fsize (cptr))) { - if (sz > RX_SIZE) uptr->flags = uptr->flags | UNIT_DEN; - else uptr->flags = uptr->flags & ~UNIT_DEN; } -uptr->capac = (uptr->flags & UNIT_DEN)? RX2_SIZE: RX_SIZE; -return attach_unit (uptr, cptr); -} - -/* Set size routine */ - -t_stat rx_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -if (uptr->flags & UNIT_ATT) return SCPE_ALATT; -if ((rx_28 == 0) && val) return SCPE_NOFNC; /* not on RX8E */ -uptr->capac = val? RX2_SIZE: RX_SIZE; -return SCPE_OK; -} - -/* Set controller type */ - -t_stat rx_settype (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -int32 i; - -if ((val < 0) || (val > 1) || (cptr != NULL)) return SCPE_ARG; -if (val == rx_28) return SCPE_OK; -for (i = 0; i < RX_NUMDR; i++) { - if (rx_unit[i].flags & UNIT_ATT) return SCPE_ALATT; } -for (i = 0; i < RX_NUMDR; i++) { - rx_unit[i].flags = rx_unit[i].flags & ~(UNIT_DEN | UNIT_AUTO); - rx_unit[i].capac = RX_SIZE; - if (val) rx_unit[i].flags = rx_unit[i].flags | UNIT_AUTO; } -rx_28 = val; -return SCPE_OK; -} - -/* Show controller type */ - -t_stat rx_showtype (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -if (rx_28) fprintf (st, "RX28"); -else fprintf (st, "RX8E"); -return SCPE_OK; -} - -/* Bootstrap routine */ - -#define BOOT_START 022 -#define BOOT_ENTRY 022 -#define BOOT_INST 060 -#define BOOT_LEN (sizeof (boot_rom) / sizeof (int16)) -#define BOOT2_START 020 -#define BOOT2_ENTRY 033 -#define BOOT2_LEN (sizeof (boot2_rom) / sizeof (int16)) - -static const uint16 boot_rom[] = { - 06755, /* 22, SDN */ - 05022, /* 23, JMP .-1 */ - 07126, /* 24, CLL CML RTL ; read command + */ - 01060, /* 25, TAD UNIT ; unit no */ - 06751, /* 26, LCD ; load read+unit */ - 07201, /* 27, CLA IAC ; AC = 1 */ - 04053, /* 30, JMS LOAD ; load sector */ - 04053, /* 31, JMS LOAD ; load track */ - 07104, /* 32, CLL RAL ; AC = 2 */ - 06755, /* 33, SDN */ - 05054, /* 34, JMP LOAD+1 */ - 06754, /* 35, SER */ - 07450, /* 36, SNA ; more to do? */ - 07610, /* 37, CLA SKP ; error */ - 05046, /* 40, JMP 46 ; go empty */ - 07402, /* 41-45, HALT ; error */ - 07402, - 07402, - 07402, - 07402, - 06751, /* 46, LCD ; load empty */ - 04053, /* 47, JMS LOAD ; get data */ - 03002, /* 50, DCA 2 ; store */ - 02050, /* 51, ISZ 50 ; incr store */ - 05047, /* 52, JMP 47 ; loop until done */ - 00000, /* LOAD, 0 */ - 06753, /* 54, STR */ - 05033, /* 55, JMP 33 */ - 06752, /* 56, XDR */ - 05453, /* 57, JMP I LOAD */ - 07024, /* UNIT, CML RAL ; for unit 1 */ - 06030 /* 61, KCC */ -}; - -static const uint16 boot2_rom[] = { - 01061, /* READ, TAD UNIT ; next unit+den */ - 01046, /* 21, TAD CON360 ; add in 360 */ - 00060, /* 22, AND CON420 ; mask to 420 */ - 03061, /* 23, DCA UNIT ; 400,420,0,20... */ - 07327, /* 24, STL CLA IAC RTL ; AC = 6 = read */ - 01061, /* 25, TAD UNIT ; +unit+den */ - 06751, /* 26, LCD ; load cmd */ - 07201, /* 27, CLA IAC; ; AC = 1 = trksec */ - 04053, /* 30, JMS LOAD ; load trk */ - 04053, /* 31, JMS LOAD ; load sec */ - 07004, /* CN7004, RAL ; AC = 2 = empty */ - 06755, /* START, SDN ; done? */ - 05054, /* 34, JMP LOAD+1 ; check xfr */ - 06754, /* 35, SER ; error? */ - 07450, /* 36, SNA ; AC=0 on start */ - 05020, /* 37, JMP RD ; try next den,un */ - 01061, /* 40, TAD UNIT ; +unit+den */ - 06751, /* 41, LCD ; load cmd */ - 01061, /* 42, TAD UNIT ; set 60 for sec boot */ - 00046, /* 43, AND CON360 ; only density */ - 01032, /* 44, TAD CN7004 ; magic */ - 03060, /* 45, DCA 60 */ - 00360, /* CON360, 360 ; NOP */ - 04053, /* 47, JMS LOAD ; get data */ - 03002, /* 50, DCA 2 ; store */ - 02050, /* 51, ISZ .-1 ; incr store */ - 05047, /* 52, JMP .-3 ; loop until done */ - 00000, /* LOAD, 0 */ - 06753, /* 54, STR ; xfr ready? */ - 05033, /* 55, JMP 33 ; no, chk done */ - 06752, /* 56, XDR ; get word */ - 05453, /* 57, JMP I 53 ; return */ - 00420, /* CON420, 420 ; toggle */ - 00020 /* UNIT, 20 ; unit+density */ -}; - -t_stat rx_boot (int32 unitno, DEVICE *dptr) -{ -int32 i; -extern int32 saved_PC; -extern uint16 M[]; - -if (rx_dib.dev != DEV_RX) return STOP_NOTSTD; /* only std devno */ -if (rx_28) { - for (i = 0; i < BOOT2_LEN; i++) M[BOOT2_START + i] = boot2_rom[i]; - saved_PC = BOOT2_ENTRY; } -else { - for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i]; - M[BOOT_INST] = unitno? 07024: 07004; - saved_PC = BOOT_ENTRY; } -return SCPE_OK; -} diff --git a/PDP8/pdp8_sys.c b/PDP8/pdp8_sys.c deleted file mode 100644 index 9149e149..00000000 --- a/PDP8/pdp8_sys.c +++ /dev/null @@ -1,515 +0,0 @@ -/* pdp8_sys.c: PDP-8 simulator interface - - 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. - - 25-Apr-03 RMS Revised for extended file support - 30-Dec-01 RMS Revised for new TTX - 26-Nov-01 RMS Added RL8A support - 17-Sep-01 RMS Removed multiconsole support - 16-Sep-01 RMS Added TSS/8 packed char support, added KL8A support - 27-May-01 RMS Added multiconsole support - 18-Mar-01 RMS Added DF32 support - 14-Mar-01 RMS Added extension detection of RIM binary tapes - 15-Feb-01 RMS Added DECtape support - 30-Oct-00 RMS Added support for examine to file - 27-Oct-98 RMS V2.4 load interface - 10-Apr-98 RMS Added RIM loader support - 17-Feb-97 RMS Fixed bug in handling of bin loader fields -*/ - -#include "pdp8_defs.h" -#include - -extern DEVICE cpu_dev; -extern UNIT cpu_unit; -extern DEVICE ptr_dev, ptp_dev; -extern DEVICE tti_dev, tto_dev; -extern DEVICE clk_dev, lpt_dev; -extern DEVICE rk_dev, rl_dev; -extern DEVICE rx_dev; -extern DEVICE df_dev, rf_dev; -extern DEVICE dt_dev, mt_dev; -extern DEVICE ttix_dev, ttox_dev; -extern REG cpu_reg[]; -extern uint16 M[]; -extern int32 sim_switches; - -/* SCP data structures and interface routines - - sim_name simulator name string - sim_PC pointer to saved PC register descriptor - sim_emax maximum number of words for examine/deposit - sim_devices array of pointers to simulated devices - sim_consoles array of pointers to consoles (if more than one) - sim_stop_messages array of pointers to stop messages - sim_load binary loader -*/ - -char sim_name[] = "PDP-8"; - -REG *sim_PC = &cpu_reg[0]; - -int32 sim_emax = 4; - -DEVICE *sim_devices[] = { - &cpu_dev, - &ptr_dev, &ptp_dev, - &tti_dev, &tto_dev, - &ttix_dev, &ttox_dev, - &clk_dev, &lpt_dev, - &rk_dev, &rl_dev, - &rx_dev, - &df_dev, &rf_dev, - &dt_dev, &mt_dev, - NULL }; - -const char *sim_stop_messages[] = { - "Unknown error", - "Unimplemented instruction", - "HALT instruction", - "Breakpoint", - "Non-standard device number" }; - -/* Binary loader - - Two loader formats are supported: RIM loader (-r) and BIN (-b) loader. - - RIM loader format consists of alternating pairs of addresses and 12-bit - words. It can only operate in field 0 and is not checksummed. - - BIN loader format consists of a string of 12-bit words (made up from - 7-bit characters) between leader and trailer (200). The last word on - tape is the checksum. A word with the "link" bit set is a new origin; - a character > 0200 indicates a change of field. -*/ - -t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag) -{ -int32 rubout, word, low, high, csum, newf, state, i; -uint32 origin, field; - -if ((*cptr != 0) || (flag != 0)) return SCPE_ARG; -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 */ - } /* 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 */ - } /* end else */ -return SCPE_FMT; /* eof? error */ -} - -/* Symbol tables */ - -#define I_V_FL 18 /* flag start */ -#define I_M_FL 07 /* flag mask */ -#define I_V_NPN 0 /* no operand */ -#define I_V_FLD 1 /* field change */ -#define I_V_MRF 2 /* mem ref */ -#define I_V_IOT 3 /* general IOT */ -#define I_V_OP1 4 /* operate 1 */ -#define I_V_OP2 5 /* operate 2 */ -#define I_V_OP3 6 /* operate 3 */ -#define I_NPN (I_V_NPN << I_V_FL) -#define I_FLD (I_V_FLD << I_V_FL) -#define I_MRF (I_V_MRF << I_V_FL) -#define I_IOT (I_V_IOT << I_V_FL) -#define I_OP1 (I_V_OP1 << I_V_FL) -#define I_OP2 (I_V_OP2 << I_V_FL) -#define I_OP3 (I_V_OP3 << I_V_FL) - -static const int32 masks[] = { - 07777, 07707, 07000, 07000, - 07416, 07571, 017457 }; - -static const char *opcode[] = { - "SKON", "ION", "IOF", "SRQ", - "GTF", "RTF", "SGT", "CAF", - "RPE", "RSF", "RRB", "RFC", "RFC RRB", - "PCE", "PSF", "PCF", "PPC", "PLS", - "KCF", "KSF", "KCC", "KRS", "KIE", "KRB", - "TLF", "TSF", "TCF", "TPC", "SPI", "TLS", - "SBE", "SPL", "CAL", - "CLEI", "CLDI", "CLSC", "CLLE", "CLCL", "CLSK", - "CINT", "RDF", "RIF", "RIB", - "RMF", "SINT", "CUF", "SUF", - "ADCL", "ADLM", "ADST", "ADRB", - "ADSK", "ADSE", "ADLE", "ADRS", - "DCMA", "DMAR", "DMAW", - "DCIM", "DSAC", "DIML", "DIMA", - "DCEA", "DEAL", "DEAC", - "DFSE", "DFSC", "DISK", "DMAC", - "DCXA", "DXAL", "DXAC", - "PSKF", "PCLF", "PSKE", - "PSTB", "PSIE", "PCLF PSTB", "PCIE", - "LWCR", "CWCR", "LCAR", - "CCAR", "LCMR", "LFGR", "LDBR", - "RWCR", "CLT", "RCAR", - "RMSR", "RCMR", "RFSR", "RDBR", - "SKEF", "SKCB", "SKJD", "SKTR", "CLF", - "DSKP", "DCLR", "DLAG", - "DLCA", "DRST", "DLDC", "DMAN", - "LCD", "XDR", "STR", - "SER", "SDN", "INTR", "INIT", - "DTRA", "DTCA", "DTXA", "DTLA", - "DTSF", "DTRB", "DTLB", - "RLDC", "RLSD", "RLMA", "RLCA", - "RLCB", "RLSA", "RLWC", - "RRER", "RRWC", "RRCA", "RRCB", - "RRSA", "RRSI", "RLSE", - - "CDF", "CIF", "CIF CDF", - "AND", "TAD", "ISZ", "DCA", "JMS", "JMP", "IOT", - "NOP", "NOP2", "NOP3", "SWAB", "SWBA", - "STL", "GLK", "STA", "LAS", "CIA", - "BSW", "RAL", "RTL", "RAR", "RTR", "RAL RAR", "RTL RTR", - "SKP", "SNL", "SZL", - "SZA", "SNA", "SZA SNL", "SNA SZL", - "SMA", "SPA", "SMA SNL", "SPA SZL", - "SMA SZA", "SPA SNA", "SMA SZA SNL", "SPA SNA SZL", - "SCL", "MUY", "DVI", "NMI", "SHL", "ASR", "LSR", - "SCA", "SCA SCL", "SCA MUY", "SCA DVI", - "SCA NMI", "SCA SHL", "SCA ASR", "SCA LSR", - "ACS", "MUY", "DVI", "NMI", "SHL", "ASR", "LSR", - "SCA", "DAD", "DST", "SWBA", - "DPSZ", "DPIC", "DCIM", "SAM", - "CLA", "CLL", "CMA", "CML", "IAC", /* encode only */ - "CLA", "OAS", "HLT", - "CLA", "MQA", "MQL", - NULL, NULL, NULL, NULL, /* decode only */ - NULL }; - -static const int32 opc_val[] = { - 06000+I_NPN, 06001+I_NPN, 06002+I_NPN, 06003+I_NPN, - 06004+I_NPN, 06005+I_NPN, 06006+I_NPN, 06007+I_NPN, - 06010+I_NPN, 06011+I_NPN, 06012+I_NPN, 06014+I_NPN, 06016+I_NPN, - 06020+I_NPN, 06021+I_NPN, 06022+I_NPN, 06024+I_NPN, 06026+I_NPN, - 06030+I_NPN, 06031+I_NPN, 06032+I_NPN, 06034+I_NPN, 06035+I_NPN, 06036+I_NPN, - 06040+I_NPN, 06041+I_NPN, 06042+I_NPN, 06044+I_NPN, 06045+I_NPN, 06046+I_NPN, - 06101+I_NPN, 06102+I_NPN, 06103+I_NPN, - 06131+I_NPN, 06132+I_NPN, 06133+I_NPN, 06135+I_NPN, 06136+I_NPN, 06137+I_NPN, - 06204+I_NPN, 06214+I_NPN, 06224+I_NPN, 06234+I_NPN, - 06244+I_NPN, 06254+I_NPN, 06264+I_NPN, 06274+I_NPN, - 06530+I_NPN, 06531+I_NPN, 06532+I_NPN, 06533+I_NPN, - 06534+I_NPN, 06535+I_NPN, 06536+I_NPN, 06537+I_NPN, - 06601+I_NPN, 06603+I_NPN, 06605+I_NPN, - 06611+I_NPN, 06612+I_NPN, 06615+I_NPN, 06616+I_NPN, - 06611+I_NPN, 06615+I_NPN, 06616+I_NPN, - 06621+I_NPN, 06622+I_NPN, 06623+I_NPN, 06626+I_NPN, - 06641+I_NPN, 06643+I_NPN, 06645+I_NPN, - 06661+I_NPN, 06662+I_NPN, 06663+I_NPN, - 06664+I_NPN, 06665+I_NPN, 06666+I_NPN, 06667+I_NPN, - 06701+I_NPN, 06702+I_NPN, 06703+I_NPN, - 06704+I_NPN, 06705+I_NPN, 06706+I_NPN, 06707+I_NPN, - 06711+I_NPN, 06712+I_NPN, 06713+I_NPN, - 06714+I_NPN, 06715+I_NPN, 06716+I_NPN, 06717+I_NPN, - 06721+I_NPN, 06722+I_NPN, 06723+I_NPN, 06724+I_NPN, 06725+I_NPN, - 06741+I_NPN, 06742+I_NPN, 06743+I_NPN, - 06744+I_NPN, 06745+I_NPN, 06746+I_NPN, 06747+I_NPN, - 06751+I_NPN, 06752+I_NPN, 06753+I_NPN, - 06754+I_NPN, 06755+I_NPN, 06756+I_NPN, 06757+I_NPN, - 06761+I_NPN, 06762+I_NPN, 06764+I_NPN, 06766+I_NPN, - 06771+I_NPN, 06772+I_NPN, 06774+I_NPN, - 06600+I_NPN, 06601+I_NPN, 06602+I_NPN, 06603+I_NPN, - 06604+I_NPN, 06605+I_NPN, 06607+I_NPN, - 06610+I_NPN, 06611+I_NPN, 06612+I_NPN, 06613+I_NPN, - 06614+I_NPN, 06615+I_NPN, 06617+I_NPN, - - 06201+I_FLD, 06202+I_FLD, 06203+I_FLD, - 00000+I_MRF, 01000+I_MRF, 02000+I_MRF, 03000+I_MRF, - 04000+I_MRF, 05000+I_MRF, 06000+I_IOT, - 07000+I_NPN, 07400+I_NPN, 07401+I_NPN, 07431+I_NPN, 07447+I_NPN, - 07120+I_NPN, 07204+I_NPN, 07240+I_NPN, 07604+I_NPN, 07041+I_NPN, - 07002+I_OP1, 07004+I_OP1, 07006+I_OP1, - 07010+I_OP1, 07012+I_OP1, 07014+I_OP1, 07016+I_OP1, - 07410+I_OP2, 07420+I_OP2, 07430+I_OP2, - 07440+I_OP2, 07450+I_OP2, 07460+I_OP2, 07470+I_OP2, - 07500+I_OP2, 07510+I_OP2, 07520+I_OP2, 07530+I_OP2, - 07540+I_OP2, 07550+I_OP2, 07560+I_OP2, 07570+I_OP2, - 07403+I_OP3, 07405+I_OP3, 07407+I_OP3, - 07411+I_OP3, 07413+I_OP3, 07415+I_OP3, 07417+I_OP3, - 07441+I_OP3, 07443+I_OP3, 07445+I_OP3, 07447+I_OP3, - 07451+I_OP3, 07453+I_OP3, 07455+I_OP3, 07457+I_OP3, - 017403+I_OP3, 017405+I_OP3, 0174017+I_OP3, - 017411+I_OP3, 017413+I_OP3, 017415+I_OP3, 017417+I_OP3, - 017441+I_OP3, 017443+I_OP3, 017445+I_OP3, 017447+I_OP3, - 017451+I_OP3, 017453+I_OP3, 017455+I_OP3, 017457+I_OP3, - 07200+I_OP1, 07100+I_OP1, 07040+I_OP1, 07020+I_OP1, 07001+I_OP1, - 07600+I_OP2, 07404+I_OP2, 07402+I_OP2, - 07601+I_OP3, 07501+I_OP3, 07421+I_OP3, - 07000+I_OP1, 07400+I_OP2, 07401+I_OP3, 017401+I_OP3, - -1 }; - -/* Operate 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 data - *uptr = pointer to unit - sw = switches - Outputs: - return = status code -*/ - -#define FMTASC(x) ((x) < 040)? "<%03o>": "%c", (x) -#define SIXTOASC(x) (((x) >= 040)? (x): (x) + 0100) -#define TSSTOASC(x) ((x) + 040) - -t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, - UNIT *uptr, int32 sw) -{ -int32 cflag, i, j, sp, inst, disp; -extern int32 emode; - -cflag = (uptr == NULL) || (uptr == &cpu_unit); -inst = val[0]; -if (sw & SWMASK ('A')) { /* ASCII? */ - if (inst > 0377) return SCPE_ARG; - fprintf (of, FMTASC (inst & 0177)); - return SCPE_OK; } -if (sw & SWMASK ('C')) { /* characters? */ - fprintf (of, "%c", SIXTOASC ((inst >> 6) & 077)); - fprintf (of, "%c", SIXTOASC (inst & 077)); - return SCPE_OK; } -if (sw & SWMASK ('T')) { /* TSS8 packed? */ - fprintf (of, "%c", TSSTOASC ((inst >> 6) & 077)); - fprintf (of, "%c", TSSTOASC (inst & 077)); - return SCPE_OK; } -if (!(sw & SWMASK ('M'))) return SCPE_ARG; - -/* Instruction decode */ - -inst = val[0] | ((emode & 1) << 12); /* include EAE mode */ -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] & 017777) == (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_FLD: /* field change */ - 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; - case I_V_IOT: /* IOT */ - 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; - 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; - 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 */ - return SCPE_OK; } /* end if */ - } /* end for */ -return SCPE_ARG; -} - -/* 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; -t_stat r; -char gbuf[CBUFSIZE]; - -cflag = (uptr == NULL) || (uptr == &cpu_unit); -while (isspace (*cptr)) cptr++; /* absorb spaces */ -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++)) { /* sixbit string? */ - if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */ - val[0] = (((t_value) cptr[0] & 077) << 6) | - ((t_value) cptr[1] & 077); - return SCPE_OK; } -if ((sw & SWMASK ('T')) || ((*cptr == '"') && cptr++)) { /* TSS8 string? */ - if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */ - val[0] = (((t_value) (cptr[0] - 040) & 077) << 6) | - ((t_value) (cptr[1] - 040) & 077); - return SCPE_OK; } - -/* Instruction parse */ - -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] & 07777; /* get value */ -j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */ - -switch (j) { /* case on class */ -case I_V_IOT: /* IOT */ - cptr = get_glyph (cptr, gbuf, 0); /* get dev+pulse */ - d = get_uint (gbuf, 8, 0777, &r); - if (r != SCPE_OK) return SCPE_ARG; - val[0] = val[0] | d; - 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) && - (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; -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); } - 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; } - 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) && - (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; } - 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 deleted file mode 100644 index 33712fb5..00000000 --- a/PDP8/pdp8_tt.c +++ /dev/null @@ -1,264 +0,0 @@ -/* pdp8_tt.c: PDP-8 console terminal simulator - - 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. - - tti,tto KL8E terminal input/output - - 25-Apr-03 RMS Revised for extended file support - 02-Mar-02 RMS Added SET TTI CTRL-C - 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 - 07-Sep-01 RMS Moved function prototypes -*/ - -#include "pdp8_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) - -extern int32 int_req, int_enable, dev_done, stop_inst; - -int32 tti (int32 IR, int32 AC); -int32 tto (int32 IR, int32 AC); -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 tti_set_ctrlc (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat tty_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc); - -/* TTI data structures - - tti_dev TTI device descriptor - tti_unit TTI unit descriptor - tti_reg TTI register list - tti_mod TTI modifiers list -*/ - -DIB tti_dib = { DEV_TTI, 1, { &tti } }; - -UNIT tti_unit = { UDATA (&tti_svc, UNIT_KSR, 0), KBD_POLL_WAIT }; - -REG tti_reg[] = { - { ORDATA (BUF, tti_unit.buf, 8) }, - { FLDATA (DONE, dev_done, INT_V_TTI) }, - { FLDATA (ENABLE, int_enable, INT_V_TTI) }, - { FLDATA (INT, int_req, INT_V_TTI) }, - { DRDATA (POS, tti_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, tti_unit.wait, 24), REG_NZ + PV_LEFT }, - { FLDATA (UC, tti_unit.flags, UNIT_V_KSR), REG_HRO }, - { NULL } }; - -MTAB tti_mod[] = { - { UNIT_KSR+UNIT_8B, UNIT_KSR, "KSR", "KSR", &tty_set_mode }, - { UNIT_KSR+UNIT_8B, 0 , "7b" , "7B" , &tty_set_mode }, - { UNIT_KSR+UNIT_8B, UNIT_8B , "8b" , "8B" , &tty_set_mode }, - { MTAB_XTD|MTAB_VDV|MTAB_VUN, 0, NULL, "CTRL-C", &tti_set_ctrlc, NULL, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "DEVNO", NULL, NULL, &show_dev, NULL }, - { 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 descriptor - tto_reg TTO register list -*/ - -DIB tto_dib = { DEV_TTO, 1, { &tto } }; - -UNIT tto_unit = { UDATA (&tto_svc, UNIT_KSR, 0), SERIAL_OUT_WAIT }; - -REG tto_reg[] = { - { ORDATA (BUF, tto_unit.buf, 8) }, - { FLDATA (DONE, dev_done, INT_V_TTO) }, - { FLDATA (ENABLE, int_enable, INT_V_TTO) }, - { FLDATA (INT, int_req, INT_V_TTO) }, - { DRDATA (POS, tto_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, tto_unit.wait, 24), PV_LEFT }, - { NULL } }; - -MTAB tto_mod[] = { - { UNIT_KSR+UNIT_8B, UNIT_KSR, "KSR", "KSR", &tty_set_mode }, - { UNIT_KSR+UNIT_8B, 0 , "7b" , "7B" , &tty_set_mode }, - { UNIT_KSR+UNIT_8B, UNIT_8B , "8b" , "8B" , &tty_set_mode }, - { MTAB_XTD|MTAB_VDV, 0, "DEVNO", NULL, NULL, &show_dev }, - { 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 }; - -/* Terminal input: IOT routine */ - -int32 tti (int32 IR, int32 AC) -{ -switch (IR & 07) { /* decode IR<9:11> */ -case 0: /* KCF */ - dev_done = dev_done & ~INT_TTI; /* clear flag */ - int_req = int_req & ~INT_TTI; - return AC; -case 1: /* KSF */ - return (dev_done & INT_TTI)? IOT_SKP + AC: AC; -case 2: /* KCC */ - dev_done = dev_done & ~INT_TTI; /* clear flag */ - int_req = int_req & ~INT_TTI; - return 0; /* clear AC */ -case 4: /* KRS */ - return (AC | tti_unit.buf); /* return buffer */ -case 5: /* KIE */ - if (AC & 1) int_enable = int_enable | (INT_TTI+INT_TTO); - else int_enable = int_enable & ~(INT_TTI+INT_TTO); - int_req = INT_UPDATE; /* update interrupts */ - return AC; -case 6: /* KRB */ - dev_done = dev_done & ~INT_TTI; /* clear flag */ - int_req = int_req & ~INT_TTI; - return (tti_unit.buf); /* return buffer */ -default: - return (stop_inst << IOT_V_REASON) + AC; } /* end switch */ -} - -/* Unit service */ - -t_stat tti_svc (UNIT *uptr) -{ -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 (c & SCPE_BREAK) tti_unit.buf = 0; /* break? */ -else if (tti_unit.flags & UNIT_KSR) { /* KSR? */ - c = c & 0177; - if (islower (c)) c = toupper (c); - tti_unit.buf = c | 0200; } /* add TTY bit */ -else tti_unit.buf = c & ((tti_unit.flags & UNIT_8B)? 0377: 0177); -tti_unit.pos = tti_unit.pos + 1; -dev_done = dev_done | INT_TTI; /* set done */ -int_req = INT_UPDATE; /* update interrupts */ -return SCPE_OK; -} - -/* Reset routine */ - -t_stat tti_reset (DEVICE *dptr) -{ -tti_unit.buf = 0; -dev_done = dev_done & ~INT_TTI; /* clear done, int */ -int_req = int_req & ~INT_TTI; -int_enable = int_enable | INT_TTI; /* set enable */ -sim_activate (&tti_unit, tti_unit.wait); /* activate unit */ -return SCPE_OK; -} - -/* Set control-C */ - -t_stat tti_set_ctrlc (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -if (cptr) return SCPE_ARG; -uptr->buf = (uptr->flags & UNIT_KSR)? 0203: 0003; -uptr->pos = uptr->pos + 1; -dev_done = dev_done | INT_TTI; /* set done */ -int_req = INT_UPDATE; /* update interrupts */ -return SCPE_OK; -} - -/* Terminal output: IOT routine */ - -int32 tto (int32 IR, int32 AC) -{ -switch (IR & 07) { /* decode IR<9:11> */ -case 0: /* TLF */ - dev_done = dev_done | INT_TTO; /* set flag */ - int_req = INT_UPDATE; /* update interrupts */ - return AC; -case 1: /* TSF */ - return (dev_done & INT_TTO)? IOT_SKP + AC: AC; -case 2: /* TCF */ - dev_done = dev_done & ~INT_TTO; /* clear flag */ - int_req = int_req & ~INT_TTO; /* clear int req */ - return AC; -case 5: /* SPI */ - return (int_req & (INT_TTI+INT_TTO))? IOT_SKP + AC: AC; -case 6: /* TLS */ - dev_done = dev_done & ~INT_TTO; /* clear flag */ - int_req = int_req & ~INT_TTO; /* clear int req */ -case 4: /* TPC */ - sim_activate (&tto_unit, tto_unit.wait); /* activate unit */ - tto_unit.buf = AC; /* load buffer */ - return AC; -default: - return (stop_inst << IOT_V_REASON) + AC; } /* end switch */ -} - -/* Unit service */ - -t_stat tto_svc (UNIT *uptr) -{ -int32 c; -t_stat r; - -dev_done = dev_done | INT_TTO; /* set done */ -int_req = INT_UPDATE; /* update interrupts */ -if (tto_unit.flags & UNIT_KSR) { /* UC only? */ - c = tto_unit.buf & 0177; - if (islower (c)) c = toupper (c); } -else c = tto_unit.buf & ((tto_unit.flags & UNIT_8B)? 0377: 0177); -if ((r = sim_putchar (c)) != SCPE_OK) return r; -tto_unit.pos = tto_unit.pos + 1; -return SCPE_OK; -} - -/* Reset routine */ - -t_stat tto_reset (DEVICE *dptr) -{ -tto_unit.buf = 0; -dev_done = dev_done & ~INT_TTO; /* clear done, int */ -int_req = int_req & ~INT_TTO; -int_enable = int_enable | INT_TTO; /* set enable */ -sim_cancel (&tto_unit); /* deactivate unit */ -return SCPE_OK; -} - -t_stat tty_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -tti_unit.flags = (tti_unit.flags & ~(UNIT_KSR | UNIT_8B)) | val; -tto_unit.flags = (tto_unit.flags & ~(UNIT_KSR | UNIT_8B)) | val; -return SCPE_OK; -} diff --git a/PDP8/pdp8_ttx.c b/PDP8/pdp8_ttx.c deleted file mode 100644 index ac6d3125..00000000 --- a/PDP8/pdp8_ttx.c +++ /dev/null @@ -1,383 +0,0 @@ -/* pdp8_ttx.c: PDP-8 additional terminals simulator - - 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. - - ttix,ttox PT08/KL8JA terminal input/output - - 09-May-03 RMS Added network device flag - 25-Apr-03 RMS Revised for extended file support - 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 - 06-Jan-02 RMS Added device enable/disable support - 30-Dec-01 RMS Complete rebuild - 30-Nov-01 RMS Added extended SET/SHOW support - - This module implements four individual serial interfaces similar in function - to the console. These interfaces are mapped to Telnet based connections as - though they were the four lines of a terminal multiplexor. The connection - polling mechanism is superimposed onto the keyboard of the first interface. -*/ - -#include "pdp8_defs.h" -#include "sim_sock.h" -#include "sim_tmxr.h" -#include - -#define TTX_LINES 4 -#define TTX_MASK (TTX_LINES - 1) - -#define UNIT_V_8B (UNIT_V_UF + 0) /* 8B */ -#define UNIT_V_UC (UNIT_V_UF + 1) /* upper case */ -#define UNIT_8B (1 << UNIT_V_8B) -#define UNIT_UC (1 << UNIT_V_UC) - -#define TTX_GETLN(x) (((x) >> 4) & TTX_MASK) - -extern int32 int_req, int_enable, dev_done, stop_inst; - -uint8 ttix_buf[TTX_LINES] = { 0 }; /* input buffers */ -uint8 ttox_buf[TTX_LINES] = { 0 }; /* output buffers */ -int32 ttx_tps = 100; /* polls per second */ -TMLN ttx_ldsc[TTX_LINES] = { 0 }; /* line descriptors */ -TMXR ttx_desc = { /* mux descriptor */ - TTX_LINES, 0, 0, &ttx_ldsc[0], &ttx_ldsc[1], &ttx_ldsc[2], &ttx_ldsc[3] }; - -DEVICE ttix_dev, ttox_dev; -int32 ttix (int32 IR, int32 AC); -int32 ttox (int32 IR, int32 AC); -t_stat ttix_svc (UNIT *uptr); -t_stat ttix_reset (DEVICE *dptr); -t_stat ttox_svc (UNIT *uptr); -t_stat ttox_reset (DEVICE *dptr); -t_stat ttx_attach (UNIT *uptr, char *cptr); -t_stat ttx_detach (UNIT *uptr); -t_stat ttx_summ (FILE *st, UNIT *uptr, int32 val, void *desc); -t_stat ttx_show (FILE *st, UNIT *uptr, int32 val, void *desc); -void ttx_enbdis (int32 dis); - -/* TTIx data structures - - ttix_dev TTIx device descriptor - ttix_unit TTIx unit descriptor - ttix_reg TTIx register list - ttix_mod TTIx modifiers list -*/ - -DIB ttix_dib = { DEV_KJ8, 8, - { &ttix, &ttox, &ttix, &ttox, &ttix, &ttox, &ttix, &ttox } }; - -UNIT ttix_unit = { UDATA (&ttix_svc, UNIT_ATTABLE, 0), KBD_POLL_WAIT }; - -REG ttix_reg[] = { - { BRDATA (BUF, ttix_buf, 8, 8, TTX_LINES) }, - { GRDATA (DONE, dev_done, 8, TTX_LINES, INT_V_TTI1) }, - { GRDATA (ENABLE, int_enable, 8, TTX_LINES, INT_V_TTI1) }, - { GRDATA (INT, int_req, 8, TTX_LINES, INT_V_TTI1) }, - { DRDATA (TIME, ttix_unit.wait, 24), REG_NZ + PV_LEFT }, - { DRDATA (TPS, ttx_tps, 10), REG_NZ + PV_LEFT }, - { ORDATA (DEVNUM, ttix_dib.dev, 6), REG_HRO }, - { NULL } }; - -MTAB ttix_mod[] = { - { UNIT_ATT, UNIT_ATT, "summary", NULL, NULL, &ttx_summ }, - { MTAB_XTD | MTAB_VDV, 1, NULL, "DISCONNECT", - &tmxr_dscln, NULL, &ttx_desc }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "CONNECTIONS", NULL, - NULL, &ttx_show, NULL }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "STATISTICS", NULL, - NULL, &ttx_show, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", - &set_dev, &show_dev, NULL }, - { 0 } }; - -DEVICE ttix_dev = { - "TTIX", &ttix_unit, ttix_reg, ttix_mod, - 1, 10, 31, 1, 8, 8, - &tmxr_ex, &tmxr_dep, &ttix_reset, - NULL, &ttx_attach, &ttx_detach, - &ttix_dib, DEV_NET | DEV_DISABLE }; - -/* TTOx data structures - - ttox_dev TTOx device descriptor - ttox_unit TTOx unit descriptor - ttox_reg TTOx register list -*/ - -UNIT ttox_unit[] = { - { UDATA (&ttox_svc, UNIT_UC, 0), SERIAL_OUT_WAIT }, - { UDATA (&ttox_svc, UNIT_UC, 0), SERIAL_OUT_WAIT }, - { UDATA (&ttox_svc, UNIT_UC, 0), SERIAL_OUT_WAIT }, - { UDATA (&ttox_svc, UNIT_UC, 0), SERIAL_OUT_WAIT } }; - -REG ttox_reg[] = { - { BRDATA (BUF, ttox_buf, 8, 8, TTX_LINES) }, - { GRDATA (DONE, dev_done, 8, TTX_LINES, INT_V_TTO1) }, - { GRDATA (ENABLE, int_enable, 8, TTX_LINES, INT_V_TTO1) }, - { GRDATA (INT, int_req, 8, TTX_LINES, INT_V_TTO1) }, - { URDATA (TIME, ttox_unit[0].wait, 10, 24, 0, - TTX_LINES, PV_LEFT) }, - { NULL } }; - -MTAB ttox_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 }, - { 0 } }; - -DEVICE ttox_dev = { - "TTOX", ttox_unit, ttox_reg, ttox_mod, - 4, 10, 31, 1, 8, 8, - NULL, NULL, &ttox_reset, - NULL, NULL, NULL, - NULL, DEV_DISABLE }; - -/* Terminal input: IOT routine */ - -int32 ttix (int32 inst, int32 AC) -{ -int32 pulse = inst & 07; /* IOT pulse */ -int32 ln = TTX_GETLN (inst); /* line # */ -int32 itti = (INT_TTI1 << ln); /* rx intr */ -int32 itto = (INT_TTO1 << ln); /* tx intr */ - -switch (pulse) { /* case IR<9:11> */ -case 0: /* KCF */ - dev_done = dev_done & ~itti; /* clear flag */ - int_req = int_req & ~itti; - break; -case 1: /* KSF */ - return (dev_done & itti)? IOT_SKP + AC: AC; -case 2: /* KCC */ - dev_done = dev_done & ~itti; /* clear flag */ - int_req = int_req & ~itti; - return 0; /* clear AC */ -case 4: /* KRS */ - return (AC | ttix_buf[ln]); /* return buf */ -case 5: /* KIE */ - if (AC & 1) int_enable = int_enable | (itti + itto); - else int_enable = int_enable & ~(itti + itto); - int_req = INT_UPDATE; /* update intr */ - break; -case 6: /* KRB */ - dev_done = dev_done & ~itti; /* clear flag */ - int_req = int_req & ~itti; - return ttix_buf[ln]; /* return buf */ -default: - return (stop_inst << IOT_V_REASON) + AC; } /* end switch */ -return AC; -} - -/* Unit service */ - -t_stat ttix_svc (UNIT *uptr) -{ -int32 ln, c, temp; - -if ((uptr->flags & UNIT_ATT) == 0) return SCPE_OK; /* attached? */ -temp = sim_rtcn_calb (ttx_tps, TMR_TTX); /* calibrate */ -sim_activate (uptr, temp); /* continue poll */ -ln = tmxr_poll_conn (&ttx_desc); /* look for connect */ -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 (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; -} - -/* Reset routine */ - -t_stat ttix_reset (DEVICE *dptr) -{ -int32 t, ln, itto; - -ttx_enbdis (dptr->flags & DEV_DIS); /* sync enables */ -if (ttix_unit.flags & UNIT_ATT) { /* if attached, */ - if (!sim_is_active (&ttix_unit)) { - t = sim_rtcn_init (ttix_unit.wait, TMR_TTX); - sim_activate (&ttix_unit, t); } } /* activate */ -else sim_cancel (&ttix_unit); /* else stop */ -for (ln = 0; ln < TTX_LINES; ln++) { /* for all lines */ - ttix_buf[ln] = 0; /* clear buf, */ - itto = (INT_TTI1 << ln); /* interrupt */ - dev_done = dev_done & ~itto; /* clr done, int */ - int_req = int_req & ~itto; - int_enable = int_enable | itto; } /* set enable */ -return SCPE_OK; -} - -/* Terminal output: IOT routine */ - -int32 ttox (int32 inst, int32 AC) -{ -int32 pulse = inst & 07; /* pulse */ -int32 ln = TTX_GETLN (inst); /* line # */ -int32 itti = (INT_TTI1 << ln); /* rx intr */ -int32 itto = (INT_TTO1 << ln); /* tx intr */ - -switch (pulse) { /* case IR<9:11> */ -case 0: /* TLF */ - dev_done = dev_done | itto; /* set flag */ - int_req = INT_UPDATE; /* update intr */ - break; -case 1: /* TSF */ - return (dev_done & itto)? IOT_SKP + AC: AC; -case 2: /* TCF */ - dev_done = dev_done & ~itto; /* clear flag */ - int_req = int_req & ~itto; /* clear intr */ - break; -case 5: /* SPI */ - return (int_req & (itti | itto))? IOT_SKP + AC: AC; -case 6: /* TLS */ - dev_done = dev_done & ~itto; /* clear flag */ - int_req = int_req & ~itto; /* clear int req */ -case 4: /* TPC */ - sim_activate (&ttox_unit[ln], ttox_unit[ln].wait); /* activate */ - ttox_buf[ln] = AC & 0377; /* load buffer */ - break; -default: - return (stop_inst << IOT_V_REASON) + AC; } /* end switch */ -return AC; -} - -/* Unit service */ - -t_stat ttox_svc (UNIT *uptr) -{ -int32 c, ln = uptr - ttox_unit; /* line # */ - -if (ttx_desc.ldsc[ln]->conn) { /* connected? */ - if (ttx_desc.ldsc[ln]->xmte) { /* tx enabled? */ - TMLN *lp = ttx_desc.ldsc[ln]; /* get line */ - if (ttox_unit[ln].flags & UNIT_UC) { /* UC mode? */ - c = ttox_buf[ln] & 0177; /* get char */ - if (islower (c)) c = toupper (c); } - else c = ttox_buf[ln] & ((ttox_unit[ln].flags & UNIT_8B)? 0377: 0177); - tmxr_putc_ln (lp, c); /* output char */ - tmxr_poll_tx (&ttx_desc); } /* poll xmt */ - else { - tmxr_poll_tx (&ttx_desc); /* poll xmt */ - sim_activate (uptr, ttox_unit[ln].wait); /* wait */ - return SCPE_OK; } } -dev_done = dev_done | (INT_TTO1 << ln); /* set done */ -int_req = INT_UPDATE; /* update intr */ -return SCPE_OK; -} - -/* Reset routine */ - -t_stat ttox_reset (DEVICE *dptr) -{ -int32 ln, itto; - -ttx_enbdis (dptr->flags & DEV_DIS); /* sync enables */ -for (ln = 0; ln < TTX_LINES; ln++) { /* for all lines */ - ttox_buf[ln] = 0; /* clear buf */ - itto = (INT_TTO1 << ln); /* interrupt */ - dev_done = dev_done & ~itto; /* clr done, int */ - int_req = int_req & ~itto; - int_enable = int_enable | itto; /* set enable */ - sim_cancel (&ttox_unit[ln]); } /* deactivate */ -return SCPE_OK; -} - -/* Attach master unit */ - -t_stat ttx_attach (UNIT *uptr, char *cptr) -{ -int32 t; -t_stat r; - -r = tmxr_attach (&ttx_desc, uptr, cptr); /* attach */ -if (r != SCPE_OK) return r; /* error */ -t = sim_rtcn_init (ttix_unit.wait, TMR_TTX); /* init calib */ -sim_activate (uptr, t); /* start poll */ -return SCPE_OK; -} - -/* Detach master unit */ - -t_stat ttx_detach (UNIT *uptr) -{ -int32 i; -t_stat r; - -r = tmxr_detach (&ttx_desc, uptr); /* detach */ -for (i = 0; i < TTX_LINES; i++) { /* all lines, */ - ttx_desc.ldsc[i]->rcve = 0; /* disable rcv */ - sim_cancel (&ttox_unit[i]); } /* stop poll */ -return r; -} - -/* Show summary processor */ - -t_stat ttx_summ (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -int32 i, t; - -for (i = t = 0; i < TTX_LINES; i++) t = t + (ttx_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 ttx_show (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -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); } } -else fprintf (st, "all disconnected\n"); -return SCPE_OK; -} - -/* Enable/disable device */ - -void ttx_enbdis (int32 dis) -{ -if (dis) { - ttix_dev.flags = ttox_dev.flags | DEV_DIS; - ttox_dev.flags = ttox_dev.flags | DEV_DIS; } -else { ttix_dev.flags = ttix_dev.flags & ~DEV_DIS; - ttox_dev.flags = ttox_dev.flags & ~DEV_DIS; } -return; -} diff --git a/Pcap-VMS/pcap-vci/VMS_PCAP.COM b/Pcap-VMS/pcap-vci/VMS_PCAP.COM index 263db128..3e9c5135 100644 --- a/Pcap-VMS/pcap-vci/VMS_PCAP.COM +++ b/Pcap-VMS/pcap-vci/VMS_PCAP.COM @@ -2,7 +2,7 @@ $ if f$search("pcap.olb") .eqs. "" $ then $ libr/crea pcap.olb $ endif -$ if p1 .eqs. "DEBUG" +$ if p1 .nes. "" $ then $ opt = "/debug/noopt" $ else diff --git a/S3/haltguide.txt b/S3/haltguide.txt deleted file mode 100644 index 24e90f86..00000000 --- a/S3/haltguide.txt +++ /dev/null @@ -1,950 +0,0 @@ - IBM System/3 Model 8/10 SCP - - ********** - Halt Guide - ********** - -This following list is my own reformatting and rewording of the -official IBM Halt Guide for the Model 8/10 SCP. - -The halts are those displayed on the message display unit. The -list is in alphabetical order for easy reference. - -When the system halts, the two 7-segment displays will display the -halt as listed here, and the system console (or printer if the log -device is the printer) will print the "SCP Message" below. To -respond to the halt, deposit one of the valid response numbers -(0 thru 3) into the SR, and then use the C command to continue. - -Unless otherwise stated, a response of 0 means to continue and accept -the error, 1 means to retry the operation or re-read the statement in -error, 2 means to cancel the job and retain added records (if any) and -3 means to end the job and discard any added records in files. - -This is a listing of those halts likely to be encountered using SCP on -the simuator, it is not the complete list of all possible halts. - -Halt SCP Message Description ----- ----------- ----------- - -00 Invalid response to another halt. Deposit a valid - value (0 thru 3) in SR. - -0A A 5448 Disk Unit not ready. - -0C 5448 Disk Equipment Check - -0E Permanent disk error during logging. - -0F ID0FXX 23 Invalid cylinder number on disk operation. - XX = Disk Drive. - -0H ID0HXX 23 Invalid sector number on disk operation - XX = Disk Drive. - -0Y IK0Y0X 123 3741 Error. X: 1=not ready 2=wrong mode - 3=parity error 5=record length error - -0 ID0 XX 23 Disk Data Check - XX = Disk Drive. - -0- ID0-XX Invalid disk operation code: Start cancels job. - XX = Disk Drive. - -10 3 No input file allocate, user error. - -11 0 23 Square root of a negative field - -12 0 23 Divide Overflow - -13 0 23 Divide by zero - -14 0 23 Varible index zero of out of range - -15 0 23 Sequenced table is out of sequence - -16 0 23 (RPG) OBject tables expected. /* Read. - -17 0 23 (RPG) Object table exceeds specified length - -18 0 23 (RPG) Terminal errors in source program. - -19 0 3 (RPG) Warning errors in source program. 0=continue. - -1A 3 (RPG) Out of core memory - -1C 23 Unidentified halt has been issued. Probable system - error. - -1E 0 3 (RPG) Demand file at end of file. - -1F 23 (RPG) End of file or end of extent. If during RPG - compilation, expand $SOURCE or $WORK. - -1H 0 23 Duplicate keys found during build of indexed file. - 0=skip this record and continue. - -1J 0 23 Out of sequence keys during build of indexed file. - 0=skip this record and continue. - -1L 0 23 Key changed during record update. User error. - 0=continue, do not update record. - -1P 01 Forms in printer need positioning. - -1U 123 No record found on direct or indexed file. - -1Y 0 23 (RPG) Invalid numeric data to DSPLY statement. - -1 0 3 Object program ready to punch tables. - -20 1 3 Disk Sort: Invalid header and no // SOURCE - -21 01 3 Disk Sort: Name on // SOURCE not found - -22 0 2 Disk Sort: Warning errors found. - -23 3 Disk Sort: Unrecoverable error. - -25 3 Disk Sort: Terminal errors in sort statements. - -27 0 Disk Sort: In debug mode, finished pass. - -2C 0 3 Disk Sort: No Input Records selected. - -2E 3 Disk Sort: Workfile too small. - -2F 23 Disk Sort: Output file too small. - -2L DT2LY2 3 Tape Record too large to process. - DT2LY7 3 No FILE statement for tape file open. - DT2LY9 3 No enough storage for tape operation - DT2LTC 3 Invalid tape header length - DT2LYF 123 Incorrect block length read from tape - -2P Permanent tape error. - -2U 12 Tape unit is write protected. - -2Y 3 Invalid device specification in object. - -2- 0 3 First statement was not a Tape Sort header. - -30 EG30 3 Space not available on R1 or F1. - UB30A1 0 3 Active files exist on output disk - UB30AF 0 3 Active files exist on 5448 disk - UB30H1 0 3 Wrong capacity or uninitialized pack - UB30NS 3 No 5448 disk for $PCOPY - UB30TP 0 3 Pack change required. - UC30AF 3 Active or system files on target - UC30BD 3 Volume label cannot be read - UC30SP 3 Not enough space for work file - UP30AF 3 Active or system files on target - -31 UI31AF 0 3 Active or system files on target - 0=proceed to next unit to initialize - UI30WP 01 3 Wrong pack, name does not match. - -32 UB32Bx 01 3 5444 pack is not a $PCOPY backup pack. - UB32NP 01 3 Unit specified is not a $PCOPY pack. - UC32BD 3 FROM pack is a TO pack from an interrupted - COPYPACK run. - UC32BP 3 Output pack is a $PCOPY output pack. - Must be initialized or reset by a RESET - statement to be used. - UC32DS 3 Packs FROM and TO are different sizes. - -33 UI33PU 0 3 Pack defective, cannot be initialized. - -34 Ux34 1 3 Keyword in a utility control statement is invalid. - -35 UC35xx 1 3 Error in $COPY or $KCOPY control statement. - -36 UI36CE 0 3 CE track defective on unit F1. - -37 UC37xx 0 3 Pack change required. xx: FP=mount on R1, - IP=pack on COPYIN, OP=pack on COPYO. - -38 UA38XX 0 3 Wrong pack mounted. - UB38DA 01 3 Dates do not match. - UB38DM 01 3 2nd 5444 pack not from same backup set as 1st. - UB38IP 01 3 PACKIN keyword pack not same as pack mounted. - UB38OP 01 3 PACKO keyword not same as pack mounted. - -3A UC3Axx 3 Key out of sequence (DP), invalid high key (HK), - out of space to copy file (XE), or disk I/O error. - -3C UC3CCS 3 COPYFILE out of core. - UC3CNF 3 Module not found, name is logged as R XXXXXX. - -3E UC3EOX 0 3 COPYFILE output not as big as size of input. - -3F UC3Fxx 1 3 Error in COPYFILE statement. - -3J UC3Fxx 3 Invalid specification for Copy/Dump. - -3P UC3Pxx 1 3 Error in COPYPACK, RESET, or LABELS statement. - -3Y UI3YIS 0 3 Requested secondary init when primary required. - -3 UI3 xx 1 3 Error in VOL statement. - -40 DD40 3 File has been referenced as an output or add file - and the file is already allocated. - -4A DD4A 3 File had already been opened and is re-opened. - -4C DD4C 3 Multivolumne file spec error. - -4E DD4E 3 FILE indicates a multivolule file being built, - but program compiled for single volume. - -4F DD4F 3 Print buffers not aligned in program. - -4H DD4H 0 3 Unordered load specified for ISAM. Ordered load - must be specified on RPG file specs. - -4J DD4J 3 All file specs have been checked and there were - errors. - -4L DD4L 3 Referenced file already allocated. - -4P DD4P 3 Prgram/FILE statement mismatch. - -4U DD4U 3 File referenced as update, already allocated. - -4Y DD4Y 3 File has an incorrect device specification. - -4 DD4 3 No FILE specification for referenced file. - -4' DD4' 3 Attempting reference to a file in 2 levels, one or - both using RETAIN-S. - -50 UA50ID 2 Bad track which can't be reassigned. - -51 UR51 12 Can't use Alternate Track program in procedure. - -52 ML52 12 EOJ for Card List program. - -53 IU53 1 3 Number of VOL statements does not agree with number - of units on UIN statement. - -54 EO54 3 End-of-file. - -55 UF55xx 1 3 Error in SCRATCH or REMOVE statement. - -56 UA56TS 0 3 ASSIGN track is over disk capacity. - UA56XX 0 3 Unit specified is uninitialized. - -57 UF57WP 01 3 File delete program. Wrong pack is mounted. - 0: Mount correct pack and continue. 1: - correct statement and retry. - -5A UA5Axx 012 Alternate track assignment error. - -5C MR5Cxx 1 3 Invalid reformat specs. - -5F UF5Fxx 1 3 Error in DISPLAY statement. - -5H UA5HEU 0123 Primary track is still defective. - -5L UF5LAF 0 3 PRogram try to delete files that are being used by - another program. - UF5LNF 0 3 File not found. - UF5LTM 23 Too many files specified. Max is 40. - -5U UI5Uxx 1 3 Error in UIN statement. - -5Y UR5Yxx 1 3 Error in REBUILD statment. - -5 UA5 xx 1 3 Error in ALT statement. - -5- 3 Tape Sort error occurred. - -5' UF5'N1 0 3 Pack cannot be used. Not inited. - UF5'NU 0 3 Pack was used as TO pack on a COPYPACK job - that required early termination. Can only - be used for another COPYPACK job. - -60 LM60SY 0 3 Cannot remove or change library size on pack - from which $MAINT was loaded. - -61 LM61EP 0 3 Trying to copy a system to a library that is - 1) not empty, 2) not allocated with large enough - SWA, or 3) not allocated with enough space. - LM61NS 0 3 System does not exist on FROM pack. - -62 LM62CS 01 3 Check Sum error. - LM62DR Can't determine if REMOVE is data or control. - LM62EF FROM, TO, or AFTER statement does not exist or - is out of sequence. - LM62ND NO data records following INSERT or REPLACE. - LM62SQ Records are out of sequence. - LM62TP Incorrect type record. - -63 LM63DE 0 3 Directory entry error. Name can't be found or - attributes don't match, or attempt to remove - dir entry with MODIFY. - -64 LM64DS 0 3 Syntax error in ALLOCATE. - -65 LM65UN 0 3 Pack not properly initialized. - -66 LA66xx 3 Error with LOAD * function. - -67 EL67NL 0 3 Library does not exist. - -68 EL68DF 0 3 No room in library or directory. - -69 XX69HE 3 Disk I/O Error while using library. - -6A LM6Axx 1 3 $MAINT has detected a syntax error on a control - statement. xx gives a hint of what might be wrong. - AL: SOURCE or OBJECT missing or invalid - AZ: SYSTEM missing or invalid - D2: FROM, TO, or WORK is R2 or F2, not available - DK: Duplicate keyword - DS: Invalid DIRSIZE - FL: Invalid or missing FILE keyword - FM: Invalid or missing FROM keyword - IK: Invalid keyword - IN: Invalid INCR keyword - IS: first 3 columns must be // blank - IV: Invalid statement identifier - LB: Invalid LIBRARY keyword - LS: Invalid LIST keyword - NK: No keywords - NM: Invalid NAME keyword - NU: Invalid NEWNAME keyword - OM: Invalid OMIT keyword - RL: Invalid RECL keyword - RS: Invalid RESER keyword - RT: Invalid RETAIN keyword - SF: INvalid SEQFLD keyword - SQ: Invalid FROM, TO, or AFTER in MODIFY mode - XC: Invalid record. - XD: Duplicate keyword - XF: $$SYFG could not be found. - XL: LIBRARY keyword missing - XM: NAME keyword missing - XN: NAME parameter is invalid - XP: Library does not exist on this pack - XS: Syntax error - XT: Invalid library type - XV: INvalid operation - -6C LM6CSP 0 3 Not enough space on pack. - LM6CSW 0 3 Space not available for work file. - -6E LM6EOF 0 3 Overflow in seq field during RESER. - LM6EDP 0 3 Entry with same name already exists in library. - -6H EL6HDT 0 3 Trying to replace perm with temp entry. - LM6HDP 0 3 NEWNAME is already in library. - -6J LM6JCC 0 3 Control statements are missing. - -6L UA6L 3 Log device is required for this program. - -6Y LM6YNN 1 3 No NEWNAME when copying to same library. - -6 LM6 BC 3 Invalid character in source record. - LM6 CM 0 3 Invalid object deck. - LM6 ND 0 3 No data between COPY and CEND. - -6- LM6-BC 01 Entry containing a blank card being placed in - library. 0: accept, 1: skip and read next card. - -6' LM6'CE 1 3 // CEND expected but not found. 1: Retry, - provide CEND. NOTE: For option 3, if a module - was being replaced, it may have been deleted but - new module not loaded. - -70 CR70 3 Too many overrides for procedure. Max is 25. - -71 CR71 0 3 OCL Syntax Error. - -73 CR73 0 // PARTITION given in invalid location. - -74 CR74 3 /& between LOAD and RUN or CALL and RUN. - -75 CR75 23 Extraneous statement. - -76 CR76 0 3 // Missing from OCL statement. - -77 CR77 23 Invalid OCL statement identifier. - -78 CR78 0 3 Unknown OCL keyword. - -79 CR79 23 Continuation expected but not received. - -7A CR7A 3 A second LOAD or CALL found before run, or a - CALL in procedure overrides. - -7C CR7C 0 3 // COMPILE found between jobs. - -7E CR7E 0 3 // DATE found between jobs. 0: Ignore and continue. - -7F CR7F 0 3 // FILE found between jobs. Must go between - // LOAD or // CALL and // RUN statements. - -7H CR7H 0 3 // SWITCH found between jobs. - -7J CR7J 23 // READER found between LOAD or CALL and RUN. - -7L CI7Lxx 23 Error when reading a tape file. - -7P New print chain expected. Load it and press START. - -7U CR7U 3 RUN statement not preceeded by LOAD or CALL. - -7Y CI7Yxx 23 Error outputing a tape file. - -7 CR7 3 Too many utility control statements, max is 25. - -7- CR7- 0 // PARTITION was read but system does not support - Dual Programming. - -7' Error during tape processing. - -80 CR80 0 // DATE card has not been entered. - -81 CR81 23 Error in LOAD statement. - -83 CR83 23 Error in LOAD * statement. - -84 CR84 23 Error in CALL statement - -85 CR85 23 Second SWITCH statement found. - -86 CR86 23 Invalid paramter in switch statement. - -88 CR88 1 3 Procedure not found. - -89 CR89 01 // DATE has already been given. - 0 - accept the new date as the date. - 1 - leave the old date as the current date. - -8A CR8A01 0 Invalid date specified. - CR8A02 0 DATE parameter missing. - -8C CR8C 23 Second DATE found. - -8E CR8E01 23 Date specified incorrectly. - -8F CR8Fxx 23 Invalid BSCA statement. - -8H CR8H 3 More than 9 levels of procedures have been called. - -8J CR8J 0 Invalid // READER parameter. - -8L CR8L 0 Desired system input device being used by other - program. - -8P CR8P 0 Output device not defined. - -8U CU8UIP 23 Invalid HIKEY in FILE statement: non-numeric. - CR8UKL Parameter length mismatch. - CR8ULO Key greater than 29. - CR8UPL HIKEY-P greater than 15. - CR8USQ HIKEY parameters not in sequence. - -8Y CR8Y 0 Not logging can be done. Log turned off by - other program level. - -8- CR8- 0 3 Logging requested but cannot be done. - -90 CR90 0 // PAUSE statement read. Check printer or console - for instructions and continue. PAUSE was outside - LOAD and RUN. - -91 CR90 0 // PAUSE statement read. Check printer or console - for instructions and continue. PAUSE was inside - LOAD and RUN. - -92 CR92 23 COMPILE already recieved for this job. - -93 CR93 23 Error in COMPILE statement. - -94 CR94 23 Error in COMPILE statement. - -95 CR95 23 Error in COMPILE statement. - -96 CR96 0 23 System error. An OCL error was found, but the system - cannot resolve the error. - -97 CR97 0 Error in LOG statement. - -98 CR98 23 Error in LOG statement. - -99 CR99 0 23 Error in LOG statement. - -9A CR9A 23 Indicated action on last OCL statement read will - be ignored due to previous errors detected. - -9C CR9Cxx 123 Incorrect tape volume online. - -9E CR9E 0 Logging device being used by other program level. - -9F CR9F 0 23 Logging device in use by other program. - -9H CR9H 23 Log device in use. - -9J CR9J 0 Error in FORMS statement. - -9L CR9L 0 23 Error in FORMS statement. - -9P CR9P 23 Error in FORMS statement. - -9U CR9U 0 3 Other program has gotten a // IMAGE or other - program level is using the printer. - -9Y CR9Y 0 23 Logging device not sysgenned or CCP has it. - -9 CR9 0 23 Same as 9Y. - -9- CR9- 0 3 Other program level received a // FORMS or - other level using the printer. - -9' CR9' 0 Same as 9Y. - -A0 CRa0xx 23 Syntax error in FILE statement. - -A1 CRA1xx 23 Keyword error in FILE statement. - -A2 CRA2xx 23 Parameter error on FILE statement. - xx gives parameter: - 01 NAME, 02 UNIT, 03 PACK, 04 LABEL, - 05 RETAIN, 06 DATE, 07 RECORDS, 08 TRACKS, - 09 LOCATION, AS ASCII, BL BLKL, CV CONVERT, - DF DEFER, DN DENSITY, EN END, PT PARITY, - RC RECL, RF RECFM, RL REEL, SP SPLIT, - TN TRANSLATE. - -A3 CRA3xx 23 Missing Parameter on FILE statement, xx = - NN: NAME, NP: PACK, NU: UNIT, OP: no - parameters. - -A4 CRA4xx 23 Invalid parameter combination in FILE statement: - AS: ASCII-YES and RECFM-D/DB on 7-track tape - AV: ASCII-YES and RECFB-V/VB - AY: RECFM-D/DB without ASCII-YES - CT: CONVERT-ON and TRANSLATE - DI: UNIT says tape but disk parameters given - DN: DENSITY-800 not supported. - FS: RECFM is fexed and block or rec len less than 18 - IL: Incorrected RECL or BLKL for RECFM - IP: SPLIT or LOCATION used with RECORDS / TRACKS. - IR: LABEL, DATE or RETAIN wirh REEL-NL or REEL-NS - NS: Not all units are 7-track - PC: CONVERT-ON and PARITY-EVEN - RC: CONVERT-ON not given with RECFM-V/VB for 7-track - SD: DENSITY-1600 invalid for 7-track - SL: LOCATION missing or invalid for SPLIT. - SM: SPLIT invalid for multivolume files. - ST: 7-track paras with 9-track unit - SU: SPlit can't be used with 5444 - TL: TRACKS/LOCATION invalid with unit - TP: UNIT is disk but tape paras given - TR: TRACKS and RECORDS both given - -A6 CRA6xx 23 Error in FILE statement for multivolumne files. - -A7 CRA7xx 23 Error in IMAGE statement. - -A8 CRA8xx 0 Error in IMAGE statements o disk. - -A9 CRA9xx 0 23 Same as A8. - -AA CRAAxx 23 Same as A8. - -AC CRAC 0 Invalid hex character in chain image. - -AE CRAE 0 23 Same as AC. - -AF CRAF 23 Same as AC. - -AH CRAH 0 Error in IMAGE statement. - -AJ CRAJ 0 23 Same as AH - -AL CRALxx 0 Error in PARTITION statement. - -AP CRMN 0 3 Either reocvery option has has been selected during - a job, or OCL errors have occurred for this job. - 0: Continue iwth next job, or no data cards in - reader for this job, otherwise, 3 to cancel. - -AU CRAUxx 23 Error in PARTITION statement. - -A CRA 23 Total number of volumes for a FILE statement - exceeds 40 (!). - -A- CRA-xx 0 23 Error in PARTITION statement. - -A' CRA' 3 No space remaining is System work area. Too many - FILE statements are in this job. - -C1-C9 IFC1 123 1442 Check, various causes. - -CL UDCLxx 1 3 5445 Data Interchange Utility error - -E7 DKE7 0 3 Incorrect record length for attached 3741 - -E8 UTE8xx 1 3 Error in Tape Init VOL statement. - -E9 UTE9xy 0 3 Error during Tape Init Processing. - -F8 DDF8 3 RPG--LIne counter specs omitted and skip past - page size for printer. - -F9 CIF9xy 23 Tape drive not available, x = drive #. - -FA CIFA 3 Program requesting Data Recorder, unsupported. - -FC CIFC 3 Program requesting CRT, unsupported. - -FE DDFE 0 3 Program requesting line line on printer that - exceeds sysgen value. - -FF RPQ routine error. Press start to continue. - -FH CIFH 123 BSCA line not supported. - -FJ CIFJ01 123 1442 not supported but requested - CIFJ02 123 3741 not supported but requested - -FL CIFL 123 Printer/keyboard not supported or unavailable. - -FP CIFP 123 Printer not supported or allocated to other level - -FU CIFU 123 MFCU not supported or allocated to other level - -FY CIFY 23 Device is not supported or in use. - -F CIF 23 Conflict with a resource being used by other level. - -H0-H9 0 23 RPG Programmed halt indicator is on. - -HA CIHA 3 Out of space on $SOURCE during compile. - -HC CIHC 3 Program given on LOAD statement not found. - -HE Hardware error. Simulator has messed up. - -HF CIHF 0 3 // COMPILE read but not required. - -HJ CIHJ01 1 3 Program not found on removable unit, 1: - mount new unit and retry. - CIHJ02 3 Program not found, but removable unit in use. - -HL CIHL 3 Inquiry request made but program is wrong type. - -HP CIHP 3 Insufficient main storage for program. - LMHP 3 $MAINT function out of storage. NOTE: After the - cancel, IPL from the system pack or the pack will - be unusable. - -HU CIHUxx 3 Source program not found on disk. IF a 1 option - is present, you can mount a new removeable pack. - -HY CCHYNN 0 A checkpoint is received and accepted. - -H CCH NN 0 23 A restart has been requested. - -H' CIH' 3 An uninitialized pack has been referenced. - -J0-J9 123 Record with specified match field out of sequence. - This is an RPG error, the 2nd digit indicates which - RPG file statement the error applies to in the - source program. 0=greater than statement 9, - otherwise indicates the file statement number. - -JA CIJA 3 Trying to laod a program that requires or allows - inquiry while another inquiry program is running - in the other level. - -JC CIJCxx 3 Program cannot be run for this reason (xx): - 01: Must be dedicated and other level active - 02: Program in other level must be dedicated - 03: $$RSTR cannot run in level 2 - 04: CHeckpointed program not allowed in level 2 - 05: Program can't run while checkpoint active - -JE CIJE 0 3 Level 1 partition too small. - -JF CIJF 3 Attempt to start inquiry program but keyboard - in use. - -JH CIJF 3 Attempt to start program which allows interrupts in - level 2. - -JJ CIJJ 3 No object library on pack requested for load. - -JL CIJL 3 Not enough storage for program. DPF only. - -JP System input device in use by other level. - -JU 0123 Cancel request made from interrupt key. 0: ignore - 1: continue, request ignored - -JY CIJYRD 0 2 Inquiry request made and accepted. - -J- 3 Attempt to run a CCP program, but CCP not running. - -J' 01 3 Inquiry request is completed, interrupted program - can now resume. - -L0-L9 123 RPG. Unidentified record, 2nd digit gives file - statement number in source program 1-9, 0 means - greater than 9. Can also occur if record is out - of sequence. - -LA CILA 23 Too little storage for number of files in program. - -LC CILC 23 Too little storage for requested allocation. - -LE CILE 23 No FILE or an incorrect FILE for a file requested - by current program. - -LH CILH 23 No space given for an output file on FILE statement. - -LJ CILJ 23 Attempt to output to existing permanent file. - -LL CILL 0 23 Attempt to output over an existing temporary file. - -LP CILP 23 File already exists. - -LU CILU 123 Pack name requested but wrong pack mounted. 1: - retry after mounting correct pack. - -LY CILYxx 23 Attempt to allocate space that isn't available. - xx=02 means space not available in split cylinder - area. - -L LML CP 01 3 $MAINT detected attempt to modify a program on - a pack with an active checkpoint. - -L- CIL- 3 Attempt to add a split cylinder to a split cyl - file while other level is fiddling with a split - cylinder file. - -L' CIl' 23 Trying to allocate a split cylinder file before - allocating the first split cylinder file in a group. - -P1-P8 Printer hardware errors, should not occur in sim. - -PC IPPC 0 23 Unprintable character. - -PH CIPH 23 LOCATION plus TRACKS goes past end of pack. - -PJ CIPJxx 1 A Pack is to be remounted, pack name printed before - half code, xx= unit. - -PU CIPU 3 Duplicate file names in the FILE statements. - -PY CIPY01 3 ISAM file requires at least 2 tracks. - CIPY02 3 ISAM file can't be split cylinder. - -P' CIP'xx 23 Too many scratch or work files. - -U0-U9 0123 RPG. Unidentified record in file, 2nd digit of - halt is file statement in RPG source, 0= greater - than 9. - -UA CIUA 3 Attempt to create a multivolume file in - invalid. - -UC CIUC 3 The printed actived file cannot be found in the - list of scratch files. - -UE CIUExx 1 3 PACK parameter does not match pack name on unit. - xx = Unit referenced. - 1 = Mount another pack and continue. - -UF CIUF 3 Disk file referenced by name and date not found. - -UH CIUH 3 Attempt to create multivolume file failed, - because name alreayd exists. - -UJ CIUJ 3 A LOCATION was specified for an existing disk file - and the file exists but not at that location. - -UL CIUL 3 File on // FILE statement not found, and no size - in TRACKS or RECORDS was given. - -UP CIUP 3 Permanent file referenced with RETAIN-S - -UU CIUU 3 Disk Pack not available. - -UY CIUY 3 File is a System/3 BASIC file which must be unique. - -U CIU 3 Existing file: TRACKS/RECORDS or LOCATION mismatch. - -U- General CCP halt. Press start to see subhalt. - Refer to CCP manual for more info. - -U' CIU' 23 VTOC is full, or more than 2 multivolume files per - pack, or more than 2 ISAM files using HIKEY - parameter. - -YH CRYH 0 3 Cards are being punched, but card read from - reader was not blank. This means you are trying to - punch with a file attached to the CDR device. - Unattach the file and take the zero option. - - 0 (blank 0) FILE WRITE switch in off position. - - 1 (blank 1) Permanent DIsk I/O Error - - 2 RC 211 3 COBOL. Out of room on $WORK. - RC 212 3 Out of room on $SOURCE. - RC 213 3 Out of room on $WORKX. - RC 214 3 Subprogram name table greater than 20. - RC 219 0 3 C or E level diagnostics during compile. - RC 2A1 23 Subscript invalid - RC 2A2 23 Negative exponent or 0 degrees in program - RC 2F1 23 MFCU File not open or opened improperly - RC 2F2 23 1442 File not open or opened improperly - RC 2F3 23 1403/5203 File not open or opened improperly - RC 2F4 23 5444 Disk File not open or opened improperly - RC 2F5 23 5444 File not open or opened improperly - RC 2F7 23 5444 File not open or opened improperly - RC 2F8 23 Tape File not open or opened improperly - RC 2H1 23 OPEN attempted after CLOSE WITH LOCK - RC 2H2 23 Error during ACCEPT - RC 2H3 23 $$STOP not found - RC 2H4 23 CHeckpoint could not be taken. - RC 2H5 23 $$STIC not found for ACCEPT - RC 2H6 23 Parameter mismatch CALL and USING - RC 2H7 23 ACCEPT after /& read - RC 2H8 23 OPEN for a file already OPEN - RC 2 0 3 Too little core for compile - RC 2 1 3 PROCEDURE or DATA division not found. - RC 2 3 3 Program has more than 65535 statements (!) - RC 2 4 3 Source name on COMPILE statement not found - - 3 R 3XX 0 3 COBOL Stop literal. XX is user-specified. - 0 continues program 3 cancels. - - 4 VF 4NF 3 Program not found. Program library and - not printed before halt message. - - 6 RF 6XX 0 23 FORTRAN stop statement. - - 7 RF 701 23 Source member on COMPILE not found - RF 702 23 Object program too large for core. - - 8 CS 8 1 3 System input device allocated to other level. - - 9 CS 9 1 3 System input device has an error. This usually - means the card hopper is empty (i.e. EOF on the - file attached to the reader but SCP wants more - input). - - A DC A 123 Number of characters entered from keyboard - incorrect. - - C DD C 0 23 Unprintable character for printer/keyboard. - - E DC E 123 Hardware error, PKB - - F DC F 0 23 End of forms, PKB - - L DD L 0 3 Records with duplicate keys have been loaded - into ISAM file. Each dup key is logged followed - by blank P halt. 0: continue. Index will - contain duplicate keys. 3: cancel, file is - not usable, reload it. - - P DD P 0 3 Duplicate key encountered. The key is printed - on the log. 0: continue, halt will recur for - any other duplicates, then blank L appears. - - U DD U 3 Disk I/O error while sorting ISAM index. - - Y DD Y 3 System error during file termination. - --0 DD-0XX 3 ISAM multivolume file being used and high key - not found for current columme, or does not agree - with HIKEY spec. XX=unit number. - --1 DD-1XX 123 Halt -P occurred and option 0 taken. But, the - pack mounted is not a part of volume set. - --2 DD-2XX 123 Multivolume load sequence error. - --3 DD-3XX 123 Multivolume load sequence error. - --4 DD-4XX 0123 Warning that one or more volumes are about to be - bypassed. - --5 DD-5XX 123 Multivolume file not found. 1: mount correct pack. - --6 DD-6XX 0 23 Warning. ENd of volume and HIKEY not found. - --7 DD-7XX 1 3 -A halt and option 1 taken. But the pack referenced - does not match pack name. - --8 DD-8XX 3 Multivolume file referenced but file isn't - multivolume. - --9 DD-9XX 3 Add to a multivolumen file, but last pack not - mounted. - --A DD-AXX 1 3 Add to existing multivolume filebut no room. - --C DD-CXX 3 Multivolume file error. Probably out of sequence - volume mounts. - --E DD-EXX 123 Next volume cannot be processed, because the - location is not available or space is not available - or there are scratch files on the pack. - --F DD-Fxx 123 Finished a volume, next cannot be processed, mount - the correct pack or cancel. - --H DD-Hxx 3 HIKEY length does not match file. - --J DD-Jxx 01 3 First volume referenced is not volumme 1. 0: - continue with this volume, 1: mount another pack. - --L DD-Lxx 3 Output to multivolume, but file isn't multivolume - or referenced volume isn't first one of set. - --P DD-PXX 0123 Mount next volume. XX=unit number. 0: continue - bypassing volumes, 1: mount next volume. - --U DD-UXX 1 3 Halt -J just occurred and 0 or 1 taken. But the - pack name is incorrect or the file isn't found. - -- DD- 123 Multivolume key error. Key too low or high for - volume. - --' DD-' 123 Sequential add to multivolume file, but HIKEY - record missing on previous volume. - -'0 GM'0DE 3 SYSGEN. I/O Error on reader. - GM'0EX 3 SYSGEN. End of extent on MACOUT or $SOURCE. - GM'0IC 1 3 SYSGEN. Option dependent on a preceding option, the - preceding one was omitted or invalid. - GM'0ID 1 3 SYSGEN invalid delimiter. - GM'0IK 1 3 SYSGEN invalid keyword. - GM'0IR 1 3 SYSGEN invalid option. - GM'0IS 1 3 SYSGEN sequence error. - GM'0NF 1 3 SYSGEN entry in cols 8-12 not found. - GM'0NS 3 SYSGEN Requested source program not found. - GM'0EM 1 3 SYSGEN. END statement not found. - GM'0NP 3 SYSGEN. Module $SGXP2, $SGXP3, $SGXP4, $SGXP5, or - $SGXP6 missing for sysgen, or $MPXP2, $MPXP3 or - $MPXP4 missing for macro processor. - -'1 GG'1 3 System Generation Errors. - -'2 0 3 Error during macro processor run. - -'3 3 Invalid 5445 disk label record. - -'4 GG'4EX 3 Out of room on Sysgen, or disk error. - ------------------------ End of haltguide.txt --------------------------- diff --git a/S3/readme_s3.txt b/S3/readme_s3.txt deleted file mode 100644 index 37afdd9c..00000000 --- a/S3/readme_s3.txt +++ /dev/null @@ -1,78 +0,0 @@ - Welcome to the IBM System/3 Model 10 SIMH simulator. - --------------------------------------------------- - - To compile under linux: - - cc s3*.c scp*.c sim_rev.c -o s3 - - This code can be compiled and run as a console application using - Microsoft Visual C++. - - - - To IPL the provided SCP distribution disk: - - ./s3 - sim> at r1 m10scp.dsk - sim> at f1 f1f1f1.dsk - sim> at lpt print.txt - sim> d sr 5471 - sim> boot r1 - - - // DATE 06/14/01 - // NOHALT - // LOAD $MAINT,R1 - // RUN - // COPY FROM-R1,LIBRARY-ALL,NAME-DIR,TO-PRINT - // END - - - (A printout of the libraries and directories on the SCP DTR - disk will be in the file print.txt) - - - The text file "system3.txt" gives details on the simulators - implementation of System/3 hardware. - - A write up on the use of the SCP and the OCL job control language is - in the text file "userguide.txt". This includes examples of using the - utility programs, and a tutorial guiding you thru a sysgen. - - A nearly complete listing of all possible SCP halts is in the - document "haltguide.txt". - - IMPORTANT NOTES: - - 1) How to correct typing errors when using the System/3 console: - If you make an error, press ESC, which will cancel the current - line being typed and print a quote in position 1. Then you - can use CTRL/R to retype characters up until the error, then - type correctly. Or simply retype the line. BACKSPACE DOES NOT - WORK with the SCP. - - 2) While the simulator allows disk images to be independently - attached to any disk unit, on the real hardware R1 and F1 were on - a single spindle, and R2 and F2 likewise. It is not possible using - SCP to attach R1 without attaching a disk image to F1 also, because - SCP will always look at F1 even when IPLed off R1. - - The OS distributed with the simulator is version 16 of the Model - 10 SCP. This is sysgenned with support only for R1 and F1. If you - do a sysgen to support R2 amd F2 also, you must have images attached - to all 4 disks when you IPL, because SCP looks at all drives when - it starts up, and you will get an "Unattached Unit" error if you - fail to have one attached. - - 3) The 1442 card reader had in reality one card input hopper - and two stackers. This means the same path is used for reading and - punching cards. When punching cards, SCP does a read operation - and inspects the card read for blanks, and if it is not blank, - issues a YH halt. SCP will not punch data onto non-blank cards. - This feature causes problems in the simulator, and as a result - if you punch cards from SCP, YOU MUST not have any file attached - to the CDR device. Leaving this device unattached presents an - infinite supply of blank cards to SCP for punching. - - - -- End of README_S3.txt -- diff --git a/S3/s3_cd.c b/S3/s3_cd.c deleted file mode 100644 index 77423b19..00000000 --- a/S3/s3_cd.c +++ /dev/null @@ -1,442 +0,0 @@ -/* s3_cd.c: IBM 1442 card reader/punch - - Copyright (c) 2001-2003, Charles E. Owen - - 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 Charles E. Owen shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Charles E. Owen. - - cdr card reader - cdp card punch - cdp2 card punch stacker 2 - - 25-Apr-03 RMS Revised for extended file support - 08-Oct-02 RMS Added impossible function catcher - - Normally, cards are represented as ASCII text streams terminated by newlines. - This allows cards to be created and edited as normal files. Set the EBCDIC - flag on the card unit allows cards to be read or punched in EBCDIC format, - suitable for binary data. -*/ - -#include "s3_defs.h" -#include - -extern uint8 M[]; -extern char ebcdic_to_ascii[256]; -extern char ascii_to_ebcdic[256]; -int32 s1sel, s2sel; -char rbuf[CBUFSIZE]; /* > CDR_WIDTH */ -t_stat cdr_svc (UNIT *uptr); -t_stat cdr_boot (int32 unitno, DEVICE *dptr); -t_stat cdr_attach (UNIT *uptr, char *cptr); -t_stat cd_reset (DEVICE *dptr); -t_stat read_card (int32 ilnt, int32 mod); -t_stat punch_card (int32 ilnt, int32 mod); - -int32 DAR; /* Data address register */ -int32 LCR; /* Length Count Register */ -int32 lastcard = 0; /* Last card switch */ -int32 carderr = 0; /* Error switch */ -int32 pcherror = 0; /* Punch error */ -int32 notready = 0; /* Not ready error */ -int32 cdr_ebcdic = 0; /* EBCDIC mode on reader */ -int32 cdp_ebcdic = 0; /* EBCDIC mode on punch */ - -extern int32 GetMem(int32 addr); -extern int32 PutMem(int32 addr, int32 data); - -/* Card reader data structures - - cdr_dev CDR descriptor - cdr_unit CDR unit descriptor - cdr_reg CDR register list -*/ - -UNIT cdr_unit = { - UDATA (&cdr_svc, UNIT_SEQ+UNIT_ATTABLE, 0), 100 }; - -REG cdr_reg[] = { - { FLDATA (LAST, lastcard, 0) }, - { FLDATA (ERR, carderr, 0) }, - { FLDATA (NOTRDY, notready, 0) }, - { HRDATA (DAR, DAR, 16) }, - { HRDATA (LCR, LCR, 16) }, - { FLDATA (EBCDIC, cdr_ebcdic, 0) }, - { FLDATA (S2, s2sel, 0) }, - { DRDATA (POS, cdr_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, cdr_unit.wait, 24), PV_LEFT }, - { BRDATA (BUF, rbuf, 8, 8, CDR_WIDTH) }, - { NULL } }; - -DEVICE cdr_dev = { - "CDR", &cdr_unit, cdr_reg, NULL, - 1, 10, 31, 1, 8, 7, - NULL, NULL, &cd_reset, - &cdr_boot, &cdr_attach, NULL }; - -/* CDP data structures - - cdp_dev CDP device descriptor - cdp_unit CDP unit descriptor - cdp_reg CDP register list -*/ - -UNIT cdp_unit = { - UDATA (NULL, UNIT_SEQ+UNIT_ATTABLE, 0) }; - -REG cdp_reg[] = { - { FLDATA (ERR, pcherror, 0) }, - { FLDATA (EBCDIC, cdp_ebcdic, 0) }, - { FLDATA (S2, s2sel, 0) }, - { FLDATA (NOTRDY, notready, 0) }, - { HRDATA (DAR, DAR, 16) }, - { HRDATA (LCR, LCR, 16) }, - { DRDATA (POS, cdp_unit.pos, T_ADDR_W), PV_LEFT }, - { NULL } }; - -DEVICE cdp_dev = { - "CDP", &cdp_unit, cdp_reg, NULL, - 1, 10, 31, 1, 8, 7, - NULL, NULL, &cd_reset, - NULL, NULL, NULL }; - -/* Stacker data structures - - stack_dev STACK device descriptor - stack_unit STACK unit descriptors - stack_reg STACK register list -*/ - -UNIT stack_unit[] = { - { UDATA (NULL, UNIT_SEQ+UNIT_ATTABLE, 0) } }; - -REG stack_reg[] = { - { DRDATA (POS0, stack_unit[0].pos, 32), PV_LEFT }, - { NULL } }; - -DEVICE stack_dev = { - "CDP2", stack_unit, stack_reg, NULL, - 1, 10, 31, 1, 8, 7, - NULL, NULL, &cd_reset, - NULL, NULL, NULL }; - - -/* -------------------------------------------------------------------- */ - -/* 1442: master routine */ - -int32 crd (int32 op, int32 m, int32 n, int32 data) -{ - int32 iodata; - switch (op) { - case 0: /* SIO 1442 */ - /* if (n == 1) - return STOP_IBKPT; */ - switch (data) { /* Select stacker */ - case 0x00: - break; - case 0x01: - s2sel = 1; - break; - default: - break; - } - switch (n) { - case 0x00: /* Feed */ - iodata = SCPE_OK; - break; - case 0x01: /* Read only */ - if (cdr_ebcdic) - iodata = read_card(0, 1); - else - iodata = read_card(0, 0); - break; - case 0x02: /* Punch and feed */ - iodata = punch_card(0, 0); - break; - case 0x03: /* Read Col Binary */ - iodata = read_card(0, 1); - break; - case 0x04: /* Punch no feed */ - iodata = punch_card(0, 1); - break; - default: - return STOP_INVDEV; - } - return iodata; - case 1: /* LIO 1442 */ - switch (n) { - case 0x00: /* Load LCR */ - LCR = data & 0xffff; - break; - case 0x04: - DAR = data & 0xffff; - break; - default: - return STOP_INVDEV; - } - return SCPE_OK; - case 2: /* TIO 1442 */ - iodata = 0; - switch (n) { - case 0x00: /* Error */ - if (carderr || pcherror || notready) - iodata = 1; - if ((cdr_unit.flags & UNIT_ATT) == 0) - iodata = 1; /* attached? */ - break; - case 0x02: /* Busy */ - if (sim_is_active (&cdr_unit)) - iodata = 1; - break; - default: - return (STOP_INVDEV << 16); - } - return ((SCPE_OK << 16) | iodata); - case 3: /* SNS 1442 */ - iodata = 0; - switch (n) { - case 0x01: - break; - case 0x02: - break; - case 0x03: - if (carderr) - iodata |= 0x80; - if (lastcard) - iodata |= 0x40; - if (pcherror) - iodata |= 0x20; - if ((cdr_unit.flags & UNIT_ATT) == 0) - iodata |= 0x08; - if (notready) - iodata |= 0x08; - break; - case 0x04: - iodata = DAR; - break; - default: - return (STOP_INVDEV << 16); - } - iodata |= ((SCPE_OK << 16) & 0xffff0000); - return (iodata); - case 4: /* APL 1442 */ - iodata = 0; - switch (n) { - case 0x00: /* Error */ - if (carderr || pcherror || notready) - iodata = 1; - if ((cdr_unit.flags & UNIT_ATT) == 0) - iodata = 1; /* attached? */ - break; - case 0x02: /* Busy */ - if (sim_is_active (&cdr_unit)) - iodata = 1; - break; - default: - return (STOP_INVDEV << 16); - } - return ((SCPE_OK << 16) | iodata); - default: - break; - } - printf (">>CRD non-existent function %d\n", op); - return SCPE_OK; -} - -/* Card read routine - mod 0 = ASCII read - mod 1 = EBCDIC read -*/ - -t_stat read_card (int32 ilnt, int32 mod) -{ -int32 i; -t_stat r; - -if (sim_is_active (&cdr_unit)) { /* busy? */ - sim_cancel (&cdr_unit); /* cancel */ - if (r = cdr_svc (&cdr_unit)) return r; /* process */ -} - -if (((cdp_unit.flags & UNIT_ATT) != 0 || - (stack_unit[0].flags & UNIT_ATT) != 0) && /* Punch is attached and */ - (cdr_unit.flags & UNIT_ATT) == 0) { /* reader is not --- */ - for (i = 0; i < 80; i++) { /* Assume blank cards in hopper */ - PutMem(DAR, 0x40); - DAR++; - } - sim_activate (&cdr_unit, cdr_unit.wait); /* activate */ - return SCPE_OK; -} - -if ((cdr_unit.flags & UNIT_ATT) == 0) return SCPE_UNATT; /* attached? */ - -lastcard = carderr = notready = s1sel = s2sel = 0; /* default stacker */ - -for (i = 0; i < CBUFSIZE; i++) rbuf[i] = 0x20; /* clear buffer */ -if (mod) { - for (i = 0; i < 80; i++) { - rbuf[i] = fgetc(cdr_unit.fileref); /* Read EBCDIC */ - } -} else { - fgets (rbuf, CBUFSIZE, cdr_unit.fileref); /* read Ascii */ -} -if (feof (cdr_unit.fileref)) { /* eof? */ - notready = 1; - return STOP_NOCD; -} -if (ferror (cdr_unit.fileref)) { /* error? */ - perror ("Card reader I/O error"); - clearerr (cdr_unit.fileref); - carderr = 1; - return SCPE_OK; } -cdr_unit.pos = ftell (cdr_unit.fileref); /* update position */ -i = getc (cdr_unit.fileref); /* see if more */ -if (feof (cdr_unit.fileref)) lastcard = 1; /* eof? set flag */ -fseek (cdr_unit.fileref, cdr_unit.pos, SEEK_SET); -for (i = 0; i < 80; i++) { - if (mod == 0) { /* If ASCII mode... */ - if (rbuf[i] == '\n' || /* remove ASCII CR/LF */ - rbuf[i] == '\r' || - rbuf[i] == 0x00) - rbuf[i] = ' '; - rbuf[i] = ascii_to_ebcdic[rbuf[i]]; /* convert to EBCDIC */ - } - PutMem(DAR, rbuf[i]); /* Copy to main memory */ - DAR++; -} -sim_activate (&cdr_unit, cdr_unit.wait); /* activate */ -return SCPE_OK; -} - -/* Card reader service. If a stacker select is active, copy to the - selected stacker. Otherwise, copy to the normal stacker. If the - unit is unattached, simply exit. -*/ - -t_stat cdr_svc (UNIT *uptr) -{ -int32 i; - -if (s2sel) uptr = &stack_unit[0]; /* stacker 1? */ -else uptr = &stack_unit[0]; /* then default */ -if ((uptr -> flags & UNIT_ATT) == 0) return SCPE_OK; /* attached? */ -for (i = 0; i < CDR_WIDTH; i++) rbuf[i] = ebcdic_to_ascii[rbuf[i]]; -for (i = CDR_WIDTH - 1; (i >= 0) && (rbuf[i] == ' '); i--) rbuf[i] = 0; -rbuf[CDR_WIDTH] = 0; /* null at end */ -fputs (rbuf, uptr -> fileref); /* write card */ -fputc ('\n', uptr -> fileref); /* plus new line */ -if (ferror (uptr -> fileref)) { /* error? */ - perror ("Card stacker I/O error"); - clearerr (uptr -> fileref); -} -uptr -> pos = ftell (uptr -> fileref); /* update position */ -return SCPE_OK; -} - -/* Card punch routine - - mod: not used -*/ - -t_stat punch_card (int32 ilnt, int32 mod) -{ -int32 i, colcount; -static char pbuf[CDP_WIDTH + 1]; /* + null */ -UNIT *uptr; - -if (s2sel) uptr = &stack_unit[0]; /* stack 2? */ -else uptr = &cdp_unit; /* normal output */ -if ((uptr -> flags & UNIT_ATT) == 0) { /* Attached? */ - notready = 1; - return SCPE_OK; -} -pcherror = s1sel = notready = 0; /* clear flags */ - -colcount = 128 - LCR; -for (i = 0; i < colcount; i++) { /* Fetch data */ - if (cdp_ebcdic) - pbuf[i] = GetMem(DAR) & 0xff; - else - pbuf[i] = ebcdic_to_ascii[GetMem(DAR)]; - DAR++; -} -for (i = CDP_WIDTH - 1; (i >= 0) && (pbuf[i] == ' '); i--) pbuf[i] = 0; -pbuf[CDP_WIDTH] = 0; /* trailing null */ -if (!cdp_ebcdic) { - fputs (pbuf, uptr -> fileref); /* output card */ - fputc ('\n', uptr -> fileref); /* plus new line */ -} else { - for (i = 0; i < 80; i++) { - fputc(pbuf[i], uptr -> fileref); - } -} -if (ferror (uptr -> fileref)) { /* error? */ - perror ("Card punch I/O error"); - clearerr (uptr -> fileref); - pcherror = 1; -} -uptr -> pos = ftell (uptr -> fileref); /* update position */ -return SCPE_OK; -} - -/* Select stack routine - - Modifiers have been checked by the caller - Modifiers are 1, 2, for the respective stack -*/ - -t_stat select_stack (int32 ilnt, int32 mod) -{ -if (mod == 1) s1sel = 1; -else if (mod == 2) s2sel = 1; -return SCPE_OK; -} - -/* Card reader/punch reset */ - -t_stat cd_reset (DEVICE *dptr) -{ -lastcard = carderr = notready = pcherror = 0; /* clear indicators */ -s1sel = s2sel = 0; /* clear stacker sel */ -sim_cancel (&cdr_unit); /* clear reader event */ -return SCPE_OK; -} - -/* Card reader attach */ - -t_stat cdr_attach (UNIT *uptr, char *cptr) -{ -carderr = lastcard = notready = 0; /* clear last card */ -return attach_unit (uptr, cptr); -} - -/* Bootstrap routine */ - -t_stat cdr_boot (int32 unitno, DEVICE *dptr) -{ -cdr_ebcdic = 1; -DAR = 0; -LCR = 80; -read_card(0, 1); -return SCPE_OK; -} diff --git a/S3/s3_cpu.c b/S3/s3_cpu.c deleted file mode 100644 index ae496175..00000000 --- a/S3/s3_cpu.c +++ /dev/null @@ -1,1832 +0,0 @@ -/* s3_cpu.c: IBM System/3 CPU simulator - - Copyright (c) 2001-2003, Charles E. Owen - HPL & SLC instruction code Copyright (c) 2001 by Henk Stegeman - Decimal Arithmetic Copyright (c) 2000 by Roger Bowler - - 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 Charles E. Owen shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Charles E. Owen. - - ------------------------------------------------------------------------------ - - cpu System/3 (models 10 and 15) central processor - - The IBM System/3 was a popular small-business computing system introduced - in 1969 as an entry-level system for businesses that could not afford - the lowest rungs of the System/360. Its architecture is inspired by and - in some ways similar to the 360, but to save cost the instruction set is - much smaller and the I/O channel system greatly simplified. There is no - compatibilty between the two systems. - - The original System/3 had two models, 6 and 10, and these came in two - configurations: card system and disk system. The unique feature of - the /3 was the use of 96-column cards, although traditional 80-column - cards were supprted also via attachment of a 1442 reader/punch. - System/3 is a batch-oriented system, controlled by an operating - system known as SCP (System Control Program), with it's own job control - language known as OCL (simpler and more logical than the JCL used on - the mainframes). Original models did not support multiprogramming - or any form of interactivity. (There was a hardware dual-program - facility available on the model 10 at the high end). - - The line grew throughout the 1970s, overlapping the low end of the 360 - line with the introduction of the model 15. The 15 (and later larger - variations of the model 12) broke the 64K limit designed in the original - models by adding a simple address translation unit to support up to 512K - bytes. The model 15 added a system of storage protection and allowed - multiprogramming in up to 3 partitions. Communications were added to - allow support of multiple 3270 terminals and the models 12 and 15 broke - the batch orientation and facilitated interactive use via the CCP - (communications control program). The System/3 was effectively replaced - by the much easier to manage and use System/34 and System/36 at the - low and middle of the range, and by System/370 or System/38 at the - high end. - - This simulator implements the model 10 and model 15. Models 4, 6, - 8, and 12 are not supported (these were technical variations on the - design which offered no functionality not present on either 10 or 15). - - The System/3 is a byte-oriented machine with a data path of 8 bits - in all models, and an address width of 16 bits. - - The register state for the System/3 CPU is: - - BAR <0:15> Operand 1 address register - AAR <0:15> Operand 2 address register - XR1 <0:15> Index Register 1 - XR2 <0:15> Index Register 2 - PSR <0:15> Condition Register - IAR [0:9]<0:15> Instruction Address Register (p1, p2, plus 1 for each interrupt) - ARR [0:9]<0:15> Address Recall Register (p1, p2, plus 1 for each interrupt) - (The P2 IAR & ARR are used for the Dual Program feature) - - Instruction formats follow the same basic pattern: a 1-byte opcode, a - 1-byte "Q byte", and one or two addresses following in a format defined - by the first 4 bits of the opcode: - - Op Code Q Byte Address(es) - - 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 - +--+--+--+--+--+--+--+--+ +--+--+--+--+--+--+--+--+ +--+--+--+--+--+--+--... - | A 1 | A 2 | operation | | (defined by operation)| | Format based on A1, A2 - +--+--+--+--+--+--+--+--+ +--+--+--+--+--+--+--+--+ +--+--+--+--+--+--+--... - - { --- } <---------------- Bits 00 = Operand 2 specified by 2-byte direct addr - Bits 01 = Operand 2 is 1-byte displacement + XR1 - Bits 10 = Operand 2 is 1-byte displacement + XR2 - Bits 11 = Operand 2 is not used - - { --- } <---------------------- Bits 00 = Operand 1 specified by 2-byte direct addr - Bits 01 = Operand 1 is 1-byte displacement + XR1 - Bits 10 = Operand 1 is 1-byte displacement + XR2 - Bits 11 = Operand 1 is not used - - Instructions come in 3 basic formats, of varying lengths which are determined - by the top 4 bits of opcode defined above. Minimum instruction length is 3 bytes, - maximum is 6. - - 1) Command Format (Bits 0-3 are 1111): - - +------------+ +------------+ +------------+ - | Opcode | | Q-byte | | R-byte + - +------------+ +------------+ +------------+ - - (The meaning of Q-byte and R-byte defined by the operation) - - - 2) One Address Instructions (either bits 0-1 or bits 2-3 are 01): - - - Direct Addressing Format: - - +------------+ +------------+ +-----------+----------+ - | Opcode | | Q-byte | | MSB + LSB + - +------------+ +------------+ +-----------+----------+ - - Base-Displacement Format: - - +------------+ +------------+ +------------+ - | Opcode | | Q-byte | |displacement+ - +------------+ +------------+ +------------+ - - Opcodes are 0011xxxx or 1100xxxx. - - Q-byte can be: 1) An immediate operand - 2) A mask - 3) A branch condition - 4) A data selection - - 2) Two Address Instructions (neither bits 0-1 nor bits 2-3 are both 11): - - Operand 1 Address Direct (opcodes 0001 or 0010): - - +------------+ +------------+ +----------+----------+ +------------+ - | Opcode | | Q-byte | | MSB + LSB + |displacement| - +------------+ +------------+ +----------+----------+ +------------+ - - Operand 2 Address Direct (opcodes 0100 or 1000): - - +------------+ +------------+ +------------+ +----------+----------+ - | Opcode | | Q-byte | |displacement| | MSB + LSB + - +------------+ +------------+ +------------+ +----------+----------+ - - Both Addresses Direct (opcode 0000): - - +------------+ +------------+ +----------+----------+ +-----------+----------+ - | Opcode | | Q-byte | | MSB + LSB + + MSB + LSB + - +------------+ +------------+ +----------+----------+ +-----------+----------+ - - Both Addresses Displacement (opcodes 0101, 0110, 1001, or 1010): - - +------------+ +------------+ +------------+ +------------+ - | Opcode | | Q-byte | |displacement| |displacement| - +------------+ +------------+ +------------+ +------------+ - - -Assembler Mnemonic Format -------------------------- - - The assembler format contains the same elements as the machine language operation, -but not always in the same format. The operation code frequently specifies both -the opcode and the Q byte, and the top nybble of the opcode is determined by -the format of the addresses. - - Addresses take two forms: the direct address in hex, or a relative address -specified thusly: (byte,XRx) where 'byte' is a 1-byte offset, and XRx is -either XR1 or XR2 for the two index registers. Use these formats when -'address' is indicated below: - - When 'reg' is mentioned, a mnemonic may be used for the register, thusly: - IAR Instruction Address Register for the current program level - ARR Address Recall Register for the current program level - P1IAR IAR for Program Level 1 - P2IAR IAR for Program Level 2 - PSR Program Status Register - 0x01 - Equal - 0x02 - Low - 0x04 - High - 0x08 - Decimal overflow - 0x10 - Test false - 0x20 - Binary overflow - 0x40 - Not used - 0x80 - Not used - XR1 Index Register 1 - XR2 Index Register 2 - IARx IAR for the interrupt level x (x = 0 thru 7) - - All other operands mentioned below are single-byte hex, except for the -length (len) operand of the two-address instructions, which is a decimal length -in the range 1-256. - - No-address formats: - ------------------ - - HPL hex,hex Halt Program Level, the operands are the Q and R bytes - - - One-address formats: - ------------------- - - A reg,address Add to register - CLI address,byte Compare Logical Immediate - MVI address,byte Move Immediate - TBF address,mask Test Bits Off - TBN address,mask Test Bits On - SBF address,mask Set Bits Off - SBN address,mask Set Bits On - ST reg,address Store Register - L reg,address Load Register - LA reg,address Load Address - JC address,cond Jump on Condition - BC address,cond Branch on Condition - - These operations do not specify a qbyte, it is implicit in the opcode: - - B address Unconditional branch to address - BE address Branch Equal - BNE address Branch Not Equal - BH address Branch High - BNH address Branch Not High - BL address Branch Low - BNL address Branch Not Low - BT address Branch True - BF address Branch False - BP address Branch Plus - BM address Branch Minus - BNP address Branch Not Plus - BNM address Branch Not Minus - BZ address Branch Zero - BNZ address Branch Not Zero - BOZ address Branch Overflow Zoned - BOL address Branch Overflow Logical - BNOZ address Branch No Overflow Zoned - BNOL address Branch No Overflow Logical - NOPB address No - never jump - - (substitute J for B above for a set of Jumps -- 1-byte operand (not 2), - always jumps forward up to 255 bytes. In this case, 'address' cannot be - less than the current address, nor greater than the current address + 255) - - Two-address formats (first address is destination, len is decimal 1-256): - ------------------- - - MVC address,address,len Move Characters - CLC address,address,len Compare Logical Characters - ALC address,address,len Add Logical Characters - SLC address,address,len Subtract Logical Characters - ED address,address,len Edit - ITC address,address,len Insert and Test Characters - AZ address,address,len Add Zoned Decimal - SZ address,address,len Subtract Zoned Decimal - - MNN address,address Move Numeric to Numeric - MNZ address,address Move Numeric to Zone - MZZ address,address Move Zone to Zone - MZN address,address Move Zone to Numeric - - I/O Format - ---------- - - In the I/O format, there are always 3 fields: - - da - Device Address 0-15 (decimal) - m - Modifier 0-1 - n - Function 0-7 - - The meaning of these is entirely defined by the device addressed. - - There may be an optional control byte, or an optional address (based on -the type of instruction). - - SNS da,m,n,address Sense I/O - LIO da,m,n,address Load I/O - TIO da,m,n,address Test I/O - - SIO da,m,n,cc Start I/O -- cc is a control byte - - APL da,m,n Advance Program Level - - - - --------------------------------------------- - Here is a handy opcode cross-reference table: - --------------------------------------------- - - | x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF ----+------------------------------------------------------------------ -0x | - - - - ZAZ - AZ SZ MVX - ED ITC MVC CLC ALC SLC -1x | - - - - ZAZ - AZ SZ MVX - ED ITC MVC CLC ALC SLC -2x | - - - - ZAZ - AZ SZ MVX - ED ITC MVC CLC ALC SLC -3x | SNS LIO - - ST L A - TBN TBF SBN SBF MVI CLI - - - | -4x | - - - - ZAZ - AZ SZ MVX - ED ITC MVC CLC ALC SLC -5x | - - - - ZAZ - AZ SZ MVX - ED ITC MVC CLC ALC SLC -6x | - - - - ZAZ - AZ SZ MVX - ED ITC MVC CLC ALC SLC -7x | SNS LIO - - ST L A - TBN TBF SBN SBF MVI CLI - - - | -8x | - - - - ZAZ - AZ SZ MVX - ED ITC MVC CLC ALC SLC -9x | - - - - ZAZ - AZ SZ MVX - ED ITC MVC CLC ALC SLC -Ax | - - - - ZAZ - AZ SZ MVX - ED ITC MVC CLC ALC SLC -Bx | SNS LIO - - ST L A - TBN TBF SBN SBF MVI CLI - - - | -Cx | BC TIO LA - - - - - - - - - - - - - -Dx | BC TIO LA - - - - - - - - - - - - - -Ex | BC TIO LA - - - - - - - - - - - - - -Fx | HPL APL JC SIO - - - - - - - - - - - - - -*/ - -/* This routine is the instruction decode routine for System/3. - 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 - program check caused by invalid opcode or qbyte or address or I/O spec - unknown I/O device and STOP_DEV flag set - I/O error in I/O simulator - - 2. Interrupts. - - There are 8 levels of interrupt, each with it's own IAR (program - counter). When an interrupt occurs, execution begins at the - location in the IAR for that level interrupt. The program - must save and restore state. Each device is assigned both a - level and a priority in hardware. Interrupts are reset via - an SIO instruction, when this happens, the program level - IAR resumes control. - - Interrupts are maintained in the global variable int_req, - which is zero if no interrupts are pending, otherwise, the - lower 16 bits represent devices, rightmost bit being device - 0. Each device requesting an interrupt sets its bit on. - - - 3. Non-existent memory. On the System/3, any reference to non-existent - memory (read or write) causes a program check and machine stop. - - 4. Adding I/O devices. These modules must be modified: - - ibms3_defs.h add interrupt request definition - ibms3_cpu.c add IOT mask, PI mask, and routine to dev_table - ibms3_sys.c add pointer to data structures to sim_devices -*/ - -#include "s3_defs.h" - -#define UNIT_V_M15 (UNIT_V_UF) /* Model 15 extensions */ -#define UNIT_M15 (1 << UNIT_V_M15) -#define UNIT_V_DPF (UNIT_V_UF+1) /* Dual Programming */ -#define UNIT_DPF (1 << UNIT_V_DPF) -#define UNIT_V_MSIZE (UNIT_V_UF+3) /* dummy mask */ -#define UNIT_MSIZE (1 << UNIT_V_MSIZE) - -uint8 M[MAXMEMSIZE] = { 0 }; /* memory */ -int32 AAR = 0; /* Operand 1 addr reg */ -int32 BAR = 0; /* Operand 2 addr reg */ -int32 XR1 = 0; /* Index register 1 */ -int32 XR2 = 0; /* Index register 2 */ -int32 PSR = 0; /* Condition Register */ -int32 IAR[10] = { 0 }; /* IAR 0-7 = int level 8=P1 9=P2 */ -int32 ARR[10] = { 0 }; /* ARR 0-7 = int level 8=P1 9=P2 */ -int32 dev_disable = 0; /* interrupt disable mask */ -int32 int_req = 0; /* Interrupt request device bitmap */ -int32 level = 8; /* Current Execution Level*/ -int32 stop_dev = 0; /* stop on ill dev */ -int32 SR = 0; /* Switch Register */ -int32 saved_PC; /* Saved (old) PC) */ -int32 debug_reg = 0; /* set for debug/trace */ -int32 debug_flag = 0; /* 1 when trace.log open */ -FILE *trace; -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); -t_stat cpu_boot (int32 unitno, DEVICE *dptr1); -extern int32 pkb (int32 op, int32 m, int32 n, int32 data); -extern int32 crd (int32 op, int32 m, int32 n, int32 data); -extern int32 lpt (int32 op, int32 m, int32 n, int32 data); -extern int32 dsk1 (int32 op, int32 m, int32 n, int32 data); -extern int32 dsk2 (int32 op, int32 m, int32 n, int32 data); -extern int32 cpu (int32 op, int32 m, int32 n, int32 data); -extern t_stat sim_activate (UNIT *uptr, int32 delay); -extern int32 fprint_sym (FILE *of, int32 addr, unsigned int32 *val, - UNIT *uptr, int32 sw); -int32 nulldev (int32 opcode, int32 m, int32 n, int32 data); -int add_zoned (int32 addr1, int32 len1, int32 addr2, int32 len2); -int32 subtract_zoned (int32 addr1, int32 len1, int32 addr2, int32 len2); -static int32 compare(int32 byte1, int32 byte2, int32 cond); -static int32 condition(int32 qbyte); -static void store_decimal (int32 addr, int32 len, uint8 *dec, int sign); -static void load_decimal (int32 addr, int32 len, uint8 *result, int32 *count, int32 *sign); -static void add_decimal (uint8 *dec1, uint8 *dec2, uint8 *result, int32 *count); -static void subtract_decimal (uint8 *dec1, uint8 *dec2, uint8 *result, int *count, int *sign); -int32 GetMem(int32 addr); -int32 PutMem(int32 addr, int32 data); - -/* IOT dispatch table */ - -/* System/3 supports only 16 unique device addresses! */ - -struct ndev dev_table[16] = { - { 0, 0, &cpu }, /* Device 0: CPU control */ - { 1, 0, &pkb }, /* Device 1: 5471 console printer/keyboard */ - { 0, 0, &nulldev }, - { 0, 0, &nulldev }, - { 0, 0, &nulldev }, - { 0, 0, &crd }, /* Device 5: 1442 card reader/punch */ - { 0, 0, &nulldev }, /* Device 6: 3410 Tape drives 1 & 2 */ - { 0, 0, &nulldev }, /* Device 7: 3410 Tape drives 3 & 4 */ - { 0, 0, &nulldev }, - { 0, 0, &nulldev }, - { 0, 0, &dsk1 }, /* Device 10: 5444 Disk Drive 1 */ - { 0, 0, &dsk2 }, /* Device 11: 5444 Disk Drive 2 */ - { 0, 0, &nulldev }, /* Device 12: 5448 Disk Drive 1 */ - { 0, 0, &nulldev }, /* DEvice 13: 5448 Disk Drive 2 */ - { 0, 0, &lpt }, /* Device 14: 1403/5203 Printer */ - { 0, 0, &nulldev } /* Device 15: 5424 MFCU */ -}; - -/* Priority assigned to interrupt levels */ - -int32 priority[8] = {8, 7, 5, 4, 3, 6, 2, 1}; - - -/* 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[] = { - { HRDATA (IAR, saved_PC, 16), REG_RO }, - { HRDATA (IAR-P1, IAR[8], 16) }, - { HRDATA (IAR-P2, IAR[9], 16) }, - { HRDATA (ARR-P1, ARR[8], 16) }, - { HRDATA (ARR-P2, ARR[9], 16) }, - { HRDATA (AAR, AAR, 16) }, - { HRDATA (BAR, BAR, 16) }, - { HRDATA (XR1, XR1, 16) }, - { HRDATA (XR2, XR2, 16) }, - { HRDATA (PSR, PSR, 16) }, - { HRDATA (SR, SR, 16) }, - { HRDATA (INT, int_req, 16), REG_RO }, - { HRDATA (LEVEL, level, 16) }, - { HRDATA (IAR0, IAR[0], 16) }, - { HRDATA (IAR1, IAR[1], 16) }, - { HRDATA (IAR2, IAR[2], 16) }, - { HRDATA (IAR3, IAR[3], 16) }, - { HRDATA (IAR4, IAR[4], 16) }, - { HRDATA (IAR5, IAR[5], 16) }, - { HRDATA (IAR6, IAR[6], 16) }, - { HRDATA (IAR7, IAR[7], 16) }, - { HRDATA (ARR0, ARR[0], 16) }, - { HRDATA (ARR1, ARR[1], 16) }, - { HRDATA (ARR2, ARR[2], 16) }, - { HRDATA (ARR3, ARR[3], 16) }, - { HRDATA (ARR4, ARR[4], 16) }, - { HRDATA (ARR5, ARR[5], 16) }, - { HRDATA (ARR6, ARR[6], 16) }, - { HRDATA (ARR7, ARR[7], 16) }, - { HRDATA (DISABLE, dev_disable, 16), REG_RO }, - { FLDATA (STOP_DEV, stop_dev, 0) }, - { HRDATA (WRU, sim_int_char, 8) }, - { HRDATA (DEBUG, debug_reg, 16) }, - { NULL } }; - -MTAB cpu_mod[] = { - { UNIT_M15, UNIT_M15, "M15", "M15", NULL }, - { UNIT_M15, 0, "M10", "M10", NULL }, - { UNIT_DPF, UNIT_DPF, "DPF", "DPF", NULL }, - { UNIT_DPF, 0, "NODPF", "NODPF", NULL }, - { UNIT_MSIZE, 8192, NULL, "8K", &cpu_set_size }, - { 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, 65535, NULL, "64K", &cpu_set_size }, - { 0 } }; - -DEVICE cpu_dev = { - "CPU", &cpu_unit, cpu_reg, cpu_mod, - 1, 16, 16, 1, 16, 8, - &cpu_ex, &cpu_dep, &cpu_reset, - NULL, NULL, NULL }; - -t_stat sim_instr (void) -{ -extern int32 sim_interval; -register int32 PC, IR; -int32 i, j, carry, zero, op1, op2; -int32 opcode = 0, qbyte = 0, rbyte = 0; -int32 opaddr, addr1, addr2, dlen1, dlen2, r; -int32 int_savelevel = 8, intpri, intlev, intdev, intmask; -int32 devno, devm, devn; -char display[3][9]; -int32 val [32]; -register t_stat reason; - -/* Restore register state */ - -PC = IAR[level]; /* load local PC */ -reason = 0; - -/* Main instruction fetch/decode loop */ - -while (reason == 0) { /* loop until halted */ -if (sim_interval <= 0) { /* check clock queue */ - if (reason = sim_process_event ()) break; } - - -if (int_req) { /* interrupt? */ - intpri = 16; - for (i = 0; i < 16; i++) { /* Get highest priority device */ - if ((int_req >> i) & 0x01) { - intlev = dev_table[i].level; - if (priority[intlev] < intpri) { - intdev = i; - intpri = priority[intlev]; - } - } - } - intmask = 1 << intdev; /* mask is interrupting dev bit */ - int_req = ~int_req & intmask; /* Turn off int_req for device */ - int_savelevel = level; /* save current level for reset */ - level = dev_table[intdev].level; /* get int level from device */ - PC = IAR[level]; /* Use int level IAR for new PC */ -} /* end interrupt */ - -if (sim_brk_summ && sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */ - reason = STOP_IBKPT; /* stop simulation */ - break; -} - -/* Machine Instruction Execution Here */ - -if ((debug_reg == 0) && debug_flag == 1) { - fclose(trace); - debug_flag = 0; -} -if (debug_reg) { - if (!debug_flag) { - trace = fopen("trace.log", "w"); - debug_flag = 1; - } -} - -if (debug_reg & 0x01) { - fprintf(trace, "ARR=%04X XR1=%04X XR2=%04X IAR=%04X ", ARR[level], XR1, XR2, PC); - val[0] = GetMem(PC); - val[1] = GetMem(PC+1); - val[2] = GetMem(PC+2); - val[3] = GetMem(PC+3); - val[4] = GetMem(PC+4); - val[5] = GetMem(PC+5); - fprint_sym(trace, PC, (uint32 *) val, &cpu_unit, SWMASK('M')); - fprintf(trace, "\n"); -} - -saved_PC = PC; -opaddr = GetMem(PC) & 0xf0; /* fetch addressing mode */ -opcode = GetMem(PC) & 0x0f; /* fetch opcode */ -PC = (PC + 1) & AMASK; -sim_interval = sim_interval - 1; - -qbyte = GetMem(PC) & 0xff; /* fetch qbyte */ -PC = (PC + 1) & AMASK; - -if (opaddr == 0xf0) { /* Is it command format? */ - rbyte = GetMem(PC) & 0xff; - PC = (PC + 1) & AMASK; - switch (opcode) { - case 0x00: /* HPL: Halt Program Level */ - for (i = 0; i < 3; i++) { - for (j = 0; j < 9; j++) { - display[i][j] = ' '; - } - } - /* First line */ - if (qbyte & 0x04) display[0][2] = '_' ; - if (rbyte & 0x04) display[0][6] = '_' ; - /* Second line */ - if (qbyte & 0x08) display[1][1] = '|' ; - if (rbyte & 0x08) display[1][5] = '|' ; - if (qbyte & 0x10) display[1][2] = '_' ; - if (rbyte & 0x10) display[1][6] = '_' ; - if (qbyte & 0x02) display[1][3] = '|' ; - if (rbyte & 0x02) display[1][7] = '|' ; - /* Third line */ - if (qbyte & 0x20) display[2][1] = '|' ; - if (rbyte & 0x20) display[2][5] = '|' ; - if (qbyte & 0x40) display[2][2] = '_' ; - if (rbyte & 0x40) display[2][6] = '_' ; - if (qbyte & 0x01) display[2][3] = '|' ; - if (rbyte & 0x01) display[2][7] = '|' ; - /* Print display segment array */ - printf("\n\r"); - for (i = 0; i < 3; i++) { - for (j = 0; j < 9; j++) { - printf ("%c", display[i][j]); - } - printf ("\n\r"); - } - reason = STOP_HALT; - break; - case 0x01: /* APL: Advance Program Level */ - devno = (qbyte >> 4) & 0x0f; - devm = (qbyte >> 3) & 0x01; - devn = qbyte & 0x07; - op1 = dev_table[devno].routine(4, devm, devn, rbyte); - if (op1 & 0x01) { - if (cpu_unit.flags & UNIT_DPF) { /* Dual Programming? */ - if (level == 8) /* Yes: switch program levels */ - level = 9; - else - level = 8; - PC = IAR[level]; - } else { /* No: Loop on this inst */ - PC = PC - 3; - } - } - reason = (op1 >> 16) & 0xffff; - break; - case 0x02: /* JC: Jump on Condition */ - if (condition(qbyte) == 1) { - PC = (PC + rbyte) & AMASK; - } - break; - case 0x03: /* SIO: Start I/O */ - devno = (qbyte >> 4) & 0x0f; - devm = (qbyte >> 3) & 0x01; - devn = qbyte & 0x07; - reason = dev_table[devno].routine(0, devm, devn, rbyte); - if (reason == RESET_INTERRUPT) { - reason = SCPE_OK; - IAR[level] = PC; - level = int_savelevel; - PC = IAR[level]; - } - break; - default: - reason = STOP_INVOP; - break; - } /* switch (opcode) */ - IAR[level] = PC; - continue; -} -/* Not command format: fetch the addresses */ - -addr1 = (opaddr >> 6) & 3; -addr2 = (opaddr >> 4) & 3; - -switch (addr1) { - case 0: - BAR = GetMem(PC) << 8; - PC = (PC + 1) & AMASK; - BAR |=GetMem(PC); - PC = (PC + 1) & AMASK; - break; - case 1: - BAR = GetMem(PC); - BAR = (BAR + XR1) & AMASK; - PC = (PC + 1) & AMASK; - break; - case 2: - BAR = GetMem(PC); - BAR = (BAR + XR2) & AMASK; - PC = (PC + 1) & AMASK; - break; - case 3: - break; - default: - break; -} /* switch (addr1) */ - -switch (addr2) { - case 0: - AAR = GetMem(PC) << 8; - PC = (PC + 1) & AMASK; - AAR |= GetMem(PC); - PC = (PC + 1) & AMASK; - break; - case 1: - AAR = GetMem(PC); - AAR = (AAR + XR1) & AMASK; - PC = (PC + 1) & AMASK; - break; - case 2: - AAR = GetMem(PC); - AAR = (AAR + XR2) & AMASK; - PC = (PC + 1) & AMASK; - break; - case 3: - break; - default: - break; -} /* switch (addr1) */ - -switch (opaddr) { - case 0x00: - case 0x10: - case 0x20: - case 0x40: - case 0x50: - case 0x60: - case 0x80: - case 0x90: - case 0xa0: - switch (opcode) { - case 4: /* ZAZ: Zero and Add Zoned */ - dlen2 = qbyte & 0x0f; - dlen1 = (qbyte >> 4) & 0xf; - dlen1 += dlen2; - op1 = BAR; - for (i = 0; i < (dlen1+1); i++) { - PutMem(op1, 0xf0); - op1--; - } - r = add_zoned(BAR, dlen1+1, AAR, dlen2+1); - PSR &= 0xF8; /* HJS mod */ - switch (r) { - case 0: - PSR |= 0x01; - break; - case 1: - PSR |= 0x02; - break; - case 2: - PSR |= 0x04; - break; - default: - break; - } - break; - case 6: /* AZ: Add Zoned */ - dlen2 = qbyte & 0x0f; - dlen1 = (qbyte >> 4) & 0xf; - dlen1 += dlen2; - r = add_zoned(BAR, dlen1+1, AAR, dlen2+1); - PSR &= 0xF0; - switch (r) { - case 0: - PSR |= 0x01; - break; - case 1: - PSR |= 0x02; - break; - case 2: - PSR |= 0x04; - break; - case 3: - PSR |= 0x08; - break; - default: - break; - } - break; - case 7: /* SZ: Subtract Zoned */ - dlen2 = qbyte & 0x0f; - dlen1 = (qbyte >> 4) & 0xf; - dlen1 += dlen2; - r = subtract_zoned(BAR, dlen1+1, AAR, dlen2+1); - PSR &= 0xF0; - switch (r) { - case 0: - PSR |= 0x01; - break; - case 1: - PSR |= 0x02; - break; - case 2: - PSR |= 0x04; - break; - case 3: - PSR |= 0x08; - break; - default: - break; - } - break; - case 8: /* MVX: Move Hex */ - op1 = GetMem(BAR); - op2 = GetMem(AAR); - switch (qbyte) { - case 0: /* Zone to zone */ - op1 = (op1 & 0x0F) | (op2 & 0xF0); - break; - case 1: /* Numeric to zone */ - op1 = (op1 & 0x0F) | (op2 << 4); - break; - case 2: /* Zone to numeric */ - op1 = (op1 & 0xF0) | (op2 >> 4); - break; - case 3: /* Numeric to numeric */ - op1 = (op1 & 0xF0) | (op2 & 0x0F); - break; - default: - reason = STOP_INVQ; - break; - } - PutMem(BAR, op1); - break; - case 0xa: /* ED: Edit */ - zero = 1; - PSR &= 0xF8; - IR = GetMem(AAR); - if ((IR & 0xf0) != 0xF0) - PSR |= 0x02; - else - PSR |= 0x04; - while (qbyte > -1) { - op2 = GetMem(AAR); - op1 = GetMem(BAR); - if (op1 == 0x20) { - op2 |= 0xf0; - PutMem(BAR, op2); - AAR--; - if (op2 != 0xF0) zero = 0; - } - BAR--; - qbyte--; - } - if (zero) - PSR |= 0x01; - break; - case 0xb: /* ITC: Insert and Test Chars */ - op2 = GetMem(AAR); - while (qbyte > -1) { - op1 = GetMem(BAR); - if (op1 >= 0xF1 && op1 <= 0xF9) - break; - PutMem(BAR, op2); - BAR++; - qbyte--; - } - ARR[level] = BAR; - break; - case 0xc: /* MVC: Move Characters */ - while (qbyte > -1) { - PutMem(BAR, GetMem(AAR)); - BAR--; - AAR--; - qbyte--; - } - break; - case 0xd: /* CLC: Compare Characters */ - PSR &= 0xF8; - i = BAR = BAR - qbyte; - j = AAR = AAR - qbyte; - while (qbyte > -1) { - if (GetMem(i) > GetMem(j)) { - PSR |= 0x04; - break; - } - if (GetMem(i) < GetMem(j)) { - PSR |= 0x02; - break; - } - i++; - j++; - qbyte--; - } - if (qbyte == -1) - PSR |= 0x01; - break; - case 0xe: /* ALC: Add Logical Characters */ - carry = 0; - zero = 1; - while (qbyte > -1) { - IR = GetMem(BAR) + GetMem(AAR) + carry; - if (IR & 0x100) - carry = 1; - else - carry = 0; - if ((IR & 0xFF) != 0) zero = 0; /* HJS mod */ - PutMem(BAR,(IR & 0xFF)); - BAR--; - AAR--; - qbyte--; - } - PSR &= 0xD8; - if (zero) - PSR |= 0x01; /* Equal */ - if (!zero && !carry) - PSR |= 0x02; /* Low */ - if (!zero && carry) - PSR |= 0x04; /* High */ - if (carry) - PSR |= 0x20; /* Overflow */ - break; - case 0xf: /* SLC: Subtract Logical Characters */ - carry = 1; - zero = 1; - while (qbyte > -1) { - IR = GetMem(BAR) + (0xFF - GetMem(AAR)) + carry; - if (IR & 0x100) - carry = 1; - else - carry = 0; - if ((IR & 0xFF) != 0) zero = 0; /* HJS mod */ - PutMem(BAR,(IR & 0xFF)); - BAR--; - AAR--; - qbyte--; - } - PSR &= 0xF8; - if (zero) - PSR |= 0x01; /* Equal */ - if (!zero && !carry) - PSR |= 0x02; /* Low */ - if (!zero && carry) - PSR |= 0x04; /* High */ - break; - default: - reason = STOP_INVOP; - break; - } - IAR[level] = PC; - continue; - break; - case 0x30: - case 0x70: - case 0xb0: - switch (opcode) { - case 0: /* SNS: Sense I/O */ - devno = (qbyte >> 4) & 0x0f; - devm = (qbyte >> 3) & 0x01; - devn = qbyte & 0x07; - i = dev_table[devno].routine(3, devm, devn, rbyte); - PutMem(BAR, i & 0xff); - BAR--; - PutMem(BAR, (i >> 8) & 0xff); - reason = (i >> 16) & 0xffff; - break; - case 1: /* LIO: Load I/O */ - devno = (qbyte >> 4) & 0x0f; - devm = (qbyte >> 3) & 0x01; - devn = qbyte & 0x07; - op1 = GetMem(BAR); - BAR--; - op1 |= (GetMem(BAR) << 8) & 0xff00; - reason = dev_table[devno].routine(1, devm, devn, op1); - break; - case 4: /* ST: Store Register */ - switch (qbyte) { - case 0x01: - PutMem(BAR, XR1 & 0xff); - BAR--; - PutMem(BAR, (XR1 >> 8) & 0xff); - break; - case 0x02: - PutMem(BAR, XR2 & 0xff); - BAR--; - PutMem(BAR, (XR2 >> 8) & 0xff); - break; - case 0x04: - PutMem(BAR, PSR & 0xFF); - BAR--; - PutMem(BAR, 0); /* LCRR, not imp. */ - break; - case 0x08: - PutMem(BAR, ARR[level] & 0xff); - BAR--; - PutMem(BAR, (ARR[level] >> 8) & 0xff); - break; - case 0x10: - PutMem(BAR, IAR[level] & 0xff); - BAR--; - PutMem(BAR, (IAR[level] >> 8) & 0xff); - break; - case 0x20: - PutMem(BAR, IAR[8] & 0xff); - BAR--; - PutMem(BAR, (IAR[8] >> 8) & 0xff); - break; - case 0x40: - PutMem(BAR, IAR[9] & 0xff); - BAR--; - PutMem(BAR, (IAR[9] >> 8) & 0xff); - break; - case 0x80: - PutMem(BAR, IAR[0] & 0xff); - BAR--; - PutMem(BAR, (IAR[0] >> 8) & 0xff); - break; - case 0x81: - PutMem(BAR, IAR[7] & 0xff); - BAR--; - PutMem(BAR, (IAR[7] >> 8) & 0xff); - break; - case 0x82: - PutMem(BAR, IAR[6] & 0xff); - BAR--; - PutMem(BAR, (IAR[6] >> 8) & 0xff); - break; - case 0x84: - PutMem(BAR, IAR[5] & 0xff); - BAR--; - PutMem(BAR, (IAR[5] >> 8) & 0xff); - break; - case 0x88: - PutMem(BAR, IAR[4] & 0xff); - BAR--; - PutMem(BAR, (IAR[4] >> 8) & 0xff); - break; - case 0x90: - PutMem(BAR, IAR[3] & 0xff); - BAR--; - PutMem(BAR, (IAR[3] >> 8) & 0xff); - break; - case 0xA0: - PutMem(BAR, IAR[2] & 0xff); - BAR--; - PutMem(BAR, (IAR[2] >> 8) & 0xff); - break; - case 0xC0: - PutMem(BAR, IAR[1] & 0xff); - BAR--; - PutMem(BAR, (IAR[1] >> 8) & 0xff); - break; - default: - reason = STOP_INVQ; - break; - } - break; - case 5: /* L: Load Register */ - switch (qbyte) { - case 0x01: - XR1 = GetMem(BAR) & 0xff; - BAR--; - XR1 |= (GetMem(BAR) << 8) & 0xff00; - break; - case 0x02: - XR2 = GetMem(BAR) & 0xff; - BAR--; - XR2 |= (GetMem(BAR) << 8) & 0xff00; - break; - case 0x04: - PSR = GetMem(BAR) & 0xff; - BAR--; - break; - case 0x08: - ARR[level] = GetMem(BAR) & 0xff; - BAR--; - ARR[level] |= (GetMem(BAR) << 8) & 0xff00; - break; - case 0x10: - IAR[level] = GetMem(BAR) & 0xff; - BAR--; - IAR[level] |= (GetMem(BAR) << 8) & 0xff00; - PC = IAR[level]; - break; - case 0x20: - IAR[8] = GetMem(BAR) & 0xff; - BAR--; - IAR[8] |= (GetMem(BAR) << 8) & 0xff00; - break; - case 0x40: - IAR[9] = GetMem(BAR) & 0xff; - BAR--; - IAR[9] |= (GetMem(BAR) << 8) & 0xff00; - break; - case 0x80: - IAR[0] = GetMem(BAR) & 0xff; - BAR--; - IAR[0] |= (GetMem(BAR) << 8) & 0xff00; - break; - case 0x81: - IAR[7] = GetMem(BAR) & 0xff; - BAR--; - IAR[7] |= (GetMem(BAR) << 8) & 0xff00; - break; - case 0x82: - IAR[6] = GetMem(BAR) & 0xff; - BAR--; - IAR[6] |= (GetMem(BAR) << 8) & 0xff00; - break; - case 0x84: - IAR[5] = GetMem(BAR) & 0xff; - BAR--; - IAR[5] |= (GetMem(BAR) << 8) & 0xff00; - break; - case 0x88: - IAR[4] = GetMem(BAR) & 0xff; - BAR--; - IAR[4] |= (GetMem(BAR) << 8) & 0xff00; - break; - case 0x90: - IAR[3] = GetMem(BAR) & 0xff; - BAR--; - IAR[3] |= (GetMem(BAR) << 8) & 0xff00; - break; - case 0xA0: - IAR[2] = GetMem(BAR) & 0xff; - BAR--; - IAR[2] |= (GetMem(BAR) << 8) & 0xff00; - break; - case 0xC0: - IAR[1] = GetMem(BAR) & 0xff; - BAR--; - IAR[1] |= (GetMem(BAR) << 8) & 0xff00; - break; - default: - reason = STOP_INVQ; - break; - } - break; - case 6: /* A: Add to Register */ - IR = GetMem(BAR) & 0x00ff; - BAR--; - IR |= (GetMem(BAR) << 8) & 0xff00; - switch (qbyte) { - case 0x01: - IR += XR1; - XR1 = IR & AMASK; - break; - case 0x02: - IR += XR2; - XR2 = IR & AMASK; - break; - case 0x04: - IR += PSR; - PSR = IR & AMASK; - break; - case 0x08: - IR += ARR[level]; - ARR[level] = IR & AMASK; - break; - case 0x10: - IR += IAR[level]; - IAR[level] = IR & AMASK; - break; - case 0x20: - IR += IAR[8]; - IAR[8] = IR & AMASK; - break; - case 0x40: - IR += IAR[9]; - IAR[9] = IR & AMASK; - break; - case 0x80: - IR += IAR[0]; - IAR[0] = IR & AMASK; - break; - case 0x81: - IR += IAR[7]; - IAR[7] = IR & AMASK; - break; - case 0x82: - IR += IAR[6]; - IAR[6] = IR & AMASK; - break; - case 0x84: - IR += IAR[5]; - IAR[5] = IR & AMASK; - break; - case 0x88: - IR += IAR[4]; - IAR[4] = IR & AMASK; - break; - case 0x90: - IR += IAR[3]; - IAR[3] = IR & AMASK; - break; - case 0xA0: - IR += IAR[2]; - IAR[2] = IR & AMASK; - break; - case 0xC0: - IR += IAR[1]; - IAR[1] = IR & AMASK; - break; - default: - reason = STOP_INVQ; - break; - } - PSR &= 0xD8; - if ((IR & 0xffff) == 0) - PSR |= 0x01; /* Zero */ - if ((IR & 0xffff) != 0 && !(IR & 0x10000)) - PSR |= 0x02; /* Low */ - if ((IR & 0xffff) != 0 && (IR & 0x10000)) - PSR |= 0x04; /* High */ - if ((IR & 0x10000)) - PSR |= 0x20; /* Bin overflow */ - break; - case 8: /* TBN: Test Bits On */ - IR = GetMem(BAR); - PSR &= 0xFF; - if ((IR & qbyte) != qbyte) - PSR |= 0x10; - break; - case 9: /* TBF: Test Bits Off */ - IR = GetMem(BAR); - PSR &= 0xFF; - if ((IR & qbyte)) - PSR |= 0x10; - break; - case 0xa: /* SBN: Set Bits On */ - IR = GetMem(BAR); - IR |= qbyte; - PutMem(BAR, IR); - break; - case 0xb: /* SBF: Set Bits Off */ - IR = GetMem(BAR); - IR &= ~qbyte; - PutMem(BAR, IR); - break; - case 0xc: /* MVI: Move Immediate */ - PutMem(BAR, qbyte); - break; - case 0xd: /* CLI: Compare Immediate */ - PSR = compare(GetMem(BAR), qbyte, PSR); - break; - default: - reason = STOP_INVOP; - break; - } - IAR[level] = PC; - continue; - break; - case 0xc0: - case 0xd0: - case 0xe0: - switch (opcode) { - case 0: /* BC: Branch on Condition */ - ARR[level] = AAR & AMASK; - if (condition(qbyte) == 1) { - IR = ARR[level]; - ARR[level] = PC & AMASK; - PC = IR; - } - break; - case 1: /* TIO: Test I/O */ - devno = (qbyte >> 4) & 0x0f; - devm = (qbyte >> 3) & 0x01; - devn = qbyte & 0x07; - op1 = dev_table[devno].routine(2, devm, devn, rbyte); - if (op1 & 0x01) { - ARR[level] = AAR & AMASK; - IR = ARR[level]; - ARR[level] = PC & AMASK; - PC = IR; - } - reason = (op1 >> 16) & 0xffff; - break; - case 2: /* LA: Load Address */ - switch (qbyte) { - case 1: - XR1 = AAR; - break; - case 2: - XR2 = AAR; - break; - default: - reason = STOP_INVQ; - break; - } - break; - default: - reason = STOP_INVOP; - break; - } /* switch (opcode) */ - IAR[level] = PC; - continue; - - default: - reason = STOP_INVOP; - break; -} /* switch (opaddr) */ - -} /* end while (reason == 0) */ - -/* Simulation halted */ - -saved_PC = PC; -return reason; -} - -/* On models 4-12, these memory functions could be inline, but - on a model 15 with ATU address mapping must be performed so - they are in functions here for future expansion. -*/ - -/* Fetch a byte from memory */ - -int32 GetMem(int32 addr) -{ - return M[addr] & 0xff; -} - -/* Place a byte in memory */ - -int32 PutMem(int32 addr, int32 data) -{ - M[addr] = data & 0xff; - return 0; -} - -/* Check the condition register against the qbyte and return 1 if true */ - -int32 condition(int32 qbyte) -{ - int32 r = 0, t, q; - t = (qbyte & 0xf0) >> 4; - q = qbyte & 0x0f; - if (qbyte & 0x80) { /* True if any condition tested = 1*/ - if (((qbyte & 0x3f) & PSR) != 0) r = 1; - } else { /* True if all conditions tested = 0 */ - if (((qbyte & 0x3f) & PSR) == 0) r = 1; - } - /* these bits reset by a test */ - if (qbyte & 0x10) - PSR &= 0xEF; /* Reset test false if used */ - if (qbyte & 0x08) - PSR &= 0xF7; /* Reset decimal overflow if tested */ - if (qbyte == 0x00) - r = 1; /* unconditional branch */ - if (qbyte == 0x80) - r = 0; /* force no branch */ - if (t >=0 && t < 8 && (q == 7 || q == 0xf)) - r = 0; /* no-op */ - if (t > 7 && t < 0x10 && (q == 7 || q == 0xf)) - r = 1; /* Force branch */ -return (r); -} -/* Given operand 1 and operand 2, compares the two and returns - the System/3 condition register bits appropriately, given the - condition register initial state in parameter 3 -*/ - -int32 compare(int32 byte1, int32 byte2, int32 cond) -{ - int32 r; - - r = cond & 0xF8; /* mask off all but unaffected bits 2,3,4 */ - if (byte1 == byte2) - r |= 0x01; /* set equal bit */ - if (byte1 < byte2) - r |= 0x02; /* set less-than bit */ - if (byte1 > byte2) - r |= 0x04; /* set greater than bit */ - return r; -} - -/*-------------------------------------------------------------------*/ -/* Add two zoned decimal operands */ -/* */ -/* Input: */ -/* addr1 Logical address of packed decimal storage operand 1 */ -/* len1 Length minus one of storage operand 1 (range 0-15) */ -/* addr2 Logical address of packed decimal storage operand 2 */ -/* len2 Length minus one of storage operand 2 (range 0-15) */ -/* Output: */ -/* The return value is the condition code: */ -/* 0=result zero, 1=result -ve, 2=result +ve, 3=overflow */ -/* */ -/* A program check may be generated if either logical address */ -/* causes an addressing, translation, or fetch protection */ -/* exception, or if either operand causes a data exception */ -/* because of invalid decimal digits or sign, or if the */ -/* first operand is store protected. Depending on the PSW */ -/* program mask, decimal overflow may cause a program check. */ -/*-------------------------------------------------------------------*/ -int32 add_zoned (int32 addr1, int32 len1, int32 addr2, int32 len2) -{ -int cc; /* Condition code */ -uint8 dec1[MAX_DECIMAL_DIGITS]; /* Work area for operand 1 */ -uint8 dec2[MAX_DECIMAL_DIGITS]; /* Work area for operand 2 */ -uint8 dec3[MAX_DECIMAL_DIGITS]; /* Work area for result */ -int count1, count2, count3; /* Significant digit counters*/ -int sign1, sign2, sign3; /* Sign of operands & result */ - - /* Load operands into work areas */ - load_decimal (addr1, len1, dec1, &count1, &sign1); - load_decimal (addr2, len2, dec2, &count2, &sign2); - - /* Add or subtract operand values */ - if (count2 == 0) - { - /* If second operand is zero then result is first operand */ - memcpy (dec3, dec1, MAX_DECIMAL_DIGITS); - count3 = count1; - sign3 = sign1; - } - else if (count1 == 0) - { - /* If first operand is zero then result is second operand */ - memcpy (dec3, dec2, MAX_DECIMAL_DIGITS); - count3 = count2; - sign3 = sign2; - } - else if (sign1 == sign2) - { - /* If signs are equal then add operands */ - add_decimal (dec1, dec2, dec3, &count3); - sign3 = sign1; - } - else - { - /* If signs are opposite then subtract operands */ - subtract_decimal (dec1, dec2, dec3, &count3, &sign3); - if (sign1 < 0) sign3 = -sign3; - } - - /* Set condition code */ - cc = (count3 == 0) ? 0 : (sign3 < 1) ? 1 : 2; - - /* Overflow if result exceeds first operand length */ - if (count3 > len1) - cc = 3; - - /* Set positive sign if result is zero */ - if (count3 == 0) - sign3 = 1; - - /* Store result into first operand location */ - store_decimal (addr1, len1, dec3, sign3); - - /* Return condition code */ - return cc; - -} /* end function add_packed */ - -/*-------------------------------------------------------------------*/ -/* Subtract two zoned decimal operands */ -/* */ -/* Input: */ -/* addr1 Logical address of packed decimal storage operand 1 */ -/* len1 Length minus one of storage operand 1 (range 0-15) */ -/* addr2 Logical address of packed decimal storage operand 2 */ -/* len2 Length minus one of storage operand 2 (range 0-15) */ -/* Output: */ -/* The return value is the condition code: */ -/* 0=result zero, 1=result -ve, 2=result +ve, 3=overflow */ -/* */ -/* A program check may be generated if either logical address */ -/* causes an addressing, translation, or fetch protection */ -/* exception, or if either operand causes a data exception */ -/* because of invalid decimal digits or sign, or if the */ -/* first operand is store protected. Depending on the PSW */ -/* program mask, decimal overflow may cause a program check. */ -/*-------------------------------------------------------------------*/ -int32 subtract_zoned (int32 addr1, int32 len1, int32 addr2, int32 len2) -{ -int cc; /* Condition code */ -uint8 dec1[MAX_DECIMAL_DIGITS]; /* Work area for operand 1 */ -uint8 dec2[MAX_DECIMAL_DIGITS]; /* Work area for operand 2 */ -uint8 dec3[MAX_DECIMAL_DIGITS]; /* Work area for result */ -int count1, count2, count3; /* Significant digit counters*/ -int sign1, sign2, sign3; /* Sign of operands & result */ - - /* Load operands into work areas */ - load_decimal (addr1, len1, dec1, &count1, &sign1); - load_decimal (addr2, len2, dec2, &count2, &sign2); - - /* Add or subtract operand values */ - if (count2 == 0) - { - /* If second operand is zero then result is first operand */ - memcpy (dec3, dec1, MAX_DECIMAL_DIGITS); - count3 = count1; - sign3 = sign1; - } - else if (count1 == 0) - { - /* If first operand is zero then result is -second operand */ - memcpy (dec3, dec2, MAX_DECIMAL_DIGITS); - count3 = count2; - sign3 = -sign2; - } - else if (sign1 != sign2) - { - /* If signs are opposite then add operands */ - add_decimal (dec1, dec2, dec3, &count3); - sign3 = sign1; - } - else - { - /* If signs are equal then subtract operands */ - subtract_decimal (dec1, dec2, dec3, &count3, &sign3); - if (sign1 < 0) sign3 = -sign3; - } - - /* Set condition code */ - cc = (count3 == 0) ? 0 : (sign3 < 1) ? 1 : 2; - - /* Overflow if result exceeds first operand length */ - if (count3 > len1) - cc = 3; - - /* Set positive sign if result is zero */ - if (count3 == 0) - sign3 = 1; - - /* Store result into first operand location */ - store_decimal (addr1, len1, dec3, sign3); - - /* Return condition code */ - return cc; - -} /* end function subtract_packed */ - - -/*-------------------------------------------------------------------*/ -/* Add two decimal byte strings as unsigned decimal numbers */ -/* */ -/* Input: */ -/* dec1 A 31-byte area containing the decimal digits of */ -/* the first operand. Each byte contains one decimal */ -/* digit in the low-order 4 bits of the byte. */ -/* dec2 A 31-byte area containing the decimal digits of */ -/* the second operand. Each byte contains one decimal */ -/* digit in the low-order 4 bits of the byte. */ -/* Output: */ -/* result Points to a 31-byte area to contain the result */ -/* digits. One decimal digit is placed in the low-order */ -/* 4 bits of each byte. */ -/* count Points to an integer to receive the number of */ -/* digits in the result excluding leading zeroes. */ -/* This field is set to zero if the result is all zero, */ -/* or to MAX_DECIMAL_DIGITS+1 if overflow occurred. */ -/*-------------------------------------------------------------------*/ -static void add_decimal (uint8 *dec1, uint8 *dec2, uint8 *result, int32 *count) -{ -int d; /* Decimal digit */ -int i; /* Array subscript */ -int n = 0; /* Significant digit counter */ -int carry = 0; /* Carry indicator */ - - /* Add digits from right to left */ - for (i = MAX_DECIMAL_DIGITS - 1; i >= 0; i--) - { - /* Add digits from first and second operands */ - d = dec1[i] + dec2[i] + carry; - - /* Check for carry into next digit */ - if (d > 9) { - d -= 10; - carry = 1; - } else { - carry = 0; - } - - /* Check for significant digit */ - if (d != 0) - n = MAX_DECIMAL_DIGITS - i; - - /* Store digit in result */ - result[i] = d; - - } /* end for */ - - /* Check for carry out of leftmost digit */ - if (carry) - n = MAX_DECIMAL_DIGITS + 1; - - /* Return significant digit counter */ - *count = n; - -} /* end function add_decimal */ - -/*-------------------------------------------------------------------*/ -/* Subtract two decimal byte strings as unsigned decimal numbers */ -/* */ -/* Input: */ -/* dec1 A 31-byte area containing the decimal digits of */ -/* the first operand. Each byte contains one decimal */ -/* digit in the low-order 4 bits of the byte. */ -/* dec2 A 31-byte area containing the decimal digits of */ -/* the second operand. Each byte contains one decimal */ -/* digit in the low-order 4 bits of the byte. */ -/* Output: */ -/* result Points to a 31-byte area to contain the result */ -/* digits. One decimal digit is placed in the low-order */ -/* 4 bits of each byte. */ -/* count Points to an integer to receive the number of */ -/* digits in the result excluding leading zeroes. */ -/* This field is set to zero if the result is all zero. */ -/* sign -1 if the result is negative (operand2 > operand1) */ -/* +1 if the result is positive (operand2 <= operand1) */ -/*-------------------------------------------------------------------*/ -static void subtract_decimal (uint8 *dec1, uint8 *dec2, uint8 *result, int *count, int *sign) -{ -int d; /* Decimal digit */ -int i; /* Array subscript */ -int n = 0; /* Significant digit counter */ -int borrow = 0; /* Borrow indicator */ -int rc; /* Return code */ -uint8 *higher; /* -> Higher value operand */ -uint8 *lower; /* -> Lower value operand */ - - /* Compare digits to find which operand has higher numeric value */ - rc = memcmp (dec1, dec2, MAX_DECIMAL_DIGITS); - - /* Return positive zero result if both operands are equal */ - if (rc == 0) { - memset (result, 0, MAX_DECIMAL_DIGITS); - *count = 0; - *sign = +1; - return; - } - - /* Point to higher and lower value operands and set sign */ - if (rc > 0) { - higher = dec1; - lower = dec2; - *sign = +1; - } else { - lower = dec1; - higher = dec2; - *sign = -1; - } - - /* Subtract digits from right to left */ - for (i = MAX_DECIMAL_DIGITS - 1; i >= 0; i--) - { - /* Subtract lower operand digit from higher operand digit */ - d = higher[i] - lower[i] - borrow; - - /* Check for borrow from next digit */ - if (d < 0) { - d += 10; - borrow = 1; - } else { - borrow = 0; - } - - /* Check for significant digit */ - if (d != 0) - n = MAX_DECIMAL_DIGITS - i; - - /* Store digit in result */ - result[i] = d; - - } /* end for */ - - /* Return significant digit counter */ - *count = n; - -} /* end function subtract_decimal */ - -/*-------------------------------------------------------------------*/ -/* Load a zoned decimal storage operand into a decimal byte string */ -/* */ -/* Input: */ -/* addr Logical address of zoned decimal storage operand */ -/* len Length minus one of storage operand (range 0-15) */ -/* Output: */ -/* result Points to a 31-byte area into which the decimal */ -/* digits are loaded. One decimal digit is loaded */ -/* into the low-order 4 bits of each byte, and the */ -/* result is padded to the left with high-order zeroes */ -/* if the storage operand contains less than 31 digits. */ -/* count Points to an integer to receive the number of */ -/* digits in the result excluding leading zeroes. */ -/* This field is set to zero if the result is all zero. */ -/* sign Points to an integer which will be set to -1 if a */ -/* negative sign was loaded from the operand, or +1 if */ -/* a positive sign was loaded from the operand. */ -/* */ -/* A program check may be generated if the logical address */ -/* causes an addressing, translation, or fetch protection */ -/* exception, or if the operand causes a data exception */ -/* because of invalid decimal digits or sign. */ -/*-------------------------------------------------------------------*/ -static void load_decimal (int32 addr, int32 len, uint8 *result, int32 *count, int32 *sign) -{ -int h; /* Hexadecimal digit */ -int i, j; /* Array subscripts */ -int n; /* Significant digit counter */ - - if ((GetMem(addr) & 0xf0) == 0xD0) - *sign = -1; - else - *sign = 1; - j = len; - for (i = MAX_DECIMAL_DIGITS; i > -1; i--) { - if (j) { - h = GetMem(addr) & 0x0f; - addr--; - j--; - } else { - h = 0; - } - result [i-1] = h; - if (h > 0) n = i; - } - *count = 32 - n; - -} /* end function load_decimal */ - -/*-------------------------------------------------------------------*/ -/* Store decimal byte string into packed decimal storage operand */ -/* */ -/* Input: */ -/* addr Logical address of packed decimal storage operand */ -/* len Length minus one of storage operand (range 0-15) */ -/* dec A 31-byte area containing the decimal digits to be */ -/* stored. Each byte contains one decimal digit in */ -/* the low-order 4 bits of the byte. */ -/* sign -1 if a negative sign is to be stored, or +1 if a */ -/* positive sign is to be stored. */ -/* */ -/* A program check may be generated if the logical address */ -/* causes an addressing, translation, or protection exception. */ -/*-------------------------------------------------------------------*/ -static void store_decimal (int32 addr, int32 len, uint8 *dec, int sign) -{ -int i, j, a; /* Array subscripts */ - - j = len; - a = addr; - for (i = MAX_DECIMAL_DIGITS; i > -1; i--) { - if (j) { - PutMem(a, (dec[i-1] | 0xf0)); - a--; - j--; - } else { - break; - } - } - if (sign == -1) { - PutMem(addr, (GetMem(addr) & 0x0f)); - PutMem(addr, (GetMem(addr) | 0xf0)); - } - -} /* end function store_decimal */ - -/* CPU Device Control */ - -int32 cpu (int32 op, int32 m, int32 n, int32 data) -{ - int32 iodata = 0; - - switch (op) { - case 0x00: /* Start IO */ - return SCPE_OK; - case 0x01: /* LIO */ - return SCPE_OK; - case 0x02: /* TIO */ - break; - case 0x03: /* SNS */ - /* SNS CPU gets the data switches */ - iodata = SR; - break; - case 0x04: /* APL */ - break; - default: - break; - } - return ((SCPE_OK << 16) | iodata); -} - - - -/* Null device */ - -int32 nulldev (int32 opcode, int32 m, int32 n, int32 data) -{ -if (opcode == 1) - return SCPE_OK; /* Ok to LIO unconfigured devices? */ -return STOP_INVDEV; -} - -/* Reset routine */ - -t_stat cpu_reset (DEVICE *dptr) -{ -int_req = 0; -level = 8; -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] & 0xff; -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 & 0xff; -return SCPE_OK; -} - -t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -int32 mc = 0; -uint32 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; -} - -t_stat cpu_boot (int32 unitno, DEVICE *dptr) -{ -level = 8; -IAR[8] = 0; -return SCPE_OK; -} diff --git a/S3/s3_defs.h b/S3/s3_defs.h deleted file mode 100644 index f018effa..00000000 --- a/S3/s3_defs.h +++ /dev/null @@ -1,94 +0,0 @@ -/* s3_defs.h: IBM System/3 simulator definitions - - Copyright (c) 2001-2003, Charles E. Owen - - 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 Charles E. Owen shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Charles E. Owen. -*/ - -#include "sim_defs.h" /* simulator defns */ - -/* Simulator stop codes */ - -#define STOP_RSRV 1 /* must be 1 */ -#define STOP_HALT 2 /* HALT */ -#define STOP_IBKPT 3 /* breakpoint */ -#define STOP_INVOP 4 /* program check - invalid op */ -#define STOP_INVQ 5 /* Prog check - invalid Q */ -#define STOP_INVADDR 6 /* Prog check - invalid addr */ -#define STOP_INVDEV 7 /* Prog check - invalid dev cmd */ -#define STOP_NOCD 8 /* ATTN card reader */ -#define RESET_INTERRUPT 77 /* special return from SIO */ - -/* Memory */ - -#define MAXMEMSIZE 65536 /* max memory size */ -#define AMASK (MAXMEMSIZE - 1) /* logical addr mask */ -#define PAMASK (MAXMEMSIZE - 1) /* physical addr mask */ -#define MEMSIZE (cpu_unit.capac) /* actual memory size */ - -#define MAX_DECIMAL_DIGITS 31 /* max size of a decimal number */ -#define CDR_WIDTH 80 /* Max card size */ -#define CDP_WIDTH 80 /* Punch width */ -#define LPT_WIDTH 132 -#define CCT_LNT 132 - -#define DSK_SECTSIZE 256 /* Sector length */ -#define DSK_CYLSIZE 256*48 /* Cylinder length */ - -/* I/O structure - - The I/O structure is tied together by dev_table, indexed by - the device number. Each entry in dev_table consists of - - level Interrupt level for device (0-7) - priority Priority for device (1-8) - routine IOT action routine -*/ - -struct ndev { - int32 level; /* interrupt level */ - int32 pri; /* Device priority */ - int32 (*routine)(); /* dispatch routine */ -}; - -/* Structure to define operation codes */ - -struct opdef { - char op[6]; /* Mnemonic for op */ - int32 opmask; /* Bits set on in opcode */ - int32 q; /* Qbyte */ - int32 form; /* Forms are: - 0 - 1-byte hex operand - 1 - 1-byte register addr, A-Addr - 2 - A-addr,B-addr,Qbyte - 3 - A-addr,Qbyte - 4 - da,m,n - 5 - da,m,n,cc - 6 - da,m,n,A-addr - 7 - 1-address implict Q - 8 - 2-address implict Q */ - int32 group; /* Group Code: - 0 - Command Format (0xFx) - 1 - 1-address A (0xx) - 2 - 2-address (0x<0,1,2,4,5,6,8,9,A>x) - 3 - 1-address B (0x<3,7,B>x) */ -}; diff --git a/S3/s3_disk.c b/S3/s3_disk.c deleted file mode 100644 index 21d54027..00000000 --- a/S3/s3_disk.c +++ /dev/null @@ -1,788 +0,0 @@ -/* s3_disk.c: IBM 5444 Disk Drives - - Copyright (c) 2001-2003, Charles E. Owen - - 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 Charles E. Owen shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Charles E. Owen. - - r1 Removeable disk 1 - f1 Fixed disk 1 - r2 Removeable disk 2 - f2 Fixed disk 2 - - 25-Apr-03 RMS Revised for extended file support - 08-Oct-02 RMS Added impossible function catcher -*/ - -#include "s3_defs.h" -#include - -extern uint8 M[]; -extern int32 IAR[], level; -extern FILE *trace; -extern int32 debug_reg; -char dbuf[DSK_SECTSIZE]; /* Disk buffer */ -int32 dsk (int32 disk, int32 op, int32 m, int32 n, int32 data); -int32 read_sector(UNIT *uptr, char *dbuf, int32 sect); -int32 write_sector(UNIT *uptr, char *dbuf, int32 sect); -t_stat r1_svc (UNIT *uptr); -t_stat r1_boot (int32 unitno, DEVICE *dptr); -t_stat r1_attach (UNIT *uptr, char *cptr); -t_stat r1_reset (DEVICE *dptr); -t_stat f1_svc (UNIT *uptr); -t_stat f1_boot (int32 unitno, DEVICE *dptr); -t_stat f1_attach (UNIT *uptr, char *cptr); -t_stat f1_reset (DEVICE *dptr); -t_stat r2_svc (UNIT *uptr); -t_stat r2_boot (int32 unitno, DEVICE *dptr); -t_stat r2_attach (UNIT *uptr, char *cptr); -t_stat r2_reset (DEVICE *dptr); -t_stat f2_svc (UNIT *uptr); -t_stat f2_boot (int32 unitno, DEVICE *dptr); -t_stat f2_attach (UNIT *uptr, char *cptr); -t_stat f2_reset (DEVICE *dptr); -extern int32 GetMem(int32 addr); -extern int32 PutMem(int32 addr, int32 data); - -char opstr[5][5] = { "SIO", "LIO", "TIO", "SNS", "APL" }; - -int32 DDAR[2]; /* Data address register */ -int32 DCAR[2]; /* Disk Control Address Register */ -int32 diskerr[2] = { 0, 0 }; /* Error status */ -int32 notrdy[2] = { 0, 0 }; /* Not ready error */ -int32 seekbusy[2] = { 0, 0 }; /* Drive busy flags */ -int32 seekhead[2] = { 0, 0 }; /* Disk head 0,1 */ -int32 found[2] = { 0, 0 }; /* Scan found bit */ -int32 RIDsect[2] = { 0, 0 }; /* for Read ID */ - -/* Disk data structures - - xy_dev CDR descriptor - xy_unit CDR unit descriptor - xy_reg CDR register list - - x = F or R - y = 1 or 2 -*/ - -UNIT r1_unit = { - UDATA (&r1_svc, UNIT_FIX+UNIT_ATTABLE, 0), 100 }; - -REG r1_reg[] = { - { FLDATA (NOTRDY, notrdy[0], 0) }, - { FLDATA (SEEK, seekbusy[0], 0) }, - { HRDATA (DAR, DDAR[0], 16) }, - { HRDATA (CAR, DCAR[0], 16) }, - { HRDATA (ERR, diskerr[0], 16) }, - { DRDATA (CYL, r1_unit.u3, 8) }, - { DRDATA (HEAD, seekhead[0], 8) }, - { DRDATA (POS, r1_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, r1_unit.wait, 24), PV_LEFT }, - { BRDATA (BUF, dbuf, 8, 8, 256) }, - { NULL } }; - -DEVICE r1_dev = { - "R1", &r1_unit, r1_reg, NULL, - 1, 10, 31, 1, 8, 7, - NULL, NULL, &r1_reset, - &r1_boot, &r1_attach, NULL }; - -UNIT f1_unit = { - UDATA (&f1_svc, UNIT_FIX+UNIT_ATTABLE, 0), 100 }; - -REG f1_reg[] = { - { FLDATA (NOTRDY, notrdy[0], 0) }, - { FLDATA (SEEK, seekbusy[0], 0) }, - { HRDATA (DAR, DDAR[0], 16) }, - { HRDATA (CAR, DCAR[0], 16) }, - { HRDATA (ERR, diskerr[0], 16) }, - { DRDATA (CYL, f1_unit.u3, 8) }, - { DRDATA (HEAD, seekhead[0], 8) }, - { DRDATA (POS, f1_unit.pos, 32), PV_LEFT }, - { DRDATA (TIME, f1_unit.wait, 24), PV_LEFT }, - { BRDATA (BUF, dbuf, 8, 8, 256) }, - { NULL } }; - -DEVICE f1_dev = { - "F1", &f1_unit, f1_reg, NULL, - 1, 10, 31, 1, 8, 7, - NULL, NULL, &f1_reset, - &f1_boot, &f1_attach, NULL }; - -UNIT r2_unit = { - UDATA (&r2_svc, UNIT_FIX+UNIT_ATTABLE, 0), 100 }; - -REG r2_reg[] = { - { FLDATA (NOTRDY, notrdy[1], 0) }, - { FLDATA (SEEK, seekbusy[1], 0) }, - { HRDATA (DAR, DDAR[1], 16) }, - { HRDATA (CAR, DCAR[1], 16) }, - { HRDATA (ERR, diskerr[1], 16) }, - { DRDATA (CYL, r2_unit.u3, 8) }, - { DRDATA (HEAD, seekhead[1], 8) }, - { DRDATA (POS, r2_unit.pos, 32), PV_LEFT }, - { DRDATA (TIME, r2_unit.wait, 24), PV_LEFT }, - { BRDATA (BUF, dbuf, 8, 8, 256) }, - { NULL } }; - -DEVICE r2_dev = { - "R2", &r2_unit, r2_reg, NULL, - 1, 10, 31, 1, 8, 7, - NULL, NULL, &r2_reset, - &r2_boot, &r2_attach, NULL }; - -UNIT f2_unit = { - UDATA (&f2_svc, UNIT_FIX+UNIT_ATTABLE, 0), 100 }; - -REG f2_reg[] = { - { FLDATA (NOTRDY, notrdy[1], 0) }, - { FLDATA (SEEK, seekbusy[1], 0) }, - { HRDATA (DAR, DDAR[1], 16) }, - { HRDATA (CAR, DCAR[1], 16) }, - { HRDATA (ERR, diskerr[1], 16) }, - { DRDATA (CYL, f2_unit.u3, 8) }, - { DRDATA (HEAD, seekhead[1], 8) }, - { DRDATA (POS, f2_unit.pos, 32), PV_LEFT }, - { DRDATA (TIME, f2_unit.wait, 24), PV_LEFT }, - { BRDATA (BUF, dbuf, 8, 8, 256) }, - { NULL } }; - -DEVICE f2_dev = { - "F2", &f2_unit, f2_reg, NULL, - 1, 10, 31, 1, 8, 7, - NULL, NULL, &f2_reset, - &f2_boot, &f2_attach, NULL }; - - -/* -------------------------------------------------------------------- */ - -/* 5444: master routines */ - -int32 dsk1 (int32 op, int32 m, int32 n, int32 data) -{ - int32 r; - - r = dsk(0, op, m, n, data); - return (r); -} - -int32 dsk2 (int32 op, int32 m, int32 n, int32 data) -{ - int32 r; - - r = dsk(1, op, m, n, data); - return (r); -} - -/* 5444: operational routine */ - -int32 dsk (int32 disk, int32 op, int32 m, int32 n, int32 data) -{ - int32 iodata, i, j, u, sect, nsects, addr, r, c, res; - int32 F, C, S, N, usave; - UNIT *uptr; - - u = m; - if (disk == 1) u += 2; - F = GetMem(DCAR[disk]+0); /* Flag bits */ - C = GetMem(DCAR[disk]+1); /* Cylinder */ - S = GetMem(DCAR[disk]+2); /* Sector */ - N = GetMem(DCAR[disk]+3); /* Number of sectors */ - switch (u) { - case 0: - uptr = r1_dev.units; - break; - case 1: - uptr = f1_dev.units; - break; - case 2: - uptr = r2_dev.units; - break; - case 3: - uptr = f2_dev.units; - break; - default: - break; - } - if (debug_reg & 0x02) - fprintf(trace, "==> %04X %s %01X,%d,%04X DAR=%04X CAR=%04X C=%02X, S=%02X, N=%02X\n", - IAR[level], - opstr[op], - m, n, data, - DDAR[disk], - DCAR[disk], - C, S, N); - - switch (op) { - - /* SIO 5444 */ - case 0: - if ((uptr->flags & UNIT_ATT) == 0) - return SCPE_UNATT; - diskerr[disk] = 0; /* SIO resets errors */ - found[disk] = 0; /* ... and found bit */ - iodata = 0; - switch (n) { - case 0x00: /* Seek */ - if (S & 0x80) - seekhead[disk] = 1; - else - seekhead[disk] = 0; - if (S & 1) { - uptr -> u3 += N; - } else { - uptr -> u3 -= N; - } - if (uptr -> u3 < 0) - uptr -> u3 = 0; - if (uptr -> u3 > 203) { - uptr -> u3 = 0; - diskerr[disk] |= 0x0100; - if (debug_reg & 0x02) - fprintf(trace, "==> Seek Past End of Disk\n"); - } - - /*sim_activate(uptr, uptr -> wait);*/ - sim_activate(uptr, 1); - - /* Seek arms are the same for both disks on a drive: - update the other arm */ - - usave = uptr -> u3; - if (u == 0) uptr = f1_dev.units; - if (u == 1) uptr = r1_dev.units; - if (u == 2) uptr = f2_dev.units; - if (u == 3) uptr = r2_dev.units; - uptr -> u3 = usave; - - seekbusy[disk] = 1; - iodata = SCPE_OK; - break; - - case 0x01: /* Read */ - switch (data) { - case 0: /* Read data */ - sect = (S >> 2) & 0x3F; - nsects = N + 1; - addr = DDAR[disk]; - - for (i = 0; i < nsects; i++) { - r = read_sector(uptr, dbuf, sect); - if (r != 1 || uptr->u3 != C) { - diskerr[disk] |= 0x0800; - break; - } - for (j = 0; j < DSK_SECTSIZE; j++) { - PutMem(addr, dbuf[j]); - addr++; - } - - if ((sect == 55) ) { /* HJS MODS */ - S = sect; - N = nsects - i - 2; - if (N > -1) diskerr[disk] |= 0x0020; /* end of cyl. */ - DDAR[disk] = addr & 0xFFFF; /* HJS mod */ - PutMem(DCAR[disk]+2, S << 2); - PutMem(DCAR[disk]+3, N); - sim_activate(uptr, 1); - iodata = SCPE_OK; - break; - } - - sect++; - S = sect - 1; - N = nsects - i - 2; - if (sect == 24) - sect = 32; - } - DDAR[disk] = addr & 0xFFFF; /* HJS mod */ - PutMem(DCAR[disk]+2, S << 2); - PutMem(DCAR[disk]+3, N); - /*sim_activate(uptr, uptr -> wait);*/ - sim_activate(uptr, 1); - iodata = SCPE_OK; - break; - case 1: /* Read ID */ - if (uptr -> u3 > 0 && uptr -> u3 < 4) - PutMem(DCAR[disk], 1); - else - PutMem(DCAR[disk], 0); - PutMem(DCAR[disk]+1, uptr -> u3); - PutMem(DCAR[disk]+2, RIDsect[disk]); - RIDsect[disk]++; - if (RIDsect[disk] > 23) - RIDsect[disk] = 32; - if (RIDsect[disk] > 55) - RIDsect[disk] = 0; - break; - case 2: /* Read Diagnostic */ - iodata = STOP_INVDEV; - break; - case 3: /* Verify */ - sect = (S >> 2) & 0x3F; - nsects = N + 1; - addr = DDAR[disk]; - for (i = 0; i < nsects; i++) { - r = read_sector(uptr, dbuf, sect); - if (r != 1 || uptr->u3 != C) { - diskerr[disk] |= 0x0800; - break; - } - if ((sect == 55) ) { /* HJS MODS */ - S = sect; - N = nsects - i - 2; - if (N > -1) diskerr[disk] |= 0x0020; /* end of cyl. */ - DDAR[disk] = addr & 0xFFFF; - PutMem(DCAR[disk]+2, S << 2); - PutMem(DCAR[disk]+3, N); - sim_activate(uptr, 1); - iodata = SCPE_OK; - break; - } - sect++; - S = sect - 1; - N = nsects - i - 2; - if (sect == 24) - sect = 32; - } - DDAR[disk] = addr & 0xFFFF; - PutMem(DCAR[disk]+2, S << 2); - PutMem(DCAR[disk]+3, N); - /*sim_activate(uptr, uptr -> wait);*/ - sim_activate(uptr, 1); - break; - default: - return STOP_INVDEV; - } - break; - case 0x02: /* Write */ - switch (data) { - case 0: /* Write Data */ - sect = (S >> 2) & 0x3F; - nsects = N + 1; - addr = DDAR[disk]; - for (i = 0; i < nsects; i++) { - for (j = 0; j < DSK_SECTSIZE; j++) { - dbuf[j] = GetMem(addr); - addr++; - } - r = write_sector(uptr, dbuf, sect); - if (r != 1 || uptr->u3 != C) { - diskerr[disk] |= 0x0400; - break; - } - if ((sect == 55) ) { /* HJS MODS */ - S = sect; - N = nsects - i - 2; - if (N > -1) diskerr[disk] |= 0x0020; /* end of cyl. */ - DDAR[disk] = addr & 0xFFFF; - PutMem(DCAR[disk]+2, S << 2); - PutMem(DCAR[disk]+3, N); - sim_activate(uptr, 1); - iodata = SCPE_OK; - break; - } - sect++; - S = sect - 1; - N = nsects - i - 2; - if (sect == 24) - sect = 32; - } - DDAR[disk] = addr & 0xFFFF; /* HJS mod */ - PutMem(DCAR[disk]+2, S << 2); - PutMem(DCAR[disk]+3, N); - /*sim_activate(uptr, uptr -> wait);*/ - sim_activate(uptr, 1); - break; - case 1: /* Write identifier */ - if (seekhead[disk] == 0) - S = 0; - else - S = 0x80; - N = 23; - - sect = (S >> 2) & 0x3F; - nsects = N + 1; - addr = DDAR[disk]; - for (i = 0; i < nsects; i++) { - for (j = 0; j < DSK_SECTSIZE; j++) { - dbuf[j] = GetMem(addr); - } - r = write_sector(uptr, dbuf, sect); - if (r != 1) { - diskerr[disk] |= 0x0400; - break; - } - if ((sect == 55) ) { - S = sect; - N = nsects - i - 2; - if (N > 0) diskerr[disk] |= 0x0020; - DDAR[disk] = addr & 0xFFFF; - PutMem(DCAR[disk]+2, S << 2); - PutMem(DCAR[disk]+3, N); - sim_activate(uptr, 1); - iodata = SCPE_OK; - break; - } - sect++; - S = sect - 1; - N = nsects - i - 2; - if (sect == 24) - sect = 32; - } - DDAR[disk] = addr & 0xFFFF; - PutMem(DCAR[disk]+2, S << 2); - PutMem(DCAR[disk]+3, N); - /*sim_activate(uptr, uptr -> wait);*/ - sim_activate(uptr, 1); - break; - default: - return STOP_INVDEV; - } - break; - case 0x03: /* Scan */ - sect = (S >> 2) & 0x3F; - nsects = N + 1; - addr = DDAR[disk]; - for (i = 0; i < nsects; i++) { - r = read_sector(uptr, dbuf, sect); - if (r != 1 || uptr->u3 != C) { - diskerr[disk] |= 0x0800; - break; - } - res = 0; - for (j = 0; j < DSK_SECTSIZE; j++) { - c = GetMem(addr); - if (j != 0xff) { - if (dbuf[i] < c) - res = 1; - if (dbuf[i] > c) - res = 3; - } - addr++; - } - if (res == 0) - found[disk] = 1; - if (res == data) - break; - if ((sect == 55) ) { /* HJS MODS */ - S = sect; - N = nsects - i - 2; - if (N > -1) diskerr[disk] |= 0x0020; /* end of cyl. */ - DDAR[disk] = addr & 0xFFFF; - PutMem(DCAR[disk]+2, S << 2); - PutMem(DCAR[disk]+3, N); - sim_activate(uptr, 1); - iodata = SCPE_OK; - break; - } - sect++; - S = sect - 1; - N = nsects - i - 2; - if (sect == 24) - sect = 32; - } - PutMem(DCAR[disk]+2, S << 2); - PutMem(DCAR[disk]+3, N); - /*sim_activate(uptr, uptr -> wait);*/ - sim_activate(uptr, 1); - break; - default: - return STOP_INVDEV; - } - return iodata; - - /* LIO 5444 */ - case 1: - if ((uptr->flags & UNIT_ATT) == 0) - return SCPE_UNATT; - switch (n) { - case 0x04: /* Data Addr */ - DDAR[disk] = data; - break; - case 0x06: /* Control Addr */ - DCAR[disk] = data; - break; - default: - return STOP_INVDEV; - } - return SCPE_OK; - case 2: /* TIO 5444 */ - if ((uptr->flags & UNIT_ATT) == 0) - return SCPE_UNATT << 16; - iodata = 0; - switch (n) { - case 0x00: /* Error */ - if (diskerr[disk] || notrdy[disk]) - iodata = 1; - if ((uptr -> flags & UNIT_ATT) == 0) - iodata = 1; - break; - case 0x02: /* Busy */ - if (sim_is_active (uptr)) - iodata = 1; - break; - case 0x04: - if (found[disk]) - iodata = 1; - break; - default: - return (STOP_INVDEV << 16); - } - return ((SCPE_OK << 16) | iodata); - - /* SNS 5444 */ - case 3: - if ((uptr->flags & UNIT_ATT) == 0) - return SCPE_UNATT << 16; - iodata = 0; - switch (n) { - case 0x01: - break; - case 0x02: - iodata = diskerr[disk]; - if (notrdy[disk]) - iodata |= 0x4000; - if ((uptr -> flags & UNIT_ATT) == 0) - iodata |= 0x4000; - if (seekbusy[disk]) - iodata |= 0x0010; - if (uptr -> u3 == 0) - iodata |= 0x0040; - break; - case 0x03: - iodata = 0; - break; - case 0x04: - iodata = DDAR[disk]; - break; - case 0x06: - iodata = DCAR[disk]; - break; - default: - return (STOP_INVDEV << 16); - } - iodata |= ((SCPE_OK << 16) & 0xffff0000); - return (iodata); - - /* APL 5444 */ - case 4: - if ((uptr->flags & UNIT_ATT) == 0) - return SCPE_UNATT << 16; - iodata = 0; - switch (n) { - case 0x00: /* Error */ - if (diskerr[disk] || notrdy[disk]) - iodata = 1; - if ((uptr -> flags & UNIT_ATT) == 0) - iodata = 1; - break; - case 0x02: /* Busy */ - if (sim_is_active (uptr)) - iodata = 1; - break; - default: - return (STOP_INVDEV << 16); - } - return ((SCPE_OK << 16) | iodata); - default: - break; - } - printf (">>DSK%d non-existent function %d\n", disk, op); - return SCPE_OK; -} - -/* Disk unit service. If a stacker select is active, copy to the - selected stacker. Otherwise, copy to the normal stacker. If the - unit is unattached, simply exit. -*/ - -t_stat r1_svc (UNIT *uptr) -{ -seekbusy[0] = 0; -return SCPE_OK; -} -t_stat f1_svc (UNIT *uptr) -{ -seekbusy[0] = 0; -return SCPE_OK; -} -t_stat r2_svc (UNIT *uptr) -{ -seekbusy[1] = 0; -return SCPE_OK; -} -t_stat f2_svc (UNIT *uptr) -{ -seekbusy[1] = 0; -return SCPE_OK; -} - - -/* Disk reset */ - -t_stat r1_reset (DEVICE *dptr) -{ -diskerr[0] = notrdy[0] = seekbusy[0] = 0; /* clear indicators */ -found[0] = 0; -sim_cancel (&r1_unit); /* clear event */ -r1_unit.u3 = 0; /* cylinder 0 */ -return SCPE_OK; -} -t_stat f1_reset (DEVICE *dptr) -{ -diskerr[0] = notrdy[0] = seekbusy[0] = 0; /* clear indicators */ -found[0] = 0; -sim_cancel (&f1_unit); /* clear event */ -f1_unit.u3 = 0; /* cylinder 0 */ -return SCPE_OK; -} -t_stat r2_reset (DEVICE *dptr) -{ -diskerr[1] = notrdy[1] = seekbusy[1] = 0; /* clear indicators */ -found[1] = 0; -sim_cancel (&r2_unit); /* clear event */ -r2_unit.u3 = 0; /* cylinder 0 */ -return SCPE_OK; -} -t_stat f2_reset (DEVICE *dptr) -{ -diskerr[1] = notrdy[1] = seekbusy[1] = 0; /* clear indicators */ -found[1] = 0; -sim_cancel (&f2_unit); /* clear event */ -f2_unit.u3 = 0; /* cylinder 0 */ -return SCPE_OK; -} - -/* Disk unit attach */ - -t_stat r1_attach (UNIT *uptr, char *cptr) -{ -diskerr[0] = notrdy[0] = seekbusy[0] = 0; /* clear status */ -found[0] = 0; -uptr -> u3 = 0; /* cylinder 0 */ -return attach_unit (uptr, cptr); -} -t_stat f1_attach (UNIT *uptr, char *cptr) -{ -diskerr[0] = notrdy[0] = seekbusy[0] = 0; /* clear status */ -found[0] = 0; -uptr -> u3 = 0; /* cylinder 0 */ -return attach_unit (uptr, cptr); -} -t_stat r2_attach (UNIT *uptr, char *cptr) -{ -diskerr[1] = notrdy[1] = seekbusy[1] = 0; /* clear status */ -found[1] = 0; -uptr -> u3 = 0; /* cylinder 0 */ -return attach_unit (uptr, cptr); -} -t_stat f2_attach (UNIT *uptr, char *cptr) -{ -diskerr[1] = notrdy[1] = seekbusy[1] = 0; /* clear status */ -found[1] = 0; -uptr -> u3 = 0; /* cylinder 0 */ -return attach_unit (uptr, cptr); -} - -/* Bootstrap routine */ - -t_stat r1_boot (int32 unitno, DEVICE *dptr) -{ -int i; -r1_unit.u3 = 0; -read_sector(r1_dev.units, dbuf, 0); -for (i = 0; i < 256; i++) { - M[i] = dbuf[i]; -} -return SCPE_OK; -} -t_stat f1_boot (int32 unitno, DEVICE *dptr) -{ -int i; -f1_unit.u3 = 0; -read_sector(f1_dev.units, dbuf, 0); -for (i = 0; i < 256; i++) { - M[i] = dbuf[i]; -} -return SCPE_OK; -} -t_stat r2_boot (int32 unitno, DEVICE *dptr) -{ -int i; -r2_unit.u3 = 0; -read_sector(r2_dev.units, dbuf, 0); -for (i = 0; i < 256; i++) { - M[i] = dbuf[i]; -} -return SCPE_OK; -} -t_stat f2_boot (int32 unitno, DEVICE *dptr) -{ -int i; -f2_unit.u3 = 0; -read_sector(f2_dev.units, dbuf, 0); -for (i = 0; i < 256; i++) { - M[i] = dbuf[i]; -} -return SCPE_OK; -} - - -/* Raw Disk Data In/Out */ - -int32 read_sector(UNIT *uptr, char *dbuf, int32 sect) -{ - static int32 rtn, realsect; - static long pos; - - /* calculate real sector no */ - if (sect > 23) - realsect = sect - 8; - else - realsect = sect; - /* physically read the sector */ - pos = DSK_CYLSIZE * uptr -> u3; - pos += DSK_SECTSIZE * realsect; - rtn = fseek(uptr -> fileref, pos, 0); - rtn = fread(dbuf, DSK_SECTSIZE, 1, uptr -> fileref); - return (rtn); -} - -int32 write_sector(UNIT *uptr, char *dbuf, int32 sect) -{ - static int32 rtn, realsect; - static long pos; - - /* calculate real sector no */ - if (sect > 23) - realsect = sect - 8; - else - realsect = sect; - if (uptr -> u3 == 0 && realsect == 32) - rtn = 0; - /* physically write the sector */ - pos = DSK_CYLSIZE * uptr -> u3; - pos += DSK_SECTSIZE * realsect; - rtn = fseek(uptr -> fileref, pos, 0); - rtn = fwrite(dbuf, DSK_SECTSIZE, 1, uptr -> fileref); - return (rtn); -} diff --git a/S3/s3_lp.c b/S3/s3_lp.c deleted file mode 100644 index b643be61..00000000 --- a/S3/s3_lp.c +++ /dev/null @@ -1,353 +0,0 @@ -/* s3_lp.c: IBM 1403 line printer simulator - - Copyright (c) 2001-2003, Charles E. Owen - - 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 Charles E. Owen shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Charles E. Owen. - - lpt 1403 line printer - - 25-Apr-03 RMS Revised for extended file support - 08-Oct-02 RMS Added impossible function catcher -*/ - -#include "s3_defs.h" - -extern uint8 M[]; -extern char bcd_to_ascii[64]; -extern int32 iochk, ind[64]; -int32 cct[CCT_LNT] = { 03 }; -int32 cctlnt = 66, cctptr = 0, lines = 0, lflag = 0; -t_stat lpt_reset (DEVICE *dptr); -t_stat lpt_attach (UNIT *uptr, char *cptr); -t_stat write_line (int32 ilnt, int32 mod); -t_stat space (int32 lines, int32 lflag); -t_stat carriage_control (int32 action, int32 mod); -extern unsigned char ebcdic_to_ascii[256]; - -#define UNIT_V_PCHAIN (UNIT_V_UF + 0) -#define UNIT_M_PCHAIN 03 -#define M_UCS 00 /* Universal */ -#define M_PCF 00 /* full */ -#define M_PCA 01 /* business */ -#define M_PCH 02 /* Fortran */ -#define UNIT_PCHAIN (UNIT_M_PCHAIN << UNIT_V_PCHAIN) -#define UCS (M_UCS << UNIT_V_PCHAIN) -#define PCF (M_PCF << UNIT_V_PCHAIN) -#define PCA (M_PCA << UNIT_V_PCHAIN) -#define PCH (M_PCH << UNIT_V_PCHAIN) -#define GET_PCHAIN(x) (((x) >> UNIT_V_PCHAIN) & UNIT_M_PCHAIN) -#define CHP(ch,val) ((val) & (1 << (ch))) - -int32 LPDAR; /* Data Address */ -int32 LPFLR; /* Forms Length */ -int32 LPIAR; /* Image address */ -int32 linectr; /* current line # */ -int32 lpterror = 0; -int32 CC9 = 0; -int32 CC12 = 0; - -/* LPT data structures - - lpt_dev LPT device descriptor - lpt_unit LPT unit descriptor - lpt_reg LPT register list -*/ - -UNIT lpt_unit = { - UDATA (NULL, UNIT_SEQ+UNIT_ATTABLE, 0) }; - -REG lpt_reg[] = { - { FLDATA (ERR, lpterror, 0) }, - { HRDATA (LPDAR, LPDAR, 16) }, - { HRDATA (LPFLR, LPFLR, 8) }, - { HRDATA (LPIAR, LPIAR, 16) }, - { DRDATA (LINECT, linectr, 8) }, - { DRDATA (POS, lpt_unit.pos, T_ADDR_W), PV_LEFT }, - { BRDATA (CCT, cct, 8, 32, CCT_LNT) }, - { DRDATA (LINES, lines, 8), PV_LEFT }, - { DRDATA (CCTP, cctptr, 8), PV_LEFT }, - { DRDATA (CCTL, cctlnt, 8), REG_RO + PV_LEFT }, - { GRDATA (CHAIN, lpt_unit.flags, 10, 2, UNIT_V_PCHAIN), REG_HRO }, - { NULL } }; - -MTAB lpt_mod[] = { - { UNIT_PCHAIN, UCS, "UCS", "UCS", NULL }, - { UNIT_PCHAIN, PCA, "A chain", "PCA", NULL }, - { UNIT_PCHAIN, PCH, "H chain", "PCH", NULL }, - { 0 } }; - -DEVICE lpt_dev = { - "LPT", &lpt_unit, lpt_reg, lpt_mod, - 1, 10, 31, 1, 8, 7, - NULL, NULL, &lpt_reset, - NULL, NULL, NULL }; - - -/* -------------------------------------------------------------------- */ - -/* Printer: master routine */ - -int32 lpt (int32 op, int32 m, int32 n, int32 data) -{ - int32 iodata; - switch (op) { - case 0: /* SIO 1403 */ - iodata = 0; - printf("\0"); - switch (n) { - case 0x00: /* Spacing only */ - if (data > 0 && data < 4) - iodata = carriage_control(2, data); - break; - case 0x02: /* Print & space */ - iodata = write_line(0, 0); - if (data > 3) data = 0; - if (iodata == SCPE_OK) - iodata = carriage_control(2, data); - break; - case 0x04: /* Skip only */ - iodata = carriage_control(4, data); - break; - case 0x06: /* Print and skip */ - iodata = write_line(0, 0); - if (iodata == SCPE_OK) - iodata = carriage_control(4, data); - break; - default: - return STOP_INVDEV; - } - return iodata; - case 1: /* LIO 1403 */ - switch (n) { - case 0x00: /* LPFLR */ - LPFLR = (data >> 8) & 0xff; - break; - case 0x04: - LPIAR = data & 0xffff; - break; - case 0x06: - LPDAR = data & 0xffff; - break; - default: - return STOP_INVDEV; - } - return SCPE_OK; - case 2: /* TIO 1403 */ - iodata = 0; - switch (n) { - case 0x00: /* Not ready/check */ - if (lpterror) - iodata = 1; - if ((lpt_unit.flags & UNIT_ATT) == 0) - iodata = 1; - break; - case 0x02: /* Buffer Busy */ - iodata = 0; - break; - case 0x04: /* Carriage Busy */ - iodata = 0; - break; - case 0x06: /* Printer busy */ - iodata = 0; - break; - default: - return (STOP_INVDEV << 16); - } - return ((SCPE_OK << 16) | iodata); - case 3: /* SNS 1403 */ - switch (n) { - case 0x00: /* Line count */ - iodata = (linectr << 8); - break; - case 0x02: /* Timing data */ - iodata = 0; - break; - case 0x03: /* Check data */ - iodata = 0; - break; - case 0x04: /* LPIAR */ - iodata = LPIAR; - break; - case 0x06: /* LPDAR */ - iodata = LPDAR; - break; - default: - return (STOP_INVDEV << 16); - } - return ((SCPE_OK << 16) | iodata); - case 4: /* APL 1403 */ - iodata = 0; - return ((SCPE_OK << 16) | iodata); - default: - break; - } - printf (">>LPT non-existent function %d\n", op); - return SCPE_OK; -} - - -/* Print routine - - Modifiers have been checked by the caller - S = suppress automatic newline -*/ - -t_stat write_line (int32 ilnt, int32 mod) -{ -int32 i, t, lc; -static char lbuf[LPT_WIDTH + 1]; /* + null */ - -if ((lpt_unit.flags & UNIT_ATT) == 0) - return SCPE_UNATT; - -lpterror = 0; -lc = LPDAR; /* clear error */ -for (i = 0; i < LPT_WIDTH; i++) { /* convert print buf */ - t = M[lc]; - lbuf[i] = ebcdic_to_ascii[t & 0xff]; - M[lc] = 0x40; /* HJS MOD */ - lc++; -} -for (i = LPT_WIDTH - 1; (i >= 0) && (lbuf[i] == ' '); i--) lbuf[i] = 0; -fputs (lbuf, lpt_unit.fileref); /* write line */ -if (lines) space (lines, lflag); /* cc action? do it */ -else if (mod == 0) space (1, FALSE); /* default? 1 line */ -else { fputc ('\r', lpt_unit.fileref); /* sup -> overprint */ - lpt_unit.pos = ftell (lpt_unit.fileref); } /* update position */ -lines = lflag = 0; /* clear cc action */ -if (ferror (lpt_unit.fileref)) { /* error? */ - perror ("Line printer I/O error"); - clearerr (lpt_unit.fileref); - lpterror = 1; } -return SCPE_OK; -} - -/* Carriage control routine - - Parameters: - action = 00, skip to channel now - = 01, space lines after - = 02, space lines now - = 03, skip to channel after - = 04, skip to line number - mod = number of lines or channel number or line number -*/ - -t_stat carriage_control (int32 action, int32 mod) -{ -int32 i; - -if ((lpt_unit.flags & UNIT_ATT) == 0) - return SCPE_UNATT; - -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); } - return STOP_INVDEV; /* runaway channel */ -case 1: /* space after */ - if (mod <= 3) { - lines = mod; /* save # lines */ - lflag = FALSE; /* flag spacing */ - CC9 = CC12 = 0; } - return SCPE_OK; -case 2: /* space now */ - if (mod <= 3) return space (mod, FALSE); - return SCPE_OK; -case 3: /* to channel after */ - if ((mod == 0) || (mod > 12)) return SCPE_OK; /* check channel */ - CC9 = 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; } - return STOP_INVDEV; -case 4: /* To line # */ - if (mod < 2) { - fputs ("\n\f", lpt_unit.fileref); /* nl, ff */ - linectr = 1; - } else { - if (mod <= linectr) { - fputs ("\n\f", lpt_unit.fileref); - linectr = 1; - } - while (1) { - if (linectr == mod) - break; - space(1, 0); - } - } - return SCPE_OK; } -} -return SCPE_OK; -} - -/* Space routine - space or skip n lines - - Inputs: - count = number of lines to space or skip - sflag = skip (TRUE) or space (FALSE) -*/ - -t_stat space (int32 count, int32 sflag) -{ -int32 i; - -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 */ - linectr = 1; -} -else { for (i = 0; i < count; i++) fputc ('\n', lpt_unit.fileref); } -lpt_unit.pos = ftell (lpt_unit.fileref); /* update position */ -CC9 = CHP (9, cct[cctptr]) != 0; /* set indicators */ -CC12 = CHP (12, cct[cctptr]) != 0; -linectr += count; -if (linectr > LPFLR) - linectr -= LPFLR; -return SCPE_OK; -} - -/* Reset routine */ - -t_stat lpt_reset (DEVICE *dptr) -{ -cctptr = 0; /* clear cct ptr */ -lines = linectr = lflag = 0; /* no cc action */ -lpterror = 0; -return SCPE_OK; -} - -/* Attach routine */ - -t_stat lpt_attach (UNIT *uptr, char *cptr) -{ -cctptr = 0; /* clear cct ptr */ -lines = 0; /* no cc action */ -lpterror = 0; -linectr = 0; -return attach_unit (uptr, cptr); -} diff --git a/S3/s3_pkb.c b/S3/s3_pkb.c deleted file mode 100644 index 881bf360..00000000 --- a/S3/s3_pkb.c +++ /dev/null @@ -1,312 +0,0 @@ -/* s3_pkb.c: System/3 5471 console terminal simulator - - Copyright (c) 2001, Charles E. Owen - - 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 Charles E. Owen shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Charles E. Owen. - - pkb 5471 printer/keyboard - - 25-Apr-03 RMS Revised for extended file support - 08-Oct-02 RMS Added impossible function catcher -*/ - -#include "s3_defs.h" -#include - -extern int32 int_req, dev_busy, dev_done, dev_disable; -t_stat pkb_svc (UNIT *uptr); -t_stat pkb_reset (DEVICE *dptr); -extern t_stat sim_poll_kbd (void); -extern t_stat sim_putchar (int32 out); -extern int32 IAR[], level; -extern int32 debug_reg; - -/* 5471 data structures - - pkb_dev TTI device descriptor - pkb_unit TTI unit descriptor - pkb_reg TTI register list - pkb_mod TTI/TTO modifiers list -*/ - -/* Flag bits : (kept in pkb_unit.u3) */ - -#define PRT_INTREQ 0x800 /* Printer interrupt pending */ -#define KBD_INTREQ 0x400 /* Request key interrupt pending */ -#define KBD_INTEND 0x200 /* End or cancel key interrupt pending */ -#define KBD_INTKEY 0x100 /* Return or other key interrupt pending */ -#define KBD_REQLIGHT 0x20 /* Request Pending Indicator (light on/off) */ -#define KBD_PROLIGHT 0x10 /* Proceed indicator (light on/off) */ -#define KBD_REQINT 0x04 /* Req key interrupts enabled */ -#define KBD_KEYINT 0x02 /* Other key interrupts enabled */ -#define PRT_PRTINT 0x01 /* Printer interrupts enabled */ - -/* Keys mapped to 5471 functions */ - -int32 key_req = 0x01; /* Request key: ^A */ -int32 key_rtn = 0x12; /* Return key: ^R */ -int32 key_can = 0x1B; /* Cancel key: ESC */ -int32 key_end = 0x0d; /* End key - CR */ - -UNIT pkb_unit = { UDATA (&pkb_svc, 0, 0), KBD_POLL_WAIT }; - -REG pkb_reg[] = { - { HRDATA (FLAG, pkb_unit.u3, 16) }, - { HRDATA (IBUF, pkb_unit.buf, 8) }, - { HRDATA (OBUF, pkb_unit.u4, 8) }, - { HRDATA (REQKEY, key_req, 8) }, - { HRDATA (RTNKEY, key_rtn, 8) }, - { HRDATA (CANKEY, key_can, 8) }, - { HRDATA (ENDKEY, key_end, 8) }, - { DRDATA (POS, pkb_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, pkb_unit.wait, 24), REG_NZ + PV_LEFT }, - { NULL } }; - -MTAB pkb_mod[] = { - { 0 } }; - -DEVICE pkb_dev = { - "PKB", &pkb_unit, pkb_reg, pkb_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &pkb_reset, - NULL, NULL, NULL }; - - -/*-------------------------------------------------------------------*/ -/* EBCDIC to ASCII translate table */ -/*-------------------------------------------------------------------*/ -unsigned char ebcdic_to_ascii[] = { -"\x00\x01\x02\x03\xA6\x09\xA7\x7F\xA9\xB0\xB1\x0B\x0C\x0D\x0E\x0F" -"\x10\x11\x12\x13\xB2\xB4\x08\xB7\x18\x19\x1A\xB8\xBA\x1D\xBB\x1F" -"\xBD\xC0\x1C\xC1\xC2\x0A\x17\x1B\xC3\xC4\xC5\xC6\xC7\x05\x06\x07" -"\xC8\xC9\x16\xCB\xCC\x1E\xCD\x04\xCE\xD0\xD1\xD2\x14\x15\xD3\xFC" -"\x20\xD4\x83\x84\x85\xA0\xD5\x86\x87\xA4\xD6\x2E\x3C\x28\x2B\xD7" -"\x26\x82\x88\x89\x8A\xA1\x8C\x8B\x8D\xD8\x21\x24\x2A\x29\x3B\x5E" -"\x2D\x2F\xD9\x8E\xDB\xDC\xDD\x8F\x80\xA5\x7C\x2C\x25\x5F\x3E\x3F" -"\xDE\x90\xDF\xE0\xE2\xE3\xE4\xE5\xE6\x60\x3A\x23\x40\x27\x3D\x22" -"\xE7\x61\x62\x63\x64\x65\x66\x67\x68\x69\xAE\xAF\xE8\xE9\xEA\xEC" -"\xF0\x6A\x6B\x6C\x6D\x6E\x6F\x70\x71\x72\xF1\xF2\x91\xF3\x92\xF4" -"\xF5\x7E\x73\x74\x75\x76\x77\x78\x79\x7A\xAD\xA8\xF6\x5B\xF7\xF8" -"\x9B\x9C\x9D\x9E\x9F\xB5\xB6\xAC\xAB\xB9\xAA\xB3\xBC\x5D\xBE\xBF" -"\x7B\x41\x42\x43\x44\x45\x46\x47\x48\x49\xCA\x93\x94\x95\xA2\xCF" -"\x7D\x4A\x4B\x4C\x4D\x4E\x4F\x50\x51\x52\xDA\x96\x81\x97\xA3\x98" -"\x5C\xE1\x53\x54\x55\x56\x57\x58\x59\x5A\xFD\xEB\x99\xED\xEE\xEF" -"\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\xFE\xFB\x9A\xF9\xFA\xFF" -}; - -/*-------------------------------------------------------------------*/ -/* ASCII to EBCDIC translate table */ -/*-------------------------------------------------------------------*/ -unsigned char ascii_to_ebcdic[] = { -"\x00\x01\x02\x03\x37\x2D\x2E\x2F\x16\x05\x25\x0B\x0C\x0D\x0E\x0F" -"\x10\x11\x12\x13\x3C\x3D\x32\x26\x18\x19\x1A\x27\x22\x1D\x35\x1F" -"\x40\x5A\x7F\x7B\x5B\x6C\x50\x7D\x4D\x5D\x5C\x4E\x6B\x60\x4B\x61" -"\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\x7A\x5E\x4C\x7E\x6E\x6F" -"\x7C\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xD1\xD2\xD3\xD4\xD5\xD6" -"\xD7\xD8\xD9\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xAD\xE0\xBD\x5F\x6D" -"\x79\x81\x82\x83\x84\x85\x86\x87\x88\x89\x91\x92\x93\x94\x95\x96" -"\x97\x98\x99\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xC0\x6A\xD0\xA1\x07" -"\x68\xDC\x51\x42\x43\x44\x47\x48\x52\x53\x54\x57\x56\x58\x63\x67" -"\x71\x9C\x9E\xCB\xCC\xCD\xDB\xDD\xDF\xEC\xFC\xB0\xB1\xB2\xB3\xB4" -"\x45\x55\xCE\xDE\x49\x69\x04\x06\xAB\x08\xBA\xB8\xB7\xAA\x8A\x8B" -"\x09\x0A\x14\xBB\x15\xB5\xB6\x17\x1B\xB9\x1C\x1E\xBC\x20\xBE\xBF" -"\x21\x23\x24\x28\x29\x2A\x2B\x2C\x30\x31\xCA\x33\x34\x36\x38\xCF" -"\x39\x3A\x3B\x3E\x41\x46\x4A\x4F\x59\x62\xDA\x64\x65\x66\x70\x72" -"\x73\xE1\x74\x75\x76\x77\x78\x80\x8C\x8D\x8E\xEB\x8F\xED\xEE\xEF" -"\x90\x9A\x9B\x9D\x9F\xA0\xAC\xAE\xAF\xFD\xFE\xFB\x3F\xEA\xFA\xFF" -}; - -/* -------------------------------------------------------------------- */ - -/* Console Input: master routine */ - -int32 pkb (int32 op, int32 m, int32 n, int32 data) -{ - int32 iodata= 0, ec, ac; - switch (op) { - case 0: /* SIO 5471 */ - if (n != 0) - return STOP_INVDEV; - /*printf("%04X SIO %d,%d,%02X\n\r", IAR[level]-4, m, n, data);*/ - if (m == 0) { /* Keyboard */ - pkb_unit.u3 &= 0xFC1; - pkb_unit.u3 |= data; - if (data & 0x01) { - pkb_unit.u3 &= ~KBD_INTREQ; - pkb_unit.u3 &= ~KBD_INTKEY; - pkb_unit.u3 &= ~KBD_INTEND; - return RESET_INTERRUPT; - } - } else { /* Printer */ - if (data & 0x80) { /* start print bit */ - if (debug_reg & 0x80) - return STOP_IBKPT; - ec = pkb_unit.u4 & 0xff; - ac = ebcdic_to_ascii[ec]; - sim_putchar(ac); - pkb_unit.u3 |= PRT_INTREQ; - } - if (data & 0x40) { /* Carr. Return */ - sim_putchar('\n'); - sim_putchar('\r'); - pkb_unit.u3 |= PRT_INTREQ; - } - pkb_unit.u3 &= 0xFFe; - if (data & 0x04) /* Print interrupt flag */ - pkb_unit.u3 |= PRT_PRTINT; - if (data & 0x01) { /* Reset Interrupt */ - if (level < 8) { - if (!(data & 0x80)) - pkb_unit.u3 &= ~PRT_INTREQ; - return RESET_INTERRUPT; - } - } - } - return SCPE_OK; - case 1: /* LIO 5471 */ - if (n != 0) - return STOP_INVDEV; - if (m != 1) - return STOP_INVDEV; - pkb_unit.u4 = (data >> 8) & 0xff; - return SCPE_OK; - break; - case 2: /* TIO 5471 */ - return STOP_INVDEV; - case 3: /* SNS 5471 */ - if (n != 1 && n != 3) - return (STOP_INVDEV << 16); - if (m == 0) { /* Keyboard data */ - if (n == 1) { /* Sense bytes 0 & 1 */ - iodata = (pkb_unit.buf << 8) & 0xff00; - if (pkb_unit.u3 & KBD_INTREQ) - iodata |= 0x80; - if (pkb_unit.u3 & KBD_INTEND) - iodata |= 0x40; - if (pkb_unit.u3 & KBD_INTKEY) - iodata |= 0x08; - if (pkb_unit.buf == 0x12) /* Return key */ - iodata |= 0x04; - if (pkb_unit.buf == 0x03) /* Cancel key */ - iodata |= 0x20; - if (pkb_unit.buf == 0x0d) /* End key */ - iodata |= 0x10; - iodata |= ((SCPE_OK << 16) & 0xffff0000); - } else { /* Sense bytes 2 & 3 */ - iodata = 0; /* Manual says CE use only */ - } - } else { /* Printer Data */ - if (n == 1) { /* Sense bytes 0 & 1 */ - iodata = 0; - if (pkb_unit.u3 & PRT_INTREQ) - iodata |= 0x80; - } else { - iodata = 0; /* CE use only */ - } - } - iodata |= ((SCPE_OK << 16) & 0xffff0000); - return (iodata); - case 4: /* APL 5471 */ - return STOP_INVDEV; - default: - break; - } - printf (">>PKB non-existent function %d\n", op); - return SCPE_OK; -} - -/* Unit service */ - -t_stat pkb_svc (UNIT *uptr) -{ -int32 temp, ac, ec; - -sim_activate (&pkb_unit, pkb_unit.wait); /* continue poll */ - -if (pkb_unit.u3 & PRT_INTREQ) { /* Printer Interrupt */ - int_req |= 2; - return SCPE_OK; -} - -/* Keyboard : handle input */ - -if ((temp = sim_poll_kbd ()) < SCPE_KFLAG) return temp; /* no char or error? */ - -ac = temp & 0x7f; /* placed type ASCII char in ac */ -if (pkb_unit.u3 & KBD_REQINT) { - if (ac == key_req) { /* Request Key */ - pkb_unit.u3 |= KBD_INTREQ; - int_req |= 2; - return SCPE_OK; - } -} -if (islower(ac)) - ac = toupper(ac); -ec = ascii_to_ebcdic[ac]; /* Translate */ -pkb_unit.buf = ec; /* put in buf */ -pkb_unit.pos = pkb_unit.pos + 1; -if (ac == key_end) { /* End key */ - if (pkb_unit.u3 & KBD_KEYINT) { - pkb_unit.u3 |= KBD_INTEND; - pkb_unit.buf = 0x0d; - int_req |= 2; - } - return SCPE_OK; -} -if (ac == key_can) { /* Cancel key */ - if (pkb_unit.u3 & KBD_KEYINT) { - pkb_unit.u3 |= KBD_INTEND; - pkb_unit.buf = 0x03; - int_req |= 2; - } - return SCPE_OK; -} -if (ac == key_rtn) { /* Return key */ - if (pkb_unit.u3 & KBD_KEYINT) { - pkb_unit.u3 |= KBD_INTKEY; - pkb_unit.buf = 0x12; - int_req |= 2; - } - return SCPE_OK; -} -if (pkb_unit.u3 & KBD_KEYINT) { /* Key interupts enabled ? */ - int_req |= 2; /* Device 1 Interrupt! */ - pkb_unit.u3 |= KBD_INTKEY; /* Set pending flag */ -} -return SCPE_OK; -} - -/* Reset routine */ - -t_stat pkb_reset (DEVICE *dptr) -{ -pkb_unit.buf = 0; -int_req = int_req & ~0x02; /* reset interrupt */ -sim_activate (&pkb_unit, pkb_unit.wait); /* activate unit */ -return SCPE_OK; -} - -t_stat pkb_setmod (UNIT *uptr, int32 value) -{ -return SCPE_OK; -} - diff --git a/S3/s3_sys.c b/S3/s3_sys.c deleted file mode 100644 index c18e1506..00000000 --- a/S3/s3_sys.c +++ /dev/null @@ -1,942 +0,0 @@ -/* s3_sys.c: IBM System/3 system interface - - Copyright (c) 2001-2003, Charles E. Owen - - 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 Charles E. Owen shall not - be used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Charles E. Owen. -*/ - -#include -#include "s3_defs.h" - -extern DEVICE cpu_dev; -extern DEVICE pkb_dev; -extern DEVICE cdr_dev; -extern DEVICE cdp_dev; -extern DEVICE stack_dev; -extern DEVICE lpt_dev; -extern DEVICE r1_dev; -extern DEVICE f1_dev; -extern DEVICE r2_dev; -extern DEVICE f2_dev; -extern UNIT cpu_unit; -extern REG cpu_reg[]; -extern unsigned char M[]; -extern int32 saved_PC, IAR[]; -extern char ebcdic_to_ascii[256]; -char *parse_addr(char *cptr, char *gbuf, int32 *addr, int32 *addrtype); - -int32 printf_sym (FILE *of, char *strg, int32 addr, unsigned int32 *val, - UNIT *uptr, int32 sw); - -/* SCP data structures - - sim_name simulator name string - sim_PC pointer to saved PC register descriptor - sim_emax number of words needed 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[] = "System/3"; - -REG *sim_PC = &cpu_reg[0]; - -int32 sim_emax = 6; - -DEVICE *sim_devices[] = { &cpu_dev, - &pkb_dev, - &cdr_dev, - &cdp_dev, - &stack_dev, - &lpt_dev, - &r1_dev, - &f1_dev, - &r2_dev, - &f2_dev, - NULL }; - -const char *sim_stop_messages[] = { - "Unknown error", - "Unknown I/O Instruction", - "HALT instruction", - "Breakpoint", - "Invalid Opcode", - "Invalid Qbyte", - "Invalid Address", - "Invalid Device Command", - "ATTN Card Reader" -}; - -/* This is the opcode master defintion table. Each possible opcode mnemonic - is defined here, with enough information to translate to and from - symbolic to binary machine code. - First field is the opcode's mnemonic - Second field is the hex of the right nybble of the binary opcode - Third field is the Q code for those with implicit Q codes - Fourth field is the symbolic format of the operands: - 0 - (Q-byte),(R-byte) - 1 - (Q-byte),(Address) - 2 - (Address),(Address),(Qbyte) - 3 - (Address),(Qbyte) - 4 - (device),(modifier),(function) -- these 3 make up qbyte - 5 - (device),(modifier),(function),(control) - 6 - (device),(modifier),(function),(Address) - 7 - (displacement) -- Q byte is implicit in opcode - 8 - (address) -- Qbyte is implicit in opcode - 9 - (Address),(Address) -- Qbyte is implicit in opcode - Fifth Field is the group number: - 0 - Command Group (left op nybble is F) - 1 - One Address Operations A (Left Nybble C, D, or E) - 2 - Two Address Operations (Left Nybble 0,1,2,4,5,6,8,9, or A) - 3 - One Address Operations B (left Nybble 3, 7, or B) - - There is duplication in this table -- IBM defines different opcodes - that resolve to the same binary machine instruction -- e.g. JE and - JZ. On input this is no problem, on output, define the one you - want to appear first, the second will never appear on output. -*/ - -int32 nopcode = 75; -struct opdef opcode[75] = { - "HPL", 0x00,0,0,0, /* Halt Program Level */ - "A", 0x06,0,1,3, /* Add to Register: A R,AADD */ - "ST", 0x04,0,1,3, /* Store Register */ - "L", 0x05,0,1,3, /* Load Register */ - "LA", 0x02,0,1,1, /* Load Address */ - "ZAZ", 0x04,0,2,2, /* Zero and Add Zoned */ - "AZ", 0x06,0,2,2, /* Add Zoned Decimal */ - "SZ", 0x07,0,2,2, /* Subtract Zoned Decimal */ - "ALC", 0x0E,0,2,2, /* Add Logical: ALC BADD,AADD,LEN */ - "SLC", 0x0F,0,2,2, /* Sub Logical: SLC BADD,AADD,LEN */ - "MVC", 0x0C,0,2,2, /* Move Chars MVX BADD,AADD,LEN */ - "ED", 0x0A,0,2,2, /* Edit: ED BADD,AADD,LEN */ - "ITC", 0x0B,0,2,2, /* Insert Chars: ITC BADD,AADD,LEN */ - "CLC", 0x0D,0,2,2, /* Compare Logical: CLC BADD,AADD,LEN */ - "MVI", 0x0C,0,3,3, /* Move Immediate */ - "SBN", 0x0A,0,3,3, /* Set Bits On */ - "SBF", 0x0B,0,3,3, /* Set Bits Off */ - "CLI", 0x0D,0,3,3, /* Compare Immediate */ - "TBN", 0x08,0,3,3, /* Test Bits On */ - "TBF", 0x09,0,3,3, /* Test Bits Off */ - "APL", 0x01,0,4,0, /* Advance Program Level */ - "SIO", 0x03,0,5,0, /* Start I/O */ - "SNS", 0x00,0,6,3, /* Sense I/O */ - "LIO", 0x01,0,6,3, /* Load I/O */ - "TIO", 0x01,0,6,1, /* Test I/O */ - "J", 0x02,0,7,0, /* Jump Unconditional */ - "J", 0x02,0x87,7,0, /* Alternate J */ - "JH", 0x02,132,7,0, /* Jump if High */ - "JL", 0x02,130,7,0, /* Jump if Low */ - "JE", 0x02,129,7,0, /* Jump if Equal */ - "JNH", 0x02,4,7,0, /* Jump if Not High */ - "JNL", 0x02,2,7,0, /* Jump if Not Low */ - "JNE", 0x02,1,7,0, /* Jump if Not Equal */ - "JOZ", 0x02,136,7,0, /* Jump if Overflow Zoned */ - "JOL", 0x02,160,7,0, /* Jump if Overflow Logical */ - "JNOZ", 0x02,8,7,0, /* Jump if No Overflow Zoned */ - "JNOL", 0x02,32,7,0, /* Jump if No Overflow Logical */ - "JT", 0x02,16,7,0, /* Jump if True */ - "JF", 0x02,144,7,0, /* Jump if False */ - "JP", 0x02,132,7,0, /* Jump if Plus */ - "JM", 0x02,130,7,0, /* Jump if Minus */ - "JZ", 0x02,129,7,0, /* Jump if Zero */ - "JNP", 0x02,4,7,0, /* Jump if Not Plus */ - "JNM", 0x02,2,7,0, /* Jump if Not Minus */ - "JNZ", 0x02,1,7,0, /* Jump if Not Zero */ - "NOPJ", 0x02,0x80,7,0, /* Never Jump - NOP */ - "B", 0x00,0x00,8,1, /* Branch Unconditional */ - "B", 0x00,0x87,8,1, /* Alternate B */ - "BH", 0x00,0x84,8,1, /* Branch if High */ - "BL", 0x00,0x82,8,1, /* Branch if Low */ - "BE", 0x00,0x81,8,1, /* Branch if Equal */ - "BNH", 0x00,0x04,8,1, /* Branch if Not High */ - "BNL", 0x00,0x02,8,1, /* Branch if Not Low */ - "BNE", 0x00,0x01,8,1, /* Branch if Not Equal */ - "BOZ", 0x00,0x88,8,1, /* Branch if Overflow Zoned */ - "BOL", 0x00,0xA0,8,1, /* Branch if Overflow Logical */ - "BNOZ", 0x00,0x08,8,1, /* Branch if No Overflow Zoned */ - "BNOL", 0x00,0x20,8,1, /* Branch if No Overflow Logical */ - "BT", 0x00,0x10,8,1, /* Branch if True */ - "BF", 0x00,0x90,8,1, /* Branch if False */ - "BP", 0x00,0x84,8,1, /* Branch if Plus */ - "BM", 0x00,0x82,8,1, /* Branch if Minus */ - "BZ", 0x00,0x81,8,1, /* Branch if Zero */ - "BNP", 0x00,0x04,8,1, /* Branch if Not Plus */ - "BNM", 0x00,0x02,8,1, /* Branch if Not Minus */ - "BNZ", 0x00,0x01,8,1, /* Branch if Not Zero */ - "NOPB", 0x00,0x80,8,1, /* Never Branch - NOP */ - "MZZ", 0x08,0,9,2, /* Move Zone to Zone */ - "MNZ", 0x08,1,9,2, /* Move Numeric to Zone */ - "MZN", 0x08,2,9,2, /* Move Zone to Numeric */ - "MNN", 0x08,3,9,2, /* Move Numeric to Numeric */ - "MVX", 0x08,0,2,2, /* Move Hex: MVX BADD,AADD,CODE */ - "JC", 0x02,0,3,0, /* Jump on Specified Condition bits */ - "BC", 0x00,0,3,1, /* Branch on Specified Condition */ - "***", 0x00,0,0,0 -}; - -int32 regcode[15] = { 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, - 0x80, 0xC0, 0xA0, 0x90, 0x88, 0x84, 0x82, 0x81 }; - -char regname[15][8] = { "(P2IAR)", - "(P1IAR)", - "(IAR)", - "(ARR)", - "(PSR)", - "(XR2)", - "(XR1)", - "(IAR0)", - "(IAR1)", - "(IAR2)", - "(IAR3)", - "(IAR4)", - "(IAR5)", - "(IAR6)", - "(IAR7)" }; - -/* This is the binary loader. The input file is considered to be - a string of literal bytes with no special format. The - load starts at the current value of the P1IAR. -*/ - -int32 sim_load (FILE *fileref, char *cptr, char *fnam, int flag) -{ -int32 i, addr = 0, cnt = 0; - -if ((*cptr != 0) || (flag != 0)) return SCPE_ARG; -addr = IAR[8]; -while ((i = getc (fileref)) != EOF) { - M[addr] = i & 0xff; - addr++; - cnt++; - } /* end while */ -printf ("%d Bytes loaded.\n", cnt); -return (SCPE_OK); -} - -/* Symbolic output - - Inputs: - *of = output stream - addr = current PC - *val = pointer to values - *uptr = pointer to unit - sw = switches - Outputs: - status = error code -*/ - -int32 fprint_sym (FILE *of, int32 addr, unsigned int32 *val, - UNIT *uptr, int32 sw) -{ - int32 r; - char strg[256]; - - strcpy(strg, ""); - r = printf_sym(of, strg, addr, val, uptr, sw); - if (sw & SWMASK ('A')) - strcpy(strg, ""); - else - fprintf(of, "%s", strg); - return (r); -} - -int32 printf_sym (FILE *of, char *strg, int32 addr, unsigned int32 *val, - UNIT *uptr, int32 sw) -{ -int32 cflag, c1, c2, group, len1, len2, inst, aaddr, baddr; -int32 oplen, groupno, i, j, vpos, qbyte, da, m, n; -char bld[128], bldaddr[32], boperand[32], aoperand[32]; -int32 blk[16], blt[16]; -int32 blkadd; - -cflag = (uptr == NULL) || (uptr == &cpu_unit); -c1 = val[0] & 0xff; -if (sw & SWMASK ('A')) { - for (i = 0; i < 16; i++) { - blkadd = addr + (i*16); - for (j = 0; j < 16; j++) { - blk[j] = M[blkadd+j] & 0xff; - c2 = ebcdic_to_ascii[blk[j]]; - if (c2 < 040 || c2 > 0177 || blk[j] == 07) { - blt[j] = '.'; - } else { - blt[j] = c2; - } - } - if (i == 0) { - fprintf(of, "%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X [%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c]\n ", - blk[0], blk[1], blk[2], blk[3], blk[4], blk[5], blk[6], blk[7], - blk[8], blk[9], blk[10], blk[11], blk[12], blk[13], blk[14], blk[15], - blt[0], blt[1], blt[2], blt[3], blt[4], blt[5], blt[6], blt[7], - blt[8], blt[9], blt[10], blt[11], blt[12], blt[13], blt[14], blt[15]); - } else { - fprintf(of, "%X\t%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X [%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c]\n ", - blkadd, blk[0], blk[1], blk[2], blk[3], blk[4], blk[5], blk[6], blk[7], - blk[8], blk[9], blk[10], blk[11], blk[12], blk[13], blk[14], blk[15], - blt[0], blt[1], blt[2], blt[3], blt[4], blt[5], blt[6], blt[7], - blt[8], blt[9], blt[10], blt[11], blt[12], blt[13], blt[14], blt[15]); - } - } - return SCPE_OK; } -if (sw & SWMASK ('C')) { - c2 = ebcdic_to_ascii[c1]; - if (c2 < 040 || c2 > 0177) { - sprintf(strg, "<%02X>", c1 & 0xff); - } else { - sprintf (strg, "%c", c2 & 0xff); - } - return SCPE_OK; } -if (!(sw & SWMASK ('M'))) return SCPE_ARG; - -inst = val[0] & 0x0f; -len1 = (val[0] >> 6) & 3; -len2 = (val[0] >> 4) & 3; -group = (val[0] >> 4) & 0x0f; -qbyte = val[1]; - -/* Get total length of instruction */ - -if (group == 0x0f) { - oplen = 3; -} else { - oplen = 2; - if (len1 == 0) oplen += 2; - if (len1 == 1 || len1 == 2) oplen++; - if (len2 == 0) oplen += 2; - if (len2 == 1 || len2 == 2) oplen++; -} - -/* Find which group it belongs to */ - -switch (group) { - case 0x0f: - groupno = 0; - break; - case 0x0c: - case 0x0d: - case 0x0e: - groupno = 1; - break; - case 0x03: - case 0x07: - case 0x0b: - groupno = 3; - break; - default: - groupno = 2; - break; -} - -/* find the table entry */ - -for (i = 0; i < nopcode; i++) { - if (opcode[i].form < 7) { /* Explicit Q */ - if (opcode[i].group == groupno && - opcode[i].opmask == inst) break; - } else { /* Implicit Q */ - if (opcode[i].group == groupno && - opcode[i].opmask == inst && - opcode[i].q == qbyte) break; - } -} - -/* print the opcode */ - -if (i >= nopcode) { - sprintf(strg, "%02X", val[0]); - oplen = 1; -} else { - sprintf(bld, "%s ", opcode[i].op); - - /* Extract the addresses into aaddr and baddr */ - - strcpy(aoperand, "ERROR"); - strcpy(boperand, "ERROR"); - vpos = 2; - aaddr = baddr = 0; - switch (len1) { - case 0: - baddr = ((val[vpos] << 8) & 0xff00) | (val[vpos + 1] & 0x00ff); - sprintf(boperand, "%04X", baddr); - vpos = 4; - break; - case 1: - baddr = val[vpos] & 255; - sprintf(boperand, "(%02X,XR1)", baddr); - vpos = 3; - break; - case 2: - baddr = val[vpos] & 255; - sprintf(boperand, "(%02X,XR2)", baddr); - vpos = 3; - break; - default: - baddr = 0; - break; - } - switch (len2) { - case 0: - aaddr = ((val[vpos] << 8) & 0xff00) | (val[vpos + 1] & 0x00ff); - if (group == 0x0C || group == 0x0D || group == 0x0E) - sprintf(boperand, "%04X", aaddr); - else - sprintf(aoperand, "%04X", aaddr); - break; - case 1: - aaddr = val[vpos] & 255; - if (group == 0x0C || group == 0x0D || group == 0x0E) - sprintf(boperand, "(%02X,XR1)", aaddr); - else - sprintf(aoperand, "(%02X,XR1)", aaddr); - break; - case 2: - aaddr = val[vpos] & 255; - if (group == 0x0C || group == 0x0D || group == 0x0E) - sprintf(boperand, "(%02X,XR2)", aaddr); - else - sprintf(aoperand, "(%02X,XR2)", aaddr); - break; - default: - aaddr = 0; - break; - } - - /* Display the operands in the correct format */ - - da = (qbyte >> 4) & 0x0f; - m = (qbyte >> 3) & 0x01; - n = (qbyte) & 0x07; - - switch (opcode[i].form) { - case 0: - sprintf(bldaddr, "%02X,%02X", qbyte, val[2]); - break; - case 1: - if (inst == 2 || inst == 4 || inst == 5 || inst == 6) { - for (i = 0; i < 16; i++) { - if (regcode[i] == qbyte) - break; - } - if (i < 16) { - sprintf(bldaddr, "%s,%s", regname[i], boperand); - } else { - sprintf(bldaddr, "%02X,%s", qbyte, boperand); - } - } else { - sprintf(bldaddr, "%02X,%s", qbyte, boperand); - } - break; - case 2: - if (inst > 9 || inst == 4 || inst == 6 || inst == 7) - qbyte++; /* special +1 for length display */ - sprintf(bldaddr, "%s,%s,%d", boperand, aoperand, qbyte); - break; - case 3: - if (strcmp(opcode[i].op, "JC") == 0) { - sprintf(bldaddr, "%04X,%02X", addr+oplen+val[2], qbyte); - } else { - sprintf(bldaddr, "%s,%02X", boperand, qbyte); - } - break; - case 4: - sprintf(bldaddr, "%d,%d,%d", da, m, n); - break; - case 5: - sprintf(bldaddr, "%d,%d,%d,%02X", da, m, n, val[2]); - break; - case 6: - sprintf(bldaddr, "%d,%d,%d,%s", da, m, n, boperand); - break; - case 7: - sprintf(bldaddr, "%04X", addr+oplen+val[2]); - break; - case 8: - sprintf(bldaddr, "%s", boperand); - break; - default: - sprintf(bldaddr, "%s,%s", boperand, aoperand); - break; - } - sprintf(strg, "%s%s", bld, bldaddr); -} - -return -(oplen - 1); -} - -/* 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 -*/ - -int32 parse_sym (char *cptr, int32 addr, UNIT *uptr, unsigned int32 *val, int32 sw) -{ -int32 cflag, i = 0, j, r, oplen, addtyp, saveaddr, vptr; -char gbuf[CBUFSIZE]; - -cflag = (uptr == NULL) || (uptr == &cpu_unit); -while (isspace (*cptr)) cptr++; /* absorb spaces */ -if ((sw & SWMASK ('A')) || ((*cptr == '\'') && cptr++)) { /* ASCII char? */ - if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */ - val[0] = (unsigned int) cptr[0]; - return SCPE_OK; } -if ((sw & SWMASK ('C')) || ((*cptr == '"') && cptr++)) { /* ASCII string? */ - if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */ - val[0] = ((unsigned int) cptr[0] << 8) + (unsigned int) cptr[1]; - return SCPE_OK; } - -/* An instruction: get opcode (all characters until null, comma, left paren, - or numeric (including spaces). -*/ - -while (1) { - if (*cptr == ',' || *cptr == '\0' || *cptr == '(' || - isdigit(*cptr)) - break; - gbuf[i] = toupper(*cptr); - cptr++; - i++; -} - -/* kill trailing spaces if any */ -gbuf[i] = '\0'; -for (j = i - 1; gbuf[j] == ' '; j--) { - gbuf[j] = '\0'; -} - -/* find opcode in table */ -for (j = 0; j < nopcode; j++) { - if (strcmp(gbuf, opcode[j].op) == 0) - break; -} -if (j >= nopcode) /* not found */ - return SCPE_ARG; - -oplen = 2; /* start with op & q */ - -val[0] = opcode[j].opmask; /* store opcode right nybble */ - -switch (opcode[j].form) { /* Get operands based on operand format */ - case 0: /* Single Byte Operand */ - if (*cptr == ',') cptr++; - cptr = get_glyph(cptr, gbuf, ','); /* Get Q Byte */ - sscanf(gbuf, "%x", &r); - val[1] = r; - if (*cptr == ',') cptr++; - cptr = get_glyph(cptr, gbuf, 0); /* Get R Byte */ - sscanf(gbuf, "%x", &r); - val[2] = r; - oplen = 3; - val[0] = 0xf0 | opcode[j].opmask; - break; - case 1: - if (*cptr == ',') cptr++; - cptr = get_glyph(cptr, gbuf, ','); - if (opcode[j].opmask == 2 || - opcode[j].opmask == 4 || - opcode[j].opmask == 5 || - opcode[j].opmask == 6) { - if (isdigit(gbuf[0])) { - sscanf(gbuf, "%x", &r); - } else { - for (i = 0; i < 16; i++) { - if (strcmp(gbuf, regname[i]) == 0) - break; - } - if (i < 16) { - r = regcode[i]; - } else { - return SCPE_ARG; - } - } - } else { - sscanf(gbuf, "%x", &r); - } - if (r > 255) return SCPE_ARG; - val[1] = r; - if (*cptr == ',') cptr++; - cptr = parse_addr(cptr, gbuf, &addr, &addtyp); - switch(addtyp) { - case 0: - val[2] = (addr >> 8) & 0x00ff; - val[3] = addr & 0xff; - oplen = 4; - if (opcode[j].group == 1) - val[0] = 0xC0 | opcode[j].opmask; - else - val[0] = 0x30 | opcode[j].opmask; - break; - case 1: - val[2] = addr & 0xff; - oplen = 3; - if (opcode[j].group == 1) - val[0] = 0xD0 | opcode[j].opmask; - else - val[0] = 0x70 | opcode[j].opmask; - break; - case 2: - val[2] = addr & 0xff; - oplen = 3; - if (opcode[j].group == 1) - val[0] = 0xE0 | opcode[j].opmask; - else - val[0] = 0xB0 | opcode[j].opmask; - break; - default: - return SCPE_ARG; - break; - } - break; - case 2: - oplen = 2; - cptr = parse_addr(cptr, gbuf, &addr, &addtyp); - switch(addtyp) { - case 0: - val[2] = (addr >> 8) & 0xff; - val[3] = addr & 0xff; - oplen += 2; - vptr = 4; - val[0] = 0x00 | opcode[j].opmask; - break; - case 1: - val[2] = addr & 0xff; - oplen += 1; - vptr = 3; - val[0] = 0x40 | opcode[j].opmask; - break; - case 2: - val[2] = addr & 0xff; - oplen += 1; - vptr = 3; - val[0] = 0x80 | opcode[j].opmask; - break; - default: - return SCPE_ARG; - break; - } - if (*cptr == ',') cptr++; - cptr = parse_addr(cptr, gbuf, &addr, &addtyp); - switch(addtyp) { - case 0: - val[vptr] = (addr >> 8) & 0xff; - val[vptr+1] = addr & 0xff; - oplen += 2; - break; - case 1: - val[vptr] = addr & 0xff; - oplen += 1; - val[0] = 0x10 | val[0]; - break; - case 2: - val[vptr] = addr & 0xff; - oplen += 1; - val[0] = 0x20 | val[0]; - break; - default: - return SCPE_ARG; - break; - } - if (*cptr == ',') cptr++; - cptr = get_glyph(cptr, gbuf, 0); - sscanf(gbuf, "%d", &r); - if (opcode[j].opmask > 9 || - opcode[j].opmask == 4 || - opcode[j].opmask == 6 || - opcode[j].opmask == 7) r--; /* special: length -1 */ - val[1] = r; - if (*cptr == ',') cptr++; - break; - case 3: - saveaddr = addr; - if (*cptr == ',') cptr++; - cptr = parse_addr(cptr, gbuf, &addr, &addtyp); - switch(addtyp) { - case 0: - if (opcode[j].group == 0) { /* Group 0 form 3 is JC with explicit Q */ - if (*cptr == ',') cptr++; - cptr = get_glyph(cptr, gbuf, 0); - sscanf(gbuf, "%x", &r); - if ((addr - (saveaddr+3)) > 255 || (addr - (saveaddr+3)) < 1) - return SCPE_ARG; - val[2] = addr - (saveaddr+3); - val[1] = r; - val[0] = 0xf0 | opcode[j].opmask; - oplen = 3; - - } else { - val[2] = (addr >> 8) & 0x00ff; - val[3] = addr & 0xff; - oplen = 4; - if (opcode[j].group == 1) - val[0] = 0xC0 | opcode[j].opmask; - else - val[0] = 0x30 | opcode[j].opmask; - } - break; - case 1: - val[2] = addr & 0xff; - oplen = 3; - if (opcode[j].group == 1) - val[0] = 0xD0 | opcode[j].opmask; - else - val[0] = 0x70 | opcode[j].opmask; - break; - case 2: - val[2] = addr & 0xff; - oplen = 3; - if (opcode[j].group == 1) - val[0] = 0xE0 | opcode[j].opmask; - else - val[0] = 0xB0 | opcode[j].opmask; - break; - default: - return SCPE_ARG; - break; - } - if (*cptr == ',') cptr++; - cptr = get_glyph(cptr, gbuf, 0); - sscanf(gbuf, "%x", &r); - if (r > 255) return SCPE_ARG; - val[1] = r; - break; - case 4: - if (*cptr == ',') cptr++; - cptr = get_glyph(cptr, gbuf, ','); - sscanf(gbuf, "%d", &r); - if (r > 15) return SCPE_ARG; - val[1] = (r << 4) & 0xf0; - val[0] = 0xf0 | opcode[j].opmask; - if (*cptr == ',') cptr++; - cptr = get_glyph(cptr, gbuf, ','); - sscanf(gbuf, "%d", &r); - if (r > 1) return SCPE_ARG; - val[1] |= (r << 3) & 0x08; - if (*cptr == ',') cptr++; - cptr = get_glyph(cptr, gbuf, 0); - sscanf(gbuf, "%d", &r); - if (r > 7) return SCPE_ARG; - val[1] |= r & 0x07; - val[2] = 0; - oplen = 3; - break; - case 5: - if (*cptr == ',') cptr++; - cptr = get_glyph(cptr, gbuf, ','); - sscanf(gbuf, "%d", &r); - if (r > 15) return SCPE_ARG; - val[1] = (r << 4) & 0xf0; - val[0] = 0xf0 | opcode[j].opmask; - if (*cptr == ',') cptr++; - cptr = get_glyph(cptr, gbuf, ','); - sscanf(gbuf, "%d", &r); - if (r > 1) return SCPE_ARG; - val[1] |= (r << 3) & 0x08; - if (*cptr == ',') cptr++; - cptr = get_glyph(cptr, gbuf, ','); - sscanf(gbuf, "%d", &r); - if (r > 7) return SCPE_ARG; - val[1] |= r & 0x07; - if (*cptr == ',') cptr++; - cptr = get_glyph(cptr, gbuf, 0); - sscanf(gbuf, "%x", &r); - if (r > 255) return SCPE_ARG; - val[2] = r; - oplen = 3; - break; - case 6: - if (*cptr == ',') cptr++; - cptr = get_glyph(cptr, gbuf, ','); - sscanf(gbuf, "%d", &r); - if (r > 15) return SCPE_ARG; - val[1] = (r << 4) & 0xf0; - if (*cptr == ',') cptr++; - cptr = get_glyph(cptr, gbuf, ','); - sscanf(gbuf, "%d", &r); - if (r > 1) return SCPE_ARG; - val[1] |= (r << 3) & 0x08; - if (*cptr == ',') cptr++; - cptr = get_glyph(cptr, gbuf, ','); - sscanf(gbuf, "%d", &r); - if (r > 7) return SCPE_ARG; - val[1] |= r & 0x07; - if (*cptr == ',') cptr++; - cptr = parse_addr(cptr, gbuf, &addr, &addtyp); - switch(addtyp) { - case 0: - val[2] = (addr >> 8) & 0x00ff; - val[3] = addr & 0xff; - oplen = 4; - if (opcode[j].group == 1) - val[0] = 0xC0 | opcode[j].opmask; - else - val[0] = 0x30 | opcode[j].opmask; - break; - case 1: - val[2] = addr & 0xff; - oplen = 3; - if (opcode[j].group == 1) - val[0] = 0xD0 | opcode[j].opmask; - else - val[0] = 0x70 | opcode[j].opmask; - break; - case 2: - val[2] = addr & 0xff; - oplen = 3; - if (opcode[j].group == 1) - val[0] = 0xE0 | opcode[j].opmask; - else - val[0] = 0xB0 | opcode[j].opmask; - break; - default: - return SCPE_ARG; - break; - } - break; - case 7: - if (*cptr == ',') cptr++; - cptr = get_glyph(cptr, gbuf, 0); - sscanf(gbuf, "%x", &r); - if ((r - (addr+3)) > 255 || (r - (addr+3)) < 1) return SCPE_ARG; - val[2] = r - (addr+3); - val[1] = opcode[j].q; - val[0] = 0xf0 | opcode[j].opmask; - oplen = 3; - break; - - case 8: - if (*cptr == ',') cptr++; - cptr = parse_addr(cptr, gbuf, &addr, &addtyp); - switch(addtyp) { - case 0: - val[2] = (addr >> 8) & 0x00ff; - val[3] = addr & 0xff; - oplen = 4; - val[0] = 0xC0 | opcode[j].opmask; - break; - case 1: - val[2] = addr & 0xff; - oplen = 3; - val[0] = 0xD0 | opcode[j].opmask; - break; - case 2: - val[2] = addr & 0xff; - oplen = 3; - val[0] = 0xE0 | opcode[j].opmask; - break; - default: - return SCPE_ARG; - break; - } - val[1] = opcode[j].q; - break; - case 9: - oplen = 2; - val[0] = 0; - cptr = parse_addr(cptr, gbuf, &addr, &addtyp); - switch(addtyp) { - case 0: - val[2] = (addr >> 8) & 0xff; - val[3] = addr & 0xff; - oplen += 2; - vptr = 4; - val[0] = 0x00 | opcode[j].opmask; - break; - case 1: - val[2] = addr & 0xff; - oplen += 1; - vptr = 3; - val[0] = 0x40 | opcode[j].opmask; - break; - case 2: - val[2] = addr & 0xff; - oplen += 1; - vptr = 3; - val[0] = 0x80 | opcode[j].opmask; - break; - default: - return SCPE_ARG; - break; - } - if (*cptr == ',') cptr++; - cptr = parse_addr(cptr, gbuf, &addr, &addtyp); - switch(addtyp) { - case 0: - val[vptr] = (addr >> 8) & 0xff; - val[vptr+1] = addr & 0xff; - oplen += 2; - break; - case 1: - val[vptr] = addr & 0xff; - oplen += 1; - val[0] = 0x10 | val[0]; - break; - case 2: - val[vptr] = addr & 0xff; - oplen += 1; - val[0] = 0x20 | val[0]; - break; - default: - return SCPE_ARG; - break; - } - val[1] = opcode[j].q; - break; - default: - break; -} - - -return (-(oplen-1)); -} - -char *parse_addr(char *cptr, char *gbuf, int32 *addr, int32 *addrtype) -{ -int32 nybble = 0; -char temp[32]; - -cptr = get_glyph(cptr, gbuf, ','); -if (gbuf[0] == '(') { /* XR relative */ - strcpy(temp, gbuf+1); - sscanf(temp, "%x", addr); - if (*cptr == ',') cptr++; - cptr = get_glyph(cptr, gbuf, ','); - nybble = -1; - if (strcmp(gbuf, "XR1)") == 0) - nybble = 1; - if (strcmp(gbuf, "XR2)") == 0) - nybble = 2; -} else { /* Direct */ - sscanf(gbuf, "%x", addr); - nybble = 0; -} -*addrtype = nybble; -return cptr; -} - diff --git a/S3/system3.txt b/S3/system3.txt deleted file mode 100644 index e01a97df..00000000 --- a/S3/system3.txt +++ /dev/null @@ -1,472 +0,0 @@ - The IBM System/3 simulator is configured as follows: - - CPU 5410 (Model 10) CPU with 64KB of memory. - PKB 5471 Printer/Keyboard console. - CDR 1442 Card Reader - CDP 1442 Card Punch - CDP2 1442 2nd stacker - LPT 1403 Line Printer - R1 5444 Top Drive (removeable) - F1 5444 Top Drive (fixed) - R2 5444 Bottom Drive (removeable) - F2 5444 Bottom Drive (fixed - - The only CPU options are to set Model 15 mode (not implemented), DPF -(Dual Programming Facility, not implemented), and the memory size 8K, 16K, -32K, 48K, or 64K. - - CPU registers are the standard System/3 set: - - name size Description - - IAR-P1 16 Instruction Address Register for Program Level 1 - ARR-P2 16 Address Recall Register for Program Level 1 - IAR-P2 16 IAR for Program Level 2 (not implemented) - ARR-P2 16 ARR for Program Level 2 (not implemented) - AAR 16 A-Address Register - BAR 16 B-Address Register - PSR 16 Program Status Register - XR1 16 Index Register 1 - XR2 16 Index Register 2 - IAR<0:7> 16 IAR for interrupt level 0 thru 7 - ARR<0:7> 16 ARR for interrupt level 0 thru 7 - - Plus these simulator registers: - - IAR 16 Value of last IAR used. - LEVEL 8 Current operating level (8=P1, 9=P2, - 0 thru 7 = Interrupt level) - SR 16 Front Panel switches - INT 16 Interrupt Request Flags - WRU 8 Simulator Interrupt Character - BREAK 17 Breakpoint Address - DEBUG 16 Debugging bits: - 0x01: Write all instructions executed to - file trace.log. - 0x02: Write details of all Disk I/O - requests to trace.log. - 0x80: Breakpoint on first character - written to 5471 printer. - -1 5471 Printer/Keyboard - - This is the operator console. It has the following registers: - - FLAG 5471 Flag Bytes - IBUF: Input character from keyboard - OBUF: Output character to printer - POS: Number of characters printed - TIME: Delay for device operation - REQKEY: ASCII value of key mapped to 5471 REQUEST key - RTNKEY: ASCII value of key mapped to 5471 RETURN key - ENDKEY: ASCII value of key mapped to 5471 END key - CANKEY: ASCII value of key mapped to 5471 CANCEL key - - -2 1442 Card Reader. This reader reads 80-column cards; the input - is usually an ASCII file which is translated to EBCDIC when read, - but optionally can be a binary file in EBCDIC format (such as an - object program). - - LAST Last card switch - ERR Card Reader Error - NOTRDY 1442 reader not ready (not attached or past EOF) - DAR Data Address Register (shared with punch) - LCR Length Count Register (shared with punch) - EBCDIC EBCDIC mode flag: if 1, input is 80-col EBCDIC binary. - (IPL from 1442 automatically sets this to 1). - S2 Stacker 2 is selected when this is 1 - POS Number of cards read - TIME Device Delay - - The real hardware 1442 had only 1 hopper for cards, whether - these were used for blank cards for punching, or cards to be - read. Cards could be read without a feed cycle, then - punched. When punching cards, the SCP does a read of a card, - makes sure it is blank, and then punches it. To simulate - this without requiring that a stack of blank lines be attached - to the card reader device, a special feature of the simulator - is this: if no file is attached to the cdr device, but a file - is attached to the cdp or the cdp2 devices, any read from the - reader will return a blank card -- i.e. when punching, an - unattached cdr device is assumed to be loaded with an unlimited - supply of blank cards. - - -3 1442 Card Punch. Normally cards are written to the attached - disk file as ASCII with newline/cr delimiters. But an optional - flag allows writing as 80-column binary EBCDIC. - - ERR Card Punch Error - EBCDIC When this is 1, output will be 80-col EBCDIC. - S2 When this is 1, output is placed in stacker 2 - NOTRDY 1442 punch not ready (not attached) - DAR Data Address Register (shared with reader) - LCR Length Count Register (shared with reader) - POS Number of cards punched - TIME Device Delay - -4 1442 Stacker 2. When cards are to be punched in stacker 2, - attach a disk file to this device (cdp2) to hold that output. - Note: When SCP punches cards, the default is to punch in - stacker 2. - - POS0 Number of cards punched. - -5 1403 Printer. This is a 132-column output device, emulating - the famous IBM 1403, models 2, 6, and N1. Output is always - translated to ASCII with newline/CR delimiters. Page advance - is output as a form feed. - - ERR 1403 error flags - LPDAR Data Address Register - LPFLR Forms Length Register - LPIAR Image Address Register - LINECT Current Line on form - POS Number of lines printed - -6 5444 Disk Drives (R1, R2, F1, F2) - - The 5444 came as a set of two drives, each with two disks. The - top disk in a drive was removable, the bottom fixed. The first - drive consists of disks R1 and F1, the second drive R2 and F2. - Each disk holds 2,467,600 bytes of user data, plus 3 alternate - tracks and a CE track. Flagging of alternate tracks is not - supported in this version of the simulator. - - NOTRDY Drive not ready (not attached) - SEEK Drive is busy with a seek operation - DAR Data Address Register - CAR Control Address Register - ERR Error Flags (16 bits) - CYL Current Cylinder (0 thru 203) - HEAD Current head (0 or 1) - POS Current position in attached disk file - TIME Device Delay - -7 Symbolic Display and Input - - The System/3 Simulator supports symbolic display and input. - Display is controlled by command line switches: - - (none) display as hex EBCDIC - -c display bytes as characters - -m display instruction mnemonics. - -a display a 256-byte block of memory in both hex and ASCII. - - The symbolic format contains the same elements as the machine - language operation, but not always in the same order. The - operation code frequently specifies both the opcode and the Q byte, - and the top nybble of the opcode is determined by the format of the - addresses. - - Addresses take two forms: the direct address in hex, or a relative - address specified thusly: (byte,XRx) where 'byte' is a 1-byte - offset, and XRx is either XR1 or XR2 for the two index registers. - Use these formats when 'address' is indicated below: - - When 'reg' is mentioned, a mnemonic may be used for the register, - thusly: - - IAR Instruction Address Register for the current program level - ARR Address Recall Register for the current program level - P1IAR IAR for Program Level 1 - P2IAR IAR for Program Level 2 - PSR Program Status Register - XR1 Index Register 1 - XR2 Index Register 2 - IARx IAR for the interrupt level x (x = 0 thru 7) - - All other operands mentioned below are single-byte hex, except for - the length (len) operand of the two-address instructions, which is a - decimal length in the range 1-256. - - In operations where there is a source and a destination, the - destination is always operand 1, the source is operand 2. - - No-address formats: - ------------------ - - HPL hex,hex Halt Program Level, the operands are the - Q and R bytes. - - - One-address formats: - ------------------- - - A reg,address Add to register - CLI address,byte Compare Logical Immediate - MVI address,byte Move Immediate - TBF address,mask Test Bits Off - TBN address,mask Test Bits On - SBF address,mask Set Bits Off - SBN address,mask Set Bits On - ST reg,address Store Register - L reg,address Load Register - LA reg,address Load Address (reg can only be XR1 or XR2) - JC address,cond Jump on Condition - BC address,cond Branch on Condition - - These operations do not specify a qbyte, it is implicit in the - opcode: - - B address Unconditional branch to address - BE address Branch Equal - BNE address Branch Not Equal - BH address Branch High - BNH address Branch Not High - BL address Branch Low - BNL address Branch Not Low - BT address Branch True - BF address Branch False - BP address Branch Plus - BM address Branch Minus - BNP address Branch Not Plus - BNM address Branch Not Minus - BZ address Branch Zero - BNZ address Branch Not Zero - BOZ address Branch Overflow Zoned - BOL address Branch Overflow Logical - BNOZ address Branch No Overflow Zoned - BNOL address Branch No Overflow Logical - NOPB address No - never branch - - (substitute J for B above for a set of Jumps -- 1-byte operand (not - 2), always jumps forward up to 255 bytes from the address following - the Jump instruction. In this case, 'address' cannot be less than - the current address, nor greater than the current address + 255) - - Two-address formats (first address is destination, len is decimal 1-256): - ------------------- - - MVC address,address,len Move Characters - CLC address,address,len Compare Logical Characters - ALC address,address,len Add Logical Characters - SLC address,address,len Subtract Logical Characters - ED address,address,len Edit - ITC address,address,len Insert and Test Characters - AZ address,address,len Add Zoned Decimal - SZ address,address,len Subtract Zoned Decimal - - MNN address,address Move Numeric to Numeric - MNZ address,address Move Numeric to Zone - MZZ address,address Move Zone to Zone - MZN address,address Move Zone to Numeric - - I/O Format - ---------- - - In the I/O format, there are always 3 fields: - - da - Device Address 0-15 (decimal) - m - Modifier 0-1 - n - Function 0-7 - - The meaning of these is entirely defined by the device addressed. - - There may be an optional control byte, or an optional address (based - on the type of instruction). - - SNS da,m,n,address Sense I/O - LIO da,m,n,address Load I/O - TIO da,m,n,address Test I/O - - SIO da,m,n,cc Start I/O -- cc is a control byte - - APL da,m,n Advance Program Level - - -8 Device Programming. - - Note: On a model 15, interrupts are used for all devices. On - other models, interrupts are only used for the printer/keyboard. - - This is a summary of the DA, M, N, and CC codes for all supported - devices: - - 5471 Printer Keyboard - --------------------- - - The PKB has 2 visible indicators: Proceed and Request - Pending. It has a normal keyboard and 4 special keys: - Request, Return, End, and Cancel. - - SIO 1,0,0,XX Start Keyboard Operation, bit masks for XX are: - X'20': Request Pending Indicator On - X'10': Proceed Indicator On - X'04': Request Key Interrupts Enable (1) Disable (0) - X'02': Other Key Interrupts Enable (1) Disable (0) - X'01': Reset request key and other key interrupts - - SIO 1,1,0,XX Start Printer Operation, bit masks for XX are: - X'80': Start Printing - X'40': Start Carrier Return - X'04': Printer Interrupt Enable(1) or Disable (0) - X'01': Reset Printer Interrupt - - LIO 1,1,0,addr Load Printer Output Character - addr is address of low-order (highest numbered) - byte of two-byte field, and high-order byte - (that is, addr - 1) is loaded into output - register to print. Printing is done one character - at a time. - - SNS 1,0,1,addr Sense Status Bytes 0 and 1: - Byte 0 (leftmost) is the character typed in - in EBCDIC. - Byte 1 is status: - X'80': Request key interrupt pending - X'40': End or Cancel key interrupt pending - X'20': Cancel key pressed - X'10': End Key Pressed - X'08': Return or data key interrupt pending - X'04': Return key pressed - - SNS 1,0,3,addr Sense Status Bytes 2 and 3: returns 0000 in - this sim. - - 1442 Reader/Punch - ----------------- - - SIO 5,0,0,XX Feed Card without reading/punching - XX is stacker select for all functions: 0 = stacker - 1 (normal), 1 = stacker 2. - - SIO 5,0,1,XX Read Card - SIO 5,0,2,XX Punch and Feed - SIO 5,0,3,XX Read Column Binary - SIO 5,0,4,XX Punch with no feed - - TIO 5,0,0,addr Branch to addr if not ready or busy - TIO 5,0,2,addr Branch to addr if busy - TIO 5,0,5,addr (mod 15 only) branch if interrupt pending - - APL 5,0,0 Loop (or switch prog levels) if not ready/busy - APL 5,0,2 Loop (or switch) if busy - APL 5,0,5 Loop (or switch) if interrupt pending (mod 15 only) - - LIO 5,0,0,addr Load 2-byte field to Length Count Register - LIO 5,0,4,addr Load 2-byte field to Data Address Register - (DAR is incremented by a read/punch operation and must - be reset every card) - - SNS 5,0,1,addr Sense CE indicators (0000 returned in this sim) - SNS 5,0,2,addr Sense CE indicators (0000 returned in this sim) - SNS 5,0,3,addr Sense Status Indicators: (only simulated bits shown) - X'8000': Read Check - X'4000': Last Card - X'2000': Punch Check - X'1000': Data Overrun - X'0800': Not Ready - - - 1403 Printer - ------------ - - SIO 14,0,0,XX Line space XX lines (0-3 valid in XX) - SIO 14,0,2,XX Print a line space (0-3 valid in XX) - SIO 14,0,4,XX Skip Only (line number 1-112 in XX) - - SIO 14,0,6,XX Print and Skip (line number 0-112 in XX) - - TIO 14,0,0,addr Branch to addr if not ready - TIO 14,0,2,addr Branch to addr if buffer busy - TIO 14,0,3,addr Branch to addr if interrupt pending (mod 15 only) - TIO 14,0,4,addr Branch if carriage busy - TIO 14,0,6,addr Branch if printer busy - - APL 14,0,0 Loop (or switch prog levels) if not ready/check - APL 14,0,2 Loop (or switch) if buffer busy - APL 14,0,3 Loop (or switch) if interrupt pending (mod 15 only) - APL 14,0,4 Loop (or switch) if carriage busy - APL 14,0,6 Loop (or switch) if printer busy - - LIO 14,0,0,addr Load 1 byte to Forms Length Reg at addr-1 - LIO 14,0,4,addr Load 2 bytes to Chain Image Address Register - LIO 14,0,6,addr Load 2 bytes to Data Address Register - - SNS 14,0,0,addr Sense Character Count - SNS 14,0,4,addr Sense LPIAR (Image Address Register) - SNS 14,0,6,addr Sense LPDAR (data addres register) - - - 5444 Disk Drives - ---------------- - - Each drive has two disks (upper and lower), each disk - has two surfaces (upper and lower), each surface has - 24 256-byte sectors, sectors are number 0 thru 23 on - upper surface, 32 thru 55 on lower. - - d = drive, 0 is R1/F1, 1 is R2/F2 - s = surface, 0 = upper (removable), 1 = lower (fixed) - - The Control register points to the leftmost byte of a 4-byte - control field in memory with these bytes: - - F - Flag byte (not supported in this sim) - C - Cylinder Address (0-203) - S - Sector Number (0-23, or 32-55) in top 6 bits - N - Number of sectors minus 1 - - These have meaning for all operations except seek, seek uses - the fields differently. - - SIO 1d,s,0,XX Seek, XX not used, control field is used: - - F - not used - C - not used - S - high bit is head to be used 0-upper 1-lower - low bit is direction to move 0-back 1-forward - N - number of cylinders to move - - SIO 1d,s,1,XX Read, values of XX are as follows: - X'00': Read Data - X'01': Read Identifier (updates control field, no - data is read) - X'02': Read Data Diagnostic - X'03': Verify (does not read, but checks) - - SIO 1d,s,2,XX Write, values of XX are as follows: - X'00': Write Data - X'01': Write Identifier (24 sectors with byte at - data address register) - - SIO 1d,s,3,XX Scan. All 256 bytes in memory at data - address register are compared to disk - sectors on current track, except those - bytes of X'FF' are not compared. Values of - XX are: - - X'00': Scan Equal - X'01': Scan Low or Equal - X'02': Scan High or Equal - - LIO 1d,0,4,addr Load Data Address Register - LIO 1d,0,6,addr Load Disk Control Address Register - - TIO 1d,0,0,addr Branch if not ready/unit check - TIO 1d,0,2,addr Branch if busy - TIO 1d,0,4,addr Branch if Scan Found - - APL 1d,0,0 Loop if not ready/unit check - APL 1d,0,2 Loop if busy - APL 1d,0,4 Loop if scan found - - SNS 1d,0,2,addr Sense Status Bytes 0 and 1: (simulated - bits only are shown, otehrs are 0): - X'1000': equipment check - X'0800': data check - X'0400': No record found - X'0100': Seek Check (past cyl 203) - X'0080': Scan equal Hit - X'0040': Cylinder 0 - X'0020': End of Cylinder - X'0010': Seek Busy - SNS 1d,0,3,addr Sense bytes 2 and 3 (0000 in this sim) - SNS 1d,0,4,addr Sense Data Address Register - SNS 1d,0,6,addr Sense Control Address Register - - - - diff --git a/SDS/sds_cpu.c b/SDS/sds_cpu.c deleted file mode 100644 index 2489cd13..00000000 --- a/SDS/sds_cpu.c +++ /dev/null @@ -1,1282 +0,0 @@ -/* sds_cpu.c: SDS 940 CPU 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. - - 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 - - 01-Mar-03 RMS Added SET/SHOW RTC FREQ support -*/ - -/* 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); -t_stat rtc_set_freq (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat rtc_show_freq (FILE *st, UNIT *uptr, int32 val, void *desc); - -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), PV_LEFT + REG_HRO }, - { NULL } }; - -MTAB rtc_mod[] = { - { MTAB_XTD|MTAB_VDV, 50, NULL, "50HZ", - &rtc_set_freq, NULL, NULL }, - { MTAB_XTD|MTAB_VDV, 60, NULL, "60HZ", - &rtc_set_freq, NULL, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "FREQUENCY", NULL, - NULL, &rtc_show_freq, NULL }, - { 0 } }; - -DEVICE rtc_dev = { - "RTC", &rtc_unit, rtc_reg, rtc_mod, - 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 */ - -uint32 RelocC (int32 va, int32 sw) -{ -uint32 nml = nml_mode, usr = usr_mode; -uint32 pa, pgn, map; - -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) -{ -uint32 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) -{ -uint32 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; -uint32 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) == (uint32) 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; -} - -/* Clock interrupt instruction */ - -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; -} - -/* Clock reset */ - -t_stat rtc_reset (DEVICE *dptr) -{ -rtc_pie = 0; /* disable pulse */ -sim_activate (&rtc_unit, rtc_unit.wait); /* activate unit */ -return SCPE_OK; -} - -/* Set frequency */ - -t_stat rtc_set_freq (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -if (cptr) return SCPE_ARG; -if ((val != 50) && (val != 60)) return SCPE_IERR; -rtc_tps = val; -return SCPE_OK; -} - -/* Show frequency */ - -t_stat rtc_show_freq (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -fprintf (st, (rtc_tps == 50)? "50Hz": "60Hz"); -return SCPE_OK; -} diff --git a/SDS/sds_defs.h b/SDS/sds_defs.h deleted file mode 100644 index d6b6a549..00000000 --- a/SDS/sds_defs.h +++ /dev/null @@ -1,403 +0,0 @@ -/* sds_defs.h: SDS 940 simulator definitions - - 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. - - 25-Apr-03 RMS Revised for extended file support -*/ - -#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) (((uint32) (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 deleted file mode 100644 index 6f095a7f..00000000 --- a/SDS/sds_diag.txt +++ /dev/null @@ -1,113 +0,0 @@ -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 deleted file mode 100644 index 97ec45c8..00000000 --- a/SDS/sds_doc.txt +++ /dev/null @@ -1,536 +0,0 @@ -To: Users -From: Bob Supnik -Subj: SDS 940 Simulator Usage -Date: 15-Mar-2003 - - COPYRIGHT NOTICE - -The following copyright notice applies to both the SIMH source and binary: - - 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"), - 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_tape.h - sim_tmxr.h - scp.c - scp_tty.c - sim_sock.c - sim_tape.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 channel-letter - -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) frequency can be adjusted as follows: - - SET RTC 60HZ set frequency to 60Hz - SET RTC 50HZ set frequency to 50Hz - -The default is 60Hz. - -The clock implements these registers: - - name size comments - - PIE 1 interrupt enable - TIME 24 tick interval - -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 terminal multiplexor does 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 - -The rapid access disk is buffered in memory; end of file and OS I/O errors -cannot occur. 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 - - end of file x assume rest of disk is zero - - OS I/O error x report error and stop - - -By default, the moving head 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 deleted file mode 100644 index c41d5550..00000000 --- a/SDS/sds_drm.c +++ /dev/null @@ -1,270 +0,0 @@ -/* sds_drm.c: SDS 940 Project Genie drum simulator - - 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"), - 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 deleted file mode 100644 index adedeefa..00000000 --- a/SDS/sds_dsk.c +++ /dev/null @@ -1,357 +0,0 @@ -/* sds_dsk.c: SDS 940 moving head disk 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. - - 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 deleted file mode 100644 index 702ea412..00000000 --- a/SDS/sds_io.c +++ /dev/null @@ -1,886 +0,0 @@ -/* sds_io.c: SDS 940 I/O 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. -*/ - -#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 deleted file mode 100644 index f3e4ffc5..00000000 --- a/SDS/sds_lp.c +++ /dev/null @@ -1,285 +0,0 @@ -/* sds_lp.c: SDS 940 line printer 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. - - lpt line printer - - 25-Apr-03 RMS Revised for extended file support -*/ - -#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, T_ADDR_W), 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 deleted file mode 100644 index 7d62a81d..00000000 --- a/SDS/sds_mt.c +++ /dev/null @@ -1,443 +0,0 @@ -/* sds_mt.c: SDS 940 magnetic tape 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. - - mt 7 track magnetic tape - - 25-Apr-03 RMS Revised for extended file support - 28-Mar-03 RMS Added multiformat support - 28-Feb-03 RMS Revised for magtape library - - 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" -#include "sim_tape.h" - -#define MT_MAXFR (32768 * 4) -#define MT_NUMDR 8 /* number drives */ -#define MT_UNIT 07 -#define botf u3 /* bot tape flag */ -#define eotf u4 /* eot tape flag */ - -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, T_ADDR_W, 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[] = { - { MTUF_WLK, 0, "write enabled", "WRITEENABLED", NULL }, - { MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL }, - { MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT", - &sim_tape_set_fmt, &sim_tape_show_fmt, 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? */ - sim_tape_rewind (uptr); /* rewind unit */ - uptr->eotf = 0; /* clr 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 (!sim_tape_wrp (uptr)) *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 tbc; -t_stat st, r = SCPE_OK; - -if ((uptr->flags & UNIT_ATT) == 0) { /* attached? */ - mt_set_err (uptr); /* no, err, disc */ - return SCPE_UNATT; } -if (mt_inst & CHC_REV) /* reverse? */ - st = sim_tape_rdrecr (uptr, mtxb, &tbc, MT_MAXFR); /* read rec rev */ -else st = sim_tape_rdrecf (uptr, mtxb, &tbc, MT_MAXFR); /* no, fwd */ -if (st == MTSE_TMK) { /* tape mark? */ - mt_eof = 1; /* set eof flag */ - mtxb[0] = mtxb[1] = 017; /* EOR char */ - mt_blnt = 2; /* store 2 */ - return SCPE_OK; } -if (st != MTSE_OK) { /* other error? */ - mt_set_err (uptr); /* err, disc */ - if (st == MTSE_IOERR) return SCPE_IOERR; /* IO error? */ - if (st == MTSE_INVRL) return SCPE_MTRLNT; /* inv rec lnt? */ - if (st == MTSE_EOM) uptr->eotf = 1; /* eom? set eot */ - return SCPE_OK; } -mt_blnt = tbc; /* set buf lnt */ -return SCPE_OK; -} - -/* 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) -{ -UNIT *uptr = mt_dev.units + (dev & MT_UNIT); -t_mtrlnt tbc; -t_stat st; - -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 (sim_tape_wrp (uptr)) { /* write lock? */ - mt_set_err (uptr); /* yes, err, disc */ - return SCPE_OK; } -if (dev & DEV_MTS) { /* erase? */ - if (mt_inst & CHC_REV) /* reverse? */ - sim_tape_sprecr (uptr, &tbc); /* backspace */ - st = sim_tape_wreom (uptr); /* write eom */ - } -else { - if ((mt_bptr == 1) && (mtxb[0] == 017) && /* wr eof? */ - ((mt_inst & 01670) == 00050)) - st = sim_tape_wrtmk (uptr); /* write tape mark */ - else st = sim_tape_wrrecf (uptr, mtxb, mt_bptr); /* write record */ - } -mt_bptr = 0; -if (st != MTSE_OK) mt_set_err (uptr); /* error? */ -if (st == MTSE_IOERR) 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]); - sim_tape_reset (&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 = sim_tape_attach (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 sim_tape_detach (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 deleted file mode 100644 index 65192e08..00000000 --- a/SDS/sds_mux.c +++ /dev/null @@ -1,506 +0,0 @@ -/* sds_mux.c: SDS 940 terminal multiplexor 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. - - mux terminal multiplexor - - 09-May-03 RMS Added network device flag - - 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_NET | 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 deleted file mode 100644 index d111ba4d..00000000 --- a/SDS/sds_rad.c +++ /dev/null @@ -1,290 +0,0 @@ -/* sds_rad.c: SDS 940 fixed head disk 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. - - 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; -uint32 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) -{ -uint32 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 deleted file mode 100644 index 02892571..00000000 --- a/SDS/sds_stddev.c +++ /dev/null @@ -1,557 +0,0 @@ -/* sds_stddev.c: SDS 940 standard devices - - 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. - - ptr paper tape reader - ptp paper tape punch - tti keyboard - tto teleprinter - - 25-Apr-03 RMS Revised for extended file support -*/ - -#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, T_ADDR_W), 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, T_ADDR_W), 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, T_ADDR_W), 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, T_ADDR_W), 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 deleted file mode 100644 index 8ff8d2af..00000000 --- a/SDS/sds_sys.c +++ /dev/null @@ -1,576 +0,0 @@ -/* sds_sys.c: SDS 940 simulator interface - - 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. -*/ - -#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/ka655.bin b/VAX/ka655.bin deleted file mode 100644 index 1edd8b93..00000000 Binary files a/VAX/ka655.bin and /dev/null differ diff --git a/VAX/vax_cpu.c b/VAX/vax_cpu.c deleted file mode 100644 index 6a851f48..00000000 --- a/VAX/vax_cpu.c +++ /dev/null @@ -1,2505 +0,0 @@ -/* vax_cpu.c: VAX CPU simulator - - 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"), - 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 CVAX central processor - - 17-May-03 RMS Fixed operand order in EMODx - 23-Apr-03 RMS Revised for 32b/64b t_addr - 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) - 02-May-02 RMS Fixed bug in indexed autoincrement register logging - 30-Apr-02 RMS Added TODR powerup routine - 18-Apr-02 RMS Cleanup ambiguous signed left shifts - 15-Apr-02 RMS Fixed bug in CASEL condition codes - - The register state for the VAX is: - - R[0:15] general registers - PSL<31:0> processor status longword - TP<30> trace pending - FPD<27> first part done - IS<26> interrupt stack - CM<25:24> current mode - PM<23:22> previous mode - IPL<20:16> interrupt priority level - PSW<15:0> non-privileged processor status word - DV<7> decimal overflow trap enable - FU<6> floating underflow fault enable - IV<5> integer overflow trap enable - T<4> trace trap enable - CC<3:0> condition codes - SCBB system control block base - PCBB process control block base - SBR system page table base - SLR system page table length - P0BR process region 0 page table base - P0LR process region 0 page table length - P1BR process region 1 page table base - P1LR process region 1 page table length - SIRR/SISR software interrupt request/summary register - ASTLVL AST level register - - The CVAX CPU adds a few specific IPRs: - - CADR cache disable register - MSER memory system error register -*/ - -/* The VAX has a variable length instruction format with up to six operands: - - opcode byte - operand 1 specifier - : - operand n specifier - - Each operand specifier is a byte consisting of an addressing mode, a - register, and possibly 1-8 bytes of extension: - - number name extension mnemonic operation - - 0-3 short literal - #n op <- specifier - 4 index - [Rn] index by Rn - 5 register - Rn op <- Rn - 6 register def - (Rn) op <- M[Rn] - 7 autodecrement - -(Rn) Rn <- Rn - length - op <- M[Rn] - 8 autoincrement - (Rn)+ op <- M[Rn] - Rn <- Rn + length - 9 auto deferred - @(Rn)+ op <- M[M[Rn]] - Rn <- Rn + 4 - A byte displ byte d d(Rn) op <- M[Rn + sxt.d] - B byte displ def byte d @d(Rn) op <- M[M[Rn + sxt.d]] - C word displ word d d(Rn) op <- M[Rn + sxt.d] - D word displ def word d @d(Rn) op <- M[M[Rn + sxt.d]] - E long displ long d d(Rn) op <- M[Rn + d] - F long displ def long d @d(Rn) op <- M[M[Rn + d]] - - When the general register is the PC, certain modes are forbidden, and - others have special interpretations: - - 4F index fault - 5F register fault - 6F register def fault - 7F autodecrement fault - 8F immediate 1-8B #imm op <- imm - 9 absolute 4B @#imm op <- M[imm] - A byte relative byte d d(Rn) op <- M[PC + sxt.d] - B byte rel def byte d @d(Rn) op <- M[M[PC + sxt.d]] - C word relative word d d(Rn) op <- M[PC + sxt.d] - D word rel def word d @d(Rn) op <- M[M[PC + sxt.d]] - E long relative long d d(Rn) op <- M[PC + d] - F long rel def long d @d(Rn) op <- M[M[PC + d]] -*/ - -/* This routine is the instruction decode routine for the VAX. It - is called from the simulator control program to execute instructions - in simulated memory, starting at the simulated PC. It runs until an - enabled exception is encountered. - - General notes: - - 1. Traps and interrupts. Variable trpirq microencodes the outstanding - trap request (if any) and the level of the highest outstanding - interrupt (if any). - - 2. Interrupt requests are maintained in the int_req array, one word per - interrupt level, one bit per device. - - 3. Adding I/O devices. These modules must be modified: - - vax_defs.h add device address and interrupt definitions - vax_sys.c add sim_devices table entry -*/ - -/* Definitions */ - -#include "vax_defs.h" - -#define OP_MEM -1 -#define UNIT_V_CONH (UNIT_V_UF + 0) /* halt to console */ -#define UNIT_V_MSIZE (UNIT_V_UF + 1) /* dummy */ -#define UNIT_CONH (1u << UNIT_V_CONH) -#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] -#define op3 opnd[3] -#define op4 opnd[4] -#define op5 opnd[5] -#define op6 opnd[6] -#define op7 opnd[7] -#define op8 opnd[8] -#define CHECK_FOR_PC if (rn == nPC) RSVD_ADDR_FAULT -#define CHECK_FOR_SP if (rn >= nSP) RSVD_ADDR_FAULT -#define RECW(l) ((l) << 4) | rn -#define WRITE_B(r) if (spec > (GRN | nPC)) Write (va, r, L_BYTE, WA); \ - else R[rn] = (R[rn] & ~BMASK) | ((r) & BMASK) -#define WRITE_W(r) if (spec > (GRN | nPC)) Write (va, r, L_WORD, WA); \ - else R[rn] = (R[rn] & ~WMASK) | ((r) & WMASK) -#define WRITE_L(r) if (spec > (GRN | nPC)) Write (va, r, L_LONG, WA); \ - else R[rn] = (r) -#define WRITE_Q(rl,rh) if (spec > (GRN | nPC)) { \ - if (Test (va + 7, WA, &mstat) >= 0) \ - Write (va, rl, L_LONG, WA); \ - 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 */ -int32 PSL; /* PSL */ -int32 SCBB = 0; /* SCB base */ -int32 PCBB = 0; /* PCB base */ -int32 P0BR = 0; /* P0 mem mgt */ -int32 P0LR = 0; -int32 P1BR = 0; /* P1 mem mgt */ -int32 P1LR = 0; -int32 SBR = 0; /* S0 mem mgt */ -int32 SLR = 0; -int32 SISR; /* swre int req */ -int32 ASTLVL; /* AST level */ -int32 CADR = 0; /* cache disable */ -int32 MSER = 0; /* mem error */ -int32 mapen; /* map enable */ -int32 trpirq; /* trap/intr req */ -int32 conpc, conpsl; /* console reg */ -int32 in_ie = 0; /* in exc, int */ -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_p = 0; /* PC queue ptr */ -int32 hst_p = 0; /* history pointer */ -int32 hst_lnt = 0; /* history length */ -int32 badabo = 0; -int32 cpu_astop = 0; -int32 dbg_stop = 0; -int32 mchk_va, mchk_ref; /* mem ref param */ -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, - 0x0000001F, 0x0000003F, 0x0000007F, 0x000000FF, - 0x000001FF, 0x000003FF, 0x000007FF, 0x00000FFF, - 0x00001FFF, 0x00003FFF, 0x00007FFF, 0x0000FFFF, - 0x0001FFFF, 0x0003FFFF, 0x0007FFFF, 0x000FFFFF, - 0x001FFFFF, 0x003FFFFF, 0x007FFFFF, 0x00FFFFFF, - 0x01FFFFFF, 0x03FFFFFF, 0x07FFFFFF, 0x0FFFFFFF, - 0x1FFFFFFF, 0x3FFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF }; -const uint32 byte_sign[33] = { 0x00000000, - 0x00000001, 0x00000002, 0x00000004, 0x00000008, - 0x00000010, 0x00000020, 0x00000040, 0x00000080, - 0x00000100, 0x00000200, 0x00000400, 0x00000800, - 0x00001000, 0x00002000, 0x00004000, 0x00008000, - 0x00010000, 0x00020000, 0x00040000, 0x00080000, - 0x00100000, 0x00200000, 0x00400000, 0x00800000, - 0x01000000, 0x02000000, 0x04000000, 0x08000000, - 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; -extern int32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */ -extern UNIT clk_unit; - -extern t_stat build_dib_tab (void); -extern UNIT rom_unit, nvr_unit; -extern int32 op_ashq (int32 *opnd, int32 *rh, int32 *flg); -extern int32 op_emul (int32 mpy, int32 mpc, int32 *rh); -extern int32 op_ediv (int32 *opnd, int32 *rh, int32 *flg); -extern int32 op_bb_n (int32 *opnd, int32 acc); -extern int32 op_bb_x (int32 *opnd, int32 newb, int32 acc); -extern int32 op_extv (int32 *opnd, int32 vfldrp1, int32 acc); -extern int32 op_ffs (uint32 fld, int32 size); -extern void op_insv (int32 *opnd, int32 vfldrp1, int32 acc); -extern int32 op_call (int32 *opnd, t_bool gs, int32 acc); -extern int32 op_ret (int32 acc); -extern int32 op_insque (int32 *opnd, int32 acc); -extern int32 op_remque (int32 *opnd, int32 acc); -extern int32 op_insqhi (int32 *opnd, int32 acc); -extern int32 op_insqti (int32 *opnd, int32 acc); -extern int32 op_remqhi (int32 *opnd, int32 acc); -extern int32 op_remqti (int32 *opnd, int32 acc); -extern void op_pushr (int32 *opnd, int32 acc); -extern void op_popr (int32 *opnd, int32 acc); -extern int32 op_movc (int32 *opnd, int32 opc, int32 acc); -extern int32 op_cmpc (int32 *opnd, int32 opc, int32 acc); -extern int32 op_locskp (int32 *opnd, int32 opc, int32 acc); -extern int32 op_scnspn (int32 *opnd, int32 opc, int32 acc); -extern int32 op_chm (int32 *opnd, int32 cc, int32 opc); -extern int32 op_rei (int32 acc); -extern void op_ldpctx (int32 acc); -extern void op_svpctx (int32 acc); -extern int32 op_probe (int32 *opnd, int32 opc); -extern int32 op_mtpr (int32 *opnd); -extern int32 op_mfpr (int32 *opnd); -extern int32 op_movfd (int32 val); -extern int32 op_movg (int32 val); -extern int32 op_mnegfd (int32 val); -extern int32 op_mnegg (int32 val); -extern int32 op_cmpfd (int32 h1, int32 l1, int32 h2, int32 l2); -extern int32 op_cmpg (int32 h1, int32 l1, int32 h2, int32 l2); -extern int32 op_cvtifdg (int32 val, int32 *rh, int32 opc); -extern int32 op_cvtfdgi (int32 *opnd, int32 *rh, int32 opc); -extern int32 op_cvtdf (int32 *opnd); -extern int32 op_cvtgf (int32 *opnd); -extern int32 op_cvtfg (int32 *opnd, int32 *rh); -extern int32 op_addf (int32 *opnd, t_bool sub); -extern int32 op_addd (int32 *opnd, int32 *rh, t_bool sub); -extern int32 op_addg (int32 *opnd, int32 *rh, t_bool sub); -extern int32 op_mulf (int32 *opnd); -extern int32 op_muld (int32 *opnd, int32 *rh); -extern int32 op_mulg (int32 *opnd, int32 *rh); -extern int32 op_divf (int32 *opnd); -extern int32 op_divd (int32 *opnd, int32 *rh); -extern int32 op_divg (int32 *opnd, int32 *rh); -extern int32 op_emodf (int32 *opnd, int32 *intgr, int32 *flg); -extern int32 op_emodd (int32 *opnd, int32 *rh, int32 *intgr, int32 *flg); -extern int32 op_emodg (int32 *opnd, int32 *rh, int32 *intgr, int32 *flg); -extern void op_polyf (int32 *opnd, int32 acc); -extern void op_polyd (int32 *opnd, int32 acc); -extern void op_polyg (int32 *opnd, int32 acc); -extern int32 op_emulate (int32 *opnd, int32 cc, int32 opc, int32 acc); -extern int32 intexc (int32 vec, int32 cc, int32 ipl, int ei); -extern int32 Read (uint32 va, int32 lnt, int32 acc); -extern void Write (uint32 va, int32 val, int32 lnt, int32 acc); -extern int32 ReadB (uint32 pa); -extern int32 WriteB (uint32 pa, int32 val); -extern int32 Test (uint32 va, int32 acc, int32 *status); -extern int32 ReadLP (uint32 pa); -extern int32 eval_int (void); -extern int32 get_vector (int32 lvl); -extern void set_map_reg (void); -extern void rom_wr (int32 pa, int32 val, int32 lnt); -extern uint16 drom[NUM_INST][MAX_SPEC + 1]; -extern t_stat show_iospace (FILE *st, UNIT *uptr, int32 val, void *desc); - -t_stat cpu_reset (DEVICE *dptr); -t_stat cpu_boot (int32 unitno, DEVICE *dptr); -t_stat cpu_ex (t_value *vptr, t_addr exta, UNIT *uptr, int32 sw); -t_stat cpu_dep (t_value val, t_addr exta, 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 - - 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, INITMEMSIZE) }; - -REG cpu_reg[] = { - { HRDATA (PC, R[nPC], 32) }, - { HRDATA (R0, R[0], 32) }, - { HRDATA (R1, R[1], 32) }, - { HRDATA (R2, R[2], 32) }, - { HRDATA (R3, R[3], 32) }, - { HRDATA (R4, R[4], 32) }, - { HRDATA (R5, R[5], 32) }, - { HRDATA (R6, R[6], 32) }, - { HRDATA (R7, R[7], 32) }, - { HRDATA (R8, R[8], 32) }, - { HRDATA (R9, R[9], 32) }, - { HRDATA (R10, R[10], 32) }, - { HRDATA (R11, R[11], 32) }, - { HRDATA (R12, R[12], 32) }, - { HRDATA (R13, R[13], 32) }, - { HRDATA (R14, R[14], 32) }, - { HRDATA (AP, R[nAP], 32) }, - { HRDATA (FP, R[nFP], 32) }, - { HRDATA (SP, R[nSP], 32) }, - { HRDATA (PSL, PSL, 32) }, - { HRDATA (CC, PSL, 4) }, - { HRDATA (KSP, KSP, 32) }, - { HRDATA (ESP, ESP, 32) }, - { HRDATA (SSP, SSP, 32) }, - { HRDATA (USP, USP, 32) }, - { HRDATA (IS, IS, 32) }, - { HRDATA (SCBB, SCBB, 32) }, - { HRDATA (PCBB, PCBB, 32) }, - { HRDATA (P0BR, P0BR, 32) }, - { HRDATA (P0LR, P0LR, 22) }, - { HRDATA (P1BR, P1BR, 32) }, - { HRDATA (P1LR, P1LR, 22) }, - { HRDATA (SBR, SBR, 32) }, - { HRDATA (SLR, SLR, 22) }, - { HRDATA (SISR, SISR, 16) }, - { HRDATA (ASTLVL, ASTLVL, 4) }, - { HRDATA (CADR, CADR, 8) }, - { HRDATA (MSER, MSER, 8) }, - { FLDATA (MAPEN, mapen, 0) }, - { 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 }, - { HRDATA (PCQP, pcq_p, 6), REG_HRO }, - { HRDATA (BADABO, badabo, 32), REG_HRO }, - { HRDATA (WRU, sim_int_char, 8) }, - { NULL } }; - -MTAB cpu_mod[] = { - { UNIT_MSIZE, (1u << 23), NULL, "8M", &cpu_set_size }, - { UNIT_MSIZE, (1u << 24), NULL, "16M", &cpu_set_size }, - { UNIT_MSIZE, (1u << 25), NULL, "32M", &cpu_set_size }, - { UNIT_MSIZE, (1u << 26), NULL, "64M", &cpu_set_size }, - { UNIT_CONH, 0, "HALT to SIMH", "SIMHALT", NULL }, - { 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 } }; - -DEVICE cpu_dev = { - "CPU", &cpu_unit, cpu_reg, cpu_mod, - 1, 16, 32, 1, 16, 8, - &cpu_ex, &cpu_dep, &cpu_reset, - &cpu_boot, NULL, NULL, - NULL, DEV_DYNM, &cpu_set_size }; - -t_stat sim_instr (void) -{ -volatile int32 opc, cc; /* used by setjmp */ -int32 acc; /* set by setjmp */ -int abortval; -t_stat r; - -if ((r = build_dib_tab ()) != SCPE_OK) return r; /* build, chk dib_tab */ -cc = PSL & CC_MASK; /* split PSL */ -PSL = PSL & ~CC_MASK; -in_ie = 0; /* not in exc */ -set_map_reg (); /* set map reg */ -GET_CUR; /* set access mask */ -SET_IRQL; /* eval interrupts */ -FLUSH_ISTR; /* clear prefetch */ -sim_rtcn_init (clk_unit.wait, TMR_CLK); /* init clock */ - -abortval = setjmp (save_env); /* set abort hdlr */ -if (abortval > 0) { /* sim stop? */ - PSL = PSL | cc; /* put PSL together */ - pcq_r->qptr = pcq_p; /* update pc q ptr */ - return abortval; } /* return to SCP */ -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; } } - 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; - case SCB_ARITH: /* arithmetic fault */ - 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 - 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; - case 1: /* interrupt */ - break; /* just proceed */ - default: /* other */ - badabo = abortval; /* save code */ - ABORT (STOP_UNKABO); } /* panic */ -} /* end else */ - -/* Main instruction loop */ - -for ( ;; ) { -int32 spec, disp, rn, index, numspec; -int32 vfldrp1, brdisp, flg, mstat; -int32 i, j, r, rh, temp; -uint32 va, iad; -int32 opnd[OPND_SIZE]; /* operand queue */ - -if (cpu_astop) { - cpu_astop = 0; - ABORT (SCPE_STOP); } - -fault_PC = PC; -recqptr = 0; /* clr recovery q */ -if (sim_interval <= 0) { /* chk clock queue */ - temp = sim_process_event (); - if (temp) ABORT (temp); - SET_IRQL; } /* update interrupts */ - -/* Test for non-instruction dispatches, in SRM order - - - trap or interrupt (trpirq != 0) - - PSL set - - If any of these conditions are met, re-dispatch; otherwise, - set PSL from PSL. -*/ - -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; } - else if (temp = GET_IRQL (trpirq)) { /* interrupt? */ - 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; } - -if (PSL & PSL_TP) { /* trace trap? */ - PSL = PSL & ~PSL_TP; /* clear */ - cc = intexc (SCB_TP, cc, 0, IE_EXC); /* take trap */ - GET_CUR; /* set cur mode */ - continue; } -if (PSL & PSW_T) PSL = PSL | PSL_TP; /* if T, set TP */ - -if (sim_brk_summ && sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */ - ABORT (STOP_IBKPT); } /* stop simulation */ - -sim_interval = sim_interval - 1; /* count instr */ -GET_ISTR (opc, L_BYTE); /* get opcode */ -if (opc == 0xFD) { /* 2 byte op? */ - GET_ISTR (opc, L_BYTE); /* get second byte */ - opc = opc | 0x100; } /* flag */ -numspec = drom[opc][0]; /* get # specs */ -if (PSL & PSL_FPD) { - if ((numspec & DR_F) == 0) RSVD_INST_FAULT; } -else { numspec = numspec & DR_NSPMASK; /* get # specifiers */ - -/* Specifier flows. Operands are parsed and placed into queue opnd. - - r.bwl opnd[j] = value of operand - r.q opnd[j:j+1] = value of operand - a.bwlq opnd[j] = address of operand - m.bwl opnd[j] = value of operand - m.q opnd[j:j+1] = value of operand - w.bwlq opnd[j] = register/memory flag - opnd[j+1] = memory address - - For the last memory specifier, the specifier is in spec, the register - number is in rn, and the effective address is in va. Modify specifiers - (always last) can test spec > reg+PC, as short literal are illegal for - modifiers specifiers, and final index specifiers are always illegal. -*/ - - 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 */ - -/* 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; - -/* 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; - -/* 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; - -/* 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; - -/* 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; - -/* 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; - -/* 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; - -/* 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; - -/* 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; - -/* 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; - -/* 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; - -/* 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 */ - } /* end for */ -} - /* 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 */ - -switch (opc) { - -/* Single operand instructions with dest, write only - CLRx dst.wx - - spec = reg/memory flag - rn = register number - va = virtual address -*/ - -case CLRB: - WRITE_B (0); /* store result */ - CC_ZZ1P; /* set cc's */ - break; -case CLRW: - WRITE_W (0); /* store result */ - CC_ZZ1P; /* set cc's */ - break; -case CLRL: - WRITE_L (0); /* store result */ - CC_ZZ1P; /* set cc's */ - break; -case CLRQ: - WRITE_Q (0, 0); /* store result */ - CC_ZZ1P; /* set cc's */ - break; - -/* Single operand instructions with source, read only - TSTx src.rx - - opnd[0] = source - */ - -case TSTB: - CC_IIZZ_B (op0); /* set cc's */ - break; -case TSTW: - CC_IIZZ_W (op0); /* set cc's */ - break; -case TSTL: - CC_IIZZ_L (op0); /* set cc's */ - break; - -/* Single operand instructions with source, read/write - op src.mx - - opnd[0] = operand - spec = reg/mem flag - rn = register number - va = operand address -*/ - -case INCB: - r = (op0 + 1) & BMASK; /* calc result */ - WRITE_B (r); /* store result */ - CC_ADD_B (r, 1, op0); /* set cc's */ - break; -case INCW: - r = (op0 + 1) & WMASK; /* calc result */ - WRITE_W (r); /* store result */ - CC_ADD_W (r, 1, op0); /* set cc's */ - break; -case INCL: - r = (op0 + 1) & LMASK; /* calc result */ - WRITE_L (r); /* store result */ - CC_ADD_L (r, 1, op0); /* set cc's */ - break; -case DECB: - r = (op0 - 1) & BMASK; /* calc result */ - WRITE_B (r); /* store result */ - CC_SUB_B (r, 1, op0); /* set cc's */ - break; -case DECW: - r = (op0 - 1) & WMASK; /* calc result */ - WRITE_W (r); /* store result */ - CC_SUB_W (r, 1, op0); /* set cc's */ - break; -case DECL: - r = (op0 - 1) & LMASK; /* calc result */ - WRITE_L (r); /* store result */ - CC_SUB_L (r, 1, op0); /* set cc's */ - break; - -/* Push instructions - PUSHL src.rl or PUSHAx src.ax - - opnd[0] = source -*/ - -case PUSHL: case PUSHAB: case PUSHAW: case PUSHAL: case PUSHAQ: - Write (SP - 4, op0, L_LONG, WA); /* push operand */ - SP = SP - 4; /* decr stack ptr */ - CC_IIZP_L (op0); /* set cc's */ - break; - -/* Moves, converts, and ADAWI - op src.rx, dst.wx - - opnd[0] = source - spec = reg/mem flag - rn = register number - va = operand address -*/ - -case MOVB: - WRITE_B (op0); /* result */ - CC_IIZP_B (op0); /* set cc's */ - break; -case MOVW: case MOVZBW: - WRITE_W (op0); /* result */ - CC_IIZP_W (op0); /* set cc's */ - break; -case MOVL: case MOVZBL: case MOVZWL: -case MOVAB: case MOVAW: case MOVAL: case MOVAQ: - WRITE_L (op0); /* result */ - CC_IIZP_L (op0); /* set cc's */ - break; -case MCOMB: - r = op0 ^ BMASK; /* compl opnd */ - WRITE_B (r); /* store result */ - CC_IIZP_B (r); /* set cc's */ - break; -case MCOMW: - r = op0 ^ WMASK; /* compl opnd */ - WRITE_W (r); /* store result */ - CC_IIZP_W (r); /* set cc's */ - break; -case MCOML: - r = op0 ^ LMASK; /* compl opnd */ - WRITE_L (r); /* store result */ - CC_IIZP_L (r); /* set cc's */ - break; -case MNEGB: - r = (-op0) & BMASK; /* negate opnd */ - WRITE_B (r); /* store result */ - CC_SUB_B (r, op0, 0); /* set cc's */ - break; -case MNEGW: - r = (-op0) & WMASK; /* negate opnd */ - WRITE_W (r); /* store result */ - CC_SUB_W (r, op0, 0); /* set cc's */ - break; -case MNEGL: - r = (-op0) & LMASK; /* negate opnd */ - WRITE_L (r); /* store result */ - CC_SUB_L (r, op0, 0); /* set cc's */ - break; - -case CVTBW: - r = SXTBW (op0); /* ext sign */ - WRITE_W (r); /* store result */ - CC_IIZZ_W (r); /* set cc's */ - break; -case CVTBL: - r = SXTB (op0); /* ext sign */ - WRITE_L (r); /* store result */ - CC_IIZZ_L (r); /* set cc's */ - break; -case CVTWL: - r = SXTW (op0); /* ext sign */ - WRITE_L (r); /* store result */ - CC_IIZZ_L (r); /* set cc's */ - break; -case CVTLB: - r = op0 & BMASK; /* set result */ - WRITE_B (r); /* store result */ - CC_IIZZ_B (r); /* initial cc's */ - if ((op0 > 127) || (op0 < -128)) { V_INTOV; } - break; -case CVTLW: - r = op0 & WMASK; /* set result */ - WRITE_W (r); /* store result */ - CC_IIZZ_W (r); /* initial cc's */ - if ((op0 > 32767) || (op0 < -32768)) { V_INTOV; } - break; -case CVTWB: - r = op0 & BMASK; /* set result */ - WRITE_B (r); /* store result */ - CC_IIZZ_B (r); /* initial cc's */ - temp = SXTW (op0); /* cvt op to long */ - if ((temp > 127) || (temp < -128)) { V_INTOV; } - break; - -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); } - CC_ADD_W (r, op0, temp); /* set cc's */ - break; - -/* Integer operates, 2 operand, read only - op src1.rx, src2.rx - - opnd[0] = source1 - opnd[1] = source2 -*/ - -case CMPB: - CC_CMP_B (op0, op1); /* set cc's */ - break; -case CMPW: - CC_CMP_W (op0, op1); /* set cc's */ - break; -case CMPL: - CC_CMP_L (op0, op1); /* set cc's */ - break; -case BITB: - r = op1 & op0; /* calc result */ - CC_IIZP_B (r); /* set cc's */ - break; -case BITW: - r = op1 & op0; /* calc result */ - CC_IIZP_W (r); /* set cc's */ - break; -case BITL: - r = op1 & op0; /* calc result */ - CC_IIZP_L (r); /* set cc's */ - break; - -/* Integer operates, 2 operand read/write, and 3 operand, also MOVQ - op2 src.rx, dst.mx op3 src.rx, src.rx, dst.wx - - opnd[0] = source1 - opnd[1] = source2 - spec = register/memory flag - rn = register number - va = memory address -*/ - -case ADDB2: case ADDB3: - r = (op1 + op0) & BMASK; /* calc result */ - WRITE_B (r); /* store result */ - CC_ADD_B (r, op0, op1); /* set cc's */ - break; -case ADDW2: case ADDW3: - r = (op1 + op0) & WMASK; /* calc result */ - WRITE_W (r); /* store result */ - CC_ADD_W (r, op0, op1); /* set cc's */ - break; -case ADWC: - r = (op1 + op0 + (cc & CC_C)) & LMASK; /* calc result */ - WRITE_L (r); /* store result */ - CC_ADD_L (r, op0, op1); /* set cc's */ - if ((r == op1) && op0) cc = cc | CC_C; /* special case */ - break; -case ADDL2: case ADDL3: - r = (op1 + op0) & LMASK; /* calc result */ - WRITE_L (r); /* store result */ - CC_ADD_L (r, op0, op1); /* set cc's */ - break; -case SUBB2: case SUBB3: - r = (op1 - op0) & BMASK; /* calc result */ - WRITE_B (r); /* store result */ - CC_SUB_B (r, op0, op1); /* set cc's */ - break; -case SUBW2: case SUBW3: - r = (op1 - op0) & WMASK; /* calc result */ - WRITE_W (r); /* store result */ - CC_SUB_W (r, op0, op1); /* set cc's */ - break; -case SBWC: - r = (op1 - op0 - (cc & CC_C)) & LMASK; /* calc result */ - WRITE_L (r); /* store result */ - CC_SUB_L (r, op0, op1); /* set cc's */ - if ((op0 == op1) && r) cc = cc | CC_C; /* special case */ - break; -case SUBL2: case SUBL3: - r = (op1 - op0) & LMASK; /* calc result */ - WRITE_L (r); /* store result */ - CC_SUB_L (r, op0, op1); /* set cc's */ - break; -case MULB2: case MULB3: - temp = SXTB (op0) * SXTB (op1); /* multiply */ - r = temp & BMASK; /* mask to result */ - WRITE_B (r); /* store result */ - CC_IIZZ_B (r); /* set cc's */ - if ((temp > 127) || (temp < -128)) { V_INTOV; } - break; -case MULW2: case MULW3: - temp = SXTW (op0) * SXTW (op1); /* multiply */ - r = temp & WMASK; /* mask to result */ - WRITE_W (r); /* store result */ - CC_IIZZ_W (r); /* set cc's */ - if ((temp > 32767) || (temp < -32768)) { V_INTOV; } - break; -case MULL2: case MULL3: - r = op_emul (op0, op1, &rh); /* get 64b result */ - WRITE_L (r); /* store result */ - CC_IIZZ_L (r); /* set cc's */ - if (rh != ((r & LSIGN)? -1: 0)) { V_INTOV; } /* chk overflow */ - break; -case DIVB2: case DIVB3: - if (op0 == 0) { /* div by zero? */ - 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; } - 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); } - else if ((op0 == WMASK) && (op1 == WSIGN)) { /* overflow? */ - 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); } - else if ((op0 == LMASK) && (op1 == LSIGN)) { /* overflow? */ - 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 */ - break; - -case BISB2: case BISB3: - r = op1 | op0; /* calc result */ - WRITE_B (r); /* store result */ - CC_IIZP_B (r); /* set cc's */ - break; -case BISW2: case BISW3: - r = op1 | op0; /* calc result */ - WRITE_W (r); /* store result */ - CC_IIZP_W (r); /* set cc's */ - break; -case BISL2: case BISL3: - r = op1 | op0; /* calc result */ - WRITE_L (r); /* store result */ - CC_IIZP_L (r); /* set cc's */ - break; -case BICB2: case BICB3: - r = op1 & ~op0; /* calc result */ - WRITE_B (r); /* store result */ - CC_IIZP_B (r); /* set cc's */ - break; -case BICW2: case BICW3: - r = op1 & ~op0; /* calc result */ - WRITE_W (r); /* store result */ - CC_IIZP_W (r); /* set cc's */ - break; -case BICL2: case BICL3: - r = op1 & ~op0; /* calc result */ - WRITE_L (r); /* store result */ - CC_IIZP_L (r); /* set cc's */ - break; -case XORB2: case XORB3: - r = op1 ^ op0; /* calc result */ - WRITE_B (r); /* store result */ - CC_IIZP_B (r); /* set cc's */ - break; -case XORW2: case XORW3: - r = op1 ^ op0; /* calc result */ - WRITE_W (r); /* store result */ - CC_IIZP_W (r); /* set cc's */ - break; -case XORL2: case XORL3: - r = op1 ^ op0; /* calc result */ - WRITE_L (r); /* store result */ - CC_IIZP_L (r); /* set cc's */ - break; - -/* MOVQ - movq src.rq, dst.wq - - opnd[0:1] = source - spec = register/memory flag - rn = register number - va = memory address - -*/ - -case MOVQ: - WRITE_Q (op0, op1); /* store result */ - CC_IIZP_Q (op0, op1); - break; - -/* Shifts - op shf.rb,src.rl,dst.wl - - opnd[0] = shift count - opnd[1] = source - spec = register/memory flag - rn = register number - va = memory address -*/ - -case ROTL: - j = op0 % 32; /* reduce sc, mod 32 */ - if (j) r = ((((uint32) op1) << j) | - (((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 */ - 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? */ - break; -case ASHQ: - r = op_ashq (opnd, &rh, &flg); /* do qw shift */ - WRITE_Q (r, rh); /* store results */ - CC_IIZZ_Q (r, rh); /* set cc's */ - if (flg) { V_INTOV; } /* if ovflo, set */ - break; - -/* EMUL - emul mplr.rl,mpcn.rl,add.rl,dst.wq - - op0 = multiplier - op1 = multiplicand - op2 = adder - op3:op4 = destination (.wq) -*/ - -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); - WRITE_Q (r, rh); /* write result */ - CC_IIZZ_Q (r, rh); /* set cc's */ - break; - -/* EDIV - ediv dvr.rl,dvd.rq,quo.wl,rem.wl - - op0 = divisor (.rl) - op1:op2 = dividend (.rq) - op3:op4 = quotient address (.wl) - op5:op6 = remainder address (.wl) -*/ - -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 */ - if (op3 >= 0) R[op3] = r; /* store quotient */ - else Write (op4, r, L_LONG, WA); - if (op5 >= 0) R[op5] = rh; /* store remainder */ - else Write (op6, rh, L_LONG, WA); - CC_IIZZ_L (r); /* set cc's */ - cc = cc | flg; /* set V if required */ - break; - -/* Control instructions */ - -/* Simple branches and subroutine calls */ - -case BRB: - BRANCHB (brdisp); /* branch */ - if ((PC == fault_PC) && (PSL_GETIPL (PSL) == 0x1F)) - ABORT (STOP_LOOP); - break; - -case BRW: - BRANCHW (brdisp); /* branch */ - if ((PC == fault_PC) && (PSL_GETIPL (PSL) == 0x1F)) - ABORT (STOP_LOOP); - break; - -case BSBB: - Write (SP - 4, PC, L_LONG, WA); /* push PC on stk */ - SP = SP - 4; /* decr stk ptr */ - BRANCHB (brdisp); /* branch */ - break; - -case BSBW: - Write (SP - 4, PC, L_LONG, WA); /* push PC on stk */ - SP = SP - 4; /* decr stk ptr */ - BRANCHW (brdisp); /* branch */ - break; - -case BGEQ: - if (!(cc & CC_N)) BRANCHB (brdisp); /* br if N = 0 */ - break; -case BLSS: - if (cc & CC_N) BRANCHB (brdisp); /* br if N = 1 */ - break; -case BNEQ: - if (!(cc & CC_Z)) BRANCHB (brdisp); /* br if Z = 0 */ - break; -case BEQL: - if (cc & CC_Z) BRANCHB (brdisp); /* br if Z = 1 */ - break; -case BVC: - if (!(cc & CC_V)) BRANCHB (brdisp); /* br if V = 0 */ - break; -case BVS: - if (cc & CC_V) BRANCHB (brdisp); /* br if V = 1 */ - break; -case BGEQU: - if (!(cc & CC_C)) BRANCHB (brdisp); /* br if C = 0 */ - break; -case BLSSU: - if (cc & CC_C) BRANCHB (brdisp); /* br if C = 1 */ - break; -case BGTR: - if (!(cc & (CC_N | CC_Z))) BRANCHB (brdisp); /* br if N | Z = 0 */ - break; -case BLEQ: - if (cc & (CC_N | CC_Z)) BRANCHB (brdisp); /* br if N | Z = 1 */ - break; -case BGTRU: - if (!(cc & (CC_C | CC_Z))) BRANCHB (brdisp); /* br if C | Z = 0 */ - break; -case BLEQU: - if (cc & (CC_C | CC_Z)) BRANCHB (brdisp); /* br if C | Z = 1 */ - break; - -/* Simple jumps and subroutine calls - op addr.ab - - opnd[0] = address -*/ - -case JSB: - Write (SP - 4, PC, L_LONG, WA); /* push PC on stk */ - SP = SP - 4; /* decr stk ptr */ -case JMP: - JUMP (op0); /* jump */ - break; - -case RSB: - temp = Read (SP, L_LONG, RA); /* get top of stk */ - SP = SP + 4; /* incr stk ptr */ - JUMP (temp); - break; - -/* SOB instructions - op idx.ml,disp.bb - - opnd[0] = index - spec = register/memory flag - rn = register number - va = memory address -*/ - -case SOBGEQ: - r = op0 - 1; /* decr index */ - WRITE_L (r); /* store result */ - CC_IIZP_L (r); /* set cc's */ - V_SUB_L (r, 1, op0); /* test for ovflo */ - if (r >= 0) BRANCHB (brdisp); /* if >= 0, branch */ - break; -case SOBGTR: - r = op0 - 1; /* decr index */ - WRITE_L (r); /* store result */ - CC_IIZP_L (r); /* set cc's */ - V_SUB_L (r, 1, op0); /* test for ovflo */ - if (r > 0) BRANCHB (brdisp); /* if >= 0, branch */ - break; - -/* AOB instructions - op limit.rl,idx.ml,disp.bb - - opnd[0] = limit - opnd[1] = index - spec = register/memory flag - rn = register number - va = memory address -*/ - -case AOBLSS: - r = op1 + 1; /* incr index */ - WRITE_L (r); /* store result */ - CC_IIZP_L (r); /* set cc's */ - V_ADD_L (r, 1, op1); /* test for ovflo */ - if (r < op0) BRANCHB (brdisp); /* if < lim, branch */ - break; -case AOBLEQ: - r = op1 + 1; /* incr index */ - WRITE_L (r); /* store result */ - CC_IIZP_L (r); /* set cc's */ - V_ADD_L (r, 1, op1); /* test for ovflo */ - if (r <= op0) BRANCHB (brdisp); /* if < lim, branch */ - break; - -/* ACB instructions - op limit.rx,add.rx,index.mx,disp.bw - - opnd[0] = limit - opnd[1] = adder - opnd[2] = index - spec = register/memory flag - rn = register number - va = memory address -*/ - -case ACBB: - r = (op2 + op1) & BMASK; /* calc result */ - WRITE_B (r); /* store result */ - 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); - break; -case ACBW: - r = (op2 + op1) & WMASK; /* calc result */ - WRITE_W (r); /* store result */ - 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); - break; -case ACBL: - r = (op2 + op1) & LMASK; /* calc result */ - WRITE_L (r); /* store result */ - 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); - break; - -/* CASE instructions - casex sel.rx,base.rx,lim.rx - - opnd[0] = selector - opnd[1] = base - opnd[2] = limit -*/ - -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); } - 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); } - 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); } - break; - -/* Branch on bit instructions - bbxy pos.rl,op.wb,disp.bb - - opnd[0] = position - opnd[1] = register number/memory flag - opnd[2] = memory address, if memory -*/ - -case BBS: - if (op_bb_n (opnd, acc)) BRANCHB (brdisp); /* br if bit set */ - break; -case BBC: - if (!op_bb_n (opnd, acc)) BRANCHB (brdisp); /* br if bit clr */ - break; -case BBSS: case BBSSI: - if (op_bb_x (opnd, 1, acc)) BRANCHB (brdisp); /* br if set, set */ - break; -case BBCC: case BBCCI: - if (!op_bb_x (opnd, 0, acc)) BRANCHB (brdisp); /* br if clr, clr*/ - break; -case BBSC: - if (op_bb_x (opnd, 0, acc)) BRANCHB (brdisp); /* br if clr, set */ - break; -case BBCS: - if (!op_bb_x (opnd, 1, acc)) BRANCHB (brdisp); /* br if set, clr */ - break; -case BLBS: - if (op0 & 1) BRANCHB (brdisp); /* br if bit set */ - break; -case BLBC: - if ((op0 & 1) == 0) BRANCHB (brdisp); /* br if bit clear */ - break; - -/* Extract field instructions - ext?v pos.rl,size.rb,base.wb,dst.wl - - opnd[0] = position - opnd[1] = size - opnd[2] = register number/memory flag - opnd[3] = register content/memory address - spec = register/memory flag - rn = register number - va = memory address -*/ - -case EXTV: - r = op_extv (opnd, vfldrp1, acc); /* get field */ - if (r & byte_sign[op1]) r = r | ~byte_mask[op1]; - WRITE_L (r); /* store field */ - CC_IIZP_L (r); /* set cc's */ - break; -case EXTZV: - r = op_extv (opnd, vfldrp1, acc); /* get field */ - WRITE_L (r); /* store field */ - CC_IIZP_L (r); /* set cc's */ - break; - -/* Compare field instructions - cmp?v pos.rl,size.rb,base.wb,src2.rl - - opnd[0] = position - opnd[1] = size - opnd[2] = register number/memory flag - opnd[3] = register content/memory address - opnd[4] = source2 -*/ - -case CMPV: - r = op_extv (opnd, vfldrp1, acc); /* get field */ - if (r & byte_sign[op1]) r = r | ~byte_mask[op1]; - CC_CMP_L (r, op4); /* set cc's */ - break; -case CMPZV: - r = op_extv (opnd, vfldrp1, acc); /* get field */ - CC_CMP_L (r, op4); /* set cc's */ - break; - -/* Find first field instructions - ff? pos.rl,size.rb,base.wb,dst.wl - - opnd[0] = position - opnd[1] = size - opnd[2] = register number/memory flag - opnd[3] = register content/memory address - spec = register/memory flag - rn = register number - va = memory address -*/ - -case FFS: - r = op_extv (opnd, vfldrp1, acc); /* get field */ - temp = op_ffs (r, op1); /* find first 1 */ - WRITE_L (op0 + temp); /* store result */ - cc = r? 0: CC_Z; /* set cc's */ - break; -case FFC: - r = op_extv (opnd, vfldrp1, acc); /* get field */ - r = r ^ byte_mask[op1]; /* invert bits */ - temp = op_ffs (r, op1); /* find first 1 */ - WRITE_L (op0 + temp); /* store result */ - cc = r? 0: CC_Z; /* set cc's */ - break; - -/* Insert field instruction - insv src.rl,pos.rb,size.rl,base.wb - - opnd[0] = source - opnd[1] = position - opnd[2] = size - opnd[3] = register number/memory flag - opnd[4] = register content/memory address -*/ - -case INSV: - op_insv (opnd, vfldrp1, acc); /* insert field */ - break; - -/* Call and return - call? arg.rx,proc.ab - - opnd[0] = argument - opnd[1] = procedure address -*/ - -case CALLS: - cc = op_call (opnd, TRUE, acc); - break; -case CALLG: - cc = op_call (opnd, FALSE, acc); - break; -case RET: - cc = op_ret (acc); - break; - -/* Miscellaneous instructions */ - -case HALT: - if (PSL & PSL_CUR) RSVD_INST_FAULT; /* not kern? rsvd inst */ - 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: - SETPC (fault_PC); - cc = intexc (SCB_BPT, cc, 0, IE_EXC); - GET_CUR; - break; -case XFC: - SETPC (fault_PC); - cc = intexc (SCB_XFC, cc, 0, IE_EXC); - GET_CUR; - break; -case BISPSW: - if (opnd[0] & PSW_MBZ) RSVD_OPND_FAULT; - PSL = PSL | (opnd[0] & ~CC_MASK); - cc = cc | (opnd[0] & CC_MASK); - break; -case BICPSW: - if (opnd[0] & PSW_MBZ) RSVD_OPND_FAULT; - PSL = PSL & ~opnd[0]; - cc = cc & ~opnd[0]; - break; -case MOVPSL: - r = PSL | cc; - WRITE_L (r); - break; -case PUSHR: - op_pushr (opnd, acc); - break; -case POPR: - op_popr (opnd, acc); - break; -case INDEX: - if ((op0 < op1) || (op0 > op2)) SET_TRAP (TRAP_SUBSCR); - r = (op0 + op4) * op3; - WRITE_L (r); - CC_IIZZ_L (r); - break; - -/* Queue and interlocked queue */ - -case INSQUE: - cc = op_insque (opnd, acc); - break; -case REMQUE: - cc = op_remque (opnd, acc); - break; -case INSQHI: - cc = op_insqhi (opnd, acc); - break; -case INSQTI: - cc = op_insqti (opnd, acc); - break; -case REMQHI: - cc = op_remqhi (opnd, acc); - break; -case REMQTI: - cc = op_remqti (opnd, acc); - break; - -/* String instructions */ - -case MOVC3: -case MOVC5: - cc = op_movc (opnd, opc & 4, acc); - break; -case CMPC3: -case CMPC5: - cc = op_cmpc (opnd, opc & 4, acc); - break; -case LOCC: -case SKPC: - cc = op_locskp (opnd, opc & 1, acc); - break; -case SCANC: -case SPANC: - cc = op_scnspn (opnd, opc & 1, acc); - break; - -/* Floating point instructions */ - -case TSTF: case TSTD: - r = op_movfd (op0); - CC_IIZZ_FP (r); - break; -case TSTG: - r = op_movg (op0); - CC_IIZZ_FP (r); - break; - -case MOVF: - r = op_movfd (op0); - WRITE_L (r); - CC_IIZP_FP (r); - break; -case MOVD: - if ((r = op_movfd (op0)) == 0) op1 = 0; - WRITE_Q (r, op1); - CC_IIZP_FP (r); - break; -case MOVG: - if ((r = op_movg (op0)) == 0) op1 = 0; - WRITE_Q (r, op1); - CC_IIZP_FP (r); - break; - -case MNEGF: - r = op_mnegfd (op0); - WRITE_L (r); - CC_IIZZ_FP (r); - break; -case MNEGD: - if ((r = op_mnegfd (op0)) == 0) op1 = 0; - WRITE_Q (r, op1); - CC_IIZZ_FP (r); - break; -case MNEGG: - if ((r = op_mnegg (op0)) == 0) op1 = 0; - WRITE_Q (r, op1); - CC_IIZZ_FP (r); - break; - -case CMPF: - cc = op_cmpfd (op0, 0, op1, 0); - break; -case CMPD: - cc = op_cmpfd (op0, op1, op2, op3); - break; -case CMPG: - cc = op_cmpg (op0, op1, op2, op3); - break; - -case CVTBF: - r = op_cvtifdg (SXTB (op0), NULL, opc); - WRITE_L (r); - CC_IIZZ_FP (r); - break; -case CVTWF: - r = op_cvtifdg (SXTW (op0), NULL, opc); - WRITE_L (r); - CC_IIZZ_FP (r); - break; -case CVTLF: - r = op_cvtifdg (op0, NULL, opc); - WRITE_L (r); - CC_IIZZ_FP (r); - break; -case CVTBD: case CVTBG: - r = op_cvtifdg (SXTB (op0), &rh, opc); - WRITE_Q (r, rh); - CC_IIZZ_FP (r); - break; -case CVTWD: case CVTWG: - r = op_cvtifdg (SXTW (op0), &rh, opc); - WRITE_Q (r, rh); - CC_IIZZ_FP (r); - break; -case CVTLD: case CVTLG: - r = op_cvtifdg (op0, &rh, opc); - WRITE_Q (r, rh); - CC_IIZZ_FP (r); - break; - -case CVTFB: case CVTDB: case CVTGB: - r = op_cvtfdgi (opnd, &temp, opc) & BMASK; - WRITE_B (r); - CC_IIZZ_B (r); - cc = cc | temp; - break; -case CVTFW: case CVTDW: case CVTGW: - r = op_cvtfdgi (opnd, &temp, opc) & WMASK; - WRITE_W (r); - CC_IIZZ_W (r); - cc = cc | temp; - break; -case CVTFL: case CVTDL: case CVTGL: -case CVTRFL: case CVTRDL: case CVTRGL: - r = op_cvtfdgi (opnd, &temp, opc) & LMASK; - WRITE_L (r); - CC_IIZZ_L (r); - cc = cc | temp; - break; - -case CVTFD: - r = op_movfd (op0); - WRITE_Q (r, 0); - CC_IIZZ_FP (r); - break; -case CVTDF: - r = op_cvtdf (opnd); - WRITE_L (r); - CC_IIZZ_FP (r); - break; -case CVTFG: - r = op_cvtfg (opnd, &rh); - WRITE_Q (r, rh); - CC_IIZZ_FP (r); - break; -case CVTGF: - r = op_cvtgf (opnd); - WRITE_L (r); - CC_IIZZ_FP (r); - break; - -case ADDF2: case ADDF3: - r = op_addf (opnd, FALSE); - WRITE_L (r); - CC_IIZZ_FP (r); - break; -case ADDD2: case ADDD3: - r = op_addd (opnd, &rh, FALSE); - WRITE_Q (r, rh); - CC_IIZZ_FP (r); - break; -case ADDG2: case ADDG3: - r = op_addg (opnd, &rh, FALSE); - WRITE_Q (r, rh); - CC_IIZZ_FP (r); - break; -case SUBF2: case SUBF3: - r = op_addf (opnd, TRUE); - WRITE_L (r); - CC_IIZZ_FP (r); - break; -case SUBD2: case SUBD3: - r = op_addd (opnd, &rh, TRUE); - WRITE_Q (r, rh); - CC_IIZZ_FP (r); - break; -case SUBG2: case SUBG3: - r = op_addg (opnd, &rh, TRUE); - WRITE_Q (r, rh); - CC_IIZZ_FP (r); - break; -case MULF2: case MULF3: - r = op_mulf (opnd); - WRITE_L (r); - CC_IIZZ_FP (r); - break; -case MULD2: case MULD3: - r = op_muld (opnd, &rh); - WRITE_Q (r, rh); - CC_IIZZ_FP (r); - break; -case MULG2: case MULG3: - r = op_mulg (opnd, &rh); - WRITE_Q (r, rh); - CC_IIZZ_FP (r); - break; -case DIVF2: case DIVF3: - r = op_divf (opnd); - WRITE_L (r); - CC_IIZZ_FP (r); - break; -case DIVD2: case DIVD3: - r = op_divd (opnd, &rh); - WRITE_Q (r, rh); - CC_IIZZ_FP (r); - break; -case DIVG2: case DIVG3: - r = op_divg (opnd, &rh); - WRITE_Q (r, rh); - CC_IIZZ_FP (r); - break; - -case ACBF: - r = op_addf (opnd + 1, FALSE); /* add + index */ - temp = op_cmpfd (r, 0, op0, 0); /* result : limit */ - 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); - break; -case ACBD: - r = op_addd (opnd + 2, &rh, FALSE); - temp = op_cmpfd (r, rh, op0, op1); - 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); - break; -case ACBG: - r = op_addg (opnd + 2, &rh, FALSE); - temp = op_cmpg (r, rh, op0, op1); - 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); - break; - -/* EMODF - - op0 = multiplier - op1 = extension - op2 = multiplicand - op3:op4 = integer destination (int.wl) - op5:op6 = floating destination (flt.wl) -*/ - -case EMODF: - r = op_emodf (opnd, &temp, &flg); - if (op5 < 0) Read (op6, L_LONG, WA); - if (op3 >= 0) R[op3] = temp; - else Write (op4, temp, L_LONG, WA); - WRITE_L (r); - CC_IIZZ_FP (r); - if (flg) { V_INTOV; } - break; - -/* EMODD, EMODG - - op0:op1 = multiplier - op2 = extension - op3:op4 = multiplicand - op5:op6 = integer destination (int.wl) - op7:op8 = floating destination (flt.wq) -*/ - -case EMODD: - r = op_emodd (opnd, &rh, &temp, &flg); - if (op7 < 0) Read (op8, L_LONG, WA); - if (op5 >= 0) R[op5] = temp; - else Write (op6, temp, L_LONG, WA); - WRITE_Q (r, rh); - CC_IIZZ_FP (r); - if (flg) { V_INTOV; } - break; - -case EMODG: - r = op_emodg (opnd, &rh, &temp, &flg); - if (op7 < 0) Read (op8, L_LONG, WA); - if (op5 >= 0) R[op5] = temp; - else Write (op6, temp, L_LONG, WA); - WRITE_Q (r, rh); - CC_IIZZ_FP (r); - if (flg) { V_INTOV; } - break; - -/* POLY */ - -case POLYF: - op_polyf (opnd, acc); - CC_IIZZ_FP (R[0]); - break; - -case POLYD: - op_polyd (opnd, acc); - CC_IIZZ_FP (R[0]); - break; - -case POLYG: - op_polyg (opnd, acc); - CC_IIZZ_FP (R[0]); - break; - -/* Operating system instructions */ - -case CHMK: case CHME: case CHMS: case CHMU: - cc = op_chm (opnd, cc, opc); /* CHMx */ - GET_CUR; /* update cur mode */ - SET_IRQL; /* update intreq */ - break; -case REI: - cc = op_rei (acc); /* REI */ - GET_CUR; /* update cur mode */ - SET_IRQL; /* update intreq */ - break; -case LDPCTX: - op_ldpctx (acc); - break; -case SVPCTX: - op_svpctx (acc); - break; -case PROBER: case PROBEW: - cc = (cc & CC_C) | op_probe (opnd, opc & 1); - break; -case MTPR: - cc = (cc & CC_C) | op_mtpr (opnd); - SET_IRQL; /* update intreq */ - break; -case MFPR: - r = op_mfpr (opnd); - WRITE_L (r); - CC_IIZP_L (r); - break; - -/* Emulated instructions */ - -case CVTPL: - opnd[2] = (opnd[2] >= 0)? ~opnd[2]: opnd[3]; -case MOVP: case CMPP3: case CMPP4: case CVTLP: -case CVTPS: case CVTSP: case CVTTP: case CVTPT: -case ADDP4: case ADDP6: case SUBP4: case SUBP6: -case MULP: case DIVP: case ASHP: case CRC: -case MOVTC: case MOVTUC: case MATCHC: case EDITPC: - cc = op_emulate (opnd, cc, opc, acc); - break; -default: - RSVD_INST_FAULT; - break; } /* end case op */ -} /* end for */ -ABORT (STOP_UNKNOWN); -} /* end sim_instr */ - -/* Prefetch buffer routine - - Prefetch buffer state - - ibufl, ibufh = the prefetch buffer - ibcnt = number of bytes available (0, 4, 8) - ppc = physical PC - - The get_istr routines fetches the indicated number of bytes from - the prefetch buffer. Although it is complicated, it is faster - than calling Read on every byte of the instruction stream. - - If the prefetch buffer has enough bytes, the required bytes are - extracted from the prefetch buffer and returned. If it does not - have enough bytes, enough prefetch words are fetched until there - are. A longword is only prefetched if data is needed from it, - so any translation errors are real. -*/ - -int32 get_istr (int32 lnt, int32 acc) -{ -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 */ -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; } -else if (bo) { /* unaligned lw? */ - 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; } -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 -*/ - -/* Reset */ - -t_stat cpu_reset (DEVICE *dptr) -{ -mem_err = 0; -crd_err = 0; -hlt_pin = 0; -PSL = PSL_IS | PSL_IPL1F; -SISR = 0; -ASTLVL = 4; -MSER = 0; -CADR = 0; -mapen = 0; -if (M == NULL) M = calloc (((uint32) MEMSIZE) >> 2, sizeof (int32)); -if (M == NULL) return SCPE_MEM; -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; -} - -/* Bootstrap */ - -t_stat cpu_boot (int32 unitno, DEVICE *dptr) -{ -extern int32 clk_csr; -extern t_stat qba_powerup (void); -extern t_stat sysd_powerup (void); -extern t_stat todr_powerup (void); -extern uint32 *rom; -extern t_stat load_cmd (int32 flag, char *cptr); -extern FILE *sim_log; -t_stat r; - -qba_powerup (); -sysd_powerup (); -todr_powerup (); -PC = ROMBASE; -PSL = PSL_IS | PSL_IPL1F; -conpc = 0; -conpsl = PSL_IS | PSL_IPL1F | CON_PWRUP; -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"); - r = load_cmd (0, "-R ka655.bin"); - if (r != SCPE_OK) return r; } -return SCPE_OK; -} - -/* Memory examine */ - -t_stat cpu_ex (t_value *vptr, t_addr exta, UNIT *uptr, int32 sw) -{ -int32 st; -uint32 addr = (uint32) exta; - -if (vptr == NULL) return SCPE_ARG; -if (sw & SWMASK ('V')) addr = Test (addr, RD, &st); -else addr = addr & PAMASK; -if (ADDR_IS_MEM (addr) || ADDR_IS_CDG (addr) || - ADDR_IS_ROM (addr) || ADDR_IS_NVR (addr)) { - *vptr = (uint32) ReadB (addr); - return SCPE_OK; } -return SCPE_NXM; -} - -/* Memory deposit */ - -t_stat cpu_dep (t_value val, t_addr exta, UNIT *uptr, int32 sw) -{ -int32 st; -uint32 addr = (uint32) exta; - -if (sw & SWMASK ('V')) addr = Test (addr, RD, &st); -else addr = addr & PAMASK; -if (ADDR_IS_MEM (addr) || ADDR_IS_CDG (addr) || - ADDR_IS_NVR (addr)) { - WriteB (addr, (int32) val); - return SCPE_OK; } -if (ADDR_IS_ROM (addr)) { - rom_wr (addr, (int32) val, L_BYTE); - return SCPE_OK; } -return SCPE_NXM; -} - -/* Memory allocation */ - -t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -int32 mc = 0; -uint32 i, clim; -uint32 *nM = NULL; - -if ((val <= 0) || (val > MAXMEMSIZE)) 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; -nM = calloc (val >> 2, sizeof (uint32)); -if (nM == NULL) return SCPE_MEM; -clim = (uint32) ((((uint32) val) < MEMSIZE)? val: MEMSIZE); -for (i = 0; i < clim; i = i + 4) nM[i >> 2] = M[i >> 2]; -free (M); -M = nM; -MEMSIZE = val; -return SCPE_OK; } - -/* Virtual address translation */ - -t_stat cpu_show_virt (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -t_stat r; -uint32 va, pa; -int32 st; -static const char *mm_str[] = { - "Access control violation", - "Length violation", - "Process PTE access control violation", - "Process PTE length violation", - "Translation not valid", - "Internal error", - "Process PTE translation not valid" }; - -if (cptr == NULL) return SCPE_ARG; -va = (uint32) get_uint (cptr, 16, 0xFFFFFFFF, &r); -if (r != SCPE_OK) return SCPE_ARG; -pa = Test (va, RD, &st); -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 deleted file mode 100644 index ad1f6c23..00000000 --- a/VAX/vax_cpu1.c +++ /dev/null @@ -1,1492 +0,0 @@ -/* vax_cpu1.c: VAX complex instructions - - 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"), - 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. - - 30-Apr-02 RMS Fixed interrupt/exception handler to clear traps - 17-Apr-02 RMS Fixed pos > 31 test in bit fields (should be unsigned) - 14-Apr-02 RMS Fixed prv_mode handling for interrupts (found by Tim Stark) - Fixed PROBEx to mask mode to 2b (found by Kevin Handy) - - This module contains the instruction simulators for - - Field instructions: - - BBS, BBC, BBSSI, BBCCI - - BBSC, BBCC, BBCS, BBSS - - EXTV, EXTZV, CMPV, CMPZV - - FFS, FFC, INSV - - Call/return and push/pop instructions: - - CALLS, CALLG, RET - - PUSHR, POPR - - Queue instructions: - - INSQUE, REMQUE - - INSQHI, INSQTI, REMQHI, REMQTI - - String instructions: - - MOVC3, MOVC5, CMPC3, CMPC5 - - LOCC, SKPC, SCANC, SPANC - - Operating system interface instructions: - - CHMK, CHME, CHMS, CHMU - - PROBER, PROBEW, REI - - MTPR, MFPR - - LDPCTX, SVPCTX - - (interrupt and exception routine) - - Emulated instructions: - - MOVP, CMPP3, CMPP4, ASHP - - ADDP4, ADDP6, SUBP4, SUBP6 - - MULP, DIVP, CVTLP, CVTPL, - - CVTPT, CVTTP, CVTPS, CVTSP - - EDITPC, CRC - - MATCHC, MOVTC, MOVTUC -*/ - -#include "vax_defs.h" - -static const uint8 rcnt[128] = { - 0, 4, 4, 8, 4, 8, 8,12, 4, 8, 8,12, 8,12,12,16, /* 00 - 0F */ - 4, 8, 8,12, 8,12,12,16, 8,12,12,16,12,16,16,20, /* 10 - 1F */ - 4, 8, 8,12, 8,12,12,16, 8,12,12,16,12,16,16,20, /* 20 - 2F */ - 8,12,12,16,12,16,16,20,12,16,16,20,16,20,20,24, /* 30 - 3F */ - 4, 8, 8,12, 8,12,12,16, 8,12,12,16,12,16,16,20, /* 40 - 4F */ - 8,12,12,16,12,16,16,20,12,16,16,20,16,20,20,24, /* 50 - 5F */ - 8,12,12,16,12,16,16,20,12,16,16,20,16,20,20,24, /* 60 - 6F */ -12,16,16,20,16,20,20,24,16,20,20,24,20,24,24,28 /* 70 - 7F */ -}; - -int32 last_chm = 0; - -extern uint32 *M; -extern uint32 byte_mask[33]; -extern int32 R[16]; -extern int32 STK[5]; -extern int32 PSL; -extern int32 SCBB, PCBB, SBR, SLR; -extern int32 P0BR, P0LR, P1BR, P1LR; -extern int32 ASTLVL, SISR, mapen; -extern int32 CADR, MSER; -extern int32 trpirq; -extern int32 p1, p2; -extern int32 conpsl, conpc; -extern int32 fault_PC; -extern int32 pcq[PCQ_SIZE]; -extern int32 pcq_p; -extern int32 in_ie; -extern int32 mchk_va; -extern int32 sim_interval; -extern int32 ibcnt, ppc; -extern int32 cpu_log; -extern FILE *sim_log; - -extern int32 Read (uint32 va, int32 lnt, int32 acc); -extern void Write (uint32 va, int32 val, int32 lnt, int32 acc); -extern int32 Test (uint32 va, int32 acc, int32 *status); -extern int32 ReadLP (uint32 pa); -extern void WriteLP (uint32 pa, int32 val); -extern void set_map_reg (void); -extern void zap_tb (int stb); -extern void zap_tb_ent (uint32 va); -extern t_bool chk_tb_ent (uint32 va); -extern int32 ReadIPR (int32 rg); -extern void WriteIPR (int32 rg, int32 val); -extern jmp_buf save_env; - -/* Branch on bit and no modify - Branch on bit and modify - - opnd[0] = position (pos.rl) - opnd[1] = register number/memory flag - opnd[2] = memory address, if memory - Returns bit to be tested -*/ - -int32 op_bb_n (int32 *opnd, int32 acc) -{ -int32 pos = opnd[0]; -int32 rn = opnd[1]; -int32 ea, by; - -if (rn >= 0) { /* register? */ - if (((uint32) pos) > 31) RSVD_OPND_FAULT; /* pos > 31? fault */ - return (R[rn] >> pos) & 1; } /* get bit */ -ea = opnd[2] + (pos >> 3); /* base byte addr */ -pos = pos & 07; /* pos in byte */ -by = Read (ea, L_BYTE, RA); /* read byte */ -return ((by >> pos) & 1); /* get bit */ -} - -int32 op_bb_x (int32 *opnd, int32 newb, int32 acc) -{ -int32 pos = opnd[0]; -int32 rn = opnd[1]; -int32 ea, by, bit; - -if (rn >= 0) { /* register? */ - if (((uint32) pos) > 31) RSVD_OPND_FAULT; /* pos > 31? fault */ - bit = (R[rn] >> pos) & 1; /* get bit */ - R[rn] = newb? (R[rn] | (1u << pos)): (R[rn] & ~(1u << pos)); - return bit; } -ea = opnd[2] + (pos >> 3); /* base byte addr */ -pos = pos & 07; /* pos in byte */ -by = Read (ea, L_BYTE, WA); /* read byte */ -bit = (by >> pos) & 1; /* get bit */ -by = newb? (by | (1u << pos)): (by & ~(1u << pos)); /* change bit */ -Write (ea, by, L_BYTE, WA); /* rewrite byte */ -return bit; -} - -/* Extract field - - opnd[0] = position (pos.rl) - opnd[1] = size (size.rb) - opnd[2] = register number/memory flag - opnd[3] = register content/memory address - - If the field is in a register, rn + 1 is in vfldrp1 -*/ - -int32 op_extv (int32 *opnd, int32 vfldrp1, int32 acc) -{ -int32 pos = opnd[0]; -int32 size = opnd[1]; -int32 rn = opnd[2]; -uint32 wd = opnd[3]; -int32 ba, wd1 = 0; - -if (size == 0) return 0; /* size 0? field = 0 */ -if (size > 32) RSVD_OPND_FAULT; /* size > 32? fault */ -if (rn >= 0) { /* register? */ - if (((uint32) pos) > 31) RSVD_OPND_FAULT; /* pos > 31? fault */ - if (pos) wd = (wd >> pos) | (((uint32) vfldrp1) << (32 - pos)); } -else { ba = wd + (pos >> 3); /* base byte addr */ - pos = (pos & 07) | ((ba & 03) << 3); /* bit offset */ - ba = ba & ~03; /* lw align base */ - wd = Read (ba, L_LONG, RA); /* read field */ - if ((size + pos) > 32) wd1 = Read (ba + 4, L_LONG, RA); - if (pos) wd = (wd >> pos) | (((uint32) wd1) << (32 - pos)); } -return wd & byte_mask[size]; -} - -/* Insert field - - opnd[0] = field (src.rl) - opnd[1] = position (pos.rl) - opnd[2] = size (size.rb) - opnd[3] = register number/memory flag - opnd[4] = register content/memory address - - If the field is in a register, rn + 1 is in vfldrp1 -*/ - -void op_insv (int32 *opnd, int32 vfldrp1, int32 acc) -{ -uint32 ins = opnd[0]; -int32 pos = opnd[1]; -int32 size = opnd[2]; -int32 rn = opnd[3]; -int32 val, mask, ba, wd, wd1; - -if (size == 0) return; /* size = 0? done */ -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); } - mask = byte_mask[size] << pos; /* insert field */ - val = ins << pos; - R[rn] = (R[rn] & ~mask) | (val & mask); } -else { ba = opnd[4] + (pos >> 3); /* base byte addr */ - pos = (pos & 07) | ((ba & 03) << 3); /* bit offset */ - 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); } - mask = byte_mask[size] << pos; /* insert field */ - val = ins << pos; - Write (ba, (wd & ~mask) | (val & mask), L_LONG, WA); } -return; -} - -/* Find first */ - -int32 op_ffs (uint32 wd, int32 size) -{ -int32 i; - -for (i = 0; wd; i++, wd = wd >> 1) if (wd & 1) return i; -return size; -} - -#define CALL_DV 0x8000 /* DV set */ -#define CALL_IV 0x4000 /* IV set */ -#define CALL_MBZ 0x3000 /* MBZ */ -#define CALL_MASK 0x0FFF /* mask */ -#define CALL_V_SPA 30 /* SPA */ -#define CALL_M_SPA 03 -#define CALL_V_S 29 /* S flag */ -#define CALL_S (1 << CALL_V_S) -#define CALL_V_MASK 16 -#define CALL_PUSH(n) if ((mask >> (n)) & 1) { \ - tsp = tsp - 4; \ - Write (tsp, R[n], L_LONG, WA); } -#define CALL_GETSPA(x) (((x) >> CALL_V_SPA) & CALL_M_SPA) -#define RET_POP(n) if ((spamask >> (n + CALL_V_MASK)) & 1) { \ - R[n] = Read (tsp, L_LONG, RA); \ - tsp = tsp + 4; } -#define PUSHR_PUSH(n) CALL_PUSH(n) -#define POPR_POP(n) if ((mask >> (n)) & 1) { \ - R[n] = Read (SP, L_LONG, RA); \ - SP = SP + 4; } - -/* CALLG, CALLS - - opnd[0] = argument (arg.rx) - opnd[1] = procedure address (adr.ab) - flg = CALLG (0), CALLS (1) - acc = access mask - - These instructions implement a generalized procedure call and return facility. - The principal data structure involved is the stack frame. - CALLS and CALLG build a stack frame in the following format: - - - +---------------------------------------------------------------+ - | condition handler (initially 0) | - +---+-+-+-----------------------+--------------------+----------+ - |SPA|S|0| entry mask<11:0> | saved PSW<15:5> | 0 0 0 0 0| - +---+-+-+-----------------------+--------------------+----------+ - | saved AP | - +---------------------------------------------------------------+ - | saved FP | - +---------------------------------------------------------------+ - | saved PC | - +---------------------------------------------------------------+ - | saved R0 (...) | - +---------------------------------------------------------------+ - . . - . (according to entry mask<11:0>) . - . . - +---------------------------------------------------------------+ - | saved R11 (...) | - +---------------+-----------------------------------------------+ - | #args (CALLS) | (0-3 bytes needed to align stack) | - +---------------+-----------------------------------------------+ - | | 0 0 0 (CALLS) | - +---------------+-----------------------------------------------+ - - RET expects to find this structure based at the frame pointer (FP). - - For CALLG and CALLS, the entry mask specifies the new settings of - DV and IV, and also which registers are to be saved on entry: - - 15 14 13 12 11 0 - +--+--+-----+----------------------------------+ - |DV|IV| MBZ | register mask | - +--+--+-----+----------------------------------+ - - CALLG/CALLS operation: - - read the procedure entry mask - make sure that the stack frame will be accessible - if CALLS, push the number of arguments onto the stack - align the stack to the next lower longword boundary - push the registers specified by the procedure entry mask - push PC, AP, FP, saved SPA/S0/mask/PSW, condition handler - update PC, SP, FP, AP - update PSW traps, clear condition codes -*/ - -int32 op_call (int32 *opnd, t_bool gs, int32 acc) -{ -int32 addr = opnd[1]; -int32 mask, stklen, tsp, wd; - -mask = Read (addr, L_WORD, RA); /* get proc mask */ -if (mask & CALL_MBZ) RSVD_OPND_FAULT; /* test mbz */ -stklen = rcnt[mask & 077] + rcnt[(mask >> 6) & 077] + (gs? 24: 20); -Read (SP - stklen, L_BYTE, WA); /* wchk stk */ -if (gs) { - Write (SP - 4, opnd[0], L_LONG, WA); /* if S, push #arg */ - SP = SP - 4; } /* stack is valid */ -tsp = SP & ~CALL_M_SPA; /* lw align stack */ -CALL_PUSH (11); /* check mask bits, */ -CALL_PUSH (10); /* push sel reg */ -CALL_PUSH (9); -CALL_PUSH (8); -CALL_PUSH (7); -CALL_PUSH (6); -CALL_PUSH (5); -CALL_PUSH (4); -CALL_PUSH (3); -CALL_PUSH (2); -CALL_PUSH (1); -CALL_PUSH (0); -Write (tsp - 4, PC, L_LONG, WA); /* push PC */ -Write (tsp - 8, FP, L_LONG, WA); /* push AP */ -Write (tsp - 12, AP, L_LONG, WA); /* push FP */ -wd = ((SP & CALL_M_SPA) << CALL_V_SPA) | (gs << CALL_V_S) | - ((mask & CALL_MASK) << CALL_V_MASK) | (PSL & 0xFFE0); -Write (tsp - 16, wd, L_LONG, WA); /* push spa/s/mask/psw */ -Write (tsp - 20, 0, L_LONG, WA); /* push cond hdlr */ -if (gs) AP = SP; /* update AP */ -else AP = opnd[0]; -SP = FP = tsp - 20; /* update FP, SP */ -PSL = (PSL & ~(PSW_DV | PSW_FU | PSW_IV)) | /* update PSW */ - ((mask & CALL_DV)? PSW_DV: 0) | - ((mask & CALL_IV)? PSW_IV: 0); -JUMP (addr + 2); /* new PC */ -return 0; /* new cc's */ -} - -int32 op_ret (int32 acc) -{ -int32 spamask, stklen, newpc, nargs; -int32 tsp = FP; - -spamask = Read (tsp + 4, L_LONG, RA); /* spa/s/mask/psw */ -if (spamask & PSW_MBZ) RSVD_OPND_FAULT; /* test mbz */ -stklen = rcnt[(spamask >> CALL_V_MASK) & 077] + - rcnt[(spamask >> (CALL_V_MASK + 6)) & 077] + ((spamask & CALL_S)? 23: 19); -Read (tsp + stklen, L_BYTE, RA); /* rchk stk end */ -AP = Read (tsp + 8, L_LONG, RA); /* restore AP */ -FP = Read (tsp + 12, L_LONG, RA); /* restore FP */ -newpc = Read (tsp + 16, L_LONG, RA); /* get new PC */ -tsp = tsp + 20; /* update stk ptr */ -RET_POP (0); /* chk mask bits, */ -RET_POP (1); /* pop sel regs */ -RET_POP (2); -RET_POP (3); -RET_POP (4); -RET_POP (5); -RET_POP (6); -RET_POP (7); -RET_POP (8); -RET_POP (9); -RET_POP (10); -RET_POP (11); -SP = tsp + CALL_GETSPA (spamask); /* dealign stack */ -if (spamask & CALL_S) { /* CALLS? */ - nargs = Read (SP, L_LONG, RA); /* read #args */ - SP = SP + 4 + ((nargs & BMASK) << 2); } /* pop arg list */ -PSL = (PSL & ~(PSW_DV | PSW_FU | PSW_IV | PSW_T)) | /* reset PSW */ - (spamask & (PSW_DV | PSW_FU | PSW_IV | PSW_T)); -JUMP (newpc); /* set new PC */ -return spamask & (CC_MASK); /* return cc's */ -} - -/* PUSHR and POPR */ - -void op_pushr (int32 *opnd, int32 acc) -{ -int32 mask = opnd[0] & 0x7FFF; -int32 stklen, tsp; - -if (mask == 0) return; -stklen = rcnt[(mask >> 7) & 0177] + rcnt[mask & 0177] + - ((mask & 0x4000)? 4: 0); -Read (SP - stklen, L_BYTE, WA); /* wchk stk end */ -tsp = SP; /* temp stk ptr */ -PUSHR_PUSH (14); /* check mask bits, */ -PUSHR_PUSH (13); /* push sel reg */ -PUSHR_PUSH (12); -PUSHR_PUSH (11); -PUSHR_PUSH (10); -PUSHR_PUSH (9); -PUSHR_PUSH (8); -PUSHR_PUSH (7); -PUSHR_PUSH (6); -PUSHR_PUSH (5); -PUSHR_PUSH (4); -PUSHR_PUSH (3); -PUSHR_PUSH (2); -PUSHR_PUSH (1); -PUSHR_PUSH (0); -SP = tsp; /* update stk ptr */ -return; -} - -void op_popr (int32 *opnd, int32 acc) -{ -int32 mask = opnd[0] & 0x7FFF; -int32 stklen; - -if (mask == 0) return; -stklen = rcnt[(mask >> 7) & 0177] + rcnt[mask & 0177] + - ((mask & 0x4000)? 4: 0); -Read (SP + stklen - 1, L_BYTE, RA); /* rchk stk end */ -POPR_POP (0); /* check mask bits, */ -POPR_POP (1); /* pop sel regs */ -POPR_POP (2); -POPR_POP (3); -POPR_POP (4); -POPR_POP (5); -POPR_POP (6); -POPR_POP (7); -POPR_POP (8); -POPR_POP (9); -POPR_POP (10); -POPR_POP (11); -POPR_POP (12); -POPR_POP (13); -if (mask & 0x4000) SP = Read (SP, L_LONG, RA); /* if pop SP, no inc */ -return; -} - -/* INSQUE - - opnd[0] = entry address (ent.ab) - opnd[1] = predecessor address (pred.ab) - - Condition codes returned to caller on comparison of (ent):(ent+4). - All writes must be checked before any writes are done. - - Pictorially: - - BEFORE AFTER - - P: S P: E W - P+4: (n/a) P+4: (n/a) - - E: --- E: S W - E+4: --- E+4: P W - - S: (n/a) S: (n/a) - S+4: P S+4: E W - - s+4 must be tested with a read modify rather than a probe, as it - might be misaligned. -*/ - -int32 op_insque (int32 *opnd, int32 acc) -{ -int32 p = opnd[1]; -int32 e = opnd[0]; -int32 s, cc; - -s = Read (p, L_LONG, WA); /* s <- (p), wchk */ -Read (s + 4, L_LONG, WA); /* wchk s+4 */ -Read (e + 4, L_LONG, WA); /* wchk e+4 */ -Write (e, s, L_LONG, WA); /* (e) <- s */ -Write (e + 4, p, L_LONG, WA); /* (e+4) <- p */ -Write (s + 4, e, L_LONG, WA); /* (s+4) <- ent */ -Write (p, e, L_LONG, WA); /* (p) <- e */ -CC_CMP_L (s, p); /* set cc's */ -return cc; -} - -/* REMQUE - - opnd[0] = entry address (ent.ab) - opnd[1:2] = destination address (dst.wl) - - Condition codes returned to caller based on (ent):(ent+4). - All writes must be checked before any writes are done. - - Pictorially: - - BEFORE AFTER - - P: E P: S W - P+4: (n/a) P+4: (n/a) - - E: S W E: S - E+4: P W E+4: P - - S: (n/a) S: (n/a) - S+4: E W S+4: P - -*/ - -int32 op_remque (int32 *opnd, int32 acc) -{ -int32 e = opnd[0]; -int32 s, p, cc; - -s = Read (e, L_LONG, RA); /* s <- (e) */ -p = Read (e + 4, L_LONG, RA); /* p <- (e+4) */ -CC_CMP_L (s, p); /* set cc's */ -if (e != p) { /* queue !empty? */ - Read (s + 4, L_LONG, WA); /* wchk (s+4) */ - if (opnd[1] < 0) Read (opnd[2], L_LONG, WA); /* wchk dest */ - Write (p, s, L_LONG, WA); /* (p) <- s */ - Write (s + 4, p, L_LONG, WA); } /* (s+4) <- p */ -else cc = cc | CC_V; /* else set v */ -if (opnd[1] >= 0) R[opnd[1]] = e; /* store result */ -else Write (opnd[2], e, L_LONG, WA); -return cc; -} - -/* Interlocked insert instructions - - opnd[0] = entry (ent.ab) - opnd[1] = header (hdr.aq) - - Pictorially: - - BEFORE AFTER INSQHI AFTER INSQTI - - H: A-H H: D-H W H: A-H W for interlock - H+4: C-H H+4: C-H H+4: D-H W - - A: B-A A: B-A A: B-A - A+4: H-A A+4: D-A W A+4: H-A - - B: C-B B: C-B B: C-B - B+4: A-B B+4: A-B B+4: A-B - - C: H-C C: H-C C: D-C W - C+4: B-C C+4: B-C C+4: B-C - - D: --- D: A-D W D: H-D W - D+4: --- D+4: H-D W D+4: C-D W - - Note that the queue header, the entry to be inserted, and all - the intermediate entries that are "touched" in any way must be - QUADWORD aligned. In addition, the header and the entry must - not be equal. -*/ - -int32 op_insqhi (int32 *opnd, int32 acc) -{ -int32 h = opnd[1]; -int32 d = opnd[0]; -int32 a, t; - -if ((h == d) || ((h | d) & 07)) RSVD_OPND_FAULT; /* h, d quad align? */ -Read (d, L_BYTE, WA); /* wchk ent */ -a = Read (h, L_LONG, WA); /* a <- (h), wchk */ -if (a & 06) RSVD_OPND_FAULT; /* chk quad align */ -if (a & 01) return CC_C; /* busy, cc = 0001 */ -Write (h, a | 1, L_LONG, WA); /* get interlock */ -a = a + h; /* abs addr of a */ -if (Test (a, WA, &t) < 0) Write (h, a - h, L_LONG, WA); /* wtst a, rls if err */ -Write (a + 4, d - a, L_LONG, WA); /* (a+4) <- d-a, flt ok */ -Write (d, a - d, L_LONG, WA); /* (d) <- a-d */ -Write (d + 4, h - d, L_LONG, WA); /* (d+4) <- h-d */ -Write (h, d - h, L_LONG, WA); /* (h) <- d-h, rls int */ -return (a == h)? CC_Z: 0; /* Z = 1 if a = h */ -} - -int32 op_insqti (int32 *opnd, int32 acc) -{ -int32 h = opnd[1]; -int32 d = opnd[0]; -int32 a, c, t; - -if ((h == d) || ((h | d) & 07)) RSVD_OPND_FAULT; /* h, d quad align? */ -Read (d, L_BYTE, WA); /* wchk ent */ -a = Read (h, L_LONG, WA); /* a <- (h), wchk */ -if (a == 0) return op_insqhi (opnd, acc); /* if empty, ins hd */ -if (a & 06) RSVD_OPND_FAULT; /* chk quad align */ -if (a & 01) return CC_C; /* busy, cc = 0001 */ -Write (h, a | 1, L_LONG, WA); /* acquire interlock */ -c = Read (h + 4, L_LONG, RA) + h; /* c <- (h+4) + h */ -if (c & 07) { /* c quad aligned? */ - Write (h, a, L_LONG, WA); /* release interlock */ - RSVD_OPND_FAULT; } /* fault */ -if (Test (c, WA, &t) < 0) Write (h, a, L_LONG, WA); /* wtst c, rls if err */ -Write (c, d - c, L_LONG, WA); /* (c) <- d-c, flt ok */ -Write (d, h - d, L_LONG, WA); /* (d) <- h-d */ -Write (d + 4, c - d, L_LONG, WA); /* (d+4) <- c-d */ -Write (h + 4, d - h, L_LONG, WA); /* (h+4) <- d-h */ -Write (h, a, L_LONG, WA); /* release interlock */ -return 0; /* q >= 2 entries */ -} - -/* Interlocked remove instructions - - opnd[0] = header (hdr.aq) - opnd[1:2] = destination address (dst.al) - - Pictorially: - - BEFORE AFTER REMQHI AFTER REMQTI - - H: A-H H: B-H W H: A-H W for interlock - H+4: C-H H+4: C-H H+4: B-H W - - A: B-A A: B-A R A: B-A - A+4: H-A A+4: H-A A+4: H-A - - B: C-B B: C-B B: H-B W - B+4: A-B B+4: H-B W B+4: A-B - - C: H-C C: H-C C: H-C - C+4: B-C C+4: B-C C+4: B-C R - - Note that the queue header and all the entries that are - "touched" in any way must be QUADWORD aligned. In addition, - the header and the destination must not be equal. -*/ - -int32 op_remqhi (int32 *opnd, int32 acc) -{ -int32 h = opnd[0]; -int32 ar, a, b, t; - -if (h & 07) RSVD_OPND_FAULT; /* h quad aligned? */ -if (opnd[1] < 0) { /* mem destination? */ - if (h == opnd[2]) RSVD_OPND_FAULT; /* hdr = dst? */ - Read (opnd[2], L_LONG, WA); } /* wchk dst */ -ar = Read (h, L_LONG, WA); /* ar <- (h) */ -if (ar & 06) RSVD_OPND_FAULT; /* a quad aligned? */ -if (ar & 01) return CC_V | CC_C; /* busy, cc = 0011 */ -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 */ - 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 */ - if (Test (b, WA, &t) < 0) /* write test b */ - 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 */ -else Write (opnd[2], a, L_LONG, WA); -if (ar == 0) return CC_Z | CC_V; /* empty, cc = 0110 */ -return (b == h)? CC_Z: 0; /* if b = h, q empty */ -} - -int32 op_remqti (int32 *opnd, int32 acc) -{ -int32 h = opnd[0]; -int32 ar, b, c, t; - -if (h & 07) RSVD_OPND_FAULT; /* h quad aligned? */ -if (opnd[1] < 0) { /* mem destination? */ - if (h == opnd[2]) RSVD_OPND_FAULT; /* hdr = dst? */ - Read (opnd[2], L_LONG, WA); } /* wchk dst */ -ar = Read (h, L_LONG, WA); /* a <- (h) */ -if (ar & 06) RSVD_OPND_FAULT; /* a quad aligned? */ -if (ar & 01) return CC_V | CC_C; /* busy, cc = 0011 */ -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 */ - if (c & 07) { /* c quad aligned? */ - 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 */ - 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 */ - if (Test (b, WA, &t) < 0) /* write test b */ - 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 */ -else c = h; /* empty, result = h */ -if (opnd[1] >= 0) R[opnd[1]] = c; /* store result */ -else Write (opnd[2], c, L_LONG, WA); -if (ar == 0) return CC_Z | CC_V; /* empty, cc = 0110 */ -return 0; /* q can't be empty */ -} - -/* String instructions */ - -#define MVC_FRWD 0 /* movc state codes */ -#define MVC_BACK 1 -#define MVC_FILL 3 /* must be 3 */ -#define MVC_M_STATE 3 -#define MVC_V_CC 2 -#define STR_V_DPC 24 -#define STR_M_DPC 0xFF -#define STR_V_CHR 16 -#define STR_M_CHR 0xFF -#define STR_LNMASK 0xFFFF -#define STR_GETDPC(x) (((x) >> STR_V_DPC) & STR_M_DPC) -#define STR_GETCHR(x) (((x) >> STR_V_CHR) & STR_M_CHR) -#define STR_PACK(m,x) ((((PC - fault_PC) & STR_M_DPC) << STR_V_DPC) | \ - (((m) & STR_M_CHR) << STR_V_CHR) | ((x) & STR_LNMASK)) - -/* MOVC3, MOVC5 - - if PSL = 0 and MOVC3, - opnd[0] = length - opnd[1] = source address - opnd[2] = dest address - - if PSL = 0 and MOVC5, - opnd[0] = source length - opnd[1] = source address - opnd[2] = fill - opnd[3] = dest length - opnd[4] = dest address - - if PSL = 1, - R0 = delta-PC/fill/initial move length - R1 = current source address - R2 = current move length - R3 = current dest address - R4 = dstlen - srclen (loop count if fill state) - R5 = cc/state -*/ - -int32 op_movc (int32 *opnd, int32 movc5, int32 acc) -{ -int32 i, cc, fill, wd; -int32 j, lnt, mlnt[3]; -static const int32 looplnt[3] = { L_BYTE, L_LONG, L_BYTE }; - -if (PSL & PSL_FPD) { /* FPD set? */ - SETPC (fault_PC + STR_GETDPC (R[0])); /* reset PC */ - fill = STR_GETCHR (R[0]); /* get fill */ - R[2] = R[2] & STR_LNMASK; /* mask lengths */ - 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[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 */ - 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 */ - -/* At this point, - - R0 = delta PC'fill'initial move length - R1 = current src addr - R2 = current move length - R3 = current dst addr - R4 = dst length - src length - R5 = cc'state -*/ - -switch (R[5] & MVC_M_STATE) { /* case on state */ -case MVC_FRWD: /* move forward */ - mlnt[0] = (4 - R[3]) & 3; /* length to align */ - if (mlnt[0] > R[2]) mlnt[0] = R[2]; /* cant exceed total */ - 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 */ - goto FILL; /* check for fill */ -case MVC_BACK: /* move backward */ - mlnt[0] = R[3] & 03; /* length to align */ - if (mlnt[0] > R[2]) mlnt[0] = R[2]; /* cant exceed total */ - 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 */ - 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 */ -FILL: - if (R[4] <= 0) break; /* any fill? */ - R[5] = R[5] | MVC_FILL; /* set state */ - mlnt[0] = (4 - R[3]) & 3; /* length to align */ - if (mlnt[0] > R[4]) mlnt[0] = R[4]; /* cant exceed total */ - 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 */ - break; -default: /* bad state */ - RSVD_OPND_FAULT; } /* you lose */ -PSL = PSL & ~PSL_FPD; /* clear FPD */ -cc = (R[5] >> MVC_V_CC) & CC_MASK; /* get cc's */ -R[0] = NEG (R[4]); /* set R0 */ -R[2] = R[4] = R[5] = 0; /* clear reg */ -return cc; -} - -/* CMPC3, CMPC5 - - if PSL = 0 and CMPC3, - opnd[0] = length - opnd[1] = source1 address - opnd[2] = source2 address - - if PSL = 0 and CMPC5, - opnd[0] = source1 length - opnd[1] = source1 address - opnd[2] = fill - opnd[3] = source2 length - opnd[4] = source2 address - - if PSL = 1, - R0 = delta-PC/fill/source1 length - R1 = source1 address - R2 = source2 length - R3 = source2 address -*/ - -int32 op_cmpc (int32 *opnd, int32 cmpc5, int32 acc) -{ -int32 cc, s1, s2, fill; - -if (PSL & PSL_FPD) { /* FPD set? */ - SETPC (fault_PC + STR_GETDPC (R[0])); /* reset PC */ - 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[0] = STR_PACK (fill, opnd[0]); /* src1len + FPD data */ - PSL = PSL | PSL_FPD; } -R[2] = R[2] & STR_LNMASK; /* mask src2len */ -for (s1 = s2 = 0; ((R[0] | R[2]) & STR_LNMASK) != 0; sim_interval--) { -/* if (sim_interval == 0) ABORT (ABORT_INTR); /* timer event */ - if (R[0] & STR_LNMASK) s1 = Read (R[1], L_BYTE, RA); /* src1? read */ - else s1 = fill; /* no, use fill */ - if (R[2]) s2 = Read (R[3], L_BYTE, RA); /* src2? read */ - 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; } - if (R[2]) { /* if src2, decr */ - 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 */ -return cc; -} - -/* LOCC, SKPC - - if PSL = 0, - opnd[0] = match character - opnd[1] = source length - opnd[2] = source address - - if PSL = 1, - R0 = delta-PC/match/source length - R1 = source address -*/ - -int32 op_locskp (int32 *opnd, int32 skpc, int32 acc) -{ -int32 c, match; - -if (PSL & PSL_FPD) { /* FPD set? */ - SETPC (fault_PC + STR_GETDPC (R[0])); /* reset PC */ - match = STR_GETCHR (R[0]); } /* get match char */ -else { match = opnd[0]; /* get operands */ - R[0] = STR_PACK (match, opnd[1]); /* src len + FPD data */ - R[1] = opnd[2]; /* src addr */ - PSL = PSL | PSL_FPD; } -for ( ; (R[0] & STR_LNMASK) != 0; sim_interval-- ) { /* loop thru string */ -/* if (sim_interval == 0) ABORT (ABORT_INTR); /* timer event? */ - c = Read (R[1], L_BYTE, RA); /* get src byte */ - if ((c == match) ^ skpc) break; /* match & locc? */ - R[0] = (R[0] & ~STR_LNMASK) | ((R[0] - 1) & STR_LNMASK); - R[1] = R[1] + 1; } /* incr src1adr */ -PSL = PSL & ~PSL_FPD; /* clear FPD */ -R[0] = R[0] & STR_LNMASK; /* clear packup */ -return (R[0]? 0: CC_Z); /* set cc's */ -} - -/* SCANC, SPANC - - if PSL = 0, - opnd[0] = source length - opnd[1] = source address - opnd[2] = table address - opnd[3] = mask - - if PSL = 1, - R0 = delta-PC/char/source length - R1 = source address - R3 = table address -*/ - -int32 op_scnspn (int32 *opnd, int32 spanc, int32 acc) -{ -int32 c, t, mask; - -if (PSL & PSL_FPD) { /* FPD set? */ - SETPC (fault_PC + STR_GETDPC (R[0])); /* reset PC */ - mask = STR_GETCHR (R[0]); } /* get mask */ -else { R[1] = opnd[1]; /* src addr */ - R[3] = opnd[2]; /* tblad */ - mask = opnd[3]; /* mask */ - R[0] = STR_PACK (mask, opnd[0]); /* srclen + FPD data */ - PSL = PSL | PSL_FPD; } -for ( ; (R[0] & STR_LNMASK) != 0; sim_interval-- ) { /* loop thru string */ -/* if (sim_interval == 0) ABORT (ABORT_INTR); /* timer event? */ - c = Read (R[1], L_BYTE, RA); /* get byte */ - t = Read (R[3] + c, L_BYTE, RA); /* get table ent */ - if (((t & mask) != 0) ^ spanc) break; /* test vs instr */ - R[0] = (R[0] & ~STR_LNMASK) | ((R[0] - 1) & STR_LNMASK); - R[1] = R[1] + 1; } -PSL = PSL & ~PSL_FPD; -R[0] = R[0] & STR_LNMASK; /* clear packup */ -R[2] = 0; -return (R[0]? 0: CC_Z); -} - -/* Operating system interfaces */ - -/* Interrupt or exception - - vec = SCB vector - cc = condition codes - ipl = new IPL if interrupt - ei = -1: severe exception - 0: normal exception - 1: interrupt -*/ - -int32 intexc (int32 vec, int32 cc, int32 ipl, int ei) -{ -int32 oldpsl = PSL | cc; -int32 oldcur = PSL_GETCUR (oldpsl); -int32 oldsp = SP; -int32 newpsl; -int32 newpc; -int32 acc; - -in_ie = 1; /* flag int/exc */ -CLR_TRAPS; /* clear traps */ -newpc = ReadLP ((SCBB + vec) & PAMASK); /* read new PC */ -if (ei < 0) newpc = newpc | 1; /* severe? on istk */ -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 */ -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); -if (DBG_LOG (LOG_CPU_I)) fprintf (sim_log, - ">>IEX: PC=%08x, PSL=%08x, SP=%08x, VEC=%08x, nPSL=%08x, nSP=%08x\n", - PC, oldpsl, oldsp, vec, PSL, SP); -acc = ACC_MASK (KERN); /* new mode is kernel */ -Write (SP - 4, oldpsl, L_LONG, WA); /* push old PSL */ -Write (SP - 8, PC, L_LONG, WA); /* push old PC */ -SP = SP - 8; /* update stk ptr */ -JUMP (newpc & ~3); /* change PC */ -in_ie = 0; /* out of flows */ -return 0; -} - -/* CHMK, CHME, CHMS, CHMU - - opnd[0] = operand -*/ - -int32 op_chm (int32 *opnd, int32 cc, int32 opc) -{ -int32 mode = opc & PSL_M_MODE; -int32 cur = PSL_GETCUR (PSL); -int32 tsp, newpc, acc, sta; - -if (PSL & PSL_IS) ABORT (STOP_CHMFI); -newpc = ReadLP ((SCBB + SCB_CHMK + (mode << 2)) & PAMASK); -if (cur < mode) mode = cur; /* only inward */ -STK[cur] = SP; /* save stack */ -tsp = STK[mode]; /* get new stk */ -acc = ACC_MASK (mode); /* set new mode */ -if (Test (p2 = tsp - 1, WA, &sta) < 0) { /* probe stk */ - p1 = MM_WRITE | (sta & MM_EMASK); - ABORT ((sta & 4)? ABORT_TNV: ABORT_ACV); } -if (Test (p2 = tsp - 12, WA, &sta) < 0) { - p1 = MM_WRITE | (sta & MM_EMASK); - ABORT ((sta & 4)? ABORT_TNV: ABORT_ACV); } -Write (tsp - 12, SXTW (opnd[0]), L_LONG, WA); /* push argument */ -Write (tsp - 8, PC, L_LONG, WA); /* push PC */ -Write (tsp - 4, PSL | cc, L_LONG, WA); /* push PSL */ -SP = tsp - 12; /* set new stk */ -PSL = (mode << PSL_V_CUR) | (PSL & PSL_IPL) | /* set new PSL */ - (cur << PSL_V_PRV); -last_chm = fault_PC; -JUMP (newpc & ~03); /* set new PC */ -return 0; /* cc = 0 */ -} - -/* REI - return from exception or interrupt - -The lengthiest part of the REI instruction is the validity checking of the PSL -popped off the stack. The new PSL is checked against the following eight rules: - -let tmp = new PSL popped off the stack -let PSL = current PSL - -Rule SRM formulation Comment ----- --------------- ------- - 1 tmp<25:24> GEQ PSL<25:24> tmp GEQ PSL - 2 tmp<26> LEQ PSL<26> tmp LEQ tmp - 3 tmp<26> = 1 => tmp<25:24> = 0 tmp = 1 => tmp = ker - 4 tmp<26> = 1 => tmp<20:16> > 0 tmp = 1 => tmp > 0 - 5 tmp<20:16> > 0 => tmp<25:24> = 0 tmp > 0 => tmp = ker - 6 tmp<25:24> LEQ tmp<23:22> tmp LEQ tmp - 7 tmp<20:16> LEQ PSL<20:16> tmp LEQ PSL - 8 tmp<31,29:28,21,15:8> = 0 tmp = 0 -*/ - -int32 op_rei (int32 acc) -{ -int32 newpc = Read (SP, L_LONG, RA); -int32 newpsl = Read (SP + 4, L_LONG, RA); -int32 newcur = PSL_GETCUR (newpsl); -int32 oldcur = PSL_GETCUR (PSL); -int32 newipl; - -if ((newpsl & PSL_MBZ) || /* rule 8 */ - (newcur < oldcur)) RSVD_OPND_FAULT; /* rule 1 */ -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 */ -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 */ - if (newipl > PSL_GETIPL (PSL)) RSVD_OPND_FAULT; /* test rule 7 */ - } /* end if kernel */ -SP = SP + 8; /* pop stack */ -if (PSL & PSL_IS) IS = SP; /* save stack */ -else STK[oldcur] = SP; -if (DBG_LOG (LOG_CPU_R)) fprintf (sim_log, - ">>REI: PC=%08x, PSL=%08x, SP=%08x, nPC=%08x, nPSL=%08x, nSP=%08x\n", - PC, PSL, SP - 8, newpc, newpsl, ((newpsl & IS)? IS: STK[newcur])); -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; } } -JUMP (newpc); /* set new PC */ -return newpsl & CC_MASK; /* set new cc */ -} - -/* LDCPTX - load process context */ - -void op_ldpctx (int32 acc) -{ -int32 newpc, newpsl, pcbpa; - -if (PSL & PSL_CUR) RSVD_INST_FAULT; /* must be kernel */ -pcbpa = PCBB & PAMASK; /* phys address */ -KSP = ReadLP (pcbpa); /* restore stk ptrs */ -ESP = ReadLP (pcbpa + 4); -SSP = ReadLP (pcbpa + 8); -USP = ReadLP (pcbpa + 12); -R[0] = ReadLP (pcbpa + 16); /* restore registers */ -R[1] = ReadLP (pcbpa + 20); -R[2] = ReadLP (pcbpa + 24); -R[3] = ReadLP (pcbpa + 28); -R[4] = ReadLP (pcbpa + 32); -R[5] = ReadLP (pcbpa + 36); -R[6] = ReadLP (pcbpa + 40); -R[7] = ReadLP (pcbpa + 44); -R[8] = ReadLP (pcbpa + 48); -R[9] = ReadLP (pcbpa + 52); -R[10] = ReadLP (pcbpa + 56); -R[11] = ReadLP (pcbpa + 60); -R[12] = ReadLP (pcbpa + 64); -R[13] = ReadLP (pcbpa + 68); -newpc = ReadLP (pcbpa + 72); /* get PC, PSL */ -newpsl = ReadLP (pcbpa + 76); -P0BR = ReadLP (pcbpa + 80); /* restore mem mgt */ -P0LR = ReadLP (pcbpa + 84); -P1BR = ReadLP (pcbpa + 88); -P1LR = ReadLP (pcbpa + 92); -ASTLVL = (P0LR >> 24) & AST_MASK; /* restore AST */ -P0BR = P0BR & BR_MASK; -P0LR = P0LR & LR_MASK; -P1BR = P1BR & BR_MASK; -P1LR = P1LR & LR_MASK; -zap_tb (0); /* clear process TB */ -set_map_reg (); -if (DBG_LOG (LOG_CPU_P)) fprintf (sim_log, - ">>LDP: PC=%08x, PSL=%08x, SP=%08x, nPC=%08x, nPSL=%08x, nSP=%08x\n", - PC, PSL, SP, newpc, newpsl, KSP); -if (PSL & PSL_IS) IS = SP; /* if istk, */ -PSL = PSL & ~PSL_IS; /* switch to kstk */ -SP = KSP - 8; -Write (SP, newpc, L_LONG, WA); /* push PC, PSL */ -Write (SP + 4, newpsl, L_LONG, WA); -return; -} - -/* SVPCTX - save processor context */ - -void op_svpctx (int32 acc) -{ -int32 savpc, savpsl, pcbpa; - -if (PSL & PSL_CUR) RSVD_INST_FAULT; /* must be kernel */ -savpc = Read (SP, L_LONG, RA); /* pop PC, PSL */ -savpsl = Read (SP + 4, L_LONG, RA); -if (DBG_LOG (LOG_CPU_P)) fprintf (sim_log, - ">>SVP: PC=%08x, PSL=%08x, SP=%08x, oPC=%08x, oPSL=%08x\n", - PC, PSL, SP, savpc, savpsl); -if (PSL & PSL_IS) SP = SP + 8; /* int stack? */ -else { KSP = SP + 8; /* pop kernel stack */ - SP = IS; /* switch to int stk */ - if ((PSL & PSL_IPL) == 0) PSL = PSL | PSL_IPL1; /* make IPL > 0 */ - PSL = PSL | PSL_IS; } /* set PSL */ -pcbpa = PCBB & PAMASK; -WriteLP (pcbpa, KSP); /* save stk ptrs */ -WriteLP (pcbpa + 4, ESP); -WriteLP (pcbpa + 8, SSP); -WriteLP (pcbpa + 12, USP); -WriteLP (pcbpa + 16, R[0]); /* save registers */ -WriteLP (pcbpa + 20, R[1]); -WriteLP (pcbpa + 24, R[2]); -WriteLP (pcbpa + 28, R[3]); -WriteLP (pcbpa + 32, R[4]); -WriteLP (pcbpa + 36, R[5]); -WriteLP (pcbpa + 40, R[6]); -WriteLP (pcbpa + 44, R[7]); -WriteLP (pcbpa + 48, R[8]); -WriteLP (pcbpa + 52, R[9]); -WriteLP (pcbpa + 56, R[10]); -WriteLP (pcbpa + 60, R[11]); -WriteLP (pcbpa + 64, R[12]); -WriteLP (pcbpa + 68, R[13]); -WriteLP (pcbpa + 72, savpc); /* save PC, PSL */ -WriteLP (pcbpa + 76, savpsl); -return; -} - -/* PROBER and PROBEW - - opnd[0] = mode - opnd[1] = length - opnd[2] = base address -*/ - -int32 op_probe (int32 *opnd, int32 rw) -{ -int32 mode = opnd[0] & PSL_M_MODE; /* mask mode */ -int32 length = opnd[1]; -int32 ba = opnd[2]; -int32 prv = PSL_GETPRV (PSL); -int32 acc, sta, sta1; - -if (prv > mode) mode = prv; /* maximize mode */ -acc = ACC_MASK (mode) << (rw? TLB_V_WACC: 0); /* set acc mask */ -Test (ba, acc, &sta); /* probe */ -switch (sta) { /* case on status */ -case PR_PTNV: /* pte TNV */ - p1 = MM_PARAM (rw, PR_PTNV); - p2 = ba; - ABORT (ABORT_TNV); /* force TNV */ -case PR_TNV: case PR_OK: /* TNV or ok */ - break; /* continue */ -default: /* other */ - return CC_Z; } /* lose */ -Test (ba + length - 1, acc, &sta1); /* probe end addr */ -switch (sta1) { /* case on status */ -case PR_PTNV: /* pte TNV */ - p1 = MM_PARAM (rw, PR_PTNV); - p2 = ba + length - 1; - ABORT (ABORT_TNV); /* force TNV */ -case PR_TNV: case PR_OK: /* TNV or ok */ - break; /* win */ -default: /* other */ - return CC_Z; } /* lose */ -return 0; -} - - -/* MTPR - move to processor register - - opnd[0] = data - opnd[1] = register number -*/ - -int32 op_mtpr (int32 *opnd) -{ -int32 val = opnd[0]; -int32 prn = opnd[1]; -int32 cc; - -if (PSL & PSL_CUR) RSVD_INST_FAULT; /* must be kernel */ -if (prn > 63) RSVD_OPND_FAULT; /* reg# > 63? fault */ -CC_IIZZ_L (val); /* set cc's */ -switch (prn) { /* case on reg # */ -case MT_KSP: /* KSP */ - if (PSL & PSL_IS) KSP = val; /* on IS? store KSP */ - else SP = val; /* else store SP */ - break; -case MT_ESP: case MT_SSP: case MT_USP: /* ESP, SSP, USP */ - STK[prn] = val; /* store stack */ - break; -case MT_IS: /* IS */ - if (PSL & PSL_IS) SP = val; /* on IS? store SP */ - else IS = val; /* else store IS */ - break; -case MT_P0BR: /* P0BR */ - P0BR = val & BR_MASK; /* lw aligned */ - zap_tb (0); /* clr proc TLB */ - set_map_reg (); - break; -case MT_P0LR: /* P0LR */ - P0LR = val & LR_MASK; - zap_tb (0); /* clr proc TLB */ - set_map_reg (); - break; -case MT_P1BR: /* P1BR */ - P1BR = val & BR_MASK; /* lw aligned */ - zap_tb (0); /* clr proc TLB */ - set_map_reg (); - break; -case MT_P1LR: /* P1LR */ - P1LR = val & LR_MASK; - zap_tb (0); /* clr proc TLB */ - set_map_reg (); - break; -case MT_SBR: /* SBR */ - SBR = val & BR_MASK; /* lw aligned */ - zap_tb (1); /* clr entire TLB */ - set_map_reg (); - break; -case MT_SLR: /* SLR */ - SLR = val & LR_MASK; - zap_tb (1); /* clr entire TLB */ - set_map_reg (); - break; -case MT_SCBB: /* SCBB */ - SCBB = val & BR_MASK; /* lw aligned */ - break; -case MT_PCBB: /* PCBB */ - PCBB = val & BR_MASK; /* lw aligned */ - break; -case MT_IPL: /* IPL */ - PSL = (PSL & ~PSL_IPL) | ((val & PSL_M_IPL) << PSL_V_IPL); - break; -case MT_ASTLVL: /* ASTLVL */ - if (val > AST_MAX) RSVD_OPND_FAULT; /* > 4? fault */ - ASTLVL = val; - break; -case MT_SIRR: /* SIRR */ - if ((val > 0xF) || (val == 0)) RSVD_OPND_FAULT; - SISR = SISR | (1 << val); /* set bit in SISR */ - break; -case MT_SISR: /* SISR */ - SISR = val & SISR_MASK; - break; -case MT_CADR: /* CADR */ - CADR = (val & CADR_RW) | CADR_MBO; - break; -case MT_MSER: /* MSER */ - MSER = MSER & MSER_HM; - break; -case MT_MAPEN: /* MAPEN */ - mapen = val & 1; -case MT_TBIA: /* TBIA */ - zap_tb (1); /* clr entire TLB */ - break; -case MT_TBIS: /* TBIS */ - zap_tb_ent (val); - break; -case MT_SID: -case MT_CONPC: -case MT_CONPSL: - RSVD_OPND_FAULT; /* read only */ -case MT_TBCHK: /* TBCHK */ - if (chk_tb_ent (val)) cc = cc | CC_V; - break; -default: - WriteIPR (prn, val); /* others */ - break; } -return cc; -} - -int32 op_mfpr (int32 *opnd) -{ -int32 prn = opnd[0]; -int32 val; - -if (PSL & PSL_CUR) RSVD_INST_FAULT; /* must be kernel */ -if (prn > 63) RSVD_OPND_FAULT; /* reg# > 63? fault */ -switch (prn) { /* case on reg# */ -case MT_KSP: /* KSP */ - val = (PSL & PSL_IS)? KSP: SP; /* return KSP or SP */ - break; -case MT_ESP: case MT_SSP: case MT_USP: /* ESP, SSP, USP */ - val = STK[prn]; /* return stk ptr */ - break; -case MT_IS: /* IS */ - val = (PSL & PSL_IS)? SP: IS; /* return SP or IS */ - break; -case MT_P0BR: /* P0BR */ - val = P0BR; - break; -case MT_P0LR: /* P0LR */ - val = P0LR; - break; -case MT_P1BR: /* P1BR */ - val = P1BR; - break; -case MT_P1LR: /* P1LR */ - val = P1LR; - break; -case MT_SBR: /* SBR */ - val = SBR; - break; -case MT_SLR: /* SLR */ - val = SLR; - break; -case MT_SCBB: /* SCBB */ - val = SCBB; - break; -case MT_PCBB: /* PCBB */ - val = PCBB; - break; -case MT_IPL: /* IPL */ - val = PSL_GETIPL (PSL); - break; -case MT_ASTLVL: /* ASTLVL */ - val = ASTLVL; - break; -case MT_SISR: /* SISR */ - val = SISR & SISR_MASK; - break; -case MT_CADR: /* CADR */ - val = CADR & 0xFF; - break; -case MT_MSER: /* MSER */ - val = MSER & 0xFF; - break; -case MT_CONPC: /* console PC */ - val = conpc; - break; -case MT_CONPSL: /* console PSL */ - val = conpsl; - break; -case MT_MAPEN: /* MAPEN */ - val = mapen; - break; -case MT_SID: /* SID */ - val = CVAX_SID | CVAX_UREV; - break; -case MT_SIRR: -case MT_TBIA: -case MT_TBIS: -case MT_TBCHK: - RSVD_OPND_FAULT; /* write only */ -default: /* others */ - val = ReadIPR (prn); /* read from SSC */ - break; } -return val; -} - -/* Emulated instructions - - opnd[0:5] = six operands to be pushed (if PSL = 0) - cc = condition codes - opc = opcode - - If FPD is set, push old PC and PSL on stack, vector thru SCB. - If FPD is clear, push opcode, old PC, operands, new PC, and PSL - on stack, vector thru SCB. - In both cases, the exception occurs in the current mode. -*/ - -int32 op_emulate (int32 *opnd, int32 cc, int32 opc, int32 acc) -{ -int32 vec; - -if (PSL & PSL_FPD) { /* FPD set? */ - Read (SP - 1, L_BYTE, WA); /* wchk stack */ - Write (SP - 8, fault_PC, L_LONG, WA); /* push old PC */ - Write (SP - 4, PSL | cc, L_LONG, WA); /* push PSL */ - SP = SP - 8; /* decr stk ptr */ - vec = ReadLP ((SCBB + SCB_EMULFPD) & PAMASK); } -else { Read (SP - 1, L_BYTE, WA); /* wchk stack */ - Write (SP - 48, opc, L_LONG, WA); /* push opcode */ - Write (SP - 44, fault_PC, L_LONG, WA); /* push old PC */ - Write (SP - 40, opnd[0], L_LONG, WA); /* push operands */ - Write (SP - 36, opnd[1], L_LONG, WA); - Write (SP - 32, opnd[2], L_LONG, WA); - Write (SP - 28, opnd[3], L_LONG, WA); - Write (SP - 24, opnd[4], L_LONG, WA); - Write (SP - 20, opnd[5], L_LONG, WA); - Write (SP - 8, PC, L_LONG, WA); /* push cur PC */ - Write (SP - 4, PSL | cc, L_LONG, WA); /* push PSL */ - SP = SP - 48; /* decr stk ptr */ - vec = ReadLP ((SCBB + SCB_EMULATE) & PAMASK); } -PSL = PSL & ~(PSL_TP | PSL_FPD | PSW_DV | PSW_FU | PSW_IV | PSW_T); -JUMP (vec & ~03); /* set new PC */ -return 0; /* set new cc's */ -} diff --git a/VAX/vax_defs.h b/VAX/vax_defs.h deleted file mode 100644 index 6541c71f..00000000 --- a/VAX/vax_defs.h +++ /dev/null @@ -1,575 +0,0 @@ -/* vax_defs.h: VAX architecture definitions file - - 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"), - 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 Stephen Shirron, Antonio - Carlini, and Kevin Peterson in providing specifications for the Qbus VAX's - - 19-May-03 RMS Revised for new conditional compilation scheme - 14-Jul-02 RMS Added infinite loop message - 30-Apr-02 RMS Added CLR_TRAPS macro -*/ - -#ifndef _VAX_DEFS_H -#define _VAX_DEFS_H 0 - -#ifndef VM_VAX -#define VM_VAX 0 -#endif - -#include "sim_defs.h" -#include - -/* Stops and aborts */ - -#define STOP_HALT 1 /* halt */ -#define STOP_IBKPT 2 /* breakpoint */ -#define STOP_CHMFI 3 /* chg mode IS */ -#define STOP_ILLVEC 4 /* illegal vector */ -#define STOP_INIE 5 /* exc in intexc */ -#define STOP_PPTE 6 /* proc pte in Px */ -#define STOP_UIPL 7 /* undefined IPL */ -#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 */ -#define ABORT_RESAD (-SCB_RESAD) /* rsvd addr mode */ -#define ABORT_RESOP (-SCB_RESOP) /* rsvd operand */ -#define ABORT_ARITH (-SCB_ARITH) /* arithmetic trap */ -#define ABORT_ACV (-SCB_ACV) /* access violation */ -#define ABORT_TNV (-SCB_TNV) /* transl not vaid */ -#define ABORT(x) longjmp (save_env, (x)) /* abort */ -#define RSVD_INST_FAULT ABORT (ABORT_RESIN) -#define RSVD_ADDR_FAULT ABORT (ABORT_RESAD) -#define RSVD_OPND_FAULT ABORT (ABORT_RESOP) -#define FLT_OVFL_FAULT p1 = FLT_OVRFLO, ABORT (ABORT_ARITH) -#define FLT_DZRO_FAULT p1 = FLT_DIVZRO, ABORT (ABORT_ARITH) -#define FLT_UNFL_FAULT p1 = FLT_UNDFLO, ABORT (ABORT_ARITH) -#define MACH_CHECK(cd) p1 = (cd), ABORT (ABORT_MCHK) - -/* Address space */ - -#define VAMASK 0xFFFFFFFF /* virt addr mask */ -#define PAWIDTH 30 /* phys addr width */ -#define PASIZE (1 << PAWIDTH) /* phys addr size */ -#define PAMASK (PASIZE - 1) /* phys addr mask */ -#define IOPAGE (1 << (PAWIDTH - 1)) /* start of I/O page */ - -/* Architectural constants */ - -#define BMASK 0x000000FF /* byte */ -#define BSIGN 0x00000080 -#define WMASK 0x0000FFFF /* word */ -#define WSIGN 0x00008000 -#define LMASK 0xFFFFFFFF /* longword */ -#define LSIGN 0x80000000 -#define FPSIGN 0x00008000 /* floating point */ -#define L_BYTE 1 /* bytes per */ -#define L_WORD 2 /* data type */ -#define L_LONG 4 -#define L_QUAD 8 -#define NUM_INST 512 /* one byte+two byte */ -#define MAX_SPEC 6 /* max spec/instr */ - -/* Memory management modes */ - -#define KERN 0 -#define EXEC 1 -#define SUPV 2 -#define USER 3 - -/* Register and stack aliases */ - -#define nAP 12 -#define nFP 13 -#define nSP 14 -#define nPC 15 -#define AP R[nAP] -#define FP R[nFP] -#define SP R[nSP] -#define PC R[nPC] -#define RGMASK 0xF -#define rnplus1 ((rn + 1) & RGMASK) -#define KSP STK[KERN] -#define ESP STK[EXEC] -#define SSP STK[SUPV] -#define USP STK[USER] -#define IS STK[4] - -/* PSL, PSW, and condition codes */ - -#define PSL_V_TP 30 /* trace pending */ -#define PSL_TP (1 << PSL_V_TP) -#define PSL_V_FPD 27 /* first part done */ -#define PSL_FPD (1 << PSL_V_FPD) -#define PSL_V_IS 26 /* interrupt stack */ -#define PSL_IS (1 << PSL_V_IS) -#define PSL_V_CUR 24 /* current mode */ -#define PSL_V_PRV 22 /* previous mode */ -#define PSL_M_MODE 0x3 /* mode mask */ -#define PSL_CUR (PSL_M_MODE << PSL_V_CUR) -#define PSL_PRV (PSL_M_MODE << PSL_V_CUR) -#define PSL_V_IPL 16 /* int priority lvl */ -#define PSL_M_IPL 0x1F -#define PSL_IPL (PSL_M_IPL << PSL_V_IPL) -#define PSL_IPL1 (0x01 << PSL_V_IPL) -#define PSL_IPL1F (0x1F << PSL_V_IPL) -#define PSL_MBZ (0xB0200000 | PSW_MBZ) /* must be zero */ -#define PSW_MBZ 0xFF00 /* must be zero */ -#define PSW_DV 0x80 /* dec ovflo enable */ -#define PSW_FU 0x40 /* flt undflo enable */ -#define PSW_IV 0x20 /* int ovflo enable */ -#define PSW_T 0x10 /* trace enable */ -#define CC_N 0x08 /* negative */ -#define CC_Z 0x04 /* zero */ -#define CC_V 0x02 /* overflow */ -#define CC_C 0x01 /* carry */ -#define CC_MASK (CC_N | CC_Z | CC_V | CC_C) -#define PSL_GETCUR(x) (((x) >> PSL_V_CUR) & PSL_M_MODE) -#define PSL_GETPRV(x) (((x) >> PSL_V_PRV) & PSL_M_MODE) -#define PSL_GETIPL(x) (((x) >> PSL_V_IPL) & PSL_M_IPL) - -/* Software interrupt summary register */ - -#define SISR_MASK 0xFFFE -#define SISR_2 (1 << 2) - -/* AST register */ - -#define AST_MASK 7 -#define AST_MAX 4 - -/* Virtual address */ - -#define VA_N_OFF 9 /* offset size */ -#define VA_PAGSIZE (1u << VA_N_OFF) /* page size */ -#define VA_M_OFF ((1u << VA_N_OFF) - 1) /* offset mask */ -#define VA_V_VPN VA_N_OFF /* vpn start */ -#define VA_N_VPN (31 - VA_N_OFF) /* vpn size */ -#define VA_M_VPN ((1u << VA_N_VPN) - 1) /* vpn mask */ -#define VA_S0 (1u << 31) /* S0 space */ -#define VA_P1 (1u << 30) /* P1 space */ -#define VA_N_TBI 12 /* TB index size */ -#define VA_TBSIZE (1u << VA_N_TBI) /* TB size */ -#define VA_M_TBI ((1u << VA_N_TBI) - 1) /* TB index mask */ -#define VA_GETOFF(x) ((x) & VA_M_OFF) -#define VA_GETVPN(x) (((x) >> VA_V_VPN) & VA_M_VPN) -#define VA_GETTBI(x) ((x) & VA_M_TBI) - -/* PTE */ - -#define PTE_V_V 31 /* valid */ -#define PTE_V (1u << PTE_V_V) -#define PTE_V_ACC 27 /* access */ -#define PTE_M_ACC 0xF -#define PTE_V_M 26 /* modified */ -#define PTE_M (1u << PTE_V_M) -#define PTE_GETACC(x) (((x) >> PTE_V_ACC) & PTE_M_ACC) - -/* TLB entry */ - -#define TLB_V_RACC 0 /* rd acc field */ -#define TLB_V_WACC 4 /* wr acc field */ -#define TLB_M_ACC 0xF -#define TLB_RACC (TLB_M_ACC << TLB_V_RACC) -#define TLB_WACC (TLB_M_ACC << TLB_V_WACC) -#define TLB_V_M 8 /* m bit */ -#define TLB_M (1u << TLB_V_M) -#define TLB_N_PFN (PAWIDTH - VA_N_OFF) /* ppfn size */ -#define TLB_M_PFN ((1u << TLB_N_PFN) - 1) /* ppfn mask */ -#define TLB_PFN (TLB_M_PFN << VA_V_VPN) - -/* Traps and interrupt requests */ - -#define TIR_V_IRQL 0 /* int request lvl */ -#define TIR_V_TRAP 5 /* trap requests */ -#define TIR_M_TRAP 07 -#define TIR_TRAP (TIR_M_TRAP << TIR_V_TRAP) -#define TRAP_INTOV (1 << TIR_V_TRAP) /* integer overflow */ -#define TRAP_DIVZRO (2 << TIR_V_TRAP) /* divide by zero */ -#define TRAP_SUBSCR (7 << TIR_V_TRAP) /* subscript range */ -#define SET_TRAP(x) trpirq = (trpirq & PSL_M_IPL) | (x) -#define CLR_TRAPS trpirq = trpirq & ~TIR_TRAP -#define SET_IRQL trpirq = (trpirq & TIR_TRAP) | eval_int () -#define GET_TRAP(x) (((x) >> TIR_V_TRAP) & TIR_M_TRAP) -#define GET_IRQL(x) (((x) >> TIR_V_IRQL) & PSL_M_IPL) - -/* Floating point fault parameters */ - -#define FLT_OVRFLO 0x8 /* flt overflow */ -#define FLT_DIVZRO 0x9 /* flt div by zero */ -#define FLT_UNDFLO 0xA /* flt underflow */ - -/* SCB offsets */ - -#define SCB_MCHK 0x04 /* machine chk */ -#define SCB_KSNV 0x08 /* ker stk invalid */ -#define SCB_PWRFL 0x0C /* power fail */ -#define SCB_RESIN 0x10 /* rsvd/priv instr */ -#define SCB_XFC 0x14 /* XFC instr */ -#define SCB_RESOP 0x18 /* rsvd operand */ -#define SCB_RESAD 0x1C /* rsvd addr mode */ -#define SCB_ACV 0x20 /* ACV */ -#define SCB_TNV 0x24 /* TNV */ -#define SCB_TP 0x28 /* trace pending */ -#define SCB_BPT 0x2C /* BPT instr */ -#define SCB_ARITH 0x34 /* arith fault */ -#define SCB_CHMK 0x40 /* CHMK */ -#define SCB_CHME 0x44 /* CHME */ -#define SCB_CHMS 0x48 /* CHMS */ -#define SCB_CHMU 0x4C /* CHMU */ -#define SCB_CRDERR 0x54 /* CRD err intr */ -#define SCB_MEMERR 0x60 /* mem err intr */ -#define SCB_IPLSOFT 0x80 /* software intr */ -#define SCB_INTTIM 0xC0 /* timer intr */ -#define SCB_EMULATE 0xC8 /* emulation */ -#define SCB_EMULFPD 0xCC /* emulation, FPD */ -#define SCB_CSI 0xF0 /* constor input */ -#define SCB_CSO 0xF4 /* constor output */ -#define SCB_TTI 0xF8 /* console input */ -#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 */ - -/* Interrupt and exception types */ - -#define IE_SVE -1 /* severe exception */ -#define IE_EXC 0 /* normal exception */ -#define IE_INT 1 /* interrupt */ - -/* Decode ROM: opcode entry */ - -#define DR_F 0x80 /* FPD ok flag */ -#define DR_NSPMASK 0x07 /* #specifiers */ -#define DR_USPMASK 0x70 /* #spec, sym_ */ - -/* Decode ROM: specifier entry */ - -#define DR_ACMASK 0xC /* type */ -#define DR_LNMASK 0x3 /* length mask */ -#define DR_LNT(x) (1 << (x & DR_LNMASK)) /* disp to lnt */ - -/* Decode ROM: operand type */ - -#define SH0 0x00 /* short literal */ -#define SH1 0x10 -#define SH2 0x20 -#define SH3 0x30 -#define IDX 0x40 /* indexed */ -#define GRN 0x50 /* register */ -#define RGD 0x60 /* register def */ -#define ADC 0x70 /* autodecrement */ -#define AIN 0x80 /* autoincrement */ -#define AID 0x90 /* autoinc def */ -#define BDP 0xA0 /* byte disp */ -#define BDD 0xB0 /* byte disp def */ -#define WDP 0xC0 /* word disp */ -#define WDD 0xD0 /* word disp def */ -#define LDP 0xE0 /* long disp */ -#define LDD 0xF0 /* long disp def */ - -/* Decode ROM: access type and length */ - -#define RB 0x0 /* .rb */ -#define RW 0x1 /* .rw */ -#define RL 0x2 /* .rl */ -#define RQ 0x3 /* .rq */ -#define MB 0x4 /* .mb */ -#define MW 0x5 /* .mw */ -#define ML 0x6 /* .ml */ -#define MQ 0x7 /* .mq */ -#define AB 0x8 /* .ab */ -#define AW 0x9 /* .aw */ -#define AL 0xA /* .al */ -#define AQ 0xB /* .aq */ -#define WB 0xC /* .wb */ -#define WW 0xD /* .ww */ -#define WL 0xE /* .wl */ -#define WQ 0xF /* .wq */ - -/* Special dispatches. - - vb = variable bit field, treated as wb except for register - rf = f_floating, treated as rl except for short literal - rd = d_floating, treated as rl except for short literal - rg = g_floating, treated as rl except for short literal - bw = branch byte displacement - bw = branch word displacement - - The 'underlying' access type and length must be correct for - indexing, which only looks at the low order 4b. rg works because - rq and mq are treated identically. -*/ - -#define VB (0x100|WB) /* .vb */ -#define RF (0x100|RL) /* .rf */ -#define RD (0x100|RQ) /* .rd */ -#define RG (0x100|MQ) /* .rg */ -#define BB (0x1F0|WB) /* byte branch */ -#define BW (0x1F0|WW) /* word branch */ -#define OC (0x1F0|WQ) /* octa, sym_ */ - -/* Probe results and memory management fault codes */ - -#define PR_ACV 0 /* ACV */ -#define PR_LNV 1 /* length viol */ -/* #define PR_PACV 2 /* impossible */ -#define PR_PLNV 3 /* pte len viol */ -#define PR_TNV 4 /* TNV */ -/* #define PR_TB 5 /* impossible */ -#define PR_PTNV 6 /* pte TNV */ -#define PR_OK 7 /* ok */ -#define MM_PARAM(w,p) (((w)? 4: 0) | ((p) & 3)) /* fault param */ - -/* Memory management errors */ - -#define MM_WRITE 4 /* write */ -#define MM_EMASK 3 /* against probe */ - -/* Privileged registers */ - -#define MT_KSP 0 -#define MT_ESP 1 -#define MT_SSP 2 -#define MT_USP 3 -#define MT_IS 4 -#define MT_P0BR 8 -#define MT_P0LR 9 -#define MT_P1BR 10 -#define MT_P1LR 11 -#define MT_SBR 12 -#define MT_SLR 13 -#define MT_PCBB 16 -#define MT_SCBB 17 -#define MT_IPL 18 -#define MT_ASTLVL 19 -#define MT_SIRR 20 -#define MT_SISR 21 -#define MT_ICCS 24 -#define MT_TODR 27 -#define MT_CSRS 28 -#define MT_CSRD 29 -#define MT_CSTS 30 -#define MT_CSTD 31 -#define MT_RXCS 32 -#define MT_RXDB 33 -#define MT_TXCS 34 -#define MT_TXDB 35 -#define MT_CADR 37 -#define MT_MSER 39 -#define MT_CONPC 42 -#define MT_CONPSL 43 -#define MT_IORESET 55 -#define MT_MAPEN 56 -#define MT_TBIA 57 -#define MT_TBIS 58 -#define MT_SID 62 -#define MT_TBCHK 63 - -#define BR_MASK 0xFFFFFFFC -#define LR_MASK 0x003FFFFF - -/* Opcodes */ - -enum opcodes { - HALT, NOP, REI, BPT, RET, RSB, LDPCTX, SVPCTX, - CVTPS, CVTSP, INDEX, CRC, PROBER, PROBEW, INSQUE, REMQUE, - BSBB, BRB, BNEQ, BEQL, BGTR, BLEQ, JSB, JMP, - BGEQ, BLSS, BGTRU, BLEQU, BVC, BVS, BGEQU, BLSSU, - ADDP4, ADDP6, SUBP4, SUBP6, CVTPT, MULP, CVTTP, DIVP, - MOVC3, CMPC3, SCANC, SPANC, MOVC5, CMPC5, MOVTC, MOVTUC, - BSBW, BRW, CVTWL, CVTWB, MOVP, CMPP3, CVTPL, CMPP4, - EDITPC, MATCHC, LOCC, SKPC, MOVZWL, ACBW, MOVAW, PUSHAW, - ADDF2, ADDF3, SUBF2, SUBF3, MULF2, MULF3, DIVF2, DIVF3, - CVTFB, CVTFW, CVTFL, CVTRFL, CVTBF, CVTWF, CVTLF, ACBF, - MOVF, CMPF, MNEGF, TSTF, EMODF, POLYF, CVTFD, - ADAWI = 0x58, INSQHI = 0x5C, INSQTI, REMQHI, REMQTI, - ADDD2, ADDD3, SUBD2, SUBD3, MULD2, MULD3, DIVD2, DIVD3, - CVTDB, CVTDW, CVTDL, CVTRDL, CVTBD, CVTWD, CVTLD, ACBD, - MOVD, CMPD, MNEGD, TSTD, EMODD, POLYD, CVTDF, - ASHL = 0x78, ASHQ, EMUL, EDIV, CLRQ, MOVQ, MOVAQ, PUSHAQ, - ADDB2, ADDB3, SUBB2, SUBB3, MULB2, MULB3, DIVB2, DIVB3, - BISB2, BISB3, BICB2, BICB3, XORB2, XORB3, MNEGB, CASEB, - MOVB, CMPB, MCOMB, BITB, CLRB, TSTB, INCB, DECB, - CVTBL, CVTBW, MOVZBL, MOVZBW, ROTL, ACBB, MOVAB, PUSHAB, - ADDW2, ADDW3, SUBW2, SUBW3, MULW2, MULW3, DIVW2, DIVW3, - BISW2, BISW3, BICW2, BICW3, XORW2, XORW3, MNEGW, CASEW, - MOVW, CMPW, MCOMW, BITW, CLRW, TSTW, INCW, DECW, - BISPSW, BICPSW, POPR, PUSHR, CHMK, CHME, CHMS, CHMU, - ADDL2, ADDL3, SUBL2, SUBL3, MULL2, MULL3, DIVL2, DIVL3, - BISL2, BISL3, BICL2, BICL3, XORL2, XORL3, MNEGL, CASEL, - MOVL, CMPL, MCOML, BITL, CLRL, TSTL, INCL, DECL, - ADWC, SBWC, MTPR, MFPR, MOVPSL, PUSHL, MOVAL, PUSHAL, - BBS, BBC, BBSS, BBCS, BBSC, BBCC, BBSSI, BBCCI, - BLBS, BLBC, FFS, FFC, CMPV, CMPZV, EXTV, EXTZV, - INSV, ACBL, AOBLSS, AOBLEQ, SOBGEQ, SOBGTR, CVTLB, CVTLW, - ASHP, CVTLP, CALLG, CALLS, XFC, CVTGF = 0x133, - ADDG2= 0x140, ADDG3, SUBG2, SUBG3, MULG2, MULG3, DIVG2, DIVG3, - CVTGB, CVTGW, CVTGL, CVTRGL, CVTBG, CVTWG, CVTLG, ACBG, - MOVG, CMPG, MNEGG, TSTG, EMODG, POLYG, CVTFG = 0x199 }; - -/* Repeated operations */ - -#define SXTB(x) (((x) & BSIGN)? ((x) | ~BMASK): ((x) & BMASK)) -#define SXTW(x) (((x) & WSIGN)? ((x) | ~WMASK): ((x) & WMASK)) -#define SXTBW(x) (((x) & BSIGN)? ((x) | (WMASK - BMASK)): ((x) & BMASK)) -#define SXTL(x) (((x) & LSIGN)? ((x) | ~LMASK): ((x) & LMASK)) -#define INTOV if (PSL & PSW_IV) SET_TRAP (TRAP_INTOV) -#define V_INTOV cc = cc | CC_V; INTOV -#define NEG(x) ((~(x) + 1) & LMASK) - -/* Istream access */ - -#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] = fault_PC -#define GET_ISTR(d,l) d = get_istr (l, acc) -#define BRANCHB(d) PCQ_ENTRY, PC = PC + SXTB (d), FLUSH_ISTR -#define BRANCHW(d) PCQ_ENTRY, PC = PC + SXTW (d), FLUSH_ISTR -#define JUMP(d) PCQ_ENTRY, PC = (d), FLUSH_ISTR -#define SETPC(d) PC = (d), FLUSH_ISTR -#define FLUSH_ISTR ibcnt = 0, ppc = -1 - -/* Read and write */ - -#define RA (acc) -#define WA ((acc) << TLB_V_WACC) -#define ACC_MASK(x) (1 << (x)) -#define TLB_ACCR(x) (ACC_MASK (x) << TLB_V_RACC) -#define TLB_ACCW(x) (ACC_MASK (x) << TLB_V_WACC) -#define REF_V 0 -#define REF_P 1 - -/* Condition code macros */ - -#define CC_ZZ1P cc = CC_Z | (cc & CC_C) - -#define CC_IIZZ_B(r) \ - if ((r) & BSIGN) cc = CC_N; \ - else if ((r) == 0) cc = CC_Z; \ - else cc = 0 -#define CC_IIZZ_W(r) \ - if ((r) & WSIGN) cc = CC_N; \ - else if ((r) == 0) cc = CC_Z; \ - else cc = 0 -#define CC_IIZZ_L(r) \ - if ((r) & LSIGN) cc = CC_N; \ - else if ((r) == 0) cc = CC_Z; \ - else cc = 0 -#define CC_IIZZ_Q(rl,rh) \ - if ((rh) & LSIGN) cc = CC_N; \ - else if (((rl) | (rh)) == 0) cc = CC_Z; \ - else cc = 0 -#define CC_IIZZ_FP CC_IIZZ_W - -#define CC_IIZP_B(r) \ - if ((r) & BSIGN) cc = CC_N | (cc & CC_C); \ - else if ((r) == 0) cc = CC_Z | (cc & CC_C); \ - else cc = cc & CC_C -#define CC_IIZP_W(r) \ - if ((r) & WSIGN) cc = CC_N | (cc & CC_C); \ - else if ((r) == 0) cc = CC_Z | (cc & CC_C); \ - else cc = cc & CC_C -#define CC_IIZP_L(r) \ - if ((r) & LSIGN) cc = CC_N | (cc & CC_C); \ - else if ((r) == 0) cc = CC_Z | (cc & CC_C); \ - else cc = cc & CC_C -#define CC_IIZP_Q(rl,rh) \ - if ((rh) & LSIGN) cc = CC_N | (cc & CC_C); \ - else if (((rl) | (rh)) == 0) cc = CC_Z | (cc & CC_C); \ - else cc = cc & CC_C -#define CC_IIZP_FP CC_IIZP_W - -#define V_ADD_B(r,s1,s2) \ - if (((~(s1) ^ (s2)) & ((s1) ^ (r))) & BSIGN) { V_INTOV; } -#define V_ADD_W(r,s1,s2) \ - if (((~(s1) ^ (s2)) & ((s1) ^ (r))) & WSIGN) { V_INTOV; } -#define V_ADD_L(r,s1,s2) \ - if (((~(s1) ^ (s2)) & ((s1) ^ (r))) & LSIGN) { V_INTOV; } -#define C_ADD(r,s1,s2) \ - if (((uint32) r) < ((uint32) s2)) cc = cc | CC_C - -#define CC_ADD_B(r,s1,s2) \ - CC_IIZZ_B (r); \ - V_ADD_B (r, s1, s2); \ - C_ADD (r, s1, s2) -#define CC_ADD_W(r,s1,s2) \ - CC_IIZZ_W (r); \ - V_ADD_W (r, s1, s2); \ - C_ADD (r, s1, s2) -#define CC_ADD_L(r,s1,s2) \ - CC_IIZZ_L (r); \ - V_ADD_L (r, s1, s2); \ - C_ADD (r, s1, s2) - -#define V_SUB_B(r,s1,s2) \ - if ((((s1) ^ (s2)) & (~(s1) ^ (r))) & BSIGN) { V_INTOV; } -#define V_SUB_W(r,s1,s2) \ - if ((((s1) ^ (s2)) & (~(s1) ^ (r))) & WSIGN) { V_INTOV; } -#define V_SUB_L(r,s1,s2) \ - if ((((s1) ^ (s2)) & (~(s1) ^ (r))) & LSIGN) { V_INTOV; } -#define C_SUB(r,s1,s2) \ - if (((uint32) s2) < ((uint32) s1)) cc = cc | CC_C - -#define CC_SUB_B(r,s1,s2) \ - CC_IIZZ_B (r); \ - V_SUB_B (r, s1, s2); \ - C_SUB (r, s1, s2) -#define CC_SUB_W(r,s1,s2) \ - CC_IIZZ_W (r); \ - V_SUB_W (r, s1, s2); \ - C_SUB (r, s1, s2) -#define CC_SUB_L(r,s1,s2) \ - CC_IIZZ_L (r); \ - V_SUB_L (r, s1, s2); \ - C_SUB (r, s1, s2) - -#define CC_CMP_B(s1,s2) \ - if (SXTB (s1) < SXTB (s2)) cc = CC_N; \ - else if ((s1) == (s2)) cc = CC_Z; \ - else cc = 0; \ - if (((uint32) s1) < ((uint32) s2)) cc = cc | CC_C -#define CC_CMP_W(s1,s2) \ - if (SXTW (s1) < SXTW (s2)) cc = CC_N; \ - else if ((s1) == (s2)) cc = CC_Z; \ - else cc = 0; \ - if (((uint32) s1) < ((uint32) s2)) cc = cc | CC_C -#define CC_CMP_L(s1,s2) \ - if ((s1) < (s2)) cc = CC_N; \ - else if ((s1) == (s2)) cc = CC_Z; \ - else cc = 0; \ - if (((uint32) s1) < ((uint32) s2)) cc = cc | CC_C - -/* Model dependent definitions */ - -#include "vaxmod_defs.h" - -#endif /* _VAX_DEFS_H */ diff --git a/VAX/vax_doc.txt b/VAX/vax_doc.txt deleted file mode 100644 index a8c12387..00000000 --- a/VAX/vax_doc.txt +++ /dev/null @@ -1,923 +0,0 @@ -To: Users -From: Bob Supnik -Subj: VAX Simulator Usage -Date: 15-Jul-2003 - - COPYRIGHT NOTICE - -The following copyright notice applies to both the SIMH source and binary: - - 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"), - 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 VAX simulator. - - -1. Simulator Files - -To compile the VAX, you must define VM_VAX and USE_INT64 as part of the compilation -command line. To enable extended file support (files greater than 2GB), you must -define USE_ADDR64 as part of the command line as well. - -sim/ sim_defs.h - sim_ether.h - sim_rev.h - sim_sock.h - sim_tape.h - sim_tmxr.h - scp.c - scp_tty.c - sim_ether.c - sim_sock.c - sim_tape.c - sim_tmxr.c - -sim/vax/ vax_defs.h - vaxmod_defs.h - vax_cpu.c - vax_cpu1.c - vax_fpa.c - vax_io.c - vax_mmu.c - vax_stddev.c - vax_sys.c - vax_sysdev.c - -sim/pdp11/ pdp11_mscp.h - pdp11_uqssp.h - pdp11_xq.h - pdp11_xq_bootrom.h - pdp11_dz.c - pdp11_lp.c - pdp11_pt.c - pdp11_rl.c - pdp11_rq.c - pdp11_tq.c - pdp11_ts.c - pdp11_xp.c - -2. VAX Features - -The VAX simulator is configured as follows: - -device simulates -name(s) - -CPU KA655 CPU with 16MB-64MB of memory -TLB translation buffer -ROM read-only memory -NVR non-volatile memory -SYSD system devices -QBA Qbus adapter -PTR,PTP PCV11 paper tape reader/punch -TTI,TTO console terminal -LPT LPV11 line printer -CLK real-time clock -DZ DZV11 4-line terminal multiplexor (up to 4) -RL RLV12/RL01(2) cartridge disk controller with four drives -RQ RQDX3 MSCP controller with four drives -RQB second RQDX3 MSCP controller with four drives -RQC third RQDX3 MSCP controller with four drives -RQD fourth RQDX3 MSCP controller with four drives -TS TSV11/TSV05 magnetic tape controller with one drive -TQ TQK50 TMSCP magnetic tape controller with four drives -XQ DELQA/DEQNA Ethernet controller -XQB second DELQA/DEQNA Ethernet controller - -The PTR, PTP, LPT, DZ, RL, RQ, RQB, RQC, RQD, TS, TQ, XQ, and XQB devices -can be set DISABLED. RQB, RQC, RQD, and XQB are disabled by default. - -The VAX simulator implements several unique stop conditions: - - - change mode to interrupt stack - - illegal vector (bits<1:0> = 2 or 3) - - unexpected exception during interrupt or exception - - process PTE in P0 or P1 space instead of system space - - unknown IPL - - infinite loop (BRB/W to self at IPL 1F) - -The VAX supports a simple binary format consisting of a stream of -binary bytes without origin or checksum, for loading memory, the boot -ROM, or the non-volatile memory. - -2.1 CPU and System Devices - -2.2 CPU - -CPU options include the size of main memory and the treatment of the -HALT instruction. - - SET CPU 16M set memory size = 16MB - SET CPU 32M set memory size = 32MB - SET CPU 48M set memory size = 48MB - SET CPU 64M set memory size = 64MB - SET CPU SIMHALT kernel HALT returns to simulator - SET CPU CONHALT kernel HALT returns to boot ROM console - -The CPU implements a show command to display the I/O address map: - - SHOW CPU IOSPACE show I/O space address map - -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 16MB. If the simulator -is running VMS, the operating system will not recognize memory size changes -until AUTOGEN is run. - -Memory can be loaded with a binary byte stream using the LOAD command. -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): - - -b examine/deposit bytes - -w examine/deposit words - -l examine/deposit longwords - -d data radix is decimal - -o data radix is octal - -h data radix is hexadecimal - -v interpret address as virtual, current mode - -CPU registers include the visible state of the processor as well as the -control registers for the interrupt system. - - name size comments - - PC 32 program counter - R0..R14 32 R0..R14 - AP 32 alias for R12 - FP 32 alias for R13 - SP 32 alias for R14 - PSL 32 processor status longword - CC 4 condition codes, PSL<3:0> - KSP 32 kernel stack pointer - ESP 32 executive stack pointer - SSP 32 supervisor stack pointer - USP 32 user stack pointer - IS 32 interrupt stack pointer - SCBB 32 system control block base - PCBB 32 process controll block base - P0BR 32 P0 base register - P0LR 22 P0 length register - P1BR 32 P1 base register - P1LR 22 P1 length register - SBR 32 system base register - SLR 22 system length register - SISR 16 software interrupt summary register - ASTLVL 4 AST level register - CADR 8 cache disable register - MSER 8 memory system error register - MAPEN 1 memory management enable flag - TRPIRQ 8 trap/interrupt pending - CRDERR 1 correctible read data error flag - MEMERR 1 memory error flag - PCQ[0:63] 32 PC prior to last PC change or interrupt; - 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 -and user translation buffers, respectively. It has no registers. Each -translation buffer entry consists of two 32b words, as follows: - - word n tag - word n+1 cached PTE - -An invalid entry is indicated by a tag of FFFFFFFF. - -2.1.3 Read-only memory (ROM) - -The boot ROM consists of a single unit, representing the 128KB boot ROM. -It has no registers. The boot ROM is loaded with a binary byte stream -using the LOAD -r command: - - LOAD -r KA655.BIN load boot ROM image KA655.BIN - -ROM accesses a use a calibrated delay that slows ROM-based execution to -about 500K instructions per second. This delay is required to make the -power-up self-test routines run correctly on very fast hosts. The delay -is controlled with the commands: - - SET ROM NODELAY ROM runs like RAM - SET ROM DELAY ROM runs slowly - -2.1.4 Non-volatile Memory (NVR) - -The NVR consists of a single unit, representing 1KB of battery-backed up -memory. When the simulator starts, NVR is cleared to 0, and the SSC -battery-low indicator is set. Normally, NVR is saved and restored like -other memory in the system. Alternately, NVR can be attached to a file. -This allows its contents to be saved and restored independently of -other memories, so that NVR state can be preserved across simulator runs. - -Successfully loading an NVR image clears the SSC battery-low indicator. - -2.1.5 System Devices (SYSD) - -The system devices are the facilities implemented in KA655 CPU board, -the CMCTL memory controller, and the SSC system support chip. Note that -the simulation of these devices is incomplete and is intended strictly -to allow the patched bootstrap code to run. The SYSD registers are: - - name size comments - - CMCSR[0:17] 32 CMCTL control and status registers - CACR 8 second-level cache control register - BDR 8 front panel jumper register - BASE 29 SSC base address register - CNF 32 SSC configuration register - BTO 32 SSC bus timeout register - TCSR0 32 SSC timer 0 control/status register - TIR0 32 SSC timer 0 interval register - TNIR0 32 SSC timer 0 next interval register - TIVEC0 9 SSC timer 0 interrupt vector register - TCSR1 32 SSC timer 1 control/status register - TIR1 32 SSC timer 1 interval register - TNIR1 32 SSC timer 1 next interval register - TIVEC1 9 SSC timer 1 interrupt vector register - ADSM0 32 SSC address match 0 address - ADSK0 32 SSC address match 0 mask - ADSM1 32 SSC address match 1 address - 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: - - name size comments - - SCR 16 system configuration register - DSER 8 DMA system error register - MEAR 13 master error address register - SEAR 20 slave error address register - MBR 29 Qbus map base register - IPC 16 interprocessor communications register - IPL17 32 IPL 17 interrupt flags - IPL16 32 IPL 16 interrupt flags - IPL15 32 IPL 15 interrupt flags - IPL14 32 IPL 14 interrupt flags - -2.2 I/O Device Addressing - -Qbus I/O space is not large enough to allow all possible devices to be -configured simultaneously at fixed addresses. Instead, many devices have -floating addresses; that is, the assigned device address depends on the -presense of other devices in the configuration: - - DZ11 all instances have floating addresses - RL11 first instance has fixed address, rest floating - MSCP disk first instance has fixed address, rest floating - TMSCP tape first instance has fixed address, rest floating - -To maintain addressing consistency as the configuration changes, the -simulator implements DEC's standard I/O address and vector autoconfiguration -algorithms for devices DZ, RL, RQ, and TQ. This allows the user to -enable or disable devices without needing to manage I/O addresses -and vectors. - -In addition to autoconfiguration, most devices support the SET ADDRESS -command, which allows the I/O page address of the device to be changed, -and the SET VECTOR command, which allows the vector of the device to be -changed. Explicitly setting the I/O address of a device which normally -uses autoconfiguration DISABLES autoconfiguration for that device. As -a consequence, the user may have to manually configure all other -autoconfigured devices, because the autoconfiguration algorithm no -longer recognizes the explicitly configured device. A device can be -reset to autoconfigure with the SET AUTOCONFIGURE command. - -The current I/O map can be displayed with the SHOW CPU IOSPACE command. -Addresses that have set by autoconfiguration are marked with an asterisk (*). - -All devices support the SHOW ADDRESS and SHOW VECTOR commands, which display -the device address and vector, respectively. - -2.3 Programmed I/O Devices - -2.3.1 PC11 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 8 last data item processed - CSR 16 control/status register - INT 1 interrupt pending flag - ERR 1 error flag (CSR<15>) - BUSY 1 busy flag (CSR<11>) - DONE 1 device done flag (CSR<7>) - IE 1 interrupt enable flag (CSR<6>) - 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.3.2 PC11 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 8 last data item processed - CSR 16 control/status register - INT 1 interrupt pending flag - ERR 1 error flag (CSR<15>) - DONE 1 device done flag (CSR<7>) - IE 1 interrupt enable flag (CSR<6>) - 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.3.3 Terminal Input (TTI) - -The terminal interfaces (TTI, TTO) can be set to one of two modes: -7B or 8B. In 7B mode, input and output characters are masked to 7 -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: - - name size comments - - BUF 8 last data item processed - CSR 16 control/status register - INT 1 interrupt pending flag - ERR 1 error flag (CSR<15>) - DONE 1 device done flag (CSR<7>) - IE 1 interrupt enable flag (CSR<6>) - POS 32 number of characters input - TIME 24 keyboard polling interval - -If the simulator is compiled under Windows Visual C++, typing ^C to the -terminal input causes a fatal run-time error. Use the following command -to simulate typing ^C: - - SET TTI CTRL-C - -2.3.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 - CSR 16 control/status register - INT 1 interrupt pending flag - ERR 1 error flag (CSR<15>) - DONE 1 device done flag (CSR<7>) - IE 1 interrupt enable flag (CSR<6>) - POS 32 number of characters input - TIME 24 time from I/O initiation to interrupt - -2.3.5 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 8 last data item processed - CSR 16 control/status register - INT 1 interrupt pending flag - ERR 1 error flag (CSR<15>) - DONE 1 device done flag (CSR<7>) - IE 1 interrupt enable flag (CSR<6>) - 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 paper - - OS I/O error x report error and stop - -2.3.6 Real-Time Clock (CLK) - -The clock (CLK) implements these registers: - - name size comments - - CSR 16 control/status register - INT 1 interrupt pending flag - IE 1 interrupt enable flag (CSR<6>) - TODR 32 time-of-day register - BLOW 1 TODR battery low indicator - TIME 24 clock frequency - TPS 8 ticks per second (100) - -The real-time clock autocalibrates; the clock interval is adjusted up or -down so that the clock tracks actual elapsed time. - -2.3.7 DZV11 Terminal Multiplexor (DZ) - -The DZV11 is an 4-line terminal multiplexor. Up to 4 DZ11's (16 lines) -are supported. The number of lines can be changed with the command - - SET DZ LINES=n set line count to n - -The line count must be a multiple of 4, with a maximum of 16. - -The DZV11 supports 8-bit input and output of characters. 8-bit output -may be incompatible with certain operating systems. The command - - SET DZ 7B - -forces output characters to be masked to 7 bits. - -The terminal lines perform input and output through Telnet sessions -connected to a user-specified port. The ATTACH command specifies -the port to be used: - - ATTACH {-am} DZ set up listening port - -where port is a decimal number between 1 and 65535 that is not being used -for other TCP/IP activities. The optional switch -m turns on the DZV11's -modem controls; the optional switch -a turns on active disconnects -(disconnect session if computer clears Data Terminal Ready). Without -modem control, the DZ behaves as though terminals were directly connected; -disconnecting the Telnet session does not cause any operating system- -visible change in line status. - -Once the DZ is attached and the simulator is running, the DZ will listen -for connections on the specified port. It assumes that the incoming -connections are Telnet connections. The connection remains open until -disconnected by the simulated program, the Telnet client, a SET DZ -DISCONNECT command, or a DETACH DZ command. - -The SHOW DZ CONNECTIONS command displays the current connections to the DZ. -The SHOW DZ STATISTICS command displays statistics for active connections. -The SET DZ DISCONNECT=linenumber disconnects the specified line. - -The DZV11 implements these registers: - - name size comments - - CSR[0:3] 16 control/status register, boards 0-3 - RBUF[0:3] 16 receive buffer, boards 0-3 - LPR[0:3] 16 line parameter register, boards 0-3 - TCR[0:3] 16 transmission control register, boards 0-3 - MSR[0:3] 16 modem status register, boards 0-3 - TDR[0:3] 16 transmit data register, boards 0-3 - SAENB[0:3] 1 silo alarm enabled, boards 0-3 - RXINT 4 receive interrupts, boards 3..0 - TXINT 4 transmit interrupts, boards 3..0 - MDMTCL 1 modem control enabled - AUTODS 1 autodisconnect enabled - -The DZV11 does not support save and restore. All open connections are -lost when the simulator shuts down or the DZ is detached. - -2.4 RLV12/RL01,RL02 Cartridge Disk (RL) - -RLV12 options include the ability to set units write enabled or write locked, -to set the drive size to RL01, RL02, or autosize, and to write a DEC standard -044 compliant bad block table on the last track: - - SET RLn LOCKED set unit n write locked - SET RLn WRITEENABLED set unit n write enabled - SET RLn RL01 set size to RL01 - SET RLn RL02 set size to RL02 - SET RLn AUTOSIZE set size based on file size at attach - SET RLn BADBLOCK write bad block table on last track - -The size options can be used only when a unit is not attached to a file. The -bad block option can be used only when a unit is attached to a file. Units -can also be set ONLINE or OFFLINE. - -The RL11 implements these registers: - - name size comments - - RLCS 16 control/status - RLDA 16 disk address - RLBA 16 memory address - RLBAE 6 memory address extension (RLV12) - RLMP..RLMP2 16 multipurpose register queue - INT 1 interrupt pending flag - ERR 1 error flag (CSR<15>) - DONE 1 device done flag (CSR<7>) - IE 1 interrupt enable flag (CSR<6>) - STIME 24 seek time, per cylinder - RTIME 24 rotational delay - 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 - -2.5 RQDX3 MSCP Disk Controllers (RQ, RQB, RQC, RQD) - -The simulator implements four MSCP disk controllers, RQ, RQB, RQC, RQD. -Initially, RQB, RQC, and RQD are disabled. Each RQ controller simulates -an RQDX3 MSCP disk controller. RQ options include the ability to set -units write enabled or write locked, and to set the drive type to one -of many disk types: - - SET RQn LOCKED set unit n write locked - SET RQn WRITEENABLED set unit n write enabled - SET RQn RX50 set type to RX50 - SET RQn RX33 set type to RX33 - SET RQn RD51 set type to RD51 - SET RQn RD52 set type to RD52 - SET RQn RD53 set type to RD53 - SET RQn RD54 set type to RD54 - SET RQn RD31 set type to RD31 - SET RQn RA82 set type to RA82 - SET RQn RA72 set type to RA72 - SET RQn RA90 set type to RA90 - SET RQn RA92 set type to RA92 - SET RQn RAUSER{=n} set type to RA81 with n LBN's - -The type options can be used only when a unit is not attached to a file. -RAUSER is a "user specified" disk; the user can specify the size of the -disk in logical block numbers (LBN's, 512 bytes each). The minimum size -is 50MB. The maximum size is 2GB if the simulator is compiled without -64b addressing, 1000GB with 64b addressing. - -Units can also be set ONLINE or OFFLINE. - -Each RQ controller implements the following special SHOW commands: - - SHOW RQn TYPE show drive type - SHOW RQ RINGS show command and response rings - SHOW RQ FREEQ show packet free queue - SHOW RQ RESPQ show packet response queue - SHOW RQ UNITQ show unit queues - SHOW RQ ALL show all ring and queue state - SHOW RQn UNITQ show unit queues for unit n - -Each RQ controller implements these registers: - - name size comments - - SA 16 status/address register - S1DAT 16 step 1 init host data - CQBA 22 command queue base address - CQLNT 8 command queue length - CQIDX 8 command queue index - RQBA 22 request queue base address - RQLNT 8 request queue length - RQIDX 8 request queue index - FREE 5 head of free packet list - RESP 5 head of response packet list - PBSY 5 number of busy packets - CFLGS 16 controller flags - CSTA 4 controller state - PERR 9 port error number - CRED 5 host credits - HAT 17 host available timer - HTMO 17 host timeout value - CPKT[0:3] 5 current packet, units 0-3 - PKTQ[0:3] 5 packet queue, units 0-3 - UFLG[0:3] 16 unit flags, units 0-3 - INT 1 interrupt request - ITIME 1 response time for initialization steps - (except for step 4) - QTIME 24 response time for 'immediate' packets - XTIME 24 response time for data transfers - PKTS[33*32] 16 packet buffers, 33W each, - 32 entries - -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 TSV11/TSV05 Magnetic Tape (TS) - -TS options include the ability to make the unit write enabled or write locked. - - SET TS LOCKED set unit write locked - SET TS WRITEENABLED set unit write enabled - -The magnetic tape controller implements these registers: - - name size comments - - TSSR 16 status register - TSBA 16 bus address register - TSDBX 16 data buffer extension register - CHDR 16 command packet header - CADL 16 command packet low address or count - CADH 16 command packet high address - CLNT 16 command packet length - MHDR 16 message packet header - MRFC 16 message packet residual frame count - MXS0 16 message packet extended status 0 - MXS1 16 message packet extended status 1 - MXS2 16 message packet extended status 2 - MXS3 16 message packet extended status 3 - MXS4 16 message packet extended status 4 - WADL 16 write char packet low address - WADH 16 write char packet high address - WLNT 16 write char packet length - WOPT 16 write char packet options - WXOPT 16 write char packet extended options - ATTN 1 attention message pending - BOOT 1 boot request pending - OWNC 1 if set, tape owns command buffer - OWNM 1 if set, tape owns message buffer - TIME 24 delay - POS 32 position - -Error handling is as follows: - - error processed as - - not attached tape not ready - - end of file (read or space) end of physical tape - (write) ignored - - OS I/O error fatal tape error - -2.7 TQK50 TMSCP Disk Controller (TQ) - -The TQ controller simulates the TQK50 TMSCP disk controller. TQ options -include the ability to set units write enabled or write locked, and to -specify the controller type and tape length: - - SET TQn LOCKED set unit n write locked - SET TQn WRITEENABLED set unit n write enabled - SET TQ TK50 set controller type to TK50 - SET TQ TK70 set controller type to TK70 - SET TQ TU81 set controller type to TU81 - SET TQ TKUSER{=n} set controller type to TK50 with - tape capacity of n MB - -User-specified capacity must be between 50 and 2000 MB. - -The TQ controller implements the following special SHOW commands: - - SHOW TQ TYPE show controller type - SHOW TQ RINGS show command and response rings - SHOW TQ FREEQ show packet free queue - SHOW TQ RESPQ show packet response queue - SHOW TQ UNITQ show unit queues - SHOW TQ ALL show all ring and queue state - SHOW TQn UNITQ show unit queues for unit n - -The TQ controller implements these registers: - - name size comments - - SA 16 status/address register - S1DAT 16 step 1 init host data - CQBA 22 command queue base address - CQLNT 8 command queue length - CQIDX 8 command queue index - RQBA 22 request queue base address - RQLNT 8 request queue length - RQIDX 8 request queue index - FREE 5 head of free packet list - RESP 5 head of response packet list - PBSY 5 number of busy packets - CFLGS 16 controller flags - CSTA 4 controller state - PERR 9 port error number - CRED 5 host credits - HAT 17 host available timer - HTMO 17 host timeout value - CPKT[0:3] 5 current packet, units 0-3 - PKTQ[0:3] 5 packet queue, units 0-3 - UFLG[0:3] 16 unit flags, units 0-3 - POS[0:3] 32 tape position, units 0-3 - OBJP[0:3] 32 object position, units 0-3 - INT 1 interrupt request - ITIME 1 response time for initialization steps - (except for step 4) - QTIME 24 response time for 'immediate' packets - XTIME 24 response time for data transfers - PKTS[33*32] 16 packet buffers, 33W each, - 32 entries - -Error handling is as follows: - - error processed as - - not attached tape not ready - - end of file end of medium - - OS I/O error report error and stop - -2.8 DELQA/DEQNA Qbus Ethernet Controllers (XQ, XQB) - -The simulator implements two DELQA/DEQNA Qbus Ethernet controllers (XQ, -XQB). Initially, XQ is enabled, and XQB is disabled. Options allow -control of the MAC address, the controller mode, and the sanity timer. - - SET XQ MAC= ex. 08-00-2B-AA-BB-CC - SHOW XQ MAC - -These commands are used to change or display the MAC address. -is a valid ethernet MAC, delimited by dashes or periods. The controller -defaults to 08-00-2B-AA-BB-CC, which should be sufficient if there is -only one SIMH controller on your LAN. Two cards with the same MAC address -will see each other's packets, resulting in a serious mess. - - SET XQ TYPE={DEQNA|[DELQA]} - SHOW XQ TYPE - -These commands are used to change or display the controller mode. DELQA -mode is better and faster but may not be usable by older or non-DEC OS's. -Also, be aware that DEQNA mode is not supported by many modern OS's. The -DEQNA-LOCK mode of the DELQA card is emulated by setting the the controller -to DEQNA - there is no need for a separate mode. DEQNA-LOCK mode behaves -exactly like a DEQNA, except for the operation of the VAR and MOP processing. - - SET XQ SANITY={ON|[OFF]} - SHOW XQ SANITY - -These commands change or display the INITIALIZATION sanity timer (DEQNA -jumper W3/DELQA switch S4). The INITIALIZATION sanity timer has a default -timeout of 4 minutes, and cannot be turned off, just reset. The normal -sanity timer can be set by operating system software regardless of the -state of this switch. Note that only the DEQNA (or the DELQA in DEQNA- -LOCK mode (=DEQNA)) supports the sanity timer - it is ignored by a DELQA -in Normal mode, which uses switch S4 for a different purpose. - -To access the network, the simulated Ethernet controller must be attached -to a real Ethernet interface: - - ATTACH XQ0 {ethX|} ex. eth0 or /dev/era0 - SHOW XQ ETH - -where X in 'ethX' is the number of the ethernet controller to attach, or -the real device name. The X number is system dependant. If you only have -one ethernet controller, the number will probably be 0. To find out what -your system thinks the ethernet numbers are, use the SHOW XQ ETH command. -The device list can be quite cryptic, depending on the host system, but -is probably better than guessing. If you do not attach the device, the -controller will behave as though the ethernet cable were unplugged. - -XQ has the following registers: - - name size comments - - SA0 16 station address word 0 - SA1 16 station address word 1 - SA2 16 station address word 2 - SA3 16 station address word 3 - SA4 16 station address word 4 - SA5 16 station address word 5 - CSR 16 control status register - VAR 16 vector address register - RBDL 32 receive buffer descriptor list - XBDL 32 trans(X)mit buffer descriptorlList - -One final note: because of it's asynchronous nature, the XQ controller is -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.9 Symbolic Display and Input - -The VAX simulator implements symbolic display and input. Display is -controlled by command line switches: - - -a display as ASCII character - -c display as ASCII 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 ASCII string - alphabetic instruction mnemonic - numeric octal number - -Instruction input uses standard VAX assembler syntax. - -The syntax for specifiers is as follows: - -syntax specifier displacement comments - -#s^n, #n 0n - short literal, integer only -[Rn] 4n - indexed, second specifier - follows -Rn 5n - PC illegal -(Rn) 6n - PC illegal --(Rn) 7n - PC illegal -(Rn)+ 8n - -#i^n, #n 8F n immediate -@(Rn)+ 9n - -@#addr 9F addr absolute -{+/-}b^d(Rn) An {+/-}d byte displacement -b^d AF d - PC byte PC relative -@{+/-}b^d(Rn) Bn {+/-}d byte displacement deferred -@b^d BF d - PC byte PC relative deferred -{+/-}w^d(Rn) Cn {+/-}d word displacement -w^d CF d - PC word PC relative -@{+/-}w^d(Rn) Dn {+/-}d word displacement deferred -@w^d DF d - PC word PC relative deferred -{+/-}l^d(Rn) En {+/-}d long displacement -l^d EF d - PC long PC relative -@{+/-}l^d(Rn) Fn {+/-}d long displacement deferred -@l^d FF d - PC long PC relative deferred - -If no override is given for a literal (s^ or i^) or for a displacement or PC -relative addres (b^, w^, or l^), the simulator chooses the mode automatically. diff --git a/VAX/vax_fpa.c b/VAX/vax_fpa.c deleted file mode 100644 index 483dd9df..00000000 --- a/VAX/vax_fpa.c +++ /dev/null @@ -1,1395 +0,0 @@ -/* vax_fpa.c - VAX floating point accelerator simulator - - 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"), - 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. - - 19-Jun-03 RMS Simplified add algorithm - 16-May-03 RMS Fixed bug in floating to integer convert overflow - Fixed multiple bugs in EMODx - Integrated 32b only code - 05-Jul-02 RMS Changed internal routine names for C library conflict - 17-Apr-02 RMS Fixed bug in EDIV zero quotient - - This module contains the instruction simulators for - - - 64 bit arithmetic (ASHQ, EMUL, EDIV) - - single precision floating point - - double precision floating point, D and G format -*/ - -#include "vax_defs.h" -#include - -#define M32 0xFFFFFFFF /* 32b */ -#define M16 0x0000FFFF - -#define FD_V_EXP 7 /* f/d exponent */ -#define FD_M_EXP 0xFF -#define FD_BIAS 0x80 /* f/d bias */ -#define FD_EXP (FD_M_EXP << FD_V_EXP) -#define FD_HB (1 << FD_V_EXP) /* f/d hidden bit */ -#define FD_GUARD (15 - FD_V_EXP) /* # guard bits */ -#define FD_GETEXP(x) (((x) >> FD_V_EXP) & FD_M_EXP) - -#define G_V_EXP 4 /* g exponent */ -#define G_M_EXP 0x7FF -#define G_BIAS 0x400 /* g bias */ -#define G_EXP (G_M_EXP << G_V_EXP) -#define G_HB (1 << G_V_EXP) /* g hidden bit */ -#define G_GUARD (15 - G_V_EXP) /* # guard bits */ -#define G_GETEXP(x) (((x) >> G_V_EXP) & G_M_EXP) - -extern int32 R[16]; -extern int32 PSL; -extern int32 p1; -extern jmp_buf save_env; - -extern int32 Read (uint32 va, int32 size, int32 acc); - -#if defined (USE_INT64) - -#define M64 0xFFFFFFFFFFFFFFFF /* 64b */ -#define FD_FRACW (0xFFFF & ~(FD_EXP | FPSIGN)) -#define FD_FRACL (FD_FRACW | 0xFFFF0000) /* f/d fraction */ -#define G_FRACW (0xFFFF & ~(G_EXP | FPSIGN)) -#define G_FRACL (G_FRACW | 0xFFFF0000) /* g fraction */ -#define UNSCRAM(h,l) (((((t_uint64) (h)) << 48) & 0xFFFF000000000000) | \ - ((((t_uint64) (h)) << 16) & 0x0000FFFF00000000) | \ - ((((t_uint64) (l)) << 16) & 0x00000000FFFF0000) | \ - ((((t_uint64) (l)) >> 16) & 0x000000000000FFFF)) -#define CONCAT(h,l) ((((t_uint64) (h)) << 32) | ((uint32) (l))) - -struct ufp { - int32 sign; - int32 exp; - t_uint64 frac; }; - -typedef struct ufp UFP; - -#define UF_NM 0x8000000000000000 /* normalized */ -#define UF_FRND 0x0000008000000000 /* F round */ -#define UF_DRND 0x0000000000000080 /* D round */ -#define UF_GRND 0x0000000000000400 /* G round */ -#define UF_V_NM 63 -#define UF_V_FDHI 40 -#define UF_V_FDLO (UF_V_FDHI - 32) -#define UF_V_GHI 43 -#define UF_V_GLO (UF_V_GHI - 32) -#define UF_GETFDHI(x) (int32) ((((x) >> (16 + UF_V_FDHI)) & FD_FRACW) | \ - (((x) >> (UF_V_FDHI - 16)) & ~0xFFFF)) -#define UF_GETFDLO(x) (int32) ((((x) >> (16 + UF_V_FDLO)) & 0xFFFF) | \ - (((x) << (16 - UF_V_FDLO)) & ~0xFFFF)) -#define UF_GETGHI(x) (int32) ((((x) >> (16 + UF_V_GHI)) & G_FRACW) | \ - (((x) >> (UF_V_GHI - 16)) & ~0xFFFF)) -#define UF_GETGLO(x) (int32) ((((x) >> (16 + UF_V_GLO)) & 0xFFFF) | \ - (((x) << (16 - UF_V_GLO)) & ~0xFFFF)) - -void unpackf (int32 hi, UFP *a); -void unpackd (int32 hi, int32 lo, UFP *a); -void unpackg (int32 hi, int32 lo, UFP *a); -void norm (UFP *a); -int32 rpackfd (UFP *a, int32 *rh); -int32 rpackg (UFP *a, int32 *rh); -void vax_fadd (UFP *a, UFP *b, t_int64 mask); -void vax_fmul (UFP *a, UFP *b, int32 prec, int32 bias, t_int64 mask); -void vax_fdiv (UFP *b, UFP *a, int32 prec, int32 bias); -void vax_fmod (UFP *a, int32 bias, int32 *intgr, int32 *flg); - -/* Quadword arithmetic shift - - opnd[0] = shift count (cnt.rb) - opnd[1:2] = source (src.rq) - opnd[3:4] = destination (dst.wq) -*/ - -int32 op_ashq (int32 *opnd, int32 *rh, int32 *flg) -{ -t_int64 src, r; -int32 sc = opnd[0]; - -src = CONCAT (opnd[2], opnd[1]); /* build src */ -if (sc & BSIGN) { /* right shift? */ - *flg = 0; /* no ovflo */ - sc = 0x100 - sc; /* |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 */ -*rh = (int32) (r >> 32); /* hi result */ -return ((int32) r); /* lo result */ -} - -/* Extended multiply subroutine */ - -int32 op_emul (int32 mpy, int32 mpc, int32 *rh) -{ -t_int64 lmpy = mpy; -t_int64 lmpc = mpc; - -lmpy = lmpy * lmpc; -*rh = ((int32) (lmpy >> 32)); -return (int32) lmpy; -} - -/* Extended divide - - opnd[0] = divisor (non-zero) - opnd[1:2] = dividend -*/ - -int32 op_ediv (int32 *opnd, int32 *rh, int32 *flg) -{ -t_int64 ldvd, ldvr; -int32 quo, rem; - -*flg = CC_V; /* assume error */ -*rh = 0; -ldvr = ((opnd[0] & LSIGN)? -opnd[0]: opnd[0]) & M32; /* |divisor| */ -ldvd = CONCAT (opnd[2], opnd[1]); /* 64b dividend */ -if (opnd[2] & LSIGN) ldvd = -ldvd; /* |dividend| */ -if (((ldvd >> 32) & M32) >= ldvr) return opnd[1]; /* divide work? */ -quo = (int32) (ldvd / ldvr); /* do divide */ -rem = (int32) (ldvd % ldvr); -if ((opnd[0] ^ opnd[2]) & LSIGN) { /* result -? */ - quo = -quo; /* negate */ - if (quo && ((quo & LSIGN) == 0)) return opnd[1]; } /* right sign? */ -else if (quo & LSIGN) return opnd[1]; -if (opnd[2] & LSIGN) rem = -rem; /* sign of rem */ -*flg = 0; /* no overflow */ -*rh = rem; /* set rem */ -return quo; /* return quo */ -} - -/* Compare floating */ - -int32 op_cmpfd (int32 h1, int32 l1, int32 h2, int32 l2) -{ -t_uint64 n1, n2; - -if ((h1 & FD_EXP) == 0) { - if (h1 & FPSIGN) RSVD_OPND_FAULT; - h1 = l1 = 0; } -if ((h2 & FD_EXP) == 0) { - if (h2 & FPSIGN) RSVD_OPND_FAULT; - h2 = l2 = 0; } -if ((h1 ^ h2) & FPSIGN) return ((h1 & FPSIGN)? CC_N: 0); -n1 = UNSCRAM (h1, l1); -n2 = UNSCRAM (h2, l2); -if (n1 == n2) return CC_Z; -return (((n1 < n2) ^ ((h1 & FPSIGN) != 0))? CC_N: 0); -} - -int32 op_cmpg (int32 h1, int32 l1, int32 h2, int32 l2) -{ -t_uint64 n1, n2; - -if ((h1 & G_EXP) == 0) { - if (h1 & FPSIGN) RSVD_OPND_FAULT; - h1 = l1 = 0; } -if ((h2 & G_EXP) == 0) { - if (h2 & FPSIGN) RSVD_OPND_FAULT; - h2 = l2 = 0; } -if ((h1 ^ h2) & FPSIGN) return ((h1 & FPSIGN)? CC_N: 0); -n1 = UNSCRAM (h1, l1); -n2 = UNSCRAM (h2, l2); -if (n1 == n2) return CC_Z; -return (((n1 < n2) ^ ((h1 & FPSIGN) != 0))? CC_N: 0); -} - -/* Integer to floating convert */ - -int32 op_cvtifdg (int32 val, int32 *rh, int32 opc) -{ -UFP a; - -if (val == 0) { - if (rh) *rh = 0; - return 0; } -if (val < 0) { - a.sign = FPSIGN; - val = - val; } -else a.sign = 0; -a.exp = 32 + ((opc & 0x100)? G_BIAS: FD_BIAS); -a.frac = ((t_uint64) val) << (UF_V_NM - 31); -norm (&a); -if (opc & 0x100) return rpackg (&a, rh); -return rpackfd (&a, rh); -} - -/* Floating to integer convert */ - -int32 op_cvtfdgi (int32 *opnd, int32 *flg, int32 opc) -{ -UFP a; -int32 lnt = opc & 03; -int32 ubexp; -static t_uint64 maxv[4] = { 0x7F, 0x7FFF, 0x7FFFFFFF, 0x7FFFFFFF }; - -*flg = 0; -if (opc & 0x100) { - unpackg (opnd[0], opnd[1], &a); - ubexp = a.exp - G_BIAS; } -else { if (opc & 0x20) unpackd (opnd[0], opnd[1], &a); - else unpackf (opnd[0], &a); - ubexp = a.exp - FD_BIAS; } -if ((a.exp == 0) || (ubexp < 0)) return 0; -if (ubexp <= UF_V_NM) { - a.frac = a.frac >> (UF_V_NM - ubexp); /* leave rnd bit */ - if ((opc & 03) == 03) a.frac = a.frac + 1; /* if CVTR, round */ - a.frac = a.frac >> 1; /* now justified */ - if (a.frac > (maxv[lnt] + (a.sign? 1: 0))) *flg = CC_V; } -else { *flg = CC_V; /* set overflow */ - if (ubexp > (UF_V_NM + 32)) return 0; - a.frac = a.frac << (ubexp - UF_V_NM - 1); } /* no rnd bit */ -return ((int32) (a.sign? (a.frac ^ M32) + 1: a.frac)); -} - -/* Extended modularize - - One of three floating point instructions dropped from the architecture, - EMOD presents two sets of complications. First, it requires an extended - fraction multiply, with precise (and unusual) truncation conditions. - Second, it has two write operands, a dubious distinction it shares - with EDIV. -*/ - -int32 op_emodf (int32 *opnd, int32 *intgr, int32 *flg) -{ -UFP a, b; - -unpackf (opnd[0], &a); /* unpack operands */ -unpackf (opnd[2], &b); -a.frac = a.frac | (((t_uint64) opnd[1]) << 32); /* extend src1 */ -vax_fmul (&a, &b, 32, FD_BIAS, M32); /* multiply */ -vax_fmod (&a, FD_BIAS, intgr, flg); /* sep int & frac */ -return rpackfd (&a, NULL); /* return frac */ -} - -int32 op_emodd (int32 *opnd, int32 *flo, int32 *intgr, int32 *flg) -{ -UFP a, b; - -unpackd (opnd[0], opnd[1], &a); /* unpack operands */ -unpackd (opnd[3], opnd[4], &b); -a.frac = a.frac | opnd[2]; /* extend src1 */ -vax_fmul (&a, &b, 64, FD_BIAS, 0); /* multiply */ -vax_fmod (&a, FD_BIAS, intgr, flg); /* sep int & frac */ -return rpackfd (&a, flo); /* return frac */ -} - -int32 op_emodg (int32 *opnd, int32 *flo, int32 *intgr, int32 *flg) -{ -UFP a, b; - -unpackg (opnd[0], opnd[1], &a); /* unpack operands */ -unpackg (opnd[3], opnd[4], &b); -a.frac = a.frac | (opnd[2] >> 5); /* extend src1 */ -vax_fmul (&a, &b, 64, G_BIAS, 0); /* multiply */ -vax_fmod (&a, G_BIAS, intgr, flg); /* sep int & frac */ -return rpackg (&a, flo); /* return frac */ -} - -/* Unpacked floating point routines */ - -void vax_fadd (UFP *a, UFP *b, t_int64 mask) -{ -int32 ediff; -UFP t; - -if (a->exp == 0) { /* s1 = 0? */ - *a = *b; - return; } -if (b->exp == 0) return; /* s2 = 0? */ -if ((a->exp < b->exp) || /* |s1| < |s2|? swap */ - ((a->exp == b->exp) && (a->frac < b->frac))) { - t = *a; - *a = *b; - *b = t; } -ediff = a->exp - b->exp; /* exp diff */ -if (a->sign ^ b->sign) { /* eff sub? */ - if (ediff) { /* exp diff? */ - if (ediff > 63) b->frac = M64; /* retain sticky */ - else b->frac = ((-((t_int64) b->frac) >> ediff) | /* denormalize */ - (M64 << (64 - ediff))); /* preserve sign */ - a->frac = a->frac + b->frac; } /* add frac */ - else a->frac = a->frac - b->frac; /* sub frac */ - a->frac = a->frac & ~mask; - norm (a); } /* normalize */ -else { if (ediff > 63) b->frac = 0; /* add */ - else if (ediff) b->frac = b->frac >> ediff; /* denormalize */ - 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 = a->frac & ~mask; } -return; -} - -/* Floating multiply - 64b * 64b with cross products */ - -void vax_fmul (UFP *a, UFP *b, int32 prec, int32 bias, t_int64 mask) -{ -t_uint64 ah, bh, al, bl, rhi, rlo, rmid1, rmid2; - -if ((a->exp == 0) || (b->exp == 0)) { /* zero argument? */ - a->frac = a->sign = a->exp = 0; /* result is zero */ - return; } -a->sign = a->sign ^ b->sign; /* sign of result */ -a->exp = a->exp + b->exp - bias; /* add exponents */ -ah = (a->frac >> 32) & M32; /* split operands */ -bh = (b->frac >> 32) & M32; /* into 32b chunks */ -rhi = ah * bh; /* high result */ -if (prec > 32) { /* 64b needed? */ - al = a->frac & M32; - bl = b->frac & M32; - rmid1 = ah * bl; - rmid2 = al * bh; - rlo = al * bl; - rhi = rhi + ((rmid1 >> 32) & M32) + ((rmid2 >> 32) & M32); - rmid1 = rlo + (rmid1 << 32); /* add mid1 to lo */ - if (rmid1 < rlo) rhi = rhi + 1; /* carry? incr hi */ - rmid2 = rmid1 + (rmid2 << 32); /* add mid2 to to */ - if (rmid2 < rmid1) rhi = rhi + 1; } /* carry? incr hi */ -a->frac = rhi & ~mask; /* mask out */ -norm (a); /* normalize */ -return; -} - -/* Floating modulus - there are three cases - - exp <= bias - integer is 0, fraction is input, - no overflow - bias < exp <= bias+64 - separate integer and fraction, - integer overflow may occur - bias+64 < exp - result is integer, fraction is 0 - integer overflow -*/ - -void vax_fmod (UFP *a, int32 bias, int32 *intgr, int32 *flg) -{ -if (a->exp <= bias) *intgr = *flg = 0; /* 0 or <1? int = 0 */ -else if (a->exp <= (bias + 64)) { /* in range? */ - *intgr = (int32) (a->frac >> (64 - (a->exp - bias))); - if ((a->exp > (bias + 32)) || /* test ovflo */ - ((a->exp == (bias + 32)) && - (((uint32) *intgr) > (a->sign? 0x80000000: 0x7FFFFFFF)))) - *flg = CC_V; - else *flg = 0; - if (a->sign) *intgr = -*intgr; /* -? comp int */ - a->frac = a->frac << (a->exp - bias); - a->exp = bias; } -else { *intgr = 0; /* out of range */ - a->frac = a->sign = a->exp = 0; /* result 0 */ - *flg = CC_V; } /* overflow */ -norm (a); /* normalize */ -return; -} - -/* Floating divide - Needs to develop at least one rounding bit. Since the first - divide step can fail, caller should specify 2 more bits than - the precision of the fraction. -*/ - -void vax_fdiv (UFP *a, UFP *b, int32 prec, int32 bias) -{ -int32 i; -t_uint64 quo = 0; - -if (a->exp == 0) FLT_DZRO_FAULT; /* divr = 0? */ -if (b->exp == 0) return; /* divd = 0? */ -b->sign = b->sign ^ a->sign; /* result sign */ -b->exp = b->exp - a->exp + bias + 1; /* unbiased exp */ -a->frac = a->frac >> 1; /* allow 1 bit left */ -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 << 1; } /* shift divd */ -b->frac = quo << (UF_V_NM - i + 1); /* shift quo */ -norm (b); /* normalize */ -return; -} - -/* Support routines */ - -void unpackf (int32 hi, UFP *r) -{ -r->sign = hi & FPSIGN; /* get sign */ -r->exp = FD_GETEXP (hi); /* get exponent */ -if (r->exp == 0) { /* exp = 0? */ - if (r->sign) RSVD_OPND_FAULT; /* if -, rsvd op */ - r->frac = 0; /* else 0 */ - return; } -hi = (((hi & FD_FRACW) | FD_HB) << 16) | ((hi >> 16) & 0xFFFF); -r->frac = ((t_uint64) hi) << (32 + UF_V_FDLO); -return; -} - -void unpackd (int32 hi, int32 lo, UFP *r) -{ -r->sign = hi & FPSIGN; /* get sign */ -r->exp = FD_GETEXP (hi); /* get exponent */ -if (r->exp == 0) { /* exp = 0? */ - if (r->sign) RSVD_OPND_FAULT; /* if -, rsvd op */ - r->frac = 0; /* else 0 */ - return; } -hi = (hi & FD_FRACL) | FD_HB; /* canonical form */ -r->frac = UNSCRAM (hi, lo) << UF_V_FDLO; /* guard bits */ -return; -} - -void unpackg (int32 hi, int32 lo, UFP *r) -{ -r->sign = hi & FPSIGN; /* get sign */ -r->exp = G_GETEXP (hi); /* get exponent */ -if (r->exp == 0) { /* exp = 0? */ - if (r->sign) RSVD_OPND_FAULT; /* if -, rsvd op */ - r->frac = 0; /* else 0 */ - return; } -hi = (hi & G_FRACL) | G_HB; /* canonical form */ -r->frac = UNSCRAM (hi, lo) << UF_V_GLO; /* guard bits */ -return; -} - -void norm (UFP *r) -{ -int32 i; -static t_uint64 normmask[5] = { - 0xc000000000000000, 0xf000000000000000, 0xff00000000000000, - 0xffff000000000000, 0xffffffff00000000 }; -static int32 normtab[6] = { 1, 2, 4, 8, 16, 32}; - -if (r->frac == 0) { /* if fraction = 0 */ - r->sign = r->exp = 0; /* result is 0 */ - return; } -while ((r->frac & UF_NM) == 0) { /* normalized? */ - for (i = 0; i < 5; i++) { /* find first 1 */ - if (r->frac & normmask[i]) break; } - r->frac = r->frac << normtab[i]; /* shift frac */ - r->exp = r->exp - normtab[i]; } /* decr exp */ -return; -} - -int32 rpackfd (UFP *r, int32 *rh) -{ -if (rh) *rh = 0; /* assume 0 */ -if (r->frac == 0) return 0; /* result 0? */ -r->frac = r->frac + (rh? UF_DRND: UF_FRND); /* round */ -if ((r->frac & UF_NM) == 0) { /* carry out? */ - r->frac = r->frac >> 1; /* renormalize */ - r->exp = r->exp + 1; } -if (r->exp > (int32) FD_M_EXP) FLT_OVFL_FAULT; /* ovflo? fault */ -if (r->exp <= 0) { /* underflow? */ - if (PSL & PSW_FU) FLT_UNFL_FAULT; /* fault if fu */ - return 0; } /* else 0 */ -if (rh) *rh = UF_GETFDLO (r->frac); /* get low */ -return r->sign | (r->exp << FD_V_EXP) | UF_GETFDHI (r->frac); -} - -int32 rpackg (UFP *r, int32 *rh) -{ -*rh = 0; /* assume 0 */ -if (r->frac == 0) return 0; /* result 0? */ -r->frac = r->frac + UF_GRND; /* round */ -if ((r->frac & UF_NM) == 0) { /* carry out? */ - r->frac = r->frac >> 1; /* renormalize */ - r->exp = r->exp + 1; } -if (r->exp > (int32) G_M_EXP) FLT_OVFL_FAULT; /* ovflo? fault */ -if (r->exp <= 0) { /* underflow? */ - if (PSL & PSW_FU) FLT_UNFL_FAULT; /* fault if fu */ - return 0; } /* else 0 */ -if (rh) *rh = UF_GETGLO (r->frac); /* get low */ -return r->sign | (r->exp << G_V_EXP) | UF_GETGHI (r->frac); -} - -#else /* 32b code */ - -#define WORDSWAP(x) ((((x) & 0xFFFF) << 16) | (((x) >> 16) & 0xFFFF)) -#define INC32(x) (((x) + 1) & M32) -#define NEG32(x) (((~(x)) + 1) & M32) - -struct udp { - uint32 lo; - uint32 hi; -}; - -typedef struct udp UDP; - -struct ufp { - int32 sign; - int32 exp; - struct udp frac; }; - -typedef struct ufp UFP; - -#define UF_NM_H 0x80000000 /* normalized */ -#define UF_FRND_H 0x00000080 /* F round */ -#define UF_FRND_L 0x00000000 -#define UF_DRND_H 0x00000000 /* D round */ -#define UF_DRND_L 0x00000080 -#define UF_GRND_H 0x00000000 /* G round */ -#define UF_GRND_L 0x00000400 -#define UF_V_NM 63 - -void unpackf (uint32 hi, UFP *a); -void unpackd (uint32 hi, uint32 lo, UFP *a); -void unpackg (uint32 hi, uint32 lo, UFP *a); -void norm (UFP *a); -int32 rpackfd (UFP *a, int32 *rh); -int32 rpackg (UFP *a, int32 *rh); -void vax_fadd (UFP *a, UFP *b, uint32 mask); -void vax_fmul (UFP *a, UFP *b, int32 prec, int32 bias, uint32 mask); -void vax_fmod (UFP *a, int32 bias, int32 *intgr, int32 *flg); -void vax_fdiv (UFP *b, UFP *a, int32 prec, int32 bias); -int32 vax_fcmp (UFP *a, UFP *b); -void dp_add (UDP *a, UDP *b); -void dp_inc (UDP *a); -void dp_sub (UDP *a, UDP *b); -void dp_imul (uint32 a, uint32 b, UDP *r); -void dp_lsh (UDP *a, uint32 sc); -void dp_rsh (UDP *a, uint32 sc); -void dp_rsh_s (UDP *a, uint32 sc, uint32 neg); -void dp_neg (UDP *a); -int32 dp_cmp (UDP *a, UDP *b); - -/* Quadword arithmetic shift - - opnd[0] = shift count (cnt.rb) - opnd[1:2] = source (src.rq) - opnd[3:4] = destination (dst.wq) -*/ - -int32 op_ashq (int32 *opnd, int32 *rh, int32 *flg) -{ -UDP r, sr; -uint32 sc = opnd[0]; - -r.lo = opnd[1]; /* get source */ -r.hi = opnd[2]; -*flg = 0; /* assume no ovflo */ -if (sc & BSIGN) /* right shift? */ - dp_rsh_s (&r, 0x100 - sc, r.hi & LSIGN); /* signed right */ -else { dp_lsh (&r, sc); /* left shift */ - sr = r; /* copy result */ - dp_rsh_s (&sr, sc, sr.hi & LSIGN); /* signed right */ - if ((sr.hi != ((uint32) opnd[2])) || /* reshift != orig? */ - (sr.lo != ((uint32) opnd[1]))) *flg = 1; } /* overflow */ -*rh = r.hi; /* hi result */ -return r.lo; /* lo result */ -} - -/* Extended multiply subroutine */ - -int32 op_emul (int32 mpy, int32 mpc, int32 *rh) -{ -UDP r; -int32 sign = mpy ^ mpc; /* sign of result */ - -if (mpy & LSIGN) mpy = -mpy; /* abs value */ -if (mpc & LSIGN) mpc = -mpc; -dp_imul (mpy & M32, mpc & M32, &r); /* 32b * 32b -> 64b */ -if (sign & LSIGN) dp_neg (&r); /* negative result? */ -*rh = r.hi; -return r.lo; -} - -/* Extended divide - - opnd[0] = divisor (non-zero) - opnd[1:2] = dividend -*/ - -int32 op_ediv (int32 *opnd, int32 *rh, int32 *flg) -{ -UDP dvd; -uint32 i, dvr, quo; - -dvr = opnd[0]; /* get divisor */ -dvd.lo = opnd[1]; /* get dividend */ -dvd.hi = opnd[2]; -*flg = CC_V; /* assume error */ -*rh = 0; -if (dvd.hi & LSIGN) dp_neg (&dvd); /* |dividend| */ -if (dvr & LSIGN) dvr = NEG32 (dvr); /* |divisor| */ -if (dvd.hi >= dvr) return opnd[1]; /* divide work? */ -for (i = quo = 0; i < 32; i++) { /* 32 iterations */ - quo = quo << 1; /* shift quotient */ - dp_lsh (&dvd, 1); /* shift dividend */ - if (dvd.hi >= dvr) { /* step work? */ - dvd.hi = (dvd.hi - dvr) & M32; /* subtract dvr */ - quo = quo + 1; } } -if ((opnd[0] ^ opnd[2]) & LSIGN) { /* result -? */ - quo = NEG32 (quo); /* negate */ - if (quo && ((quo & LSIGN) == 0)) return opnd[1]; } /* right sign? */ -else if (quo & LSIGN) return opnd[1]; -if (opnd[2] & LSIGN) *rh = NEG32 (dvd.hi); /* sign of rem */ -else *rh = dvd.hi; -*flg = 0; /* no overflow */ -return quo; /* return quo */ -} - -/* Compare floating */ - -int32 op_cmpfd (int32 h1, int32 l1, int32 h2, int32 l2) -{ -UFP a, b; -int32 r; - -unpackd (h1, l1, &a); -unpackd (h2, l2, &b); -if (a.sign != b.sign) return (a.sign? CC_N: 0); -r = a.exp - b.exp; -if (r == 0) r = dp_cmp (&a.frac, &b.frac); -if (r < 0) return (a.sign? 0: CC_N); -if (r > 0) return (a.sign? CC_N: 0); -return CC_Z; -} - -int32 op_cmpg (int32 h1, int32 l1, int32 h2, int32 l2) -{ -UFP a, b; -int32 r; - -unpackg (h1, l1, &a); -unpackg (h2, l2, &b); -if (a.sign != b.sign) return (a.sign? CC_N: 0); -r = a.exp - b.exp; -if (r == 0) r = dp_cmp (&a.frac, &b.frac); -if (r < 0) return (a.sign? 0: CC_N); -if (r > 0) return (a.sign? CC_N: 0); -return CC_Z; -} - -/* Integer to floating convert */ - -int32 op_cvtifdg (int32 val, int32 *rh, int32 opc) -{ -UFP a; - -if (val == 0) { /* zero? */ - if (rh) *rh = 0; /* return true 0 */ - return 0; } -if (val < 0) { /* negative? */ - a.sign = FPSIGN; /* sign = - */ - val = -val; } -else a.sign = 0; /* else sign = + */ -a.exp = 32 + ((opc & 0x100)? G_BIAS: FD_BIAS); /* initial exp */ -a.frac.hi = val & M32; /* fraction */ -a.frac.lo = 0; -norm (&a); /* normalize */ -if (opc & 0x100) return rpackg (&a, rh); /* pack and return */ -return rpackfd (&a, rh); -} - -/* Floating to integer convert */ - -int32 op_cvtfdgi (int32 *opnd, int32 *flg, int32 opc) -{ -UFP a; -int32 lnt = opc & 03; -int32 ubexp; -static uint32 maxv[4] = { 0x7F, 0x7FFF, 0x7FFFFFFF, 0x7FFFFFFF }; - -*flg = 0; -if (opc & 0x100) { /* G? */ - unpackg (opnd[0], opnd[1], &a); /* unpack */ - ubexp = a.exp - G_BIAS; } /* unbiased exp */ -else { if (opc & 0x20) unpackd (opnd[0], opnd[1], &a); /* F or D */ - else unpackf (opnd[0], &a); /* unpack */ - ubexp = a.exp - FD_BIAS; } /* unbiased exp */ -if ((a.exp == 0) || (ubexp < 0)) return 0; /* true zero or frac? */ -if (ubexp <= UF_V_NM) { /* exp in range? */ - dp_rsh (&a.frac, UF_V_NM - ubexp); /* leave rnd bit */ - if (lnt == 03) dp_inc (&a.frac); /* if CVTR, round */ - dp_rsh (&a.frac, 1); /* now justified */ - if ((a.frac.hi != 0) || - (a.frac.lo > (maxv[lnt] + (a.sign? 1: 0)))) *flg = CC_V; } -else { *flg = CC_V; /* always ovflo */ - if (ubexp > (UF_V_NM + 32)) return 0; /* in ext range? */ - dp_lsh (&a.frac, ubexp - UF_V_NM - 1); } /* no rnd bit */ -return (a.sign? NEG32 (a.frac.lo): a.frac.lo); /* return lo frac */ -} - -/* Extended modularize - - One of three floating point instructions dropped from the architecture, - EMOD presents two sets of complications. First, it requires an extended - fraction multiply, with precise (and unusual) truncation conditions. - Second, it has two write operands, a dubious distinction it shares - with EDIV. -*/ - -int32 op_emodf (int32 *opnd, int32 *intgr, int32 *flg) -{ -UFP a, b; - -unpackf (opnd[0], &a); /* unpack operands */ -unpackf (opnd[2], &b); -a.frac.hi = a.frac.hi | opnd[1]; /* extend src1 */ -vax_fmul (&a, &b, 32, FD_BIAS, M32); /* multiply */ -vax_fmod (&a, FD_BIAS, intgr, flg); /* sep int & frac */ -return rpackfd (&a, NULL); /* return frac */ -} - -int32 op_emodd (int32 *opnd, int32 *flo, int32 *intgr, int32 *flg) -{ -UFP a, b; - -unpackd (opnd[0], opnd[1], &a); /* unpack operands */ -unpackd (opnd[3], opnd[4], &b); -a.frac.lo = a.frac.lo | opnd[2]; /* extend src1 */ -vax_fmul (&a, &b, 64, FD_BIAS, 0); /* multiply */ -vax_fmod (&a, FD_BIAS, intgr, flg); /* sep int & frac */ -return rpackfd (&a, flo); /* return frac */ -} - -int32 op_emodg (int32 *opnd, int32 *flo, int32 *intgr, int32 *flg) -{ -UFP a, b; - -unpackg (opnd[0], opnd[1], &a); /* unpack operands */ -unpackg (opnd[3], opnd[4], &b); -a.frac.lo = a.frac.lo | (opnd[2] >> 5); /* extend src1 */ -vax_fmul (&a, &b, 64, G_BIAS, 0); /* multiply */ -vax_fmod (&a, G_BIAS, intgr, flg); /* sep int & frac */ -return rpackg (&a, flo); /* return frac */ -} - -/* Unpacked floating point routines */ - -/* Floating add */ - -void vax_fadd (UFP *a, UFP *b, uint32 mask) -{ -int32 ediff; -UFP t; - -if (a->exp == 0) { /* s1 = 0? */ - *a = *b; - return; } -if (b->exp == 0) return; /* s2 = 0? */ -if ((a->exp < b->exp) || /* |s1| < |s2|? swap */ - ((a->exp == b->exp) && (dp_cmp (&a->frac, &b->frac) < 0))) { - t = *a; - *a = *b; - *b = t; } -ediff = a->exp - b->exp; /* exp diff */ -if (a->sign ^ b->sign) { /* eff sub? */ - if (ediff) { /* exp diff? */ - dp_neg (&b->frac); /* negate fraction */ - dp_rsh_s (&b->frac, ediff, 1); /* signed right */ - dp_add (&a->frac, &b->frac); } /* "add" frac */ - else dp_sub (&a->frac, &b->frac); /* a >= b */ - a->frac.lo = a->frac.lo & ~mask; /* trim low result */ - norm (a); } /* normalize */ -else { if (ediff) dp_rsh (&b->frac, ediff); /* add, denormalize */ - dp_add (&a->frac, &b->frac); /* add frac */ - if (dp_cmp (&a->frac, &b->frac) < 0) { /* chk for carry */ - dp_rsh (&a->frac, 1); /* renormalize */ - a->frac.hi = a->frac.hi | UF_NM_H; /* add norm bit */ - a->exp = a->exp + 1; } /* skip norm */ - a->frac.lo = a->frac.lo & ~mask; } /* trim low result */ -return; -} - -/* Floating compare */ - -int32 vax_fcmp (UFP *a, UFP *b) -{ -int32 r; - -if (a->sign != b->sign) return ((a->sign)? CC_N: 0); -r = a->exp - b->exp; -if (r == 0) r = dp_cmp (&a->frac, &b->frac); -if (r == 0) return CC_Z; -if (r < 0) return (a->sign? 0: CC_N); -else return (a->sign? CC_N: 0); -} - -/* Floating multiply - 64b * 64b with cross products */ - -void vax_fmul (UFP *a, UFP *b, int32 prec, int32 bias, uint32 mask) -{ -UDP rhi, rlo, rmid1, rmid2; - -if ((a->exp == 0) || (b->exp == 0)) { /* zero argument? */ - a->frac.hi = a->frac.lo = 0; /* result is zero */ - a->sign = a->exp = 0; - return; } -a->sign = a->sign ^ b->sign; /* sign of result */ -a->exp = a->exp + b->exp - bias; /* add exponents */ -dp_imul (a->frac.hi, b->frac.hi, &rhi); /* high result */ -if (prec > 32) { /* 64b needed? */ - dp_imul (a->frac.hi, b->frac.lo, &rmid1); /* cross products */ - dp_imul (a->frac.lo, b->frac.hi, &rmid2); - dp_imul (a->frac.lo, b->frac.lo, &rlo); /* low result */ - rhi.lo = (rhi.lo + rmid1.hi) & M32; /* add hi cross */ - if (rhi.lo < rmid1.hi) rhi.hi = INC32 (rhi.hi); /* to low high res */ - rhi.lo = (rhi.lo + rmid2.hi) & M32; - if (rhi.lo < rmid2.hi) rhi.hi = INC32 (rhi.hi); - rlo.hi = (rlo.hi + rmid1.lo) & M32; /* add mid1 to low res */ - if (rlo.hi < rmid1.lo) dp_inc (&rhi); /* carry? incr high res */ - rlo.hi = (rlo.hi + rmid2.lo) & M32; /* add mid2 to low res */ - if (rlo.hi < rmid1.hi) dp_inc (&rhi); } /* carry? incr high res */ -a->frac.hi = rhi.hi; /* mask low fraction */ -a->frac.lo = rhi.lo & ~mask; -norm (a); /* normalize */ -return; -} - -/* Floating modulus - there are three cases - - exp <= bias - integer is 0, fraction is input, - no overflow - bias < exp <= bias+64 - separate integer and fraction, - integer overflow may occur - bias+64 < exp - result is integer, fraction is 0 - integer overflow -*/ - -void vax_fmod (UFP *a, int32 bias, int32 *intgr, int32 *flg) -{ -UDP ifr; - -if (a->exp <= bias) *intgr = *flg = 0; /* 0 or <1? int = 0 */ -else if (a->exp <= (bias + 64)) { /* in range? */ - ifr = a->frac; - dp_rsh (&ifr, 64 - (a->exp - bias)); /* separate integer */ - if ((a->exp > (bias + 32)) || /* test ovflo */ - ((a->exp == (bias + 32)) && - (ifr.lo > (a->sign? 0x80000000: 0x7FFFFFFF)))) - *flg = CC_V; - else *flg = 0; - *intgr = ifr.lo; - if (a->sign) *intgr = -*intgr; /* -? comp int */ - dp_lsh (&a->frac, a->exp - bias); /* excise integer */ - a->exp = bias; } -else { *intgr = 0; /* out of range */ - a->frac.hi = a->frac.lo = a->sign = a->exp = 0; /* result 0 */ - *flg = CC_V; } /* overflow */ -norm (a); /* normalize */ -return; -} - -/* Floating divide - Needs to develop at least one rounding bit. Since the first - divide step can fail, caller should specify 2 more bits than - the precision of the fraction. -*/ - -void vax_fdiv (UFP *a, UFP *b, int32 prec, int32 bias) -{ -int32 i; -UDP quo = { 0, 0 }; - -if (a->exp == 0) FLT_DZRO_FAULT; /* divr = 0? */ -if (b->exp == 0) return; /* divd = 0? */ -b->sign = b->sign ^ a->sign; /* result sign */ -b->exp = b->exp - a->exp + bias + 1; /* unbiased exp */ -dp_rsh (&a->frac, 1); /* allow 1 bit left */ -dp_rsh (&b->frac, 1); -for (i = 0; i < prec; i++) { /* divide loop */ - dp_lsh (&quo, 1); /* shift quo */ - if (dp_cmp (&b->frac, &a->frac) >= 0) { /* div step ok? */ - dp_sub (&b->frac, &a->frac); /* subtract */ - quo.lo = quo.lo + 1; } /* quo bit = 1 */ - dp_lsh (&b->frac, 1); } /* shift divd */ -dp_lsh (&quo, UF_V_NM - prec + 1); /* put in position */ -b->frac = quo; -norm (b); /* normalize */ -return; -} - -/* Double precision integer routines */ - -int32 dp_cmp (UDP *a, UDP *b) -{ -if (a->hi < b->hi) return -1; /* compare hi */ -if (a->hi > b->hi) return +1; -if (a->lo < b->lo) return -1; /* hi =, compare lo */ -if (a->lo > b->lo) return +1; -return 0; /* hi, lo equal */ -} - -void dp_add (UDP *a, UDP *b) -{ -a->lo = (a->lo + b->lo) & M32; /* add lo */ -if (a->lo < b->lo) a->hi = a->hi + 1; /* carry? */ -a->hi = (a->hi + b->hi) & M32; /* add hi */ -return; -} - -void dp_inc (UDP *a) -{ -a->lo = (a->lo + 1) & M32; /* inc lo */ -if (a->lo == 0) a->hi = (a->hi + 1) & M32; /* carry? inc hi */ -return; -} - -void dp_sub (UDP *a, UDP *b) -{ -if (a->lo < b->lo) a->hi = a->hi - 1; /* borrow? decr hi */ -a->lo = (a->lo - b->lo) & M32; /* sub lo */ -a->hi = (a->hi - b->hi) & M32; /* sub hi */ -return; -} - -void dp_lsh (UDP *r, uint32 sc) -{ -if (sc > 63) r->hi = r->lo = 0; /* > 63? result 0 */ -else if (sc > 31) { /* [32,63]? */ - r->hi = (r->lo << (sc - 32)) & M32; - r->lo = 0; } -else if (sc != 0) { - r->hi = ((r->hi << sc) | (r->lo >> (32 - sc))) & M32; - r->lo = (r->lo << sc) & M32; } -return; -} - -void dp_rsh (UDP *r, uint32 sc) -{ -if (sc > 63) r->hi = r->lo = 0; /* > 63? result 0 */ -else if (sc > 31) { /* [32,63]? */ - r->lo = (r->hi >> (sc - 32)) & M32; - r->hi = 0; } -else if (sc != 0) { - r->lo = ((r->lo >> sc) | (r->hi << (32 - sc))) & M32; - r->hi = (r->hi >> sc) & M32; } -return; -} - -void dp_rsh_s (UDP *r, uint32 sc, uint32 neg) -{ -dp_rsh (r, sc); /* do unsigned right */ -if (neg && sc) { /* negative? */ - if (sc > 63) r->hi = r->lo = M32; /* > 63? result -1 */ - else { - UDP ones = { M32, M32 }; - dp_lsh (&ones, 64 - sc); /* shift ones */ - r->hi = r->hi | ones.hi; /* or into result */ - r->lo = r->lo | ones.lo; } } -return; -} - -void dp_imul (uint32 a, uint32 b, UDP *r) -{ -uint32 ah, bh, al, bl, rhi, rlo, rmid1, rmid2; - -if ((a == 0) || (b == 0)) { /* zero argument? */ - r->hi = r->lo = 0; /* result is zero */ - return; } -ah = (a >> 16) & M16; /* split operands */ -bh = (b >> 16) & M16; /* into 16b chunks */ -al = a & M16; -bl = b & M16; -rhi = ah * bh; /* high result */ -rmid1 = ah * bl; -rmid2 = al * bh; -rlo = al * bl; -rhi = rhi + ((rmid1 >> 16) & M16) + ((rmid2 >> 16) & M16); -rmid1 = (rlo + (rmid1 << 16)) & M32; /* add mid1 to lo */ -if (rmid1 < rlo) rhi = rhi + 1; /* carry? incr hi */ -rmid2 = (rmid1 + (rmid2 << 16)) & M32; /* add mid2 to to */ -if (rmid2 < rmid1) rhi = rhi + 1; /* carry? incr hi */ -r->hi = rhi & M32; /* mask result */ -r->lo = rmid2; -return; -} - -void dp_neg (UDP *r) -{ -r->lo = NEG32 (r->lo); -r->hi = (~r->hi + (r->lo == 0)) & M32; -return; -} - -/* Support routines */ - -void unpackf (uint32 hi, UFP *r) -{ -r->sign = hi & FPSIGN; /* get sign */ -r->exp = FD_GETEXP (hi); /* get exponent */ -if (r->exp == 0) { /* exp = 0? */ - if (r->sign) RSVD_OPND_FAULT; /* if -, rsvd op */ - r->frac.hi = r->frac.lo = 0; /* else 0 */ - return; } -r->frac.hi = WORDSWAP ((hi & ~(FPSIGN | FD_EXP)) | FD_HB); -r->frac.lo = 0; -dp_lsh (&r->frac, FD_GUARD); -return; -} - -void unpackd (uint32 hi, uint32 lo, UFP *r) -{ -r->sign = hi & FPSIGN; /* get sign */ -r->exp = FD_GETEXP (hi); /* get exponent */ -if (r->exp == 0) { /* exp = 0? */ - if (r->sign) RSVD_OPND_FAULT; /* if -, rsvd op */ - r->frac.hi = r->frac.lo = 0; /* else 0 */ - return; } -r->frac.hi = WORDSWAP ((hi & ~(FPSIGN | FD_EXP)) | FD_HB); -r->frac.lo = WORDSWAP (lo); -dp_lsh (&r->frac, FD_GUARD); -return; -} - -void unpackg (uint32 hi, uint32 lo, UFP *r) -{ -r->sign = hi & FPSIGN; /* get sign */ -r->exp = G_GETEXP (hi); /* get exponent */ -if (r->exp == 0) { /* exp = 0? */ - if (r->sign) RSVD_OPND_FAULT; /* if -, rsvd op */ - r->frac.hi = r->frac.lo = 0; /* else 0 */ - return; } -r->frac.hi = WORDSWAP ((hi & ~(FPSIGN | G_EXP)) | G_HB); -r->frac.lo = WORDSWAP (lo); -dp_lsh (&r->frac, G_GUARD); -return; -} - -void norm (UFP *r) -{ -int32 i; -static uint32 normmask[5] = { - 0xc0000000, 0xf0000000, 0xff000000, 0xffff0000, 0xffffffff }; -static int32 normtab[6] = { 1, 2, 4, 8, 16, 32}; - -if ((r->frac.hi == 0) && (r->frac.lo == 0)) { /* if fraction = 0 */ - r->sign = r->exp = 0; /* result is 0 */ - return; } -while ((r->frac.hi & UF_NM_H) == 0) { /* normalized? */ - for (i = 0; i < 5; i++) { /* find first 1 */ - if (r->frac.hi & normmask[i]) break; } - dp_lsh (&r->frac, normtab[i]); /* shift frac */ - r->exp = r->exp - normtab[i]; } /* decr exp */ -return; -} - -int32 rpackfd (UFP *r, int32 *rh) -{ -static UDP f_round = { UF_FRND_L, UF_FRND_H }; -static UDP d_round = { UF_DRND_L, UF_DRND_H }; - -if (rh) *rh = 0; /* assume 0 */ -if ((r->frac.hi == 0) && (r->frac.lo == 0)) return 0; /* result 0? */ -if (rh) dp_add (&r->frac, &d_round); /* round */ -else dp_add (&r->frac, &f_round); -if ((r->frac.hi & UF_NM_H) == 0) { /* carry out? */ - dp_rsh (&r->frac, 1); /* renormalize */ - r->exp = r->exp + 1; } -if (r->exp > (int32) FD_M_EXP) FLT_OVFL_FAULT; /* ovflo? fault */ -if (r->exp <= 0) { /* underflow? */ - if (PSL & PSW_FU) FLT_UNFL_FAULT; /* fault if fu */ - return 0; } /* else 0 */ -dp_rsh (&r->frac, FD_GUARD); /* remove guard */ -if (rh) *rh = WORDSWAP (r->frac.lo); /* get low */ -return r->sign | (r->exp << FD_V_EXP) | - (WORDSWAP (r->frac.hi) & ~(FD_HB | FPSIGN | FD_EXP)); -} - -int32 rpackg (UFP *r, int32 *rh) -{ -static UDP g_round = { UF_GRND_L, UF_GRND_H }; - -*rh = 0; /* assume 0 */ -if ((r->frac.hi == 0) && (r->frac.lo == 0)) return 0; /* result 0? */ -dp_add (&r->frac, &g_round); /* round */ -if ((r->frac.hi & UF_NM_H) == 0) { /* carry out? */ - dp_rsh (&r->frac, 1); /* renormalize */ - r->exp = r->exp + 1; } -if (r->exp > (int32) G_M_EXP) FLT_OVFL_FAULT; /* ovflo? fault */ -if (r->exp <= 0) { /* underflow? */ - if (PSL & PSW_FU) FLT_UNFL_FAULT; /* fault if fu */ - return 0; } /* else 0 */ -dp_rsh (&r->frac, G_GUARD); /* remove guard */ -*rh = WORDSWAP (r->frac.lo); /* get low */ -return r->sign | (r->exp << G_V_EXP) | - (WORDSWAP (r->frac.hi) & ~(G_HB | FPSIGN | G_EXP)); -} - -#endif - -/* Floating point instructions */ - -/* Move/test/move negated floating - - Note that only the high 32b is processed. - If the high 32b is not zero, it is unchanged. -*/ - -int32 op_movfd (int32 val) -{ -if (val & FD_EXP) return val; -if (val & FPSIGN) RSVD_OPND_FAULT; -return 0; -} - -int32 op_mnegfd (int32 val) -{ -if (val & FD_EXP) return (val ^ FPSIGN); -if (val & FPSIGN) RSVD_OPND_FAULT; -return 0; -} - -int32 op_movg (int32 val) -{ -if (val & G_EXP) return val; -if (val & FPSIGN) RSVD_OPND_FAULT; -return 0; -} - -int32 op_mnegg (int32 val) -{ -if (val & G_EXP) return (val ^ FPSIGN); -if (val & FPSIGN) RSVD_OPND_FAULT; -return 0; -} - -/* Floating to floating convert - F to D is essentially done with MOVFD */ - -int32 op_cvtdf (int32 *opnd) -{ -UFP a; - -unpackd (opnd[0], opnd[1], &a); -return rpackfd (&a, NULL); -} - -int32 op_cvtfg (int32 *opnd, int32 *rh) -{ -UFP a; - -unpackf (opnd[0], &a); -a.exp = a.exp - FD_BIAS + G_BIAS; -return rpackg (&a, rh); -} - -int32 op_cvtgf (int32 *opnd) -{ -UFP a; - -unpackg (opnd[0], opnd[1], &a); -a.exp = a.exp - G_BIAS + FD_BIAS; -return rpackfd (&a, NULL); -} - -/* Floating add and subtract */ - -int32 op_addf (int32 *opnd, t_bool sub) -{ -UFP a, b; - -unpackf (opnd[0], &a); /* F format */ -unpackf (opnd[1], &b); -if (sub) a.sign = a.sign ^ FPSIGN; /* sub? -s1 */ -vax_fadd (&a, &b, 0); /* add fractions */ -return rpackfd (&a, NULL); -} - -int32 op_addd (int32 *opnd, int32 *rh, t_bool sub) -{ -UFP a, b; - -unpackd (opnd[0], opnd[1], &a); -unpackd (opnd[2], opnd[3], &b); -if (sub) a.sign = a.sign ^ FPSIGN; /* sub? -s1 */ -vax_fadd (&a, &b, 0); /* add fractions */ -return rpackfd (&a, rh); -} - -int32 op_addg (int32 *opnd, int32 *rh, t_bool sub) -{ -UFP a, b; - -unpackg (opnd[0], opnd[1], &a); -unpackg (opnd[2], opnd[3], &b); -if (sub) a.sign = a.sign ^ FPSIGN; /* sub? -s1 */ -vax_fadd (&a, &b, 0); /* add fractions */ -return rpackg (&a, rh); /* round and pack */ -} - -/* Floating multiply */ - -int32 op_mulf (int32 *opnd) -{ -UFP a, b; - -unpackf (opnd[0], &a); /* F format */ -unpackf (opnd[1], &b); -vax_fmul (&a, &b, 24, FD_BIAS, 0); /* do multiply */ -return rpackfd (&a, NULL); /* round and pack */ -} - -int32 op_muld (int32 *opnd, int32 *rh) -{ -UFP a, b; - -unpackd (opnd[0], opnd[1], &a); -unpackd (opnd[2], opnd[3], &b); -vax_fmul (&a, &b, 56, FD_BIAS, 0); /* do multiply */ -return rpackfd (&a, rh); /* round and pack */ -} - -int32 op_mulg (int32 *opnd, int32 *rh) -{ -UFP a, b; - -unpackg (opnd[0], opnd[1], &a); /* G format */ -unpackg (opnd[2], opnd[3], &b); -vax_fmul (&a, &b, 53, G_BIAS, 0); /* do multiply */ -return rpackg (&a, rh); /* round and pack */ -} - -/* Floating divide */ - -int32 op_divf (int32 *opnd) -{ -UFP a, b; - -unpackf (opnd[0], &a); /* F format */ -unpackf (opnd[1], &b); -vax_fdiv (&a, &b, 26, FD_BIAS); /* do divide */ -return rpackfd (&b, NULL); /* round and pack */ -} - -int32 op_divd (int32 *opnd, int32 *rh) -{ -UFP a, b; - -unpackd (opnd[0], opnd[1], &a); -unpackd (opnd[2], opnd[3], &b); -vax_fdiv (&a, &b, 58, FD_BIAS); /* do divide */ -return rpackfd (&b, rh); /* round and pack */ -} - -int32 op_divg (int32 *opnd, int32 *rh) -{ -UFP a, b; - -unpackg (opnd[0], opnd[1], &a); /* G format */ -unpackg (opnd[2], opnd[3], &b); -vax_fdiv (&a, &b, 55, G_BIAS); /* do divide */ -return rpackg (&b, rh); /* round and pack */ -} - -/* Polynomial evaluation - The most mis-implemented instruction in the VAX (probably here too). - POLY requires a precise combination of masking versus normalizing - to achieve the desired answer. In particular, both the multiply - and add steps are masked prior to normalization. In addition, - negative small fractions must not be treated as 0 during denorm. -*/ - -void op_polyf (int32 *opnd, int32 acc) -{ -UFP r, a, c; -int32 deg = opnd[1]; -int32 ptr = opnd[2]; -int32 i, wd, res; - -if (deg > 31) RSVD_OPND_FAULT; /* degree > 31? fault */ -unpackf (opnd[0], &a); /* unpack arg */ -wd = Read (ptr, L_LONG, RD); /* get C0 */ -ptr = ptr + 4; -unpackf (wd, &r); /* unpack C0 */ -res = rpackfd (&r, NULL); /* first result */ -for (i = 0; (i < deg) && a.exp; i++) { /* loop */ - unpackf (res, &r); /* unpack result */ - vax_fmul (&r, &a, 32, FD_BIAS, M32); /* r = r * arg */ - wd = Read (ptr, L_LONG, RD); /* get Cnext */ - ptr = ptr + 4; - unpackf (wd, &c); /* unpack Cnext */ - vax_fadd (&r, &c, M32); /* r = r + Cnext */ - res = rpackfd (&r, NULL); } /* round and pack */ -R[0] = res; -R[1] = R[2] = 0; -R[3] = opnd[2] + 4 + (opnd[1] << 2); -return; -} - -void op_polyd (int32 *opnd, int32 acc) -{ -UFP r, a, c; -int32 deg = opnd[2]; -int32 ptr = opnd[3]; -int32 i, wd, wd1, res, resh; - -if (deg > 31) RSVD_OPND_FAULT; /* degree > 31? fault */ -unpackd (opnd[0], opnd[1], &a); /* unpack arg */ -wd = Read (ptr, L_LONG, RD); /* get C0 */ -wd1 = Read (ptr + 4, L_LONG, RD); -ptr = ptr + 8; -unpackd (wd, wd1, &r); /* unpack C0 */ -res = rpackfd (&r, &resh); /* first result */ -for (i = 0; (i < deg) && a.exp; i++) { /* loop */ - unpackd (res, resh, &r); /* unpack result */ - vax_fmul (&r, &a, 32, FD_BIAS, 0); /* r = r * arg */ - wd = Read (ptr, L_LONG, RD); /* get Cnext */ - wd1 = Read (ptr + 4, L_LONG, RD); - ptr = ptr + 8; - unpackd (wd, wd1, &c); /* unpack Cnext */ - vax_fadd (&r, &c, 0); /* r = r + Cnext */ - res = rpackfd (&r, &resh); } /* round and pack */ -R[0] = res; -R[1] = resh; -R[2] = 0; -R[3] = opnd[3] + 4 + (opnd[2] << 2); -return; -} - -void op_polyg (int32 *opnd, int32 acc) -{ -UFP r, a, c; -int32 deg = opnd[2]; -int32 ptr = opnd[3]; -int32 i, wd, wd1, res, resh; - -if (deg > 31) RSVD_OPND_FAULT; /* degree > 31? fault */ -unpackg (opnd[0], opnd[1], &a); /* unpack arg */ -wd = Read (ptr, L_LONG, RD); /* get C0 */ -wd1 = Read (ptr + 4, L_LONG, RD); -ptr = ptr + 8; -unpackg (wd, wd1, &r); /* unpack C0 */ -res = rpackg (&r, &resh); /* first result */ -for (i = 0; (i < deg) && a.exp; i++) { /* loop */ - unpackg (res, resh, &r); /* unpack result */ - vax_fmul (&r, &a, 32, G_BIAS, 0); /* r = r * arg */ - wd = Read (ptr, L_LONG, RD); /* get Cnext */ - wd1 = Read (ptr + 4, L_LONG, RD); - ptr = ptr + 8; - unpackg (wd, wd1, &c); /* unpack Cnext */ - vax_fadd (&r, &c, 0); /* r = r + Cnext */ - res = rpackg (&r, &resh); } /* round and pack */ -R[0] = res; -R[1] = resh; -R[2] = 0; -R[3] = opnd[3] + 4 + (opnd[2] << 2); -return; -} diff --git a/VAX/vax_io.c b/VAX/vax_io.c deleted file mode 100644 index 5074b68e..00000000 --- a/VAX/vax_io.c +++ /dev/null @@ -1,950 +0,0 @@ -/* vax_io.c: VAX Qbus IO simulator - - 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"), - 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. - - qba Qbus adapter - - 19-Apr-03 RMS Added optimized byte and word DMA routines - 12-Mar-03 RMS Added logical name support - 22-Dec-02 RMS Added console halt support - 12-Oct-02 RMS Added autoconfigure support - Added SHOW IO space routine - 29-Sep-02 RMS Added dynamic table support - 07-Sep-02 RMS Added TMSCP and variable vector support -*/ - -#include "vax_defs.h" - -/* CQBIC system configuration register */ - -#define CQSCR_POK 0x00008000 /* power ok RO1 */ -#define CQSCR_BHL 0x00004000 /* BHALT enb */ -#define CQSCR_AUX 0x00000400 /* aux mode RONI */ -#define CQSCR_DBO 0x0000000C /* offset NI */ -#define CQSCR_RW (CQSCR_BHL | CQSCR_DBO) -#define CQSCR_MASK (CQSCR_RW | CQSCR_POK | CQSCR_AUX) - -/* CQBIC DMA system error register - W1C */ - -#define CQDSER_BHL 0x00008000 /* BHALT NI */ -#define CQDSER_DCN 0x00004000 /* DC ~OK NI */ -#define CQDSER_MNX 0x00000080 /* master NXM */ -#define CQDSER_MPE 0x00000020 /* master par NI */ -#define CQDSER_SME 0x00000010 /* slv mem err NI */ -#define CQDSER_LST 0x00000008 /* lost err */ -#define CQDSER_TMO 0x00000004 /* no grant NI */ -#define CQDSER_SNX 0x00000001 /* slave NXM */ -#define CQDSER_ERR (CQDSER_MNX | CQDSER_MPE | CQDSER_TMO | CQDSER_SNX) -#define CQDSER_MASK 0x0000C0BD - -/* CQBIC master error address register */ - -#define CQMEAR_MASK 0x00001FFF /* Qbus page */ - -/* CQBIC slave error address register */ - -#define CQSEAR_MASK 0x000FFFFF /* mem page */ - -/* CQBIC map base register */ - -#define CQMBR_MASK 0x1FFF8000 /* 32KB aligned */ - -/* CQBIC IPC register */ - -#define CQIPC_QME 0x00008000 /* Qbus read NXM W1C */ -#define CQIPC_INV 0x00004000 /* CAM inval NIWO */ -#define CQIPC_AHLT 0x00000100 /* aux halt NI */ -#define CQIPC_DBIE 0x00000040 /* dbell int enb NI */ -#define CQIPC_LME 0x00000020 /* local mem enb */ -#define CQIPC_DB 0x00000001 /* doorbell req NI */ -#define CQIPC_W1C CQIPC_QME -#define CQIPC_RW (CQIPC_AHLT | CQIPC_DBIE | CQIPC_LME | CQIPC_DB) -#define CQIPC_MASK (CQIPC_RW | CQIPC_QME ) - -/* CQBIC map entry */ - -#define CQMAP_VLD 0x80000000 /* valid */ -#define CQMAP_PAG 0x000FFFFF /* mem page */ - -int32 int_req[IPL_HLVL] = { 0 }; /* intr, IPL 14-17 */ -int32 cq_scr = 0; /* SCR */ -int32 cq_dser = 0; /* DSER */ -int32 cq_mear = 0; /* MEAR */ -int32 cq_sear = 0; /* SEAR */ -int32 cq_mbr = 0; /* MBR */ -int32 cq_ipc = 0; /* IPC */ - -extern uint32 *M; -extern UNIT cpu_unit; -extern int32 PSL, SISR, trpirq, mem_err, hlt_pin; -extern int32 p1; -extern int32 ssc_bto; -extern jmp_buf save_env; -extern DEVICE *sim_devices[]; - -extern int32 ReadB (uint32 pa); -extern int32 ReadW (uint32 pa); -extern int32 ReadL (uint32 pa); -extern int32 WriteB (uint32 pa, int32 val); -extern int32 WriteW (uint32 pa, int32 val); -extern int32 WriteL (uint32 pa, int32 val); -extern FILE *sim_log; - -t_stat dbl_rd (int32 *data, int32 addr, int32 access); -t_stat dbl_wr (int32 data, int32 addr, int32 access); -int32 eval_int (void); -void cq_merr (int32 pa); -void cq_serr (int32 pa); -t_stat qba_reset (DEVICE *dptr); - -/* Qbus adapter data structures - - qba_dev QBA device descriptor - qba_unit QBA units - qba_reg QBA register list -*/ - -DIB qba_dib = { IOBA_DBL, IOLN_DBL, &dbl_rd, &dbl_wr, 0 }; - -UNIT qba_unit = { UDATA (NULL, 0, 0) }; - -REG qba_reg[] = { - { HRDATA (SCR, cq_scr, 16) }, - { HRDATA (DSER, cq_dser, 8) }, - { HRDATA (MEAR, cq_mear, 13) }, - { HRDATA (SEAR, cq_sear, 20) }, - { HRDATA (MBR, cq_mbr, 29) }, - { HRDATA (IPC, cq_ipc, 16) }, - { HRDATA (IPL17, int_req[3], 32), REG_RO }, - { HRDATA (IPL16, int_req[2], 32), REG_RO }, - { HRDATA (IPL15, int_req[1], 32), REG_RO }, - { HRDATA (IPL14, int_req[0], 32), REG_RO }, - { NULL } }; - -DEVICE qba_dev = { - "QBA", &qba_unit, qba_reg, NULL, - 1, 0, 0, 0, 0, 0, - NULL, NULL, &qba_reset, - NULL, NULL, NULL, - &qba_dib, DEV_QBUS }; - -/* IO page addresses */ - -DIB *dib_tab[DIB_MAX]; /* DIB table */ - -/* Interrupt request to interrupt action map */ - -int32 (*int_ack[IPL_HLVL][32])(); /* int ack routines */ - -/* Interrupt request to vector map */ - -int32 int_vec[IPL_HLVL][32]; /* int req to vector */ - -/* The KA65x handles errors in I/O space as follows - - - read: set DSER<7>, latch addr in MEAR, machine check - - write: set DSER<7>, latch addr in MEAR, MEMERR interrupt -*/ - -int32 ReadQb (uint32 pa) -{ -int32 i, val; -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; } } -cq_merr (pa); -MACH_CHECK (MCHK_READ); -return 0; -} - -void WriteQb (uint32 pa, int32 val, int32 mode) -{ -int32 i; -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; } } -cq_merr (pa); -mem_err = 1; -return; -} - -/* ReadIO - read I/O space - - Inputs: - pa = physical address - lnt = length (BWLQ) - Output: - longword of data -*/ - -int32 ReadIO (int32 pa, int32 lnt) -{ -int32 iod; - -iod = ReadQb (pa); /* wd from Qbus */ -if (lnt < L_LONG) iod = iod << ((pa & 2)? 16: 0); /* bw? position */ -else iod = (ReadQb (pa + 2) << 16) | iod; /* lw, get 2nd wd */ -SET_IRQL; -return iod; -} - -/* WriteIO - write I/O space - - Inputs: - pa = physical address - val = data to write, right justified in 32b longword - lnt = length (BWLQ) - Outputs: - none -*/ - -void WriteIO (int32 pa, int32 val, int32 lnt) -{ -if (lnt == L_BYTE) WriteQb (pa, val, WRITEB); -else if (lnt == L_WORD) WriteQb (pa, val, WRITE); -else { WriteQb (pa, val & 0xFFFF, WRITE); - WriteQb (pa + 2, (val >> 16) & 0xFFFF, WRITE); } -SET_IRQL; -return; -} - -/* Find highest priority outstanding interrupt */ - -int32 eval_int (void) -{ -int32 ipl = PSL_GETIPL (PSL); -int32 i, t; - -static const int32 sw_int_mask[IPL_SMAX] = { - 0xFFFE, 0xFFFC, 0xFFF8, 0xFFF0, /* 0 - 3 */ - 0xFFE0, 0xFFC0, 0xFF80, 0xFF00, /* 4 - 7 */ - 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 */ - if (int_req[i - IPL_HMIN]) return i; } /* req != 0? int */ -if (ipl >= IPL_SMAX) return 0; /* ipl >= sw max? */ -if ((t = SISR & sw_int_mask[ipl]) == 0) return 0; /* eligible req */ -for (i = IPL_SMAX; i > ipl; i--) { /* check swre int */ - if ((t >> i) & 1) return i; } /* req != 0? int */ -return 0; -} - -/* Return vector for highest priority hardware interrupt at IPL lvl */ - -int32 get_vector (int32 lvl) -{ -int32 i; -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]; } } -return 0; -} - -/* CQBIC registers - - SCR system configuration register - DSER DMA system error register (W1C) - MEAR master error address register (RO) - SEAR slave error address register (RO) - MBR map base register - IPC inter-processor communication register -*/ - -int32 cqbic_rd (int32 pa) -{ -int32 rg = (pa - CQBICBASE) >> 2; - -switch (rg) { -case 0: /* SCR */ - return (cq_scr | CQSCR_POK) & CQSCR_MASK; -case 1: /* DSER */ - return cq_dser & CQDSER_MASK; -case 2: /* MEAR */ - return cq_mear & CQMEAR_MASK; -case 3: /* SEAR */ - return cq_sear & CQSEAR_MASK; -case 4: /* MBR */ - return cq_mbr & CQMBR_MASK; } -return 0; -} - -void cqbic_wr (int32 pa, int32 val, int32 lnt) -{ -int32 nval, rg = (pa - CQBICBASE) >> 2; - -if (lnt < L_LONG) { - int32 sc = (pa & 3) << 3; - int32 mask = (lnt == L_WORD)? 0xFFFF: 0xFF; - int32 t = cqbic_rd (pa); - nval = ((val & mask) << sc) | (t & ~(mask << sc)); - val = val << sc; } -else nval = val; - -switch (rg) { -case 0: /* SCR */ - cq_scr = ((cq_scr & ~CQSCR_RW) | (nval & CQSCR_RW)) & CQSCR_MASK; - break; -case 1: /* DSER */ - cq_dser = (cq_dser & ~val) & CQDSER_MASK; - if (val & CQDSER_SME) cq_ipc = cq_ipc & ~CQIPC_QME; - break; -case 2: case 3: - cq_merr (pa); /* MEAR, SEAR */ - MACH_CHECK (MCHK_WRITE); - break; -case 4: /* MBR */ - cq_mbr = nval & CQMBR_MASK; - break; } -return; -} - -/* IPC can be read as local register or as Qbus I/O - Because of the W1C */ - -int32 cqipc_rd (int32 pa) -{ -return cq_ipc & CQIPC_MASK; /* IPC */ -} - -void cqipc_wr (int32 pa, int32 val, int32 lnt) -{ -int32 nval = val; - -if (lnt < L_LONG) { - int32 sc = (pa & 3) << 3; - nval = val << sc; } - -cq_ipc = cq_ipc & ~(nval & CQIPC_W1C); /* W1C */ -if ((pa & 3) == 0) /* low byte only */ - cq_ipc = ((cq_ipc & ~CQIPC_RW) | (val & CQIPC_RW)) & CQIPC_MASK; -return; -} - -/* I/O page routines */ - -t_stat dbl_rd (int32 *data, int32 addr, int32 access) -{ -*data = cq_ipc & CQIPC_MASK; -return SCPE_OK; -} - -t_stat dbl_wr (int32 data, int32 addr, int32 access) -{ -cqipc_wr (addr, data, (access == WRITEB)? L_BYTE: L_WORD); -return SCPE_OK; -} - -/* CQBIC map read and write (reflects to main memory) - - Read error: set DSER<0>, latch slave address, machine check - Write error: set DSER<0>, latch slave address, memory error interrupt -*/ - -int32 cqmap_rd (int32 pa) -{ -int32 ma = (pa & CQMAPAMASK) + cq_mbr; /* mem addr */ - -if (ADDR_IS_MEM (ma)) return M[ma >> 2]; -cq_serr (ma); /* set err */ -MACH_CHECK (MCHK_READ); /* mcheck */ -return 0; -} - -void cqmap_wr (int32 pa, int32 val, int32 lnt) -{ -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)); } - M[ma >> 2] = val; } -else { cq_serr (ma); /* error */ - mem_err = 1; } -return; -} - -/* CQBIC Qbus memory read and write (reflects to main memory) - - May give master or slave error, depending on where the failure occurs -*/ - -int32 cqmem_rd (int32 pa) -{ -int32 qa = pa & CQMAMASK; /* Qbus addr */ -uint32 ma; - -if (map_addr (qa, &ma)) return M[ma >> 2]; /* map addr */ -MACH_CHECK (MCHK_READ); /* err? mcheck */ -return 0; -} - -void cqmem_wr (int32 pa, int32 val, int32 lnt) -{ -int32 qa = pa & CQMAMASK; /* Qbus addr */ -uint32 ma; - -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)); } - M[ma >> 2] = val; } -else mem_err = 1; -return; -} - -/* Map an address via the translation map */ - -t_bool map_addr (uint32 qa, uint32 *ma) -{ -int32 qblk = (qa >> VA_V_VPN); /* Qbus blk */ -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; } - cq_merr (qa); /* master nxm */ - return 0; } -cq_serr (0); /* inv mem */ -return 0; -} - -/* Set master error */ - -void cq_merr (int32 pa) -{ -if (cq_dser & CQDSER_ERR) cq_dser = cq_dser | CQDSER_LST; -cq_dser = cq_dser | CQDSER_MNX; /* master nxm */ -cq_mear = (pa >> VA_V_VPN) & CQMEAR_MASK; /* page addr */ -return; -} - -/* Set slave error */ - -void cq_serr (int32 pa) -{ -if (cq_dser & CQDSER_ERR) cq_dser = cq_dser | CQDSER_LST; -cq_dser = cq_dser | CQDSER_SNX; /* slave nxm */ -cq_sear = (pa >> VA_V_VPN) & CQSEAR_MASK; -return; -} - -/* Reset I/O bus */ - -void ioreset_wr (int32 data) -{ -reset_all (5); /* from qba on... */ -return; -} - -/* Reset CQBIC */ - -t_stat qba_reset (DEVICE *dptr) -{ -int32 i; - -cq_scr = (cq_scr & CQSCR_BHL) | CQSCR_POK; -cq_dser = cq_mear = cq_sear = cq_ipc = 0; -for (i = 0; i < IPL_HLVL; i++) int_req[i] = 0; -return SCPE_OK; -} - -/* Powerup CQBIC */ - -t_stat qba_powerup (void) -{ -cq_mbr = 0; -cq_scr = CQSCR_POK; -return qba_reset (&qba_dev); -} - -/* I/O buffer routines, aligned access - - map_ReadB - fetch byte buffer from memory - map_ReadW - fetch word buffer from memory - map_ReadL - fetch longword buffer from memory - map_WriteB - store byte buffer into memory - map_WriteW - store word buffer into memory - map_WriteL - store longword buffer into memory -*/ - -int32 map_readB (uint32 ba, int32 bc, uint8 *buf) -{ -int32 i; -uint32 ma, dat; - -if ((ba | bc) & 03) { /* check alignment */ - 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); } - *buf = ReadB (ma); - ma = ma + 1; } - } -else { for (i = ma = 0; i < bc; i = i + 4, buf++) { /* by longwords */ - if ((ma & VA_M_OFF) == 0) { /* need map? */ - if (!map_addr (ba + i, &ma) || /* inv or NXM? */ - !ADDR_IS_MEM (ma)) return (bc - i); } - dat = ReadL (ma); /* get lw */ - *buf++ = dat & BMASK; /* low 8b */ - *buf++ = (dat >> 8) & BMASK; /* next 8b */ - *buf++ = (dat >> 16) & BMASK; /* next 8b */ - *buf = (dat >> 24) & BMASK; - ma = ma + 4; } - } -return 0; -} - -int32 map_readW (uint32 ba, int32 bc, uint16 *buf) -{ -int32 i; -uint32 ma,dat; - -ba = ba & ~01; -bc = bc & ~01; -if ((ba | bc) & 03) { /* check alignment */ - 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); } - *buf = ReadW (ma); - ma = ma + 2; } - } -else { for (i = ma = 0; i < bc; i = i + 4, buf++) { /* by longwords */ - if ((ma & VA_M_OFF) == 0) { /* need map? */ - if (!map_addr (ba + i, &ma) || /* inv or NXM? */ - !ADDR_IS_MEM (ma)) return (bc - i); } - dat = ReadL (ma); /* get lw */ - *buf++ = dat & WMASK; /* low 16b */ - *buf = (dat >> 16) & WMASK; /* high 16b */ - ma = ma + 4; } - } -return 0; -} - -int32 map_readL (uint32 ba, int32 bc, uint32 *buf) -{ -int32 i; -uint32 ma; - -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); } - *buf = ReadL (ma); - ma = ma + 4; } -return 0; -} - -int32 map_writeB (uint32 ba, int32 bc, uint8 *buf) -{ -int32 i; -uint32 ma, dat; - -if ((ba | bc) & 03) { /* check alignment */ - 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); } - WriteB (ma, *buf); - ma = ma + 1; } - } -else { for (i = ma = 0; i < bc; i = i + 4, buf++) { /* by longwords */ - if ((ma & VA_M_OFF) == 0) { /* need map? */ - if (!map_addr (ba + i, &ma) || /* inv or NXM? */ - !ADDR_IS_MEM (ma)) return (bc - i); } - dat = (uint32) *buf++; /* get low 8b */ - dat = dat | (((uint32) *buf++) << 8); /* merge next 8b */ - dat = dat | (((uint32) *buf++) << 16); /* merge next 8b */ - dat = dat | (((uint32) *buf) << 24); /* merge hi 8b */ - WriteL (ma, dat); /* store lw */ - ma = ma + 4; } - } -return 0; -} - -int32 map_writeW (uint32 ba, int32 bc, uint16 *buf) -{ -int32 i; -uint32 ma, dat; - -ba = ba & ~01; -bc = bc & ~01; -if ((ba | bc) & 03) { /* check alignment */ - 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); } - WriteW (ma, *buf); - ma = ma + 2; } - } -else { for (i = ma = 0; i < bc; i = i + 4, buf++) { /* by longwords */ - if ((ma & VA_M_OFF) == 0) { /* need map? */ - if (!map_addr (ba + i, &ma) || /* inv or NXM? */ - !ADDR_IS_MEM (ma)) return (bc - i); } - dat = (uint32) *buf++; /* get low 16b */ - dat = dat | (((uint32) *buf) << 16); /* merge hi 16b */ - WriteL (ma, dat); /* store lw */ - ma = ma + 4; } - } -return 0; -} - -int32 map_writeL (uint32 ba, int32 bc, uint32 *buf) -{ -int32 i; -uint32 ma; - -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); } - WriteL (ma, *buf); - ma = ma + 4; } -return 0; -} - -/* Change device address */ - -t_stat set_addr (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -DEVICE *dptr; -DIB *dibp; -uint32 newba; -t_stat r; - -if (cptr == NULL) return SCPE_ARG; -if ((val == 0) || (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; -newba = (uint32) get_uint (cptr, 16, IOPAGEBASE+IOPAGEMASK, &r); /* get new */ -if (r != SCPE_OK) return r; -if ((newba <= IOPAGEBASE) || /* must be > 0 */ - (newba % ((uint32) val))) return SCPE_ARG; /* check modulus */ -dibp->ba = newba; /* store */ -dptr->flags = dptr->flags & ~DEV_FLTA; /* not floating */ -return auto_config (0, 0); /* autoconfigure */ -} - -/* Show device address */ - -t_stat show_addr (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->ba <= IOPAGEBASE)) return SCPE_IERR; -fprintf (st, "address=%08X", dibp->ba); -if (dibp->lnt > 1) - fprintf (st, "-%08X", dibp->ba + dibp->lnt - 1); -if (dptr->flags & DEV_FLTA) fprintf (st, "*"); -return SCPE_OK; -} - -/* Set address floating */ - -t_stat set_addr_flt (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -DEVICE *dptr; - -if (cptr == NULL) return SCPE_ARG; -if ((val == 0) || (uptr == NULL)) return SCPE_IERR; -dptr = find_dev_from_unit (uptr); -if (dptr == NULL) return SCPE_IERR; -dptr->flags = dptr->flags | DEV_FLTA; /* floating */ -return auto_config (0, 0); /* autoconfigure */ -} - -/* Change device vector */ - -t_stat set_vec (UNIT *uptr, int32 arg, char *cptr, void *desc) -{ -DEVICE *dptr; -DIB *dibp; -uint32 newvec; -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; -newvec = (uint32) get_uint (cptr, 16, VEC_Q + 01000, &r); -if ((r != SCPE_OK) || (newvec <= VEC_Q) || - ((newvec + (dibp->vnum * 4)) >= (VEC_Q + 01000)) || - (newvec & ((dibp->vnum > 1)? 07: 03))) return SCPE_ARG; -dibp->vec = newvec; -return SCPE_OK; -} - -/* Show device vector */ - -t_stat show_vec (FILE *st, UNIT *uptr, int32 arg, void *desc) -{ -DEVICE *dptr; -DIB *dibp; -uint32 vec, numvec; - -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; -vec = dibp->vec; -if (arg) numvec = arg; -else numvec = dibp->vnum; -if (vec == 0) fprintf (st, "no vector"); -else { fprintf (st, "vector=%X", vec); - if (numvec > 1) fprintf (st, "-%X", vec + (4 * (numvec - 1))); } -return SCPE_OK; -} - -/* Test for conflict in device addresses */ - -t_bool dev_conflict (DIB *curr) -{ -uint32 i, end; -DEVICE *dptr; -DIB *dibp; - -end = curr->ba + curr->lnt - 1; /* get end */ -for (i = 0; (dptr = sim_devices[i]) != NULL; i++) { /* loop thru dev */ - dibp = (DIB *) dptr->ctxt; /* get DIB */ - if ((dibp == NULL) || (dibp == curr) || - (dptr->flags & DEV_DIS)) continue; - if (((curr->ba >= dibp->ba) && /* overlap start? */ - (curr->ba < (dibp->ba + dibp->lnt))) || - ((end >= dibp->ba) && /* overlap end? */ - (end < (dibp->ba + dibp->lnt)))) { - printf ("Device %s address conflict at %08X\n", - sim_dname (dptr), dibp->ba); - if (sim_log) fprintf (sim_log, - "Device %s address conflict at %08X\n", - sim_dname (dptr), dibp->ba); - return TRUE; } } -return FALSE; -} - -/* Build interrupt tables */ - -void build_int_vec (int32 vloc, int32 ivec, int32 (*iack)(void) ) -{ -int32 ilvl = vloc / 32; -int32 ibit = vloc % 32; - -if (iack != NULL) int_ack[ilvl][ibit] = iack; -else int_vec[ilvl][ibit] = ivec; -return; -} - -/* Build dib_tab from device list */ - -t_stat build_dib_tab (void) -{ -int32 i, j, k; -DEVICE *dptr; -DIB *dibp; - -for (i = 0; i < IPL_HLVL; i++) { /* clear int tables */ - for (j = 0; j < 32; j++) { - int_vec[i][j] = 0; - int_ack[i][j] = NULL; } } -for (i = j = 0; (dptr = sim_devices[i]) != NULL; i++) { /* loop thru dev */ - dibp = (DIB *) dptr->ctxt; /* get DIB */ - if (dibp && !(dptr->flags & DEV_DIS)) { /* defined, enabled? */ - if (dibp->vnum > VEC_DEVMAX) return SCPE_IERR; - for (k = 0; k < dibp->vnum; k++) /* loop thru vec */ - build_int_vec (dibp->vloc + k, /* add vector */ - dibp->vec + (k * 4), dibp->ack[k]); - if (dibp->lnt != 0) { /* I/O addresses? */ - dib_tab[j++] = dibp; /* add DIB to dib_tab */ - if (j >= DIB_MAX) return SCPE_IERR; } /* too many? */ - } /* end if enabled */ - } /* end for */ -dib_tab[j] = NULL; /* end with NULL */ -for (i = 0; (dibp = dib_tab[i]) != NULL; i++) { /* test built dib_tab */ - if (dev_conflict (dibp)) return SCPE_STOP; } /* for conflicts */ -return FALSE; -} - -/* Show dib_tab */ - -t_stat show_iospace (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -int32 i, j, done = 0; -DEVICE *dptr; -DIB *dibt; - -build_dib_tab (); /* build table */ -while (done == 0) { /* sort ascending */ - done = 1; /* assume done */ - for (i = 0; dib_tab[i + 1] != NULL; i++) { /* check table */ - if (dib_tab[i]->ba > dib_tab[i + 1]->ba) { /* out of order? */ - dibt = dib_tab[i]; /* interchange */ - dib_tab[i] = dib_tab[i + 1]; - dib_tab[i + 1] = dibt; - done = 0; } } /* not done */ - } /* end while */ -for (i = 0; dib_tab[i] != NULL; i++) { /* print table */ - for (j = 0, dptr = NULL; sim_devices[j] != NULL; j++) { - if (((DIB*) sim_devices[j]->ctxt) == dib_tab[i]) { - dptr = sim_devices[j]; - break; } } - fprintf (st, "%08X - %08X%c\t%s\n", dib_tab[i]->ba, - dib_tab[i]->ba + dib_tab[i]->lnt - 1, - (dptr && (dptr->flags & DEV_FLTA))? '*': ' ', - dptr? sim_dname (dptr): "CPU"); - } -return SCPE_OK; -} - -/* Autoconfiguration */ - -#define AUTO_DYN 0001 -#define AUTO_VEC 0002 -#define AUTO_MAXC 4 -#define AUTO_CSRBASE 0010 -#define AUTO_VECBASE 0300 - -struct auto_con { - uint32 amod; - uint32 vmod; - uint32 flags; - uint32 num; - uint32 fix; - char *dnam[AUTO_MAXC]; }; - -struct auto_con auto_tab[AUTO_LNT + 1] = { - { 0x7, 0x7 }, /* DJ11 */ - { 0xf, 0x7 }, /* DH11 */ - { 0x7, 0x7 }, /* DQ11 */ - { 0x7, 0x7 }, /* DU11 */ - { 0x7, 0x7 }, /* DUP11 */ - { 0x7, 0x7 }, /* LK11A */ - { 0x7, 0x7 }, /* DMC11 */ - { 0x7, 0x7, AUTO_VEC, DZ_MUXES, 0, { "DZ" } }, - - { 0x7, 0x7 }, /* KMC11 */ - { 0x7, 0x7 }, /* LPP11 */ - { 0x7, 0x7 }, /* VMV21 */ - { 0xf, 0x7 }, /* VMV31 */ - { 0x7, 0x7 }, /* DWR70 */ - { 0x7, 0x3, AUTO_DYN|AUTO_VEC, 0, IOBA_RL, { "RL", "RLB" } }, - { 0xf, 0x7 }, /* LPA11K */ - { 0x7, 0x7 }, /* KW11C */ - - { 0x7, 0 }, /* reserved */ - { 0x7, 0x3 }, /* RX11/RX211 */ - { 0x7, 0x3 }, /* DR11W */ - { 0x7, 0x3 }, /* DR11B */ - { 0x7, 0x7 }, /* DMP11 */ - { 0x7, 0x7 }, /* DPV11 */ - { 0x7, 0x7 }, /* ISB11 */ - { 0xf, 0x7 }, /* DMV11 */ - - { 0x7, 0x3 }, /* DEUNA/DELUA */ - { 0x3, 0x3, AUTO_DYN|AUTO_VEC, 0, IOBA_RQ, { "RQ", "RQB", "RQC", "RQD" } }, - { 0x1f, 0x3 }, /* DMF32 */ - { 0xf, 0x7 }, /* KMS11 */ - { 0xf, 0x3 }, /* VS100 */ - { 0x3, 0x3, AUTO_DYN|AUTO_VEC, 0, IOBA_TQ, { "TQ", "TQB" } }, - { 0xf, 0x7 }, /* KMV11 */ - { 0xf, 0x7 }, /* DHU11/DHQ11 */ - - { 0x1f, 0x7 }, /* DMZ32 */ - { 0x1f, 0x7 }, /* CP132 */ - { 0 }, /* padding */ -}; - -t_stat auto_config (uint32 rank, uint32 nctrl) -{ -uint32 csr = IOPAGEBASE + AUTO_CSRBASE; -uint32 vec = VEC_Q + AUTO_VECBASE; -struct auto_con *autp; -DEVICE *dptr; -DIB *dibp; -int32 i, j, k; -extern DEVICE *find_dev (char *ptr); - -if (rank > AUTO_LNT) return SCPE_IERR; /* legal rank? */ -if (rank) auto_tab[rank - 1].num = nctrl; /* update num? */ -for (i = 0, autp = auto_tab; i < AUTO_LNT; i++) { /* loop thru table */ - for (j = k = 0; (j < AUTO_MAXC) && autp->dnam[j]; j++) { - dptr = find_dev (autp->dnam[j]); /* find ctrl */ - if ((dptr == NULL) || (dptr->flags & DEV_DIS) || - !(dptr->flags & DEV_FLTA)) continue; /* enabled, floating? */ - dibp = (DIB *) dptr->ctxt; /* get DIB */ - if ((k++ == 0) && autp->fix) /* 1st & fixed? */ - dibp->ba = autp->fix; /* gets fixed CSR */ - else { /* no, float */ - dibp->ba = csr; /* set CSR */ - csr = (csr + autp->amod + 1) & ~autp->amod; /* next CSR */ - if ((autp->flags & AUTO_DYN) == 0) /* static? */ - csr = csr + ((autp->num - 1) * (autp->amod + 1)); - if (autp->flags & AUTO_VEC) { /* vectors too? */ - dibp->vec = (vec + autp->vmod) & ~autp->vmod; - if (autp->flags & AUTO_DYN) vec = vec + autp->vmod + 1; - else vec = vec + (autp->num * (autp->vmod + 1)); } - } /* end else flt */ - } /* end for j */ - autp++; - csr = (csr + autp->amod + 1) & ~autp->amod; /* gap */ - } /* end for i */ -return SCPE_OK; -} diff --git a/VAX/vax_mmu.c b/VAX/vax_mmu.c deleted file mode 100644 index 1f131b23..00000000 --- a/VAX/vax_mmu.c +++ /dev/null @@ -1,538 +0,0 @@ -/* vax_mm.c - VAX memory management simulator - - 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"), - 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. - - 01-Jun-03 RMS Fixed compilation problem with USE_ADDR64 - - This module contains the instruction simulators for - - Read - read virtual - Write - write virtual - ReadL(P) - read aligned physical longword (physical context) - WriteL(P) - write aligned physical longword (physical context) - ReadB(W) - read aligned physical byte (word) - WriteB(W) - write aligned physical byte (word) - Test - test acccess - - zap_tb - clear TB - zap_tb_ent - clear TB entry - chk_tb_ent - check TB entry - set_map_reg - set up working map registers -*/ - -#include "vax_defs.h" -#include - -struct tlbent { - int32 tag; /* tag */ - int32 pte; /* pte */ -}; - -typedef struct tlbent TLBENT; - -extern uint32 *M; -extern uint32 align[4]; -extern int32 PSL; -extern int32 mapen; -extern int32 p1, p2; -extern int32 P0BR, P0LR; -extern int32 P1BR, P1LR; -extern int32 SBR, SLR; -extern int32 SISR; -extern jmp_buf save_env; -extern UNIT cpu_unit; - -int32 p0br, p0lr; /* dynamic copies */ -int32 p1br, p1lr; /* altered per ucode */ -int32 sbr, slr; -extern int32 mchk_va, mchk_ref; /* for mcheck */ -TLBENT stlb[VA_TBSIZE], ptlb[VA_TBSIZE]; -static const int32 insert[4] = { - 0x00000000, 0x000000FF, 0x0000FFFF, 0x00FFFFFF }; -static const int32 cvtacc[16] = { 0, 0, - TLB_ACCW (KERN)+TLB_ACCR (KERN), - TLB_ACCR (KERN), - TLB_ACCW (KERN)+TLB_ACCW (EXEC)+TLB_ACCW (SUPV)+TLB_ACCW (USER)+ - TLB_ACCR (KERN)+TLB_ACCR (EXEC)+TLB_ACCR (SUPV)+TLB_ACCR (USER), - TLB_ACCW (KERN)+TLB_ACCW (EXEC)+TLB_ACCR (KERN)+TLB_ACCR (EXEC), - TLB_ACCW (KERN)+TLB_ACCR (KERN)+TLB_ACCR (EXEC), - TLB_ACCR (KERN)+TLB_ACCR (EXEC), - TLB_ACCW (KERN)+TLB_ACCW (EXEC)+TLB_ACCW (SUPV)+ - TLB_ACCR (KERN)+TLB_ACCR (EXEC)+TLB_ACCR (SUPV), - TLB_ACCW (KERN)+TLB_ACCW (EXEC)+ - TLB_ACCR (KERN)+TLB_ACCR (EXEC)+TLB_ACCR (SUPV), - TLB_ACCW (KERN)+TLB_ACCR (KERN)+TLB_ACCR (EXEC)+TLB_ACCR (SUPV), - TLB_ACCR (KERN)+TLB_ACCR (EXEC)+TLB_ACCR (SUPV), - TLB_ACCW (KERN)+TLB_ACCW (EXEC)+TLB_ACCW (SUPV)+ - TLB_ACCR (KERN)+TLB_ACCR (EXEC)+TLB_ACCR (SUPV)+TLB_ACCR (USER), - TLB_ACCW (KERN)+TLB_ACCW (EXEC)+ - TLB_ACCR (KERN)+TLB_ACCR (EXEC)+TLB_ACCR (SUPV)+TLB_ACCR (USER), - TLB_ACCW (KERN)+ - TLB_ACCR (KERN)+TLB_ACCR (EXEC)+TLB_ACCR (SUPV)+TLB_ACCR (USER), - TLB_ACCR (KERN)+TLB_ACCR (EXEC)+TLB_ACCR (SUPV)+TLB_ACCR (USER) -}; - -t_stat tlb_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw); -t_stat tlb_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw); -t_stat tlb_reset (DEVICE *dptr); - -TLBENT fill (uint32 va, int32 lnt, int32 acc, int32 *stat); -int32 ReadB (uint32 pa); -void WriteB (uint32 pa, int32 val); -int32 ReadW (uint32 pa); -void WriteW (uint32 pa, int32 val); -int32 ReadL (uint32 pa); -void WriteL (uint32 pa, int32 val); -int32 ReadLP (uint32 pa); -void WriteLP (uint32 pa, int32 val); -extern int32 ReadIO (uint32 pa, int32 lnt); -extern void WriteIO (uint32 pa, int32 val, int32 lnt); -extern int32 ReadReg (uint32 pa, int32 lnt); -extern void WriteReg (uint32 pa, int32 val, int32 lnt); - -/* TLB data structures - - tlb_dev pager device descriptor - tlb_unit pager units - pager_reg pager register list -*/ - -UNIT tlb_unit[] = { - { UDATA (NULL, UNIT_FIX, VA_TBSIZE * 2) }, - { UDATA (NULL, UNIT_FIX, VA_TBSIZE * 2) } }; - -REG tlb_reg[] = { - { NULL } }; - -DEVICE tlb_dev = { - "TLB", tlb_unit, tlb_reg, NULL, - 2, 16, VA_N_TBI * 2, 1, 16, 32, - &tlb_ex, &tlb_dep, &tlb_reset, - NULL, NULL, NULL }; - -/* Read and write virtual - - These routines logically fall into three phases: - - 1. Look up the virtual address in the translation buffer, calling - the fill routine on a tag mismatch or access mismatch (invalid - tlb entries have access = 0 and thus always mismatch). The - fill routine handles all errors. If the resulting physical - address is aligned, do an aligned physical read or write. - 2. Test for unaligned across page boundaries. If cross page, look - up the physical address of the second page. If not cross page, - the second physical address is the same as the first. - 3. Using the two physical addresses, do an unaligned read or - write, with three cases: unaligned long, unaligned word within - a longword, unaligned word crossing a longword boundary. -*/ - -/* Read virtual - - Inputs: - va = virtual address - lnt = length code (BWLQ) - acc = access code (KESU) - Output: - returned data, right justified in 32b longword -*/ - -int32 Read (uint32 va, int32 lnt, int32 acc) -{ -int32 vpn, off, tbi, pa; -int32 pa1, bo, sc, wl, wh; -TLBENT xpte; - -mchk_va = va; -if (mapen) { /* mapping on? */ - vpn = VA_GETVPN (va); /* get vpn, offset */ - off = VA_GETOFF (va); - 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 */ - pa = (xpte.pte & TLB_PFN) | off; } /* get phys addr */ -else pa = va & PAMASK; -if ((pa & (lnt - 1)) == 0) { /* aligned? */ - if (lnt >= L_LONG) return ReadL (pa); /* long, quad? */ - if (lnt == L_WORD) return ReadW (pa); /* word? */ - return ReadB (pa); } /* byte */ -if (mapen && ((off + lnt) > VA_PAGSIZE)) { /* cross page? */ - vpn = VA_GETVPN (va + lnt); /* vpn 2nd 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 */ - pa1 = (xpte.pte & TLB_PFN) | VA_GETOFF (va + 4); } -else pa1 = (pa + 4) & PAMASK; /* not cross page */ -bo = pa & 3; -if (lnt >= L_LONG) { /* lw unaligned? */ - sc = bo << 3; - wl = ReadL (pa); /* read both lw */ - wh = ReadL (pa1); /* extract */ - return (((wl >> sc) & align[bo]) | (wh << (32 - sc))); } -else if (bo == 1) return ((ReadL (pa) >> 8) & WMASK); -else { wl = ReadL (pa); /* word cross lw */ - wh = ReadL (pa1); /* read, extract */ - return (((wl >> 24) & 0xFF) | ((wh & 0xFF) << 8)); } -} - -/* Write virtual - - Inputs: - va = virtual address - val = data to be written, right justified in 32b lw - lnt = length code (BWLQ) - acc = access code (KESU) - Output: - none -*/ - -void Write (uint32 va, int32 val, int32 lnt, int32 acc) -{ -int32 vpn, off, tbi, pa; -int32 pa1, bo, sc, wl, wh; -TLBENT xpte; - -mchk_va = va; -if (mapen) { - vpn = VA_GETVPN (va); - off = VA_GETOFF (va); - 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); - pa = (xpte.pte & TLB_PFN) | off; } -else pa = va & PAMASK; -if ((pa & (lnt - 1)) == 0) { /* aligned? */ - if (lnt >= L_LONG) WriteL (pa, val); /* long, quad? */ - else if (lnt == L_WORD) WriteW (pa, val); /* word? */ - else WriteB (pa, val); /* byte */ - return; } -if (mapen && ((off + lnt) > VA_PAGSIZE)) { - vpn = VA_GETVPN (va + 4); - 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); - pa1 = (xpte.pte & TLB_PFN) | VA_GETOFF (va + 4); } -else pa1 = (pa + 4) & PAMASK; -bo = pa & 3; -wl = ReadL (pa); -if (lnt >= L_LONG) { - sc = bo << 3; - wh = ReadL (pa1); - wl = (wl & insert[bo]) | (val << sc); - wh = (wh & ~insert[bo]) | ((val >> (32 - sc)) & insert[bo]); - WriteL (pa, wl); - WriteL (pa1, wh); } -else if (bo == 1) { - wl = (wl & 0xFF0000FF) | (val << 8); - WriteL (pa, wl); } -else { wh = ReadL (pa1); - wl = (wl & 0x00FFFFFF) | (val << 24); - wh = (wh & 0xFFFFFF00) | ((val >> 8) & 0xFF); - WriteL (pa, wl); - WriteL (pa1, wh); } -return; -} - -/* Test access to a byte (VAX PROBEx) */ - -int32 Test (int32 va, int32 acc, int32 *status) -{ -int32 vpn, off, tbi; -TLBENT xpte; - -*status = PR_OK; /* assume ok */ -if (mapen) { /* mapping on? */ - vpn = VA_GETVPN (va); /* get vpn, off */ - off = VA_GETOFF (va); - 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; - xpte = fill (va, L_BYTE, acc, status); /* fill TB */ - if (*status == PR_OK) return (xpte.pte & TLB_PFN) | off; - else return -1; } -return va & PAMASK; /* ret phys addr */ -} - -/* Read aligned physical (in virtual context, unless indicated) - - Inputs: - pa = physical address, naturally aligned - Output: - returned data, right justified in 32b longword -*/ - -int32 ReadB (uint32 pa) -{ -int32 dat; - -if (ADDR_IS_MEM (pa)) dat = M[pa >> 2]; -else { mchk_ref = REF_V; - if (ADDR_IS_IO (pa)) dat = ReadIO (pa, L_BYTE); - else dat = ReadReg (pa, L_BYTE); } -return ((dat >> ((pa & 3) << 3)) & BMASK); -} - -int32 ReadW (uint32 pa) -{ -int32 dat; - -if (ADDR_IS_MEM (pa)) dat = M[pa >> 2]; -else { mchk_ref = REF_V; - if (ADDR_IS_IO (pa)) dat = ReadIO (pa, L_WORD); - else dat = ReadReg (pa, L_WORD); } -return ((dat >> ((pa & 2)? 16: 0)) & WMASK); -} - -int32 ReadL (uint32 pa) -{ -if (ADDR_IS_MEM (pa)) return M[pa >> 2]; -mchk_ref = REF_V; -if (ADDR_IS_IO (pa)) return ReadIO (pa, L_LONG); -return ReadReg (pa, L_LONG); -} - -int32 ReadLP (uint32 pa) -{ -if (ADDR_IS_MEM (pa)) return M[pa >> 2]; -mchk_va = pa; -mchk_ref = REF_P; -if (ADDR_IS_IO (pa)) return ReadIO (pa, L_LONG); -return ReadReg (pa, L_LONG); -} - -/* Write aligned physical (in virtual context, unless indicated) - - Inputs: - pa = physical address, naturally aligned - val = data to be written, right justified in 32b longword - Output: - none -*/ - -void WriteB (uint32 pa, int32 val) -{ -if (ADDR_IS_MEM (pa)) { - int32 id = pa >> 2; - int32 sc = (pa & 3) << 3; - int32 mask = 0xFF << sc; - M[id] = (M[id] & ~mask) | (val << sc); } -else { mchk_ref = REF_V; - if (ADDR_IS_IO (pa)) WriteIO (pa, val, L_BYTE); - else WriteReg (pa, val, L_BYTE); } -return; -} - -void WriteW (uint32 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; } -else { mchk_ref = REF_V; - if (ADDR_IS_IO (pa)) WriteIO (pa, val, L_WORD); - else WriteReg (pa, val, L_WORD); } -return; -} - -void WriteL (uint32 pa, int32 val) -{ -if (ADDR_IS_MEM (pa)) M[pa >> 2] = val; -else { mchk_ref = REF_V; - if (ADDR_IS_IO (pa)) WriteIO (pa, val, L_LONG); - else WriteReg (pa, val, L_LONG); } -return; -} - -void WriteLP (uint32 pa, int32 val) -{ -if (ADDR_IS_MEM (pa)) M[pa >> 2] = val; -else { mchk_va = pa; - mchk_ref = REF_P; - if (ADDR_IS_IO (pa)) WriteIO (pa, val, L_LONG); - else WriteReg (pa, val, L_LONG); } -return; -} - -/* TLB fill - - This routine fills the TLB after a tag or access mismatch, or - on a write if pte = 0. It fills the TLB and returns the - pte to the caller. On an error, it aborts directly to the - fault handler in the CPU. - - If called from map (VAX PROBEx), the error status is returned - to the caller, and no fault occurs. -*/ - -#define MM_ERR(param) { \ - if (stat) { *stat = param; return zero_pte; } \ - p1 = MM_PARAM (acc & TLB_WACC, param); \ - p2 = va; \ - ABORT ((param & PR_TNV)? ABORT_TNV: ABORT_ACV); } - -TLBENT fill (uint32 va, int32 lnt, int32 acc, int32 *stat) -{ -int32 ptidx = (((uint32) va) >> 7) & ~03; -int32 tlbpte, ptead, pte, tbi, vpn; -static TLBENT zero_pte = { 0, 0 }; - -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 { /* P0 */ - if (ptidx >= p0lr) - MM_ERR (PR_LNV); - ptead = p0br + ptidx; } - if ((ptead & VA_S0) == 0) - 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 */ - ptead = (stlb[tbi].pte & TLB_PFN) | VA_GETOFF (ptead); } -pte = ReadL (ptead); /* read pte */ -tlbpte = cvtacc[PTE_GETACC (pte)] | /* cvt access */ - ((pte << VA_N_OFF) & TLB_PFN); /* set addr */ -if ((tlbpte & acc) == 0) MM_ERR (PR_ACV); /* chk access */ -if ((pte & PTE_V) == 0) MM_ERR (PR_TNV); /* check valid */ -if (acc & TLB_WACC) { /* write? */ - if ((pte & PTE_M) == 0) WriteL (ptead, pte | PTE_M); - tlbpte = tlbpte | TLB_M; } /* set M */ -vpn = VA_GETVPN (va); -tbi = VA_GETTBI (vpn); -if ((va & VA_S0) == 0) { /* process space? */ - ptlb[tbi].tag = vpn; /* store tlb ent */ - ptlb[tbi].pte = tlbpte; - return ptlb[tbi]; } -stlb[tbi].tag = vpn; /* system space */ -stlb[tbi].pte = tlbpte; /* store tlb ent */ -return stlb[tbi]; -} - -/* Utility routines */ - -extern void set_map_reg (void) -{ -p0br = P0BR & ~03; -p1br = (P1BR - 0x800000) & ~03; /* VA<30> >> 7 */ -sbr = (SBR - 0x1000000) & ~03; /* VA<31> >> 7 */ -p0lr = (P0LR << 2); -p1lr = (P1LR << 2) + 0x800000; /* VA<30> >> 7 */ -slr = (SLR << 2) + 0x1000000; /* VA<31> >> 7 */ -return; -} - -/* Zap process (0) or whole (1) tb */ - -void zap_tb (int stb) -{ -int32 i; - -for (i = 0; i < VA_TBSIZE; i++) { - ptlb[i].tag = ptlb[i].pte = -1; - if (stb) stlb[i].tag = stlb[i].pte = -1; } -return; -} - -/* Zap single tb entry corresponding to va */ - -void zap_tb_ent (int32 va) -{ -int32 tbi = VA_GETTBI (VA_GETVPN (va)); - -if (va & VA_S0) stlb[tbi].tag = stlb[tbi].pte = -1; -else ptlb[tbi].tag = ptlb[tbi].pte = -1; -return; -} - -/* Check for tlb entry corresponding to va */ - -t_bool chk_tb_ent (int32 va) -{ -int32 vpn = VA_GETVPN (va); -int32 tbi = VA_GETTBI (vpn); -TLBENT xpte; - -xpte = (va & VA_S0)? stlb[tbi]: ptlb[tbi]; -if (xpte.tag == vpn) return TRUE; -return FALSE; -} - -/* TLB examine */ - -t_stat tlb_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) -{ -int32 tlbn = uptr - tlb_unit; -int32 idx = (uint32) addr >> 1; - -if (idx >= VA_TBSIZE) return SCPE_NXM; -if (addr & 1) *vptr = ((uint32) (tlbn? stlb[idx].pte: ptlb[idx].pte)); -else *vptr = ((uint32) (tlbn? stlb[idx].tag: ptlb[idx].tag)); -return SCPE_OK; -} - -/* TLB deposit */ - -t_stat tlb_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw) -{ -int32 tlbn = uptr - tlb_unit; -int32 idx = (uint32) addr >> 1; - -if (idx >= VA_TBSIZE) return SCPE_NXM; -if (addr & 1) { - if (tlbn) stlb[idx].pte = (int32) val; - else ptlb[idx].pte = (int32) val; } -else { if (tlbn) stlb[idx].tag = (int32) val; - else ptlb[idx].tag = (int32) val; } -return SCPE_OK; -} - -/* TLB reset */ - -t_stat tlb_reset (DEVICE *dptr) -{ -int32 i; - -for (i = 0; i < VA_TBSIZE; i++) - stlb[i].tag = ptlb[i].tag = stlb[i].pte = ptlb[i].pte = -1; -return SCPE_OK; -} diff --git a/VAX/vax_stddev.c b/VAX/vax_stddev.c deleted file mode 100644 index e33a2b40..00000000 --- a/VAX/vax_stddev.c +++ /dev/null @@ -1,385 +0,0 @@ -/* vax_stddev.c: VAX standard I/O devices simulator - - 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"), - 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. - - tti terminal input - tto terminal output - clk 100Hz and TODR clock - - 25-Apr-03 RMS Revised for extended file support - 02-Mar-02 RMS Added SET TTI CTRL-C - 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 - 30-Apr-02 RMS Automatically set TODR to VMS-correct value during boot -*/ - -#include "vax_defs.h" -#include - -#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 */ -#define CLKCSR_RW (CSR_IE) -#define CLK_DELAY 5000 /* 100 Hz */ -#define TMXR_MULT 2 /* 50 Hz */ - -#define UNIT_V_8B (UNIT_V_UF + 0) /* 8B mode */ -#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 */ -int32 clk_csr = 0; /* control/status */ -int32 clk_tps = 100; /* ticks/second */ -int32 todr_reg = 0; /* TODR register */ -int32 todr_blow = 1; /* TODR battery low */ -int32 tmxr_poll = CLK_DELAY * TMXR_MULT; /* term mux poll */ -int32 tmr_poll = CLK_DELAY; /* pgm timer poll */ - -t_stat tti_svc (UNIT *uptr); -t_stat tto_svc (UNIT *uptr); -t_stat clk_svc (UNIT *uptr); -t_stat tti_reset (DEVICE *dptr); -t_stat tto_reset (DEVICE *dptr); -t_stat clk_reset (DEVICE *dptr); -t_stat tti_set_ctrlc (UNIT *uptr, int32 val, char *cptr, void *desc); - -extern int32 sysd_hlt_enb (void); - -/* TTI data structures - - tti_dev TTI device descriptor - tti_unit TTI unit descriptor - tti_reg TTI register list -*/ - -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, 16) }, - { HRDATA (CSR, tti_csr, 16) }, - { FLDATA (INT, int_req[IPL_TTI], INT_V_TTI) }, - { FLDATA (DONE, tti_csr, CSR_V_DONE) }, - { FLDATA (IE, tti_csr, CSR_V_IE) }, - { DRDATA (POS, tti_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, tti_unit.wait, 24), REG_NZ + PV_LEFT }, - { NULL } }; - -MTAB tti_mod[] = { - { UNIT_8B, UNIT_8B, "8b", "8B", NULL }, - { UNIT_8B, 0 , "7b", "7B", NULL }, - { MTAB_XTD|MTAB_VDV|MTAB_VUN, 0, NULL, "CTRL-C", - &tti_set_ctrlc, NULL, NULL }, - { MTAB_XTD|MTAB_VDV, 0, "VECTOR", NULL, - NULL, &show_vec, NULL }, - { 0 } }; - -DEVICE tti_dev = { - "TTI", &tti_unit, tti_reg, tti_mod, - 1, 10, 31, 1, 16, 8, - NULL, NULL, &tti_reset, - NULL, NULL, NULL, - &tti_dib, 0 }; - -/* TTO data structures - - tto_dev TTO device descriptor - tto_unit TTO unit descriptor - tto_reg TTO register list -*/ - -DIB tto_dib = { 0, 0, NULL, NULL, 1, IVCL (TTO), SCB_TTO, { NULL } }; - -UNIT tto_unit = { UDATA (&tto_svc, UNIT_8B, 0), SERIAL_OUT_WAIT }; - -REG tto_reg[] = { - { HRDATA (BUF, tto_unit.buf, 8) }, - { HRDATA (CSR, tto_csr, 16) }, - { FLDATA (INT, int_req[IPL_TTO], INT_V_TTO) }, - { FLDATA (DONE, tto_csr, CSR_V_DONE) }, - { FLDATA (IE, tto_csr, CSR_V_IE) }, - { DRDATA (POS, tto_unit.pos, T_ADDR_W), PV_LEFT }, - { DRDATA (TIME, tto_unit.wait, 24), PV_LEFT }, - { NULL } }; - -MTAB tto_mod[] = { - { UNIT_8B, UNIT_8B, "8b", "8B", NULL }, - { UNIT_8B, 0 , "7b", "7B", NULL }, - { MTAB_XTD|MTAB_VDV, 0, "VECTOR", NULL, NULL, &show_vec }, - { 0 } }; - -DEVICE tto_dev = { - "TTO", &tto_unit, tto_reg, tto_mod, - 1, 10, 31, 1, 16, 8, - NULL, NULL, &tto_reset, - NULL, NULL, NULL, - &tto_dib, 0 }; - -/* CLK data structures - - clk_dev CLK device descriptor - clk_unit CLK unit descriptor - clk_reg CLK register list -*/ - -DIB clk_dib = { 0, 0, NULL, NULL, 1, IVCL (CLK), SCB_INTTIM, { NULL } }; - -UNIT clk_unit = { UDATA (&clk_svc, 0, 0), CLK_DELAY }; - -REG clk_reg[] = { - { HRDATA (CSR, clk_csr, 16) }, - { FLDATA (INT, int_req[IPL_CLK], INT_V_CLK) }, - { FLDATA (IE, clk_csr, CSR_V_IE) }, - { DRDATA (TODR, todr_reg, 32), PV_LEFT }, - { FLDATA (BLOW, todr_blow, 0) }, - { DRDATA (TIME, clk_unit.wait, 24), REG_NZ + PV_LEFT }, - { DRDATA (TPS, clk_tps, 8), REG_NZ + PV_LEFT }, - { NULL } }; - -MTAB clk_mod[] = { - { MTAB_XTD|MTAB_VDV, 0, "VECTOR", NULL, NULL, &show_vec }, - { 0 } }; - -DEVICE clk_dev = { - "CLK", &clk_unit, clk_reg, clk_mod, - 1, 0, 0, 0, 0, 0, - NULL, NULL, &clk_reset, - NULL, NULL, NULL, - &clk_dib, 0 }; - -/* Clock and terminal MxPR routines - - iccs_rd/wr interval timer - todr_rd/wr time of year clock - rxcs_rd/wr input control/status - rxdb_rd input buffer - txcs_rd/wr output control/status - txdb_wr output buffer -*/ - -int32 iccs_rd (void) -{ -return (clk_csr & CLKCSR_IMP); -} - -int32 todr_rd (void) -{ -return todr_reg; -} - -int32 rxcs_rd (void) -{ -return (tti_csr & TTICSR_IMP); -} - -int32 rxdb_rd (void) -{ -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 t; -} - -int32 txcs_rd (void) -{ -return (tto_csr & TTOCSR_IMP); -} - -void iccs_wr (int32 data) -{ -if ((data & CSR_IE) == 0) CLR_INT (CLK); -clk_csr = (clk_csr & ~CLKCSR_RW) | (data & CLKCSR_RW); -return; -} - -void todr_wr (int32 data) -{ -todr_reg = data; -if (data) todr_blow = 0; -return; -} - -void rxcs_wr (int32 data) -{ -if ((data & CSR_IE) == 0) CLR_INT (TTI); -else if ((tti_csr & (CSR_DONE + CSR_IE)) == CSR_DONE) - SET_INT (TTI); -tti_csr = (tti_csr & ~TTICSR_RW) | (data & TTICSR_RW); -return; -} - -void txcs_wr (int32 data) -{ -if ((data & CSR_IE) == 0) CLR_INT (TTO); -else if ((tto_csr & (CSR_DONE + CSR_IE)) == CSR_DONE) - SET_INT (TTO); -tto_csr = (tto_csr & ~TTOCSR_RW) | (data & TTOCSR_RW); -return; -} - -void txdb_wr (int32 data) -{ -tto_unit.buf = data & 0377; -tto_csr = tto_csr & ~CSR_DONE; -CLR_INT (TTO); -sim_activate (&tto_unit, tto_unit.wait); -return; -} - -/* Terminal input routines - - tti_svc process event (character ready) - tti_reset process reset -*/ - -t_stat tti_svc (UNIT *uptr) -{ -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 (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); -return SCPE_OK; -} - -t_stat tti_reset (DEVICE *dptr) -{ -tti_unit.buf = 0; -tti_csr = 0; -CLR_INT (TTI); -sim_activate (&tti_unit, tti_unit.wait); /* activate unit */ -return SCPE_OK; -} - -/* Set control-C */ - -t_stat tti_set_ctrlc (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -if (cptr) return SCPE_ARG; -uptr->buf = 003; -uptr->pos = uptr->pos + 1; -tti_csr = tti_csr | CSR_DONE; -if (tti_csr & CSR_IE) SET_INT (TTI); -return SCPE_OK; -} - -/* Terminal output routines - - tto_svc process event (character typed) - tto_reset process reset -*/ - -t_stat tto_svc (UNIT *uptr) -{ -int32 c; -t_stat r; - -tto_csr = tto_csr | CSR_DONE; -if (tto_csr & CSR_IE) SET_INT (TTO); -c = tto_unit.buf & ((tto_unit.flags & UNIT_8B)? 0377: 0177); -if ((r = sim_putchar (c)) != SCPE_OK) return r; -tto_unit.pos = tto_unit.pos + 1; -return SCPE_OK; -} - -t_stat tto_reset (DEVICE *dptr) -{ -tto_unit.buf = 0; -tto_csr = CSR_DONE; -CLR_INT (TTO); -sim_cancel (&tto_unit); /* deactivate unit */ -return SCPE_OK; -} - -/* Clock routines - - clk_svc process event (clock tick) - clk_reset process reset - todr_powerup powerup for TODR (get date from system) -*/ - -t_stat clk_svc (UNIT *uptr) -{ -int32 t; - -if (clk_csr & CSR_IE) SET_INT (CLK); -t = sim_rtcn_calb (clk_tps, TMR_CLK); /* calibrate clock */ -sim_activate (&clk_unit, t); /* reactivate unit */ -tmr_poll = t; /* set tmr poll */ -tmxr_poll = t * TMXR_MULT; /* set mux poll */ -if (!todr_blow) todr_reg = todr_reg + 1; /* incr TODR */ -return SCPE_OK; -} - -t_stat clk_reset (DEVICE *dptr) -{ -int32 t; - -clk_csr = 0; -CLR_INT (CLK); -t = sim_rtcn_init (clk_unit.wait, TMR_CLK); /* init timer */ -sim_activate (&clk_unit, t); /* activate unit */ -tmr_poll = t; /* set tmr poll */ -tmxr_poll = t * TMXR_MULT; /* set mux poll */ -return SCPE_OK; -} - -t_stat todr_powerup (void) -{ -uint32 base; -time_t curr; -struct tm *ctm; - -curr = time (NULL); /* get curr time */ -if (curr == (time_t) -1) return SCPE_NOFNC; /* error? */ -ctm = localtime (&curr); /* decompose */ -if (ctm == NULL) return SCPE_NOFNC; /* error? */ -base = (((((ctm->tm_yday * 24) + /* sec since 1-Jan */ - ctm->tm_hour) * 60) + - ctm->tm_min) * 60) + - ctm->tm_sec; -todr_reg = (base * 100) + 0x10000000; /* cvt to VAX form */ -todr_blow = 0; -return SCPE_OK; -} diff --git a/VAX/vax_sys.c b/VAX/vax_sys.c deleted file mode 100644 index 2933fd2e..00000000 --- a/VAX/vax_sys.c +++ /dev/null @@ -1,1373 +0,0 @@ -/* vax_sys.c: VAX simulator interface - - 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"), - 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. - - 06-May-03 RMS Added support for second DELQA - 12-Oct-02 RMS Added multiple RQ controller support - 10-Oct-02 RMS Added DELQA support - 21-Sep-02 RMS Extended symbolic ex/mod to all byte devices - 06-Sep-02 RMS Added TMSCP support - 14-Jul-02 RMS Added infinite loop message -*/ - -#include "vax_defs.h" -#include - -extern DEVICE cpu_dev; -extern DEVICE tlb_dev; -extern DEVICE rom_dev; -extern DEVICE nvr_dev; -extern DEVICE sysd_dev; -extern DEVICE qba_dev; -extern DEVICE ptr_dev, ptp_dev; -extern DEVICE tti_dev, tto_dev; -extern DEVICE csi_dev, cso_dev; -extern DEVICE lpt_dev; -extern DEVICE clk_dev; -extern DEVICE rq_dev, rqb_dev, rqc_dev, rqd_dev; -extern DEVICE rl_dev; -extern DEVICE ts_dev; -extern DEVICE tq_dev; -extern DEVICE dz_dev; -extern DEVICE xq_dev, xqb_dev; -extern UNIT cpu_unit; -extern REG cpu_reg[]; -extern uint32 *M; -extern int32 saved_PC; -extern int32 sim_switches; - -extern void WriteB (int32 pa, int32 val); -extern void rom_wr (int32 pa, int32 val, int32 lnt); -t_stat fprint_sym_m (FILE *of, uint32 addr, t_value *val); -int32 fprint_sym_qoimm (FILE *of, t_value *val, int32 vp, int32 lnt); -t_stat parse_sym_m (char *cptr, uint32 addr, t_value *val); -int32 parse_brdisp (char *cptr, uint32 addr, t_value *val, - int32 vp, int32 lnt, t_stat *r); -int32 parse_spec (char *cptr, uint32 addr, t_value *val, - int32 vp, int32 disp, t_stat *r); -char *parse_rnum (char *cptr, int32 *rn); -int32 parse_sym_qoimm (int32 *lit, t_value *val, int32 vp, - int lnt, int32 minus); - -/* 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[] = "VAX"; - -REG *sim_PC = &cpu_reg[0]; - -int32 sim_emax = 60; - -DEVICE *sim_devices[] = { - &cpu_dev, - &tlb_dev, - &rom_dev, - &nvr_dev, - &sysd_dev, - &qba_dev, - &tti_dev, - &tto_dev, - &csi_dev, - &cso_dev, - &clk_dev, - &ptr_dev, - &ptp_dev, - &lpt_dev, - &dz_dev, - &rl_dev, - &rq_dev, - &rqb_dev, - &rqc_dev, - &rqd_dev, - &ts_dev, - &tq_dev, - &xq_dev, - &xqb_dev, - NULL }; - -const char *sim_stop_messages[] = { - "Unknown error", - "HALT instruction", - "Breakpoint", - "CHMx on interrupt stack", - "Invalid SCB vector", - "Exception in interrupt or exception", - "Process PTE in P0 or P1 space", - "Interrupt at undefined IPL", - "Fatal RQDX3 error", - "Infinite loop", - "Sanity timer expired", - "Unknown error", - "Unknown abort code" }; - -/* Binary loader - - The binary loader handles absolute system images, that is, system - images linked /SYSTEM. These are simply a byte stream, with no - origin or relocation information. - - -r load ROM - -n load NVR - -o for memory, specify origin -*/ - -t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag) -{ -t_stat r; -int32 i; -uint32 origin, limit; -extern int32 ssc_cnf; -#define SSCCNF_BLO 0x80000000 - -if (flag) return SCPE_ARG; /* dump? */ -if (sim_switches & SWMASK ('R')) { /* ROM? */ - origin = ROMBASE; - limit = ROMBASE + ROMSIZE; } -else if (sim_switches & SWMASK ('N')) { /* NVR? */ - origin = NVRBASE; - limit = NVRBASE + NVRSIZE; - ssc_cnf = ssc_cnf & ~SSCCNF_BLO; } -else { origin = 0; /* memory */ - limit = (uint32) cpu_unit.capac; - if (sim_switches & SWMASK ('O')) { /* origin? */ - origin = (int32) get_uint (cptr, 16, 0xFFFFFFFF, &r); - if (r != SCPE_OK) return SCPE_ARG; } } - -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 */ - else WriteB (origin, i); /* store byte */ - origin = origin + 1; } -return SCPE_OK; -} - -/* Factory bad block table creation routine - - This routine writes a DEC standard 044 compliant bad block table on the - last track of the specified unit. The bad block table consists of 10 - repetitions of the same table, formatted as follows: - - words 0-1 pack id number - words 2-3 cylinder/sector/surface specifications - : - words n-n+1 end of table (-1,-1) - - Inputs: - uptr = pointer to unit - sec = number of sectors per surface - wds = number of words per sector - Outputs: - sta = status code -*/ - -t_stat pdp11_bad_block (UNIT *uptr, int32 sec, int32 wds) -{ -int32 i, da; -int32 *buf; - -if ((sec < 2) || (wds < 16)) return SCPE_ARG; -if ((uptr->flags & UNIT_ATT) == 0) return SCPE_UNATT; -if (!get_yn ("Overwrite last track? [N]", FALSE)) return SCPE_OK; -da = (int32) (uptr->capac - (sec * wds)) * sizeof (int16); -if (fseek (uptr->fileref, da, SEEK_SET)) return SCPE_IOERR; -if ((buf = malloc (wds * sizeof (int32))) == NULL) return SCPE_MEM; -buf[0] = 0x12345678; -buf[1] = 0; -for (i = 2; i < wds; i++) buf[i] = 0xFFFFFFFF; -for (i = 0; (i < sec) && (i < 10); i++) - fxwrite (buf, sizeof (int32), wds, uptr->fileref); -free (buf); -if (ferror (uptr->fileref)) return SCPE_IOERR; -return SCPE_OK; -} - -/* Dispatch/decoder table - - The first entry contains: - - FPD legal flag (DR_F) - - number of specifiers for decode bits 2:0> - - number of specifiers for unimplemented instructions bits<6:4> - */ - -const uint16 drom[NUM_INST][MAX_SPEC + 1] = { -0, 0, 0, 0, 0, 0, 0, /* HALT */ -0, 0, 0, 0, 0, 0, 0, /* NOP */ -0, 0, 0, 0, 0, 0, 0, /* REI */ -0, 0, 0, 0, 0, 0, 0, /* BPT */ -0, 0, 0, 0, 0, 0, 0, /* RET */ -0, 0, 0, 0, 0, 0, 0, /* RSB */ -0, 0, 0, 0, 0, 0, 0, /* LDPCTX */ -0, 0, 0, 0, 0, 0, 0, /* SVPCTX */ -4+DR_F, RW, AB, RW, AB, 0, 0, /* CVTPS */ -4+DR_F, RW, AB, RW, AB, 0, 0, /* CVTSP */ -6, RL, RL, RL, RL, RL, WL, /* INDEX */ -4+DR_F, AB, RL, RW, AB, 0, 0, /* CRC */ -3, RB, RW, AB, 0, 0, 0, /* PROBER */ -3, RB, RW, AB, 0, 0, 0, /* PROBEW */ -2, AB, AB, 0, 0, 0, 0, /* INSQUE */ -2, AB, WL, 0, 0, 0, 0, /* REMQUE */ -1, BB, 0, 0, 0, 0, 0, /* BSBB */ -1, BB, 0, 0, 0, 0, 0, /* BRB */ -1, BB, 0, 0, 0, 0, 0, /* BNEQ */ -1, BB, 0, 0, 0, 0, 0, /* BEQL */ -1, BB, 0, 0, 0, 0, 0, /* BGTR */ -1, BB, 0, 0, 0, 0, 0, /* BLEQ */ -1, AB, 0, 0, 0, 0, 0, /* JSB */ -1, AB, 0, 0, 0, 0, 0, /* JMP */ -1, BB, 0, 0, 0, 0, 0, /* BGEQ */ -1, BB, 0, 0, 0, 0, 0, /* BLSS */ -1, BB, 0, 0, 0, 0, 0, /* BGTRU */ -1, BB, 0, 0, 0, 0, 0, /* BLEQU */ -1, BB, 0, 0, 0, 0, 0, /* BVC */ -1, BB, 0, 0, 0, 0, 0, /* BVS */ -1, BB, 0, 0, 0, 0, 0, /* BCC */ -1, BB, 0, 0, 0, 0, 0, /* BCS */ -4+DR_F, RW, AB, RW, AB, 0, 0, /* ADDP4 */ -6+DR_F, RW, AB, RW, AB, RW, AB, /* ADDP6 */ -4+DR_F, RW, AB, RW, AB, 0, 0, /* SUBP4 */ -6+DR_F, RW, AB, RW, AB, RW, AB, /* SUBP6 */ -5+DR_F, RW, AB, AB, RW, AB, 0, /* CVTPT */ -6+DR_F, RW, AB, RW, AB, RW, AB, /* MULP6 */ -5+DR_F, RW, AB, AB, RW, AB, 0, /* CVTTP */ -6+DR_F, RW, AB, RW, AB, RW, AB, /* DIVP6 */ -3+DR_F, RW, AB, AB, 0, 0, 0, /* MOVC3 */ -3+DR_F, RW, AB, AB, 0, 0, 0, /* CMPC3 */ -4+DR_F, RW, AB, AB, RB, 0, 0, /* SCANC */ -4+DR_F, RW, AB, AB, RB, 0, 0, /* SPANC */ -5+DR_F, RW, AB, RB, RW, AB, 0, /* MOVC5 */ -5+DR_F, RW, AB, RB, RW, AB, 0, /* CMPC5 */ -6+DR_F, RW, AB, RB, AB, RW, AB, /* MOVTC */ -6+DR_F, RW, AB, RB, AB, RW, AB, /* MOVTUC */ -1, BW, 0, 0, 0, 0, 0, /* BSBW */ -1, BW, 0, 0, 0, 0, 0, /* BRW */ -2, RW, WL, 0, 0, 0, 0, /* CVTWL */ -2, RW, WB, 0, 0, 0, 0, /* CVTWB */ -3+DR_F, RW, AB, AB, 0, 0, 0, /* MOVP */ -3+DR_F, RW, AB, AB, 0, 0, 0, /* CMPP3 */ -3+DR_F, RW, AB, WL, 0, 0, 0, /* CVTPL */ -4+DR_F, RW, AB, RW, AB, 0, 0, /* CMPP4 */ -4+DR_F, RW, AB, AB, AB, 0, 0, /* EDITPC */ -4+DR_F, RW, AB, RW, AB, 0, 0, /* MATCHC */ -3+DR_F, RB, RW, AB, 0, 0, 0, /* LOCC */ -3+DR_F, RB, RW, AB, 0, 0, 0, /* SKPC */ -2, RW, WL, 0, 0, 0, 0, /* MOVZWL */ -4, RW, RW, MW, BW, 0, 0, /* ACBW */ -2, AW, WL, 0, 0, 0, 0, /* MOVAW */ -1, AW, 0, 0, 0, 0, 0, /* PUSHAW */ -2, RF, ML, 0, 0, 0, 0, /* ADDF2 */ -3, RF, RF, WL, 0, 0, 0, /* ADDF3 */ -2, RF, ML, 0, 0, 0, 0, /* SUBF2 */ -3, RF, RF, WL, 0, 0, 0, /* SUBF3 */ -2, RF, ML, 0, 0, 0, 0, /* MULF2 */ -3, RF, RF, WL, 0, 0, 0, /* MULF3 */ -2, RF, ML, 0, 0, 0, 0, /* DIVF2 */ -3, RF, RF, WL, 0, 0, 0, /* DIVF3 */ -2, RF, WB, 0, 0, 0, 0, /* CVTFB */ -2, RF, WW, 0, 0, 0, 0, /* CVTFW */ -2, RF, WL, 0, 0, 0, 0, /* CVTFL */ -2, RF, WL, 0, 0, 0, 0, /* CVTRFL */ -2, RB, WL, 0, 0, 0, 0, /* CVTBF */ -2, RW, WL, 0, 0, 0, 0, /* CVTWF */ -2, RL, WL, 0, 0, 0, 0, /* CVTLF */ -4, RF, RF, ML, BW, 0, 0, /* ACBF */ -2, RF, WL, 0, 0, 0, 0, /* MOVF */ -2, RF, RF, 0, 0, 0, 0, /* CMPF */ -2, RF, WL, 0, 0, 0, 0, /* MNEGF */ -1, RF, 0, 0, 0, 0, 0, /* TSTF */ -5, RF, RB, RF, WL, WL, 0, /* EMODF */ -3, RF, RW, AB, 0, 0, 0, /* POLYF */ -2, RF, WQ, 0, 0, 0, 0, /* CVTFD */ -0, 0, 0, 0, 0, 0, 0, /* reserved */ -2, RW, WW, 0, 0, 0, 0, /* ADAWI */ -0, 0, 0, 0, 0, 0, 0, /* reserved */ -0, 0, 0, 0, 0, 0, 0, /* reserved */ -0, 0, 0, 0, 0, 0, 0, /* reserved */ -2, AB, AQ, 0, 0, 0, 0, /* INSQHI */ -2, AB, AQ, 0, 0, 0, 0, /* INSQTI */ -2, AQ, WL, 0, 0, 0, 0, /* REMQHI */ -2, AQ, WL, 0, 0, 0, 0, /* REMQTI */ -2, RD, MQ, 0, 0, 0, 0, /* ADDD2 */ -3, RD, RD, WQ, 0, 0, 0, /* ADDD3 */ -2, RD, MQ, 0, 0, 0, 0, /* SUBD2 */ -3, RD, RD, WQ, 0, 0, 0, /* SUBD3 */ -2, RD, MQ, 0, 0, 0, 0, /* MULD2 */ -3, RD, RD, WQ, 0, 0, 0, /* MULD3 */ -2, RD, MQ, 0, 0, 0, 0, /* DIVD2 */ -3, RD, RD, WQ, 0, 0, 0, /* DIVD3 */ -2, RD, WB, 0, 0, 0, 0, /* CVTDB */ -2, RD, WW, 0, 0, 0, 0, /* CVTDW */ -2, RD, WL, 0, 0, 0, 0, /* CVTDL */ -2, RD, WL, 0, 0, 0, 0, /* CVTRDL */ -2, RB, WQ, 0, 0, 0, 0, /* CVTBD */ -2, RW, WQ, 0, 0, 0, 0, /* CVTWD */ -2, RL, WQ, 0, 0, 0, 0, /* CVTLD */ -4, RD, RD, MQ, BW, 0, 0, /* ACBD */ -2, RD, WQ, 0, 0, 0, 0, /* MOVD */ -2, RD, RD, 0, 0, 0, 0, /* CMPD */ -2, RD, WQ, 0, 0, 0, 0, /* MNEGD */ -1, RD, 0, 0, 0, 0, 0, /* TSTD */ -5, RD, RB, RD, WL, WQ, 0, /* EMODD */ -3, RD, RW, AB, 0, 0, 0, /* POLYD */ -2, RD, WL, 0, 0, 0, 0, /* CVTDF */ -0, 0, 0, 0, 0, 0, 0, /* reserved */ -3, RB, RL, WL, 0, 0, 0, /* ASHL */ -3, RB, RQ, WQ, 0, 0, 0, /* ASHQ */ -4, RL, RL, RL, WQ, 0, 0, /* EMUL */ -4, RL, RQ, WL, WL, 0, 0, /* EDIV */ -1, WQ, 0, 0, 0, 0, 0, /* CLRQ */ -2, RQ, WQ, 0, 0, 0, 0, /* MOVQ */ -2, AQ, WL, 0, 0, 0, 0, /* MOVAQ */ -1, AQ, 0, 0, 0, 0, 0, /* PUSHAQ */ -2, RB, MB, 0, 0, 0, 0, /* ADDB2 */ -3, RB, RB, WB, 0, 0, 0, /* ADDB3 */ -2, RB, MB, 0, 0, 0, 0, /* SUBB2 */ -3, RB, RB, WB, 0, 0, 0, /* SUBB3 */ -2, RB, MB, 0, 0, 0, 0, /* MULB2 */ -3, RB, RB, WB, 0, 0, 0, /* MULB3 */ -2, RB, MB, 0, 0, 0, 0, /* DIVB2 */ -3, RB, RB, WB, 0, 0, 0, /* DIVB3 */ -2, RB, MB, 0, 0, 0, 0, /* BISB2 */ -3, RB, RB, WB, 0, 0, 0, /* BISB3 */ -2, RB, MB, 0, 0, 0, 0, /* BICB2 */ -3, RB, RB, WB, 0, 0, 0, /* BICB3 */ -2, RB, MB, 0, 0, 0, 0, /* XORB2 */ -3, RB, RB, WB, 0, 0, 0, /* XORB3 */ -2, RB, WB, 0, 0, 0, 0, /* MNEGB */ -3, RB, RB, RB, 0, 0, 0, /* CASEB */ -2, RB, WB, 0, 0, 0, 0, /* MOVB */ -2, RB, RB, 0, 0, 0, 0, /* CMPB */ -2, RB, WB, 0, 0, 0, 0, /* MCOMB */ -2, RB, RB, 0, 0, 0, 0, /* BITB */ -1, WB, 0, 0, 0, 0, 0, /* CLRB */ -1, RB, 0, 0, 0, 0, 0, /* TSTB */ -1, MB, 0, 0, 0, 0, 0, /* INCB */ -1, MB, 0, 0, 0, 0, 0, /* DECB */ -2, RB, WL, 0, 0, 0, 0, /* CVTBL */ -2, RB, WW, 0, 0, 0, 0, /* CVTBW */ -2, RB, WL, 0, 0, 0, 0, /* MOVZBL */ -2, RB, WW, 0, 0, 0, 0, /* MOVZBW */ -3, RB, RL, WL, 0, 0, 0, /* ROTL */ -4, RB, RB, MB, BW, 0, 0, /* ACBB */ -2, AB, WL, 0, 0, 0, 0, /* MOVAB */ -1, AB, 0, 0, 0, 0, 0, /* PUSHAB */ -2, RW, MW, 0, 0, 0, 0, /* ADDW2 */ -3, RW, RW, WW, 0, 0, 0, /* ADDW3 */ -2, RW, MW, 0, 0, 0, 0, /* SUBW2 */ -3, RW, RW, WW, 0, 0, 0, /* SUBW3 */ -2, RW, MW, 0, 0, 0, 0, /* MULW2 */ -3, RW, RW, WW, 0, 0, 0, /* MULW3 */ -2, RW, MW, 0, 0, 0, 0, /* DIVW2 */ -3, RW, RW, WW, 0, 0, 0, /* DIVW3 */ -2, RW, MW, 0, 0, 0, 0, /* BISW2 */ -3, RW, RW, WW, 0, 0, 0, /* BISW3 */ -2, RW, MW, 0, 0, 0, 0, /* BICW2 */ -3, RW, RW, WW, 0, 0, 0, /* BICW3 */ -2, RW, MW, 0, 0, 0, 0, /* XORW2 */ -3, RW, RW, WW, 0, 0, 0, /* XORW3 */ -2, RW, WW, 0, 0, 0, 0, /* MNEGW */ -3, RW, RW, RW, 0, 0, 0, /* CASEW */ -2, RW, WW, 0, 0, 0, 0, /* MOVW */ -2, RW, RW, 0, 0, 0, 0, /* CMPW */ -2, RW, WW, 0, 0, 0, 0, /* MCOMW */ -2, RW, RW, 0, 0, 0, 0, /* BITW */ -1, WW, 0, 0, 0, 0, 0, /* CLRW */ -1, RW, 0, 0, 0, 0, 0, /* TSTW */ -1, MW, 0, 0, 0, 0, 0, /* INCW */ -1, MW, 0, 0, 0, 0, 0, /* DECW */ -1, RW, 0, 0, 0, 0, 0, /* BISPSW */ -1, RW, 0, 0, 0, 0, 0, /* BICPSW */ -1, RW, 0, 0, 0, 0, 0, /* POPR */ -1, RW, 0, 0, 0, 0, 0, /* PUSHR */ -1, RW, 0, 0, 0, 0, 0, /* CHMK */ -1, RW, 0, 0, 0, 0, 0, /* CHME */ -1, RW, 0, 0, 0, 0, 0, /* CHMS */ -1, RW, 0, 0, 0, 0, 0, /* CHMU */ -2, RL, ML, 0, 0, 0, 0, /* ADDL2 */ -3, RL, RL, WL, 0, 0, 0, /* ADDL3 */ -2, RL, ML, 0, 0, 0, 0, /* SUBL2 */ -3, RL, RL, WL, 0, 0, 0, /* SUBL3 */ -2, RL, ML, 0, 0, 0, 0, /* MULL2 */ -3, RL, RL, WL, 0, 0, 0, /* MULL3 */ -2, RL, ML, 0, 0, 0, 0, /* DIVL2 */ -3, RL, RL, WL, 0, 0, 0, /* DIVL3 */ -2, RL, ML, 0, 0, 0, 0, /* BISL2 */ -3, RL, RL, WL, 0, 0, 0, /* BISL3 */ -2, RL, ML, 0, 0, 0, 0, /* BICL2 */ -3, RL, RL, WL, 0, 0, 0, /* BICL3 */ -2, RL, ML, 0, 0, 0, 0, /* XORL2 */ -3, RL, RL, WL, 0, 0, 0, /* XORL3 */ -2, RL, WL, 0, 0, 0, 0, /* MNEGL */ -3, RL, RL, RL, 0, 0, 0, /* CASEL */ -2, RL, WL, 0, 0, 0, 0, /* MOVL */ -2, RL, RL, 0, 0, 0, 0, /* CMPL */ -2, RL, WL, 0, 0, 0, 0, /* MCOML */ -2, RL, RL, 0, 0, 0, 0, /* BITL */ -1, WL, 0, 0, 0, 0, 0, /* CLRL */ -1, RL, 0, 0, 0, 0, 0, /* TSTL */ -1, ML, 0, 0, 0, 0, 0, /* INCL */ -1, ML, 0, 0, 0, 0, 0, /* DECL */ -2, RL, ML, 0, 0, 0, 0, /* ADWC */ -2, RL, ML, 0, 0, 0, 0, /* SBWC */ -2, RL, RL, 0, 0, 0, 0, /* MTPR */ -2, RL, WL, 0, 0, 0, 0, /* MFPR */ -1, WL, 0, 0, 0, 0, 0, /* MOVPSL */ -1, RL, 0, 0, 0, 0, 0, /* PUSHL */ -2, AL, WL, 0, 0, 0, 0, /* MOVAL */ -1, AL, 0, 0, 0, 0, 0, /* PUSHAL */ -3, RL, VB, BB, 0, 0, 0, /* BBS */ -3, RL, VB, BB, 0, 0, 0, /* BBC */ -3, RL, VB, BB, 0, 0, 0, /* BBSS */ -3, RL, VB, BB, 0, 0, 0, /* BBCS */ -3, RL, VB, BB, 0, 0, 0, /* BBSC */ -3, RL, VB, BB, 0, 0, 0, /* BBCC */ -3, RL, VB, BB, 0, 0, 0, /* BBSSI */ -3, RL, VB, BB, 0, 0, 0, /* BBCCI */ -2, RL, BB, 0, 0, 0, 0, /* BLBS */ -2, RL, BB, 0, 0, 0, 0, /* BLBC */ -4, RL, RB, VB, WL, 0, 0, /* FFS */ -4, RL, RB, VB, WL, 0, 0, /* FFC */ -4, RL, RB, VB, RL, 0, 0, /* CMPV */ -4, RL, RB, VB, RL, 0, 0, /* CMPZV */ -4, RL, RB, VB, WL, 0, 0, /* EXTV */ -4, RL, RB, VB, WL, 0, 0, /* EXTZV */ -4, RL, RL, RB, VB, 0, 0, /* INSV */ -4, RL, RL, ML, BW, 0, 0, /* ACBL */ -3, RL, ML, BB, 0, 0, 0, /* AOBLSS */ -3, RL, ML, BB, 0, 0, 0, /* AOBLEQ */ -2, ML, BB, 0, 0, 0, 0, /* SOBGEQ */ -2, ML, BB, 0, 0, 0, 0, /* SOBGTR */ -2, RL, WB, 0, 0, 0, 0, /* CVTLB */ -2, RL, WW, 0, 0, 0, 0, /* CVTLW */ -6+DR_F, RB, RW, AB, RB, RW, AB, /* ASHP */ -3+DR_F, RL, RW, AB, 0, 0, 0, /* CVTLP */ -2, AB, AB, 0, 0, 0, 0, /* CALLG */ -2, RL, AB, 0, 0, 0, 0, /* CALLS */ -0, 0, 0, 0, 0, 0, 0, /* XFC */ -0, 0, 0, 0, 0, 0, 0, /* 0FD */ -0, 0, 0, 0, 0, 0, 0, /* 0FE */ -0, 0, 0, 0, 0, 0, 0, /* 0FF */ -0, 0, 0, 0, 0, 0, 0, /* 100-10F */ -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, /* 110-11F */ -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, /* 120-12F */ -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, /* 130-13F */ -0, 0, 0, 0, 0, 0, 0, -0x20, RD, OC, 0, 0, 0, 0, /* CVTDH */ -2, RG, WL, 0, 0, 0, 0, /* CVTGF */ -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -2, RG, MQ, 0, 0, 0, 0, /* ADDG2 */ -3, RG, RG, WQ, 0, 0, 0, /* ADDG3 */ -2, RG, MQ, 0, 0, 0, 0, /* SUBG2 */ -3, RG, RG, WQ, 0, 0, 0, /* SUBG3 */ -2, RG, MQ, 0, 0, 0, 0, /* MULG2 */ -3, RG, RG, WQ, 0, 0, 0, /* MULG3 */ -2, RG, MQ, 0, 0, 0, 0, /* DIVG2 */ -3, RG, RG, WQ, 0, 0, 0, /* DIVG3 */ -2, RG, WB, 0, 0, 0, 0, /* CVTGB */ -2, RG, WW, 0, 0, 0, 0, /* CVTGW */ -2, RG, WL, 0, 0, 0, 0, /* CVTGL */ -2, RG, WL, 0, 0, 0, 0, /* CVTRGL */ -2, RB, WQ, 0, 0, 0, 0, /* CVTBG */ -2, RW, WQ, 0, 0, 0, 0, /* CVTWG */ -2, RL, WQ, 0, 0, 0, 0, /* CVTLG */ -4, RG, RG, MQ, BW, 0, 0, /* ACBG */ -2, RG, WQ, 0, 0, 0, 0, /* MOVG */ -2, RG, RG, 0, 0, 0, 0, /* CMPG */ -2, RG, WQ, 0, 0, 0, 0, /* MNEGG */ -1, RG, 0, 0, 0, 0, 0, /* TSTG */ -5, RG, RW, RG, WL, WQ, 0, /* EMODG */ -3, RG, RW, AB, 0, 0, 0, /* POLYG */ -0x20, RG, OC, 0, 0, 0, 0, /* CVTGH */ -0, 0, 0, 0, 0, 0, 0, /* reserved */ -0, 0, 0, 0, 0, 0, 0, /* reserved */ -0, 0, 0, 0, 0, 0, 0, /* reserved */ -0, 0, 0, 0, 0, 0, 0, /* reserved */ -0, 0, 0, 0, 0, 0, 0, /* reserved */ -0, 0, 0, 0, 0, 0, 0, /* reserved */ -0, 0, 0, 0, 0, 0, 0, /* reserved */ -0, 0, 0, 0, 0, 0, 0, /* reserved */ -0, 0, 0, 0, 0, 0, 0, /* reserved */ -0x20, OC, OC, 0, 0, 0, 0, /* ADDH2 */ -0x30, OC, OC, OC, 0, 0, 0, /* ADDH3 */ -0x20, OC, OC, 0, 0, 0, 0, /* SUBH2 */ -0x30, OC, OC, OC, 0, 0, 0, /* SUBH3 */ -0x20, OC, OC, 0, 0, 0, 0, /* MULH2 */ -0x30, OC, OC, OC, 0, 0, 0, /* MULH3 */ -0x20, OC, OC, 0, 0, 0, 0, /* DIVH2 */ -0x30, OC, OC, OC, 0, 0, 0, /* DIVH3 */ -0x20, OC, WB, 0, 0, 0, 0, /* CVTHB */ -0x20, OC, WW, 0, 0, 0, 0, /* CVTHW */ -0x20, OC, WL, 0, 0, 0, 0, /* CVTHL */ -0x20, OC, WL, 0, 0, 0, 0, /* CVTRHL */ -0x20, RB, OC, 0, 0, 0, 0, /* CVTBH */ -0x20, RW, OC, 0, 0, 0, 0, /* CVTWH */ -0x20, RL, OC, 0, 0, 0, 0, /* CVTLH */ -0x40, OC, OC, OC, BW, 0, 0, /* ACBH */ -0x20, OC, OC, 0, 0, 0, 0, /* MOVH */ -0x20, OC, OC, 0, 0, 0, 0, /* CMPH */ -0x20, OC, OC, 0, 0, 0, 0, /* MNEGH */ -0x10, OC, 0, 0, 0, 0, 0, /* TSTH */ -0x50, OC, RW, OC, WL, OC, 0, /* EMODH */ -0x30, OC, RW, AB, 0, 0, 0, /* POLYH */ -0x20, OC, WQ, 0, 0, 0, 0, /* CVTHG */ -0, 0, 0, 0, 0, 0, 0, /* reserved */ -0, 0, 0, 0, 0, 0, 0, /* reserved */ -0, 0, 0, 0, 0, 0, 0, /* reserved */ -0, 0, 0, 0, 0, 0, 0, /* reserved */ -0, 0, 0, 0, 0, 0, 0, /* reserved */ -0x10, OC, 0, 0, 0, 0, 0, /* CLRO */ -0x20, OC, OC, 0, 0, 0, 0, /* MOVO */ -0x20, OC, WL, 0, 0, 0, 0, /* MOVAO*/ -0x10, OC, 0, 0, 0, 0, 0, /* PUSHAO*/ -0, 0, 0, 0, 0, 0, 0, /* 180-18F */ -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, /* 190-19F */ -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0x20, RF, OC, 0, 0, 0, 0, /* CVTFH */ -2, RF, WQ, 0, 0, 0, 0, /* CVTFG */ -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, /* 1A0-1AF */ -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, /* 1B0-1BF */ -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, /* 1C0-1CF */ -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, /* 1D0-1DF */ -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, /* 1E0-1EF */ -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, /* 1F0-1FF */ -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0x20, OC, WL, 0, 0, 0, 0, /* CVTHF */ -0x20, OC, WQ, 0, 0, 0, 0, /* CVTHD */ -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0 }; - -/* Opcode mnemonics table */ - -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", -"BGEQ", "BLSS", "BGTRU", "BLEQU", "BVC", "BVS", "BGEQU", "BLSSU", -"ADDP4", "ADDP6", "SUBP4", "SUBP6", "CVTPT", "MULP6", "CVTTP", "DIVP", -"MOVC3", "CMPC3", "SCANC", "SPANC", "MOVC5", "CMPC5", "MOVTC", "MOVTUC", -"BSBW", "BRW", "CVTWL", "CVTWB", "MOVP", "CMPP3", "CVTPL", "CMPP4", -"EDITPC", "MATCHC", "LOCC", "SKPC", "MOVZWL", "ACBW", "MOVAW", "PUSHAW", -"ADDF2", "ADDF3", "SUBF2", "SUBF3", "MULF2", "MULF3", "DIVF2", "DIVF3", -"CVTFB", "CVTFW", "CVTFL", "CVTRFL", "CVTBF", "CVTWF", "CVTLF", "ACBF", -"MOVF", "CMPF", "MNEGF", "TSTF", "EMODF", "POLYF", "CVTFD", NULL, -"ADAWI", NULL, NULL, NULL, "INSQHI", "INSQTI", "REMQHI", "REMQTI", -"ADDD2", "ADDD3", "SUBD2", "SUBD3", "MULD2", "MULD3", "DIVD2", "DIVD3", -"CVTDB", "CVTDW", "CVTDL", "CVTRDL", "CVTBD", "CVTWD", "CVTLD", "ACBD", -"MOVD", "CMPD", "MNEGD", "TSTD", "EMODD", "POLYD", "CVTDF", NULL, -"ASHL", "ASHQ", "EMUL", "EDIV", "CLRQ", "MOVQ", "MOVAQ", "PUSHAQ", -"ADDB2", "ADDB3", "SUBB2", "SUBB3", "MULB2", "MULB3", "DIVB2", "DIVB3", -"BISB2", "BISB3", "BICB2", "BICB3", "XORB2", "XORB3", "MNEGB", "CASEB", -"MOVB", "CMPB", "MCOMB", "BITB", "CLRB", "TSTB", "INCB", "DECB", -"CVTBL", "CVTBW", "MOVZBL", "MOVZBW", "ROTL", "ACBB", "MOVAB", "PUSHAB", -"ADDW2", "ADDW3", "SUBW2", "SUBW3", "MULW2", "MULW3", "DIVW2", "DIVW3", -"BISW2", "BISW3", "BICW2", "BICW3", "XORW2", "XORW3", "MNEGW", "CASEW", -"MOVW", "CMPW", "MCOMW", "BITW", "CLRW", "TSTW", "INCW", "DECW", -"BISPSW", "BICPSW", "POPR", "PUSHR", "CHMK", "CHME", "CHMS", "CHMU", -"ADDL2", "ADDL3", "SUBL2", "SUBL3", "MULL2", "MULL3", "DIVL2", "DIVL3", -"BISL2", "BISL3", "BICL2", "BICL3", "XORL2", "XORL3", "MNEGL", "CASEL", -"MOVL", "CMPL", "MCOML", "BITL", "CLRL", "TSTL", "INCL", "DECL", -"ADWC", "SBWC", "MTPR", "MFPR", "MOVPSL", "PUSHL", "MOVAL", "PUSHAL", -"BBS", "BBC", "BBSS", "BBCS", "BBSC", "BBCC", "BBSSI", "BBCCI", -"BLBS", "BLBC", "FFS", "FFC", "CMPV", "CMPZV", "EXTV", "EXTZV", -"INSV", "ACBL", "AOBLSS", "AOBLEQ", "SOBGEQ", "SOBGTR", "CVTLB", "CVTLW", -"ASHP", "CVTLP", "CALLG", "CALLS", "XFC", NULL, NULL, NULL, -NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 100 - 11F */ -NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 120 - 13F */ -NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -NULL, NULL, "CVTDH", "CVTGF", NULL, NULL, NULL, NULL, -NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -"ADDG2", "ADDG3", "SUBG2", "SUBG3", "MULG2", "MULG3", "DIVG2", "DIVG3", -"CVTGB", "CVTGW", "CVTGL", "CVTRGL", "CVTBG", "CVTWG", "CVTLG", "ACBG", -"MOVG", "CMPG", "MNEGG", "TSTG", "EMODG", "POLYG", "CVTGH", NULL, -NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -"ADDH2", "ADDH3", "SUBH2", "SUBH3", "MULH2", "MULH3", "DIVH2", "DIVH3", -"CVTHB", "CVTHW", "CVTHL", "CVTRHL", "CVTBH", "CVTWH", "CVTLH", "ACBH", -"MOVH", "CMPH", "MNEGH", "TSTH", "EMODH", "POLYH", "CVTHG", NULL, -NULL, NULL, NULL, NULL, "CLRO", "MOVO", "MOVAO", "PUSHAO", -NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 180 - 19F */ -NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -"CVTFH", "CVTFG", NULL, NULL, NULL, NULL, NULL, NULL, -NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 1A0 - 1BF */ -NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 1C0 - 1DF */ -NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 1E0 - 1FF */ -NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -NULL, NULL, NULL, NULL, NULL, NULL, "CVTHF", "CVTHD", -NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; - -const char *altcod[] = { -"CLRF", "CLRD", "CLRG", "CLRH", "MOVAF", "MOVAD", "MOVAG", "MOVAH", -"PUSHAF", "PUSHAD", "PUSHAG", "PUSHAH", "BNEQU", "BEQLU", "BCC", "BCS", -NULL }; - -const int32 altop[] = { - 0xD4, 0x7C, 0x7C, 0x17C, 0xDE, 0x7E, 0x7E, 0x17E, - 0xDF, 0x7F, 0x7F, 0x17F, 0x12, 0x13, 0x1E, 0x1F }; - -const char* regname[] = { - "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7", - "R8", "R9", "R10", "R11", "AP", "FP", "SP", "PC" }; - -#define GETNUM(d,n) for (k = d = 0; k < n; k++) \ - d = d | (((int32) val[vp++]) << (k * 8)) - -/* 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 exta, t_value *val, - UNIT *uptr, int32 sw) -{ -uint32 addr = (uint32) exta; -int32 c, k, num, vp, lnt, rdx; -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 ('L')) 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 = (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? */ - r = fprint_sym_m (of, addr, val); /* decode inst */ - if (r <= 0) return r; } - -GETNUM (num, lnt); /* get number */ -fprint_val (of, (uint32) 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, uint32 addr, t_value *val) -{ -int32 i, k, vp, inst, numspec; -int32 num, spec, rn, disp, index; - -vp = 0; /* init ptr */ -inst = (int32) val[vp++]; /* get opcode */ -if (inst == 0xFD) inst = 0x100 | (int32) val[vp++]; /* 2 byte op? */ -if (opcode[inst] == NULL) return SCPE_ARG; /* defined? */ -numspec = drom[inst][0] & DR_NSPMASK; /* get # spec */ -if (numspec == 0) numspec = (drom[inst][0] & DR_USPMASK) >> 4; -fprintf (of, "%s", opcode[inst]); /* print name */ -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); } - 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); - 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); -} - -/* Symbolic decode, quad/octa immediates - - Inputs: - *of = output stream - *val = pointer to input values - vp = current index into val - lnt = number of longwords in immediate - Outputs: - vp = updated index into val -*/ - -int32 fprint_sym_qoimm (FILE *of, t_value *val, int32 vp, int32 lnt) -{ -int32 i, k, startp, num[4]; - -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; } } -return vp; -} - -#define PUTNUM(d,n) for (k = 0; k < n; k++) val[vp++] = (d >> (k * 8)) & 0xFF - -/* Symbolic input - - Inputs: - *cptr = pointer to input string - addr = current PC - *uptr = pointer to unit - *val = pointer to output values - sw = switches - Outputs: - status = > 0 error code - <= 0 -number of extra words -*/ - -t_stat parse_sym (char *cptr, t_addr exta, UNIT *uptr, t_value *val, int32 sw) -{ -uint32 addr = (uint32) exta; -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 ('L')) 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, uint32 addr, t_value *val) -{ -int32 i, numspec, disp, opc, vp; -t_stat r; -char gbuf[CBUFSIZE]; - -cptr = get_glyph (cptr, gbuf, 0); /* get opcode */ -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 (opc < 0) return SCPE_ARG; /* undefined? */ -vp = 0; -if (opc >= 0x100) val[vp++] = 0xFD; /* 2 byte? */ -val[vp++] = opc & 0xFF; /* store opcode */ -numspec = drom[opc][0] & DR_NSPMASK; /* get # specifiers */ -if (numspec == 0) numspec = (drom[opc][0] & DR_USPMASK) >> 4; -for (i = 1; i <= numspec; i++) { /* loop thru specs */ - if (i == numspec) cptr = get_glyph (cptr, gbuf, 0); - else cptr = get_glyph (cptr, gbuf, ','); /* get specifier */ - disp = drom[opc][i]; /* get drom value */ - if (disp == BB) vp = parse_brdisp (gbuf, addr, val, vp, 0, &r); - else if (disp == BW) vp = parse_brdisp (gbuf, addr, val, vp, 1, &r); - else vp = parse_spec (gbuf, addr, val, vp, disp, &r); - if (r != SCPE_OK) return r; } -if (*cptr != 0) return SCPE_ARG; -return -(vp - 1); -} - -/* Parse a branch displacement - - Inputs: - cptr = pointer to input buffer - addr = current address - val = pointer to output array - vp = current pointer in output array - lnt = length (0 = byte, 1 = word) - r = pointer to status - Outputs: - vp = updated output pointer -*/ - -int32 parse_brdisp (char *cptr, uint32 addr, t_value *val, int32 vp, - int32 lnt, t_stat *r) -{ -int32 k, dest, num; - -dest = (int32) get_uint (cptr, 16, 0xFFFFFFFF, r); /* get value */ -num = dest - (addr + vp + lnt + 1); /* compute offset */ -if ((num > (lnt? 32767: 127)) || (num < (lnt? -32768: -128))) return SCPE_ARG; -PUTNUM (num, lnt + 1); /* store offset */ -return vp; -} - -/* Parse a specifier - - Inputs: - cptr = pointer to input buffer - addr = current address - val = pointer to output array - vp = current pointer in output array - disp = specifier dispatch - r = pointer to status - Outputs: - vp = updated output pointer -*/ - -#define SP_IND 0x200 /* indirect */ -#define SP_V_FORCE 6 -#define SP_FS 0x040 /* S^ */ -#define SP_FI 0x080 /* I^ */ -#define SP_FB 0x0C0 /* B^ */ -#define SP_FW 0x100 /* W^ */ -#define SP_FL 0x140 /* L^ */ -#define SP_LIT 0x020 /* # */ -#define SP_PLUS 0x010 /* plus */ -#define SP_MINUS 0x008 /* minus */ -#define SP_NUM 0x004 /* number */ -#define SP_IDX 0x002 /* (Rn) */ -#define SP_POSTP 0x001 /* trailing + */ -#define M1C(c,v) if (*cptr == c) { cptr++; fl = fl | v; } -#define SPUTNUM(v,d) if (fl & SP_MINUS) v = -v; PUTNUM (v, d) -#define PARSE_LOSE { *r = SCPE_ARG; return vp; } -#define SEL_LIM(p,m,u) ((fl & SP_PLUS)? (p): ((fl & SP_MINUS)? (m): (u))) - -int32 parse_spec (char *cptr, uint32 addr, t_value *val, int32 vp, int32 disp, t_stat *r) -{ -int32 i, k, litsize, rn, index; -int32 num, dispsize, mode; -int32 lit[4] = { 0 }; -int32 fl = 0; -char c, *tptr; -const char *force[] = { "S^", "I^", "B^", "W^", "L^", NULL }; - -*r = SCPE_OK; /* assume ok */ -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; } - 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; } } -M1C ('#', SP_LIT); /* look for # */ -M1C ('+', SP_PLUS); /* look for + */ -M1C ('-', SP_MINUS); /* look for - */ -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; } } -if (*cptr == '(') { /* look for (Rn) */ - cptr = parse_rnum (++cptr, &rn); - if ((cptr == NULL) || (*cptr++ != ')')) PARSE_LOSE; - fl = fl | SP_IDX; } -M1C ('+', SP_POSTP); /* look for + */ -if (*cptr == '[') { /* look for [Rx] */ - cptr = parse_rnum (++cptr, &index); - if ((cptr == NULL) || (*cptr++ != ']')) PARSE_LOSE; - val[vp++] = index | IDX; } -switch (fl) { /* case on state */ -case SP_FS|SP_LIT|SP_NUM: /* S^#n */ -case SP_FS|SP_LIT|SP_PLUS|SP_NUM: /* S^#+n */ - if ((litsize > 0) || (lit[0] & ~0x3F)) PARSE_LOSE; - val[vp++] = lit[0]; - break; -case SP_IDX: /* (Rn) */ - val[vp++] = rn | RGD; - break; -case SP_MINUS|SP_IDX: /* -(Rn) */ - val[vp++] = rn | ADC; - break; -case SP_IDX|SP_POSTP: /* (Rn)+ */ - val[vp++] = rn | AIN; - break; -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; } -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 */ -case SP_FI|SP_LIT|SP_MINUS|SP_NUM: /* I^#-n */ - val[vp++] = nPC | AIN; - 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; - case 01: /* check fit */ - 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; - case 03: /* check 2 lw */ - 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 */ - break; -case SP_IND|SP_IDX|SP_POSTP: /* @(Rn)+ */ - val[vp++] = rn | AID; - break; -case SP_IND|SP_LIT|SP_NUM: /* @#n */ - if (litsize > 0) PARSE_LOSE; - val[vp++] = nPC | AID; - PUTNUM (lit[0], 4); - break; -case SP_NUM|SP_IDX: /* d(rn) */ -case SP_PLUS|SP_NUM|SP_IDX: /* +d(rn) */ -case SP_MINUS|SP_NUM|SP_IDX: /* -d(rn) */ -case SP_IND|SP_NUM|SP_IDX: /* @d(rn) */ -case SP_IND|SP_PLUS|SP_NUM|SP_IDX: /* @+d(rn) */ -case SP_IND|SP_MINUS|SP_NUM|SP_IDX: /* @-d(rn) */ - if (litsize > 0) PARSE_LOSE; - 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; } } - val[vp++] = mode | rn | ((fl & SP_IND)? 1: 0); - SPUTNUM (lit[0], dispsize); - break; -case SP_FB|SP_NUM|SP_IDX: /* B^d(rn) */ -case SP_FB|SP_PLUS|SP_NUM|SP_IDX: /* B^+d(rn) */ -case SP_FB|SP_MINUS|SP_NUM|SP_IDX: /* B^-d(rn) */ -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; - val[vp++] = rn | BDP | ((fl & SP_IND)? 1: 0); - SPUTNUM (lit[0], 1); - break; -case SP_FW|SP_NUM|SP_IDX: /* W^d(rn) */ -case SP_FW|SP_PLUS|SP_NUM|SP_IDX: /* W^+d(rn) */ -case SP_FW|SP_MINUS|SP_NUM|SP_IDX: /* W^-d(rn) */ -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; - val[vp++] = rn | WDP | ((fl & SP_IND)? 1: 0); - SPUTNUM (lit[0], 2); - break; -case SP_FL|SP_NUM|SP_IDX: /* L^d(rn) */ -case SP_FL|SP_PLUS|SP_NUM|SP_IDX: /* L^+d(rn) */ -case SP_FL|SP_MINUS|SP_NUM|SP_IDX: /* L^-d(rn) */ -case SP_IND|SP_FL|SP_NUM|SP_IDX: /* @L^d(rn) */ -case SP_IND|SP_FL|SP_PLUS|SP_NUM|SP_IDX: /* @L^+d(rn) */ -case SP_IND|SP_FL|SP_MINUS|SP_NUM|SP_IDX: /* @L^-d(rn) */ - if ((litsize > 0) || (lit[0] < 0)) PARSE_LOSE; - val[vp++] = rn | LDP | ((fl & SP_IND)? 1: 0); - SPUTNUM (lit[0], 2); - break; -case SP_NUM: /* n */ -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; } } - val[vp++] = mode | nPC | ((fl & SP_IND)? 1: 0); - PUTNUM (num, dispsize); - break; -case SP_FB|SP_NUM: /* B^n */ -case SP_IND|SP_FB|SP_NUM: /* @B^n */ - num = lit[0] - (addr + vp + 2); - if ((litsize > 0) || (num > 127) || (num < -128)) PARSE_LOSE; - val[vp++] = nPC | BDP | ((fl & SP_IND)? 1: 0); - PUTNUM (num, 1); - break; -case SP_FW|SP_NUM: /* W^n */ -case SP_IND|SP_FW|SP_NUM: /* @W^n */ - num = lit[0] - (addr + vp + 3); - if ((litsize > 0) || (num > 32767) || (num < -32768)) PARSE_LOSE; - val[vp++] = nPC | WDP | ((fl & SP_IND)? 1: 0); - PUTNUM (num, 2); - break; -case SP_FL|SP_NUM: /* L^n */ -case SP_IND|SP_FL|SP_NUM: /* @L^n */ - num = lit[0] - (addr + vp + 5); - if (litsize > 0) PARSE_LOSE; - val[vp++] = nPC | LDP | ((fl & SP_IND)? 1: 0); - PUTNUM (num, 4); - break; -default: - PARSE_LOSE; } /* end case */ -if (*cptr != 0) *r = SCPE_ARG; /* must be done */ -return vp; -} - -char *parse_rnum (char *cptr, int32 *rn) -{ -int32 i, lnt; -t_value regnum; -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; } } -if (*cptr++ != 'R') return NULL; /* look for R */ -regnum = strtotv (cptr, &tptr, 10); /* look for reg # */ -if ((cptr == tptr) || (regnum > 15)) return NULL; -*rn = (int32) regnum; -return tptr; -} - -int32 parse_sym_qoimm (int32 *lit, t_value *val, int32 vp, int lnt, int32 minus) -{ -int32 i, k, prev; - -for (i = prev = 0; i < lnt; i++) { - if (minus) prev = lit[i] = ~lit[i] + (prev == 0); - PUTNUM (lit[i], 4); } -return vp; -} - diff --git a/VAX/vax_sysdev.c b/VAX/vax_sysdev.c deleted file mode 100644 index 77214ad1..00000000 --- a/VAX/vax_sysdev.c +++ /dev/null @@ -1,1293 +0,0 @@ -/* vax_sysreg.c: VAX system registers simulator - - 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"), - 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 module contains the CVAX system-specific devices implemented in the - CMCTL memory controller and the SSC system support chip. (The architecturally - specified devices are implemented in module vax_stddev.c.) - - rom bootstrap ROM (no registers) - nvr non-volatile ROM (no registers) - csi console storage input - cso console storage output - sysd system devices (SSC miscellany) - - 7-Jun-03 MP Added calibrated delay to ROM reads (from Mark Pizzolato) - Fixed calibration problems interval timer (from Mark Pizzolato) - 12-May-03 RMS Fixed compilation warnings from VC.Net - 23-Apr-03 RMS Revised for 32b/64b t_addr - 19-Aug-02 RMS Removed unused variables (found by David Hittner) - Allowed NVR to be attached to file - 30-May-02 RMS Widened POS to 32b - 28-Feb-02 RMS Fixed bug, missing end of table (found by Lars Brinkhoff) -*/ - -#include "vax_defs.h" - -#define UNIT_V_NODELAY (UNIT_V_UF + 0) /* ROM access equal to RAM access */ -#define UNIT_NODELAY (1u << UNIT_V_NODELAY) - -/* Console storage control/status */ - -#define CSICSR_IMP (CSR_DONE + CSR_IE) /* console input */ -#define CSICSR_RW (CSR_IE) -#define CSOCSR_IMP (CSR_DONE + CSR_IE) /* console output */ -#define CSOCSR_RW (CSR_IE) - -/* CMCTL configuration registers */ - -#define CMCNF_VLD 0x80000000 /* addr valid */ -#define CMCNF_BA 0x1FF00000 /* base addr */ -#define CMCNF_LOCK 0x00000040 /* lock NI */ -#define CMCNF_SRQ 0x00000020 /* sig req WO */ -#define CMCNF_SIG 0x0000001F /* signature */ -#define CMCNF_RW (CMCNF_VLD | CMCNF_BA) /* read/write */ -#define CMCNF_MASK (CMCNF_RW | CMCNF_SIG) -#define MEM_BANK (1 << 22) /* bank size 4MB */ -#define MEM_SIG 0x17; /* ECC, 4 x 4MB */ - -/* CMCTL error register */ - -#define CMERR_RDS 0x80000000 /* uncorr err NI */ -#define CMERR_FRQ 0x40000000 /* 2nd RDS NI */ -#define CMERR_CRD 0x20000000 /* CRD err NI */ -#define CMERR_PAG 0x1FFFFC00 /* page addr NI */ -#define CMERR_DMA 0x00000100 /* DMA err NI */ -#define CMERR_BUS 0x00000080 /* bus err NI */ -#define CMERR_SYN 0x0000007F /* syndrome NI */ -#define CMERR_W1C (CMERR_RDS | CMERR_FRQ | CMERR_CRD | \ - CMERR_DMA | CMERR_BUS) - -/* CMCTL control/status register */ - -#define CMCSR_PMI 0x00002000 /* PMI speed NI */ -#define CMCSR_CRD 0x00001000 /* enb CRD int NI */ -#define CMCSR_FRF 0x00000800 /* force ref WONI */ -#define CMCSR_DET 0x00000400 /* dis err NI */ -#define CMCSR_FDT 0x00000200 /* fast diag NI */ -#define CMCSR_DCM 0x00000080 /* diag mode NI */ -#define CMCSR_SYN 0x0000007F /* syndrome NI */ -#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 */ -#define CACR_V_DPAR 24 /* data parity */ -#define CACR_FIXED 0x00000040 /* fixed bits */ -#define CACR_CPE 0x00000020 /* parity err W1C */ -#define CACR_CEN 0x00000010 /* enable */ -#define CACR_DPE 0x00000004 /* disable par NI */ -#define CACR_WWP 0x00000002 /* write wrong par NI */ -#define CACR_DIAG 0x00000001 /* diag mode */ -#define CACR_W1C (CACR_CPE) -#define CACR_RW (CACR_CEN | CACR_DPE | CACR_WWP | CACR_DIAG) - -/* SSC base register */ - -#define SSCBASE_MBO 0x20000000 /* must be one */ -#define SSCBASE_RW 0x1FFFFC00 /* base address */ - -/* SSC configuration register */ - -#define SSCCNF_BLO 0x80000000 /* batt low W1C */ -#define SSCCNF_IVD 0x08000000 /* int dsbl NI */ -#define SSCCNF_IPL 0x03000000 /* int IPL NI */ -#define SSCCNF_ROM 0x00F70000 /* ROM param NI */ -#define SSCCNF_CTLP 0x00008000 /* ctrl P enb */ -#define SSCCNF_BAUD 0x00007700 /* baud rates NI */ -#define SSCCNF_ADS 0x00000077 /* addr strb NI */ -#define SSCCNF_W1C SSCCNF_BLO -#define SSCCNF_RW 0x0BF7F777 - -/* SSC timeout register */ - -#define SSCBTO_BTO 0x80000000 /* timeout W1C */ -#define SSCBTO_RWT 0x40000000 /* read/write W1C */ -#define SSCBTO_INTV 0x00FFFFFF /* interval NI */ -#define SSCBTO_W1C (SSCBTO_BTO | SSCBTO_RWT) -#define SSCBTO_RW SSCBTO_INTV - -/* SSC output port */ - -#define SSCOTP_MASK 0x0000000F /* output port */ - -/* SSC timer control/status */ - -#define TMR_CSR_ERR 0x80000000 /* error W1C */ -#define TMR_CSR_DON 0x00000080 /* done W1C */ -#define TMR_CSR_IE 0x00000040 /* int enb */ -#define TMR_CSR_SGL 0x00000020 /* single WO */ -#define TMR_CSR_XFR 0x00000010 /* xfer WO */ -#define TMR_CSR_STP 0x00000004 /* stop */ -#define TMR_CSR_RUN 0x00000001 /* run */ -#define TMR_CSR_W1C (TMR_CSR_ERR | TMR_CSR_DON) -#define TMR_CSR_RW (TMR_CSR_IE | TMR_CSR_STP | TMR_CSR_RUN) - -/* SSC timer intervals */ - -#define TMR_INC 10000 /* usec/interval */ - -/* SSC timer vector */ - -#define TMR_VEC_MASK 0x000003FC /* vector */ - -/* SSC address strobes */ - -#define SSCADS_MASK 0x3FFFFFFC /* match or mask */ - -extern int32 int_req[IPL_HLVL]; -extern UNIT cpu_unit; -extern UNIT clk_unit; -extern jmp_buf save_env; -extern int32 p1; -extern int32 sim_switches; -extern int32 MSER; -extern int32 tmr_poll; - -uint32 *rom = NULL; /* boot ROM */ -uint32 *nvr = NULL; /* non-volatile mem */ -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 = BDR_BRKENB; /* KA655 boot diag */ -int32 ssc_base = SSCBASE; /* SSC base */ -int32 ssc_cnf = 0; /* SSC conf */ -int32 ssc_bto = 0; /* SSC timeout */ -int32 ssc_otp = 0; /* SSC output port */ -int32 tmr_csr[2] = { 0 }; /* SSC timers */ -uint32 tmr_tir[2] = { 0 }; /* curr interval */ -uint32 tmr_tnir[2] = { 0 }; /* next interval */ -int32 tmr_tivr[2] = { 0 }; /* vector */ -uint32 tmr_inc[2] = { 0 }; /* tir increment */ -uint32 tmr_sav[2] = { 0 }; /* saved inst cnt */ -int32 ssc_adsm[2] = { 0 }; /* addr strobes */ -int32 ssc_adsk[2] = { 0 }; -int32 cdg_dat[CDASIZE >> 2]; /* cache data */ -static uint32 rom_delay = 0; - -t_stat rom_ex (t_value *vptr, t_addr exta, UNIT *uptr, int32 sw); -t_stat rom_dep (t_value val, t_addr exta, UNIT *uptr, int32 sw); -t_stat rom_reset (DEVICE *dptr); -t_stat nvr_ex (t_value *vptr, t_addr exta, UNIT *uptr, int32 sw); -t_stat nvr_dep (t_value val, t_addr exta, UNIT *uptr, int32 sw); -t_stat nvr_reset (DEVICE *dptr); -t_stat nvr_attach (UNIT *uptr, char *cptr); -t_stat nvr_detach (UNIT *uptr); -t_stat csi_reset (DEVICE *dptr); -t_stat cso_reset (DEVICE *dptr); -t_stat cso_svc (UNIT *uptr); -t_stat tmr_svc (UNIT *uptr); -t_stat sysd_reset (DEVICE *dptr); - -int32 rom_rd (int32 pa); -int32 nvr_rd (int32 pa); -void nvr_wr (int32 pa, int32 val, int32 lnt); -int32 csrs_rd (void); -int32 csrd_rd (void); -int32 csts_rd (void); -void csrs_wr (int32 dat); -void csts_wr (int32 dat); -void cstd_wr (int32 dat); -int32 cmctl_rd (int32 pa); -void cmctl_wr (int32 pa, int32 val, int32 lnt); -int32 ka_rd (int32 pa); -void ka_wr (int32 pa, int32 val, int32 lnt); -int32 cdg_rd (int32 pa); -void cdg_wr (int32 pa, int32 val, int32 lnt); -int32 ssc_rd (int32 pa); -void ssc_wr (int32 pa, int32 val, int32 lnt); -int32 tmr_tir_rd (int32 tmr, t_bool interp); -void tmr_csr_wr (int32 tmr, int32 val); -void tmr_sched (int32 tmr); -void tmr_incr (int32 tmr, uint32 inc); -int32 tmr0_inta (void); -int32 tmr1_inta (void); -int32 parity (int32 val, int32 odd); - -extern int32 cqmap_rd (int32 pa); -extern void cqmap_wr (int32 pa, int32 val, int32 lnt); -extern int32 cqipc_rd (int32 pa); -extern void cqipc_wr (int32 pa, int32 val, int32 lnt); -extern int32 cqbic_rd (int32 pa); -extern void cqbic_wr (int32 pa, int32 val, int32 lnt); -extern int32 cqmem_rd (int32 pa); -extern void cqmem_wr (int32 pa, int32 val, int32 lnt); -extern int32 iccs_rd (void); -extern int32 todr_rd (void); -extern int32 rxcs_rd (void); -extern int32 rxdb_rd (void); -extern int32 txcs_rd (void); -extern void iccs_wr (int32 dat); -extern void todr_wr (int32 dat); -extern void rxcs_wr (int32 dat); -extern void txcs_wr (int32 dat); -extern void txdb_wr (int32 dat); -extern void ioreset_wr (int32 dat); -extern uint32 sim_os_msec(); - -/* ROM data structures - - rom_dev ROM device descriptor - rom_unit ROM units - rom_reg ROM register list -*/ - -UNIT rom_unit = { UDATA (NULL, UNIT_FIX+UNIT_BINK, ROMSIZE) }; - -REG rom_reg[] = { - { NULL } }; - -MTAB rom_mod[] = { - { UNIT_NODELAY, UNIT_NODELAY, "fast access", "NODELAY", NULL }, - { UNIT_NODELAY, 0, "1usec calibrated access", "DELAY", NULL }, - { 0 } }; - -DEVICE rom_dev = { - "ROM", &rom_unit, rom_reg, rom_mod, - 1, 16, ROMAWIDTH, 4, 16, 32, - &rom_ex, &rom_dep, &rom_reset, - NULL, NULL, NULL, - NULL, 0 }; - -/* NVR data structures - - nvr_dev NVR device descriptor - nvr_unit NVR units - nvr_reg NVR register list -*/ - -UNIT nvr_unit = - { UDATA (NULL, UNIT_FIX+UNIT_BINK, NVRSIZE) }; - -REG nvr_reg[] = { - { NULL } }; - -DEVICE nvr_dev = { - "NVR", &nvr_unit, nvr_reg, NULL, - 1, 16, NVRAWIDTH, 4, 16, 32, - &nvr_ex, &nvr_dep, &nvr_reset, - NULL, &nvr_attach, &nvr_detach, - NULL, 0 }; - -/* CSI data structures - - csi_dev CSI device descriptor - csi_unit CSI unit descriptor - csi_reg CSI register list -*/ - -DIB csi_dib = { 0, 0, NULL, NULL, 1, IVCL (CSI), SCB_CSI, { NULL } }; - -UNIT csi_unit = { UDATA (NULL, 0, 0), KBD_POLL_WAIT }; - -REG csi_reg[] = { - { ORDATA (BUF, csi_unit.buf, 8) }, - { ORDATA (CSR, csi_csr, 16) }, - { FLDATA (INT, int_req[IPL_CSI], INT_V_CSI) }, - { FLDATA (DONE, csi_csr, CSR_V_DONE) }, - { FLDATA (IE, csi_csr, CSR_V_IE) }, - { DRDATA (POS, csi_unit.pos, 32), PV_LEFT }, - { DRDATA (TIME, csi_unit.wait, 24), REG_NZ + PV_LEFT }, - { NULL } }; - -MTAB csi_mod[] = { - { MTAB_XTD|MTAB_VDV, 0, "VECTOR", NULL, NULL, &show_vec }, - { 0 } }; - -DEVICE csi_dev = { - "CSI", &csi_unit, csi_reg, csi_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &csi_reset, - NULL, NULL, NULL, - &csi_dib, 0 }; - -/* CSO data structures - - cso_dev CSO device descriptor - cso_unit CSO unit descriptor - cso_reg CSO register list -*/ - -DIB cso_dib = { 0, 0, NULL, NULL, 1, IVCL (CSO), SCB_CSO, { NULL } }; - -UNIT cso_unit = { UDATA (&cso_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT }; - -REG cso_reg[] = { - { ORDATA (BUF, cso_unit.buf, 8) }, - { ORDATA (CSR, cso_csr, 16) }, - { FLDATA (INT, int_req[IPL_CSO], INT_V_CSO) }, - { FLDATA (DONE, cso_csr, CSR_V_DONE) }, - { FLDATA (IE, cso_csr, CSR_V_IE) }, - { DRDATA (POS, cso_unit.pos, 32), PV_LEFT }, - { DRDATA (TIME, cso_unit.wait, 24), PV_LEFT }, - { NULL } }; - -MTAB cso_mod[] = { - { MTAB_XTD|MTAB_VDV, 0, "VECTOR", NULL, NULL, &show_vec }, - { 0 } }; - -DEVICE cso_dev = { - "CSO", &cso_unit, cso_reg, cso_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &cso_reset, - NULL, NULL, NULL, - &cso_dib, 0 }; - -/* SYSD data structures - - sysd_dev SYSD device descriptor - sysd_unit SYSD units - sysd_reg SYSD register list -*/ - -DIB sysd_dib[] = { 0, 0, NULL, NULL, - 2, IVCL (TMR0), 0, { &tmr0_inta, &tmr1_inta } }; - -UNIT sysd_unit[] = { - { UDATA (&tmr_svc, 0, 0) }, - { UDATA (&tmr_svc, 0, 0) } }; - -REG sysd_reg[] = { - { BRDATA (CMCSR, cmctl_reg, 16, 32, CMCTLSIZE >> 2) }, - { HRDATA (CACR, ka_cacr, 8) }, - { HRDATA (BDR, ka_bdr, 8) }, - { HRDATA (BASE, ssc_base, 29) }, - { HRDATA (CNF, ssc_cnf, 32) }, - { HRDATA (BTO, ssc_bto, 32) }, - { HRDATA (OTP, ssc_otp, 4) }, - { HRDATA (TCSR0, tmr_csr[0], 32) }, - { HRDATA (TIR0, tmr_tir[0], 32) }, - { HRDATA (TNIR0, tmr_tnir[0], 32) }, - { HRDATA (TIVEC0, tmr_tivr[0], 9) }, - { HRDATA (TINC0, tmr_inc[0], 32) }, - { HRDATA (TSAV0, tmr_sav[0], 32) }, - { HRDATA (TCSR1, tmr_csr[1], 32) }, - { HRDATA (TIR1, tmr_tir[1], 32) }, - { HRDATA (TNIR1, tmr_tnir[1], 32) }, - { HRDATA (TIVEC1, tmr_tivr[1], 9) }, - { HRDATA (TINC1, tmr_inc[1], 32) }, - { HRDATA (TSAV1, tmr_sav[1], 32) }, - { HRDATA (ADSM0, ssc_adsm[0], 32) }, - { HRDATA (ADSK0, ssc_adsk[0], 32) }, - { HRDATA (ADSM1, ssc_adsm[1], 32) }, - { HRDATA (ADSK1, ssc_adsk[1], 32) }, - { BRDATA (CDGDAT, cdg_dat, 16, 32, CDASIZE >> 2) }, - { NULL } }; - -DEVICE sysd_dev = { - "SYSD", sysd_unit, sysd_reg, NULL, - 2, 16, 16, 1, 16, 8, - NULL, NULL, &sysd_reset, - NULL, NULL, NULL, - &sysd_dib, 0 }; - -/* ROM: read only memory - stored in a buffered file - Register space access routines see ROM twice - - ROM access has been 'regulated' to about 1Mhz to avoid issues - with testing the interval timers in self-test. Specifically, - the VAX boot ROM (ka655.bin) contains code which presumes that - the VAX runs at a particular slower speed when code is running - from ROM (which is not cached). These assumptions are built - into instruction based timing loops. As the host platform gets - much faster than the original VAX, the assumptions embedded in - these code loops are no longer valid. - - Code has been added to the ROM implementation to limit CPU speed - to about 500K instructions per second. This heads off any future - issues with the embedded timing loops. -*/ - -int32 rom_swapb(int32 val) -{ -return ((val << 24) & 0xff000000) | (( val << 8) & 0xff0000) | - ((val >> 8) & 0xff00) | ((val >> 24) & 0xff); -} - -int32 rom_read_delay (int32 val) -{ -uint32 i, l = rom_delay; -int32 loopval = 0; - -if (rom_unit.flags & UNIT_NODELAY) return val; - -/* Calibrate the loop delay factor when first used. - Do this 4 times to and use the largest value computed. */ - -if (rom_delay == 0) { - uint32 ts, te, c = 10000, samples = 0; - while (1) { - c = c * 2; - te = sim_os_msec(); - while (te == (ts = sim_os_msec ())); /* align on ms tick */ - -/* This is merely a busy wait with some "work" that won't get optimized - away by a good compiler. loopval always is zero. To avoid smart compilers, - the loopval variable is referenced in the function arguments so that the - function expression is not loop invariant. It also must be referenced - by subsequent code or to avoid the whole computation being eliminated. */ - - for (i = 0; i < c; i++) - loopval |= (loopval + ts) ^ rom_swapb (rom_swapb (loopval + ts)); - te = sim_os_msec (); - if ((te - ts) < 50) continue; /* sample big enough? */ - if (rom_delay < (loopval + (c / (te - ts) / 1000) + 1)) - rom_delay = loopval + (c / (te - ts) / 1000) + 1; - if (++samples >= 4) break; - c = c / 2; } - if (rom_delay < 5) rom_delay = 5; } - -for (i = 0; i < l; i++) - loopval |= (loopval + val) ^ rom_swapb (rom_swapb (loopval + val)); -return val + loopval; -} - -int32 rom_rd (int32 pa) -{ -int32 rg = ((pa - ROMBASE) & ROMAMASK) >> 2; - -return rom_read_delay (rom[rg]); -} - -void rom_wr (int32 pa, int32 val, int32 lnt) -{ -int32 rg = ((pa - ROMBASE) & ROMAMASK) >> 2; - -if (lnt < L_LONG) { /* byte or word? */ - int32 sc = (pa & 3) << 3; /* merge */ - int32 mask = (lnt == L_WORD)? 0xFFFF: 0xFF; - rom[rg] = ((val & mask) << sc) | (rom[rg] & ~(mask << sc)); } -else rom[rg] = val; -return; -} - -/* ROM examine */ - -t_stat rom_ex (t_value *vptr, t_addr exta, UNIT *uptr, int32 sw) -{ -uint32 addr = (uint32) exta; - -if ((vptr == NULL) || (addr & 03)) return SCPE_ARG; -if (addr >= ROMSIZE) return SCPE_NXM; -*vptr = rom[addr >> 2]; -return SCPE_OK; -} - -/* ROM deposit */ - -t_stat rom_dep (t_value val, t_addr exta, UNIT *uptr, int32 sw) -{ -uint32 addr = (uint32) exta; - -if (addr & 03) return SCPE_ARG; -if (addr >= ROMSIZE) return SCPE_NXM; -rom[addr >> 2] = (uint32) val; -return SCPE_OK; -} - -/* ROM reset */ - -t_stat rom_reset (DEVICE *dptr) -{ -if (rom == NULL) rom = calloc (ROMSIZE >> 2, sizeof (int32)); -if (rom == NULL) return SCPE_MEM; -return SCPE_OK; -} - -/* NVR: non-volatile RAM - stored in a buffered file */ - -int32 nvr_rd (int32 pa) -{ -int32 rg = (pa - NVRBASE) >> 2; - -return nvr[rg]; -} - -void nvr_wr (int32 pa, int32 val, int32 lnt) -{ -int32 rg = (pa - NVRBASE) >> 2; - -if (lnt < L_LONG) { /* byte or word? */ - int32 sc = (pa & 3) << 3; /* merge */ - int32 mask = (lnt == L_WORD)? 0xFFFF: 0xFF; - nvr[rg] = ((val & mask) << sc) | (nvr[rg] & ~(mask << sc)); } -else nvr[rg] = val; -return; -} - -/* NVR examine */ - -t_stat nvr_ex (t_value *vptr, t_addr exta, UNIT *uptr, int32 sw) -{ -uint32 addr = (uint32) exta; - -if ((vptr == NULL) || (addr & 03)) return SCPE_ARG; -if (addr >= NVRSIZE) return SCPE_NXM; -*vptr = nvr[addr >> 2]; -return SCPE_OK; -} - -/* NVR deposit */ - -t_stat nvr_dep (t_value val, t_addr exta, UNIT *uptr, int32 sw) -{ -uint32 addr = (uint32) exta; - -if (addr & 03) return SCPE_ARG; -if (addr >= NVRSIZE) return SCPE_NXM; -nvr[addr >> 2] = (uint32) val; -return SCPE_OK; -} - -/* NVR reset */ - -t_stat nvr_reset (DEVICE *dptr) -{ -if (nvr == NULL) { - nvr = calloc (NVRSIZE >> 2, sizeof (int32)); - nvr_unit.filebuf = nvr; - ssc_cnf = ssc_cnf | SSCCNF_BLO; } -if (nvr == NULL) return SCPE_MEM; -return SCPE_OK; -} - -/* NVR attach */ - -t_stat nvr_attach (UNIT *uptr, char *cptr) -{ -t_stat r; - -uptr->flags = uptr->flags | (UNIT_ATTABLE | UNIT_BUFABLE); -r = attach_unit (uptr, cptr); -if (r != SCPE_OK) - uptr->flags = uptr->flags & ~(UNIT_ATTABLE | UNIT_BUFABLE); -else { uptr->hwmark = uptr->capac; - ssc_cnf = ssc_cnf & ~SSCCNF_BLO; } -return r; -} - -/* NVR detach */ - -t_stat nvr_detach (UNIT *uptr) -{ -t_stat r; - -r = detach_unit (uptr); -if ((uptr->flags & UNIT_ATT) == 0) - uptr->flags = uptr->flags & ~(UNIT_ATTABLE | UNIT_BUFABLE); -return r; -} - -/* CSI: console storage input */ - -int32 csrs_rd (void) -{ -return (csi_csr & CSICSR_IMP); -} - -int32 csrd_rd (void) -{ -csi_csr = csi_csr & ~CSR_DONE; -CLR_INT (CSI); -return (csi_unit.buf & 0377); -} - -void csrs_wr (int32 data) -{ -if ((data & CSR_IE) == 0) CLR_INT (CSI); -else if ((csi_csr & (CSR_DONE + CSR_IE)) == CSR_DONE) - SET_INT (CSI); -csi_csr = (csi_csr & ~CSICSR_RW) | (data & CSICSR_RW); -return; -} - -t_stat csi_reset (DEVICE *dptr) -{ -csi_unit.buf = 0; -csi_csr = 0; -CLR_INT (CSI); -return SCPE_OK; -} - -/* CSO: console storage output */ - -int32 csts_rd (void) -{ -return (cso_csr & CSOCSR_IMP); -} - -void csts_wr (int32 data) -{ -if ((data & CSR_IE) == 0) CLR_INT (CSO); -else if ((cso_csr & (CSR_DONE + CSR_IE)) == CSR_DONE) - SET_INT (CSO); -cso_csr = (cso_csr & ~CSOCSR_RW) | (data & CSOCSR_RW); -return; -} - -void cstd_wr (int32 data) -{ -cso_unit.buf = data & 0377; -cso_csr = cso_csr & ~CSR_DONE; -CLR_INT (CSO); -sim_activate (&cso_unit, cso_unit.wait); -return; -} - -t_stat cso_svc (UNIT *uptr) -{ -cso_csr = cso_csr | CSR_DONE; -if (cso_csr & CSR_IE) SET_INT (CSO); -if ((cso_unit.flags & UNIT_ATT) == 0) return SCPE_OK; -if (putc (cso_unit.buf, cso_unit.fileref) == EOF) { - perror ("CSO I/O error"); - clearerr (cso_unit.fileref); - return SCPE_IOERR; } -cso_unit.pos = cso_unit.pos + 1; -return SCPE_OK; -} - -t_stat cso_reset (DEVICE *dptr) -{ -cso_unit.buf = 0; -cso_csr = CSR_DONE; -CLR_INT (CSO); -sim_cancel (&cso_unit); /* deactivate unit */ -return SCPE_OK; -} - -/* SYSD: SSC access mechanisms and devices - - - IPR space read/write routines - - register space read/write routines - - SSC local register read/write routines - - SSC console storage UART - - SSC timers - - CMCTL local register read/write routines -*/ - -/* Read/write IPR register space - - These routines implement the SSC's response to IPR's which are - sent off the CPU chip for processing. -*/ - -int32 ReadIPR (int32 rg) -{ -int32 val; - -switch (rg) { -case MT_ICCS: /* ICCS */ - val = iccs_rd (); - break; -case MT_CSRS: /* CSRS */ - val = csrs_rd (); - break; -case MT_CSRD: /* CSRD */ - val = csrd_rd (); - break; -case MT_CSTS: /* CSTS */ - val = csts_rd (); - break; -case MT_CSTD: /* CSTD */ - val = 0; - break; -case MT_RXCS: /* RXCS */ - val = rxcs_rd (); - break; -case MT_RXDB: /* RXDB */ - val = rxdb_rd (); - break; -case MT_TXCS: /* TXCS */ - val = txcs_rd (); - break; -case MT_TXDB: /* TXDB */ - val = 0; - break; -case MT_TODR: - val = todr_rd (); - break; -default: - ssc_bto = ssc_bto | SSCBTO_BTO; /* set BTO */ - val = 0; - break; } -return val; -} - -void WriteIPR (int32 rg, int32 val) -{ -switch (rg) { -case MT_ICCS: /* ICCS */ - iccs_wr (val); - break; -case MT_TODR: /* TODR */ - todr_wr (val); - break; -case MT_CSRS: /* CSRS */ - csrs_wr (val); - break; -case MT_CSRD: /* CSRD */ - break; -case MT_CSTS: /* CSTS */ - csts_wr (val); - break; -case MT_CSTD: /* CSTD */ - cstd_wr (val); - break; -case MT_RXCS: /* RXCS */ - rxcs_wr (val); - break; -case MT_RXDB: /* RXDB */ - break; -case MT_TXCS: /* TXCS */ - txcs_wr (val); - break; -case MT_TXDB: /* TXDB */ - txdb_wr (val); - break; -case MT_IORESET: /* IORESET */ - ioreset_wr (val); - break; -default: - ssc_bto = ssc_bto | SSCBTO_BTO; /* set BTO */ - break; } -return; -} - -/* Read/write I/O register space - - These routines are the 'catch all' for address space map. Any - address that doesn't explicitly belong to memory, I/O, or ROM - is given to these routines for processing. -*/ - -struct reglink { /* register linkage */ - int32 low; /* low addr */ - int32 high; /* high addr */ - t_stat (*read)(int32 pa); /* read routine */ - void (*write)(int32 pa, int32 val, int32 lnt); }; /* write routine */ - -struct reglink regtable[] = { - { CQMAPBASE, CQMAPBASE+CQMAPSIZE, &cqmap_rd, &cqmap_wr }, - { ROMBASE, ROMBASE+ROMSIZE+ROMSIZE, &rom_rd, NULL }, - { NVRBASE, NVRBASE+NVRSIZE, &nvr_rd, &nvr_wr }, - { CMCTLBASE, CMCTLBASE+CMCTLSIZE, &cmctl_rd, &cmctl_wr }, - { SSCBASE, SSCBASE+SSCSIZE, &ssc_rd, &ssc_wr }, - { KABASE, KABASE+KASIZE, &ka_rd, &ka_wr }, - { CQBICBASE, CQBICBASE+CQBICSIZE, &cqbic_rd, &cqbic_wr }, - { CQIPCBASE, CQIPCBASE+CQIPCSIZE, &cqipc_rd, &cqipc_wr }, - { CQMBASE, CQMBASE+CQMSIZE, &cqmem_rd, &cqmem_wr }, - { CDGBASE, CDGBASE+CDGSIZE, &cdg_rd, &cdg_wr }, - { 0, 0, NULL, NULL } }; - -/* ReadReg - read register space - - Inputs: - pa = physical address - lnt = length (BWLQ) - ignored - Output: - longword of data -*/ - -int32 ReadReg (int32 pa, int32 lnt) -{ -struct reglink *p; - -for (p = ®table[0]; p->low != 0; p++) { - if ((pa >= p->low) && (pa < p->high) && p->read) - return p->read (pa); } -ssc_bto = ssc_bto | SSCBTO_BTO | SSCBTO_RWT; -MACH_CHECK (MCHK_READ); -return 0; -} - -/* WriteReg - write register space - - Inputs: - pa = physical address - val = data to write, right justified in 32b longword - lnt = length (BWLQ) - Outputs: - none -*/ - -void WriteReg (int32 pa, int32 val, int32 lnt) -{ -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; } } -ssc_bto = ssc_bto | SSCBTO_BTO | SSCBTO_RWT; -MACH_CHECK (MCHK_WRITE); -return; -} - -/* CMCTL registers - - CMCTL00 - 15 configure memory banks 00 - 15. Note that they are - here merely to entertain the firmware; the actual configuration - of memory is unaffected by the settings here. - - CMCTL16 - error status register - - CMCTL17 - control/diagnostic status register - - The CMCTL registers are cleared at power up. -*/ - -int32 cmctl_rd (int32 pa) -{ -int32 rg = (pa - CMCTLBASE) >> 2; - -switch (rg) { -default: /* config reg */ - return cmctl_reg[rg] & CMCNF_MASK; -case 16: /* err status */ - return cmctl_reg[rg]; -case 17: /* csr */ - return cmctl_reg[rg] & CMCSR_MASK; } -return 0; -} - -void cmctl_wr (int32 pa, int32 val, int32 lnt) -{ -int32 i, rg = (pa - CMCTLBASE) >> 2; - -if (lnt < L_LONG) { /* LW write only */ - int32 sc = (pa & 3) << 3; /* shift data to */ - val = val << sc; } /* proper location */ -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; } } - cmctl_reg[rg] = (cmctl_reg[rg] & ~CMCNF_RW) | (val & CMCNF_RW); - break; -case 16: /* err status */ - cmctl_reg[rg] = cmctl_reg[rg] & ~(val & CMERR_W1C); - break; -case 17: /* csr */ - cmctl_reg[rg] = val & CMCSR_MASK; - break; } -return; -} - -/* KA655 registers */ - -int32 ka_rd (int32 pa) -{ -int32 rg = (pa - KABASE) >> 2; - -switch (rg) -{ -case 0: /* CACR */ - return ka_cacr; -case 1: /* BDR */ - return ka_bdr; } -return 0; -} - -void ka_wr (int32 pa, int32 val, int32 lnt) -{ -int32 rg = (pa - KABASE) >> 2; - -if ((rg == 0) && ((pa & 3) == 0)) { /* lo byte only */ - ka_cacr = (ka_cacr & ~(val & CACR_W1C)) | CACR_FIXED; - 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 */ - -int32 cdg_rd (int32 pa) -{ -int32 t, row = CDG_GETROW (pa); - -t = cdg_dat[row]; -ka_cacr = ka_cacr & ~CACR_DRO; /* clear diag */ -ka_cacr = ka_cacr | - (parity ((t >> 24) & 0xFF, 1) << (CACR_V_DPAR + 3)) | - (parity ((t >> 16) & 0xFF, 0) << (CACR_V_DPAR + 2)) | - (parity ((t >> 8) & 0xFF, 1) << (CACR_V_DPAR + 1)) | - (parity (t & 0xFF, 0) << CACR_V_DPAR); -return t; -} - -void cdg_wr (int32 pa, int32 val, int32 lnt) -{ -int32 row = CDG_GETROW (pa); - -if (lnt < L_LONG) { /* byte or word? */ - int32 sc = (pa & 3) << 3; /* merge */ - int32 mask = (lnt == L_WORD)? 0xFFFF: 0xFF; - int32 t = cdg_dat[row]; - val = ((val & mask) << sc) | (t & ~(mask << sc)); } -cdg_dat[row] = val; /* store data */ -return; -} - -int32 parity (int32 val, int32 odd) -{ -for ( ; val != 0; val = val >> 1) { - if (val & 1) odd = odd ^ 1; } -return odd; -} - -/* SSC registers - byte/word merges done in WriteReg */ - -int32 ssc_rd (int32 pa) -{ -int32 rg = (pa - SSCBASE) >> 2; - -switch (rg) { -case 0x00: /* base reg */ - return ssc_base; -case 0x04: /* conf reg */ - return ssc_cnf; -case 0x08: /* bus timeout */ - return ssc_bto; -case 0x0C: /* output port */ - return ssc_otp & SSCOTP_MASK; -case 0x1B: /* TODR */ - return todr_rd (); -case 0x1C: /* CSRS */ - return csrs_rd (); -case 0x1D: /* CSRD */ - return csrd_rd (); -case 0x1E: /* CSTS */ - return csts_rd (); -case 0x20: /* RXCS */ - return rxcs_rd (); -case 0x21: /* RXDB */ - return rxdb_rd (); -case 0x22: /* TXCS */ - return txcs_rd (); -case 0x40: /* T0CSR */ - return tmr_csr[0]; -case 0x41: /* T0INT */ - return tmr_tir_rd (0, FALSE); -case 0x42: /* T0NI */ - return tmr_tnir[0]; -case 0x43: /* T0VEC */ - return tmr_tivr[0]; -case 0x44: /* T1CSR */ - return tmr_csr[1]; -case 0x45: /* T1INT */ - return tmr_tir_rd (1, FALSE); -case 0x46: /* T1NI */ - return tmr_tnir[1]; -case 0x47: /* T1VEC */ - return tmr_tivr[1]; -case 0x4C: /* ADS0M */ - return ssc_adsm[0]; -case 0x4D: /* ADS0K */ - return ssc_adsk[0]; -case 0x50: /* ADS1M */ - return ssc_adsm[1]; -case 0x51: /* ADS1K */ - return ssc_adsk[1]; } -return 0; -} - -void ssc_wr (int32 pa, int32 val, int32 lnt) -{ -int32 rg = (pa - SSCBASE) >> 2; - -if (lnt < L_LONG) { /* byte or word? */ - int32 sc = (pa & 3) << 3; /* merge */ - int32 mask = (lnt == L_WORD)? 0xFFFF: 0xFF; - int32 t = ssc_rd (pa); - val = ((val & mask) << sc) | (t & ~(mask << sc)); } - -switch (rg) { -case 0x00: /* base reg */ - ssc_base = (val & SSCBASE_RW) | SSCBASE_MBO; - break; -case 0x04: /* conf reg */ - ssc_cnf = ssc_cnf & ~(val & SSCCNF_W1C); - ssc_cnf = (ssc_cnf & ~SSCCNF_RW) | (val & SSCCNF_RW); - break; -case 0x08: /* bus timeout */ - ssc_bto = ssc_bto & ~(val & SSCBTO_W1C); - ssc_bto = (ssc_bto & ~SSCBTO_RW) | (val & SSCBTO_RW); - break; -case 0x0C: /* output port */ - ssc_otp = val & SSCOTP_MASK; - break; -case 0x1B: /* TODR */ - todr_wr (val); - break; -case 0x1C: /* CSRS */ - csrs_wr (val); - break; -case 0x1E: /* CSTS */ - csts_wr (val); - break; -case 0x1F: /* CSTD */ - cstd_wr (val); - break; -case 0x20: /* RXCS */ - rxcs_wr (val); - break; -case 0x22: /* TXCS */ - txcs_wr (val); - break; -case 0x23: /* TXDB */ - txdb_wr (val); - break; -case 0x40: /* T0CSR */ - tmr_csr_wr (0, val); - break; -case 0x42: /* T0NI */ - tmr_tnir[0] = val; - break; -case 0x43: /* T0VEC */ - tmr_tivr[0] = val & TMR_VEC_MASK; - break; -case 0x44: /* T1CSR */ - tmr_csr_wr (1, val); - break; -case 0x46: /* T1NI */ - tmr_tnir[1] = val; - break; -case 0x47: /* T1VEC */ - tmr_tivr[1] = val & TMR_VEC_MASK; - break; -case 0x4C: /* ADS0M */ - ssc_adsm[0] = val & SSCADS_MASK; - break; -case 0x4D: /* ADS0K */ - ssc_adsk[0] = val & SSCADS_MASK; - break; -case 0x50: /* ADS1M */ - ssc_adsm[1] = val & SSCADS_MASK; - break; -case 0x51: /* ADS1K */ - ssc_adsk[1] = val & SSCADS_MASK; - break; } -return; -} - -/* Programmable timers - - The SSC timers, which increment at 1Mhz, cannot be accurately - simulated due to the overhead that would be required for 1M - clock events per second. Instead, a gross hack is used. When - a timer is started, the clock interval is inspected. - - if (int < 0 and small) then testing timer, count instructions. - Small is determined by when the requested interval is less - than the size of a 100hz system clock tick. - if (int >= 0 or large) then counting a real interval, schedule - clock events at 100Hz using calibrated line clock delay - and when the remaining time value gets small enough, behave - like the small case above. - - If the interval register is read, then its value between events - is interpolated using the current instruction count versus the - count when the most recent event started, the result is scaled - to the calibrated system clock, unless the interval being timed - is less than a calibrated system clock tick (or the calibrated - clock is running very slowly) at which time the result will be - the elapsed instruction count. - - The powerup TOY Test sometimes fails its tolerance test. This was - due to varying system load causing varying calibration values to be - used at different times while referencing the TIR. While timing long - intervals, we now synchronize the stepping (and calibration) of the - system tick with the opportunity to reference the value. This gives - precise tolerance measurement values (when interval timers are used - to measure the system clock), regardless of other load issues on the - host system which might cause varying values of the system clock's - calibration factor. -*/ - -int32 tmr_tir_rd (int32 tmr, t_bool interp) -{ -uint32 delta; - -if (interp || (tmr_csr[tmr] & TMR_CSR_RUN)) { /* interp, running? */ - delta = sim_grtime () - tmr_sav[tmr]; /* delta inst */ - if ((tmr_inc[tmr] == TMR_INC) && /* scale large int */ - (tmr_poll > TMR_INC)) - delta = (uint32) ((((double) delta) * TMR_INC) / tmr_poll); - if (delta >= tmr_inc[tmr]) delta = tmr_inc[tmr] - 1; - return tmr_tir[tmr] + delta; } -return tmr_tir[tmr]; -} - -void tmr_csr_wr (int32 tmr, int32 val) -{ -if ((tmr < 0) || (tmr > 1)) return; -if ((val & TMR_CSR_RUN) == 0) { /* clearing run? */ - sim_cancel (&sysd_unit[tmr]); /* cancel timer */ - if (tmr_csr[tmr] & TMR_CSR_RUN) /* run 1 -> 0? */ - tmr_tir[tmr] = tmr_tir_rd (tmr, TRUE); } /* update itr */ -tmr_csr[tmr] = tmr_csr[tmr] & ~(val & TMR_CSR_W1C); /* W1C csr */ -tmr_csr[tmr] = (tmr_csr[tmr] & ~TMR_CSR_RW) | /* new r/w */ - (val & TMR_CSR_RW); -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 */ - if (!sim_is_active (&sysd_unit[tmr])) /* not running? */ - 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 */ -if ((tmr_csr[tmr] & (TMR_CSR_DON | TMR_CSR_IE)) != /* update int */ - (TMR_CSR_DON | TMR_CSR_IE)) { - if (tmr) CLR_INT (TMR1); - else CLR_INT (TMR0); } -return; -} - -/* Unit service */ - -t_stat tmr_svc (UNIT *uptr) -{ -int32 tmr = uptr - sysd_dev.units; /* get timer # */ - -tmr_incr (tmr, tmr_inc[tmr]); /* incr timer */ -return SCPE_OK; -} - -/* Timer increment */ - -void tmr_incr (int32 tmr, uint32 inc) -{ -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; - 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 */ - if (tmr_csr[tmr] & TMR_CSR_RUN) { /* run? */ - 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); } } -else { tmr_tir[tmr] = new_tir; /* no, upd tir */ - if (tmr_csr[tmr] & TMR_CSR_RUN) /* still running? */ - tmr_sched (tmr); } /* reactivate */ -return; -} - -/* Timer scheduling */ - -void tmr_sched (int32 tmr) -{ -int32 clk_time = sim_is_active (&clk_unit) - 1; -int32 tmr_time; - -tmr_sav[tmr] = sim_grtime (); /* save intvl base */ -if (tmr_tir[tmr] > (0xFFFFFFFFu - TMR_INC)) { /* short interval? */ - tmr_inc[tmr] = (~tmr_tir[tmr] + 1); /* inc = interval */ - tmr_time = tmr_inc[tmr]; } -else { tmr_inc[tmr] = TMR_INC; /* usec/interval */ - tmr_time = tmr_poll; } -if (tmr_time == 0) tmr_time = 1; -if ((tmr_inc[tmr] = TMR_INC) && (tmr_time > clk_time)) { - -/* Align scheduled event to be identical to the event for the next clock - tick. This lets us always see a consistent calibrated value, both for - this scheduling, AND for any query of the current timer register that - may happen in tmr_tir_rd (). This presumes that sim_activate will - queue the interval timer behind the event for the clock tick. */ - - tmr_inc[tmr] = (uint32) (((double) clk_time * TMR_INC) / tmr_poll); - tmr_time = clk_time; } -sim_activate (&sysd_unit[tmr], tmr_time); -return; -} - -int32 tmr0_inta (void) -{ -return tmr_tivr[0]; -} - -int32 tmr1_inta (void) -{ -return tmr_tivr[1]; -} - -/* SYSD reset */ - -t_stat sysd_reset (DEVICE *dptr) -{ -int32 i; - -for (i = 0; i < 2; i++) { - tmr_csr[i] = tmr_tnir[i] = tmr_tir[i] = 0; - tmr_inc[i] = tmr_sav[i] = 0; - sim_cancel (&sysd_unit[i]); } -csi_csr = 0; -csi_unit.buf = 0; -sim_cancel (&csi_unit); -CLR_INT (CSI); -cso_csr = CSR_DONE; -cso_unit.buf = 0; -sim_cancel (&cso_unit); -CLR_INT (CSO); -return SCPE_OK; -} - -/* SYSD powerup */ - -t_stat sysd_powerup (void) -{ -int32 i; - -for (i = 0; i < (CMCTLSIZE >> 2); i++) cmctl_reg[i] = 0; -for (i = 0; i < 2; i++) { - tmr_tivr[i] = 0; - ssc_adsm[i] = ssc_adsk[i] = 0; } -ka_cacr = 0; -ssc_base = SSCBASE; -ssc_cnf = ssc_cnf & SSCCNF_BLO; -ssc_bto = 0; -ssc_otp = 0; -return sysd_reset (&sysd_dev); -} - diff --git a/VAX/vaxmod_defs.h b/VAX/vaxmod_defs.h deleted file mode 100644 index 66a72894..00000000 --- a/VAX/vaxmod_defs.h +++ /dev/null @@ -1,410 +0,0 @@ -/* vaxmod_defs.h: VAX model-specific definitions file - - Copyright (c) 1998-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. - - 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 - 06-Sep-02 RMS Added TMSCP support - 14-Jul-02 RMS Added additional console halt codes - 28-Apr-02 RMS Fixed DZV vector base and number of lines - - This file covers the KA65x ("Mayfair") series of CVAX-based Qbus systems. - - System memory map - - 0000 0000 - 03FF FFFF main memory - 0400 0000 - 0FFF FFFF reserved - 1000 0000 - 13FF FFFF secondary cache diagnostic space - 1400 0000 - 1FFF FFFF reserved - - 2000 0000 - 2000 1FFF Qbus I/O page - 2000 2000 - 2003 FFFF reserved - 2004 0000 - 2005 FFFF ROM space, halt protected - 2006 0000 - 2007 FFFF ROM space, halt unprotected - 2008 0000 - 201F FFFF Local register space - 2020 0000 - 2FFF FFFF reserved - 3000 0000 - 303F FFFF Qbus memory space - 3400 0000 - 3FFF FFFF reserved -*/ - -/* Microcode constructs */ - -#define CVAX_SID (10 << 24) /* system ID */ -#define CVAX_UREV 6 /* ucode revision */ -#define CON_HLTPIN 0x0200 /* external CPU halt */ -#define CON_PWRUP 0x0300 /* powerup code */ -#define CON_HLTINS 0x0600 /* HALT instruction */ -#define CON_BADPSL 0x4000 /* invalid PSL flag */ -#define CON_MAPON 0x8000 /* mapping on flag */ -#define MCHK_TBM_P0 0x05 /* PPTE in P0 */ -#define MCHK_TBM_P1 0x06 /* PPTE in P1 */ -#define MCHK_M0_P0 0x07 /* PPTE in P0 */ -#define MCHK_M0_P1 0x08 /* PPTE in P1 */ -#define MCHK_INTIPL 0x09 /* invalid ireq */ -#define MCHK_READ 0x80 /* read check */ -#define MCHK_WRITE 0x82 /* write check */ - -/* Memory system error register */ - -#define MSER_HM 0x80 /* hit/miss */ -#define MSER_CPE 0x40 /* CDAL par err */ -#define MSER_CPM 0x20 /* CDAL mchk */ - -/* Cache disable register */ - -#define CADR_RW 0xF3 -#define CADR_MBO 0x0C - -/* Memory */ - -#define MAXMEMWIDTH 26 /* max mem addr width */ -#define MAXMEMSIZE (1 << MAXMEMWIDTH) /* max mem size */ -#define MAXMEMMASK (MAXMEMSIZE - 1) /* max mem addr mask */ -#define INITMEMSIZE (1 << 24) /* initial memory size */ -#define MEMSIZE (cpu_unit.capac) -#define ADDR_IS_MEM(x) (((uint32) (x)) < MEMSIZE) - -/* Cache diagnostic space */ - -#define CDAAWIDTH 16 /* cache dat addr width */ -#define CDASIZE (1u << CDAAWIDTH) /* cache dat length */ -#define CDAMASK (CDASIZE - 1) /* cache dat mask */ -#define CTGAWIDTH 10 /* cache tag addr width */ -#define CTGSIZE (1u << CTGAWIDTH) /* cache tag length */ -#define CTGMASK (CTGSIZE - 1) /* cache tag mask */ -#define CDGSIZE (CDASIZE * CTGSIZE) /* diag addr length */ -#define CDGBASE 0x10000000 /* diag addr base */ -#define CDG_GETROW(x) (((x) & CDAMASK) >> 2) -#define CDG_GETTAG(x) (((x) >> CDAAWIDTH) & CTGMASK) -#define CTG_V (1u << (CTGAWIDTH + 0)) /* tag valid */ -#define CTG_WP (1u << (CTGAWIDTH + 1)) /* wrong parity */ -#define ADDR_IS_CDG(x) ((((uint32) (x)) >= CDGBASE) && \ - (((uint32) (x)) < (CDGBASE + CDGSIZE))) - -/* Qbus I/O registers */ - -#define IOPAGEAWIDTH 13 /* IO addr width */ -#define IOPAGESIZE (1u << IOPAGEAWIDTH) /* IO page length */ -#define IOPAGEMASK (IOPAGESIZE - 1) /* IO addr mask */ -#define IOPAGEBASE 0x20000000 /* IO page base */ -#define ADDR_IS_IO(x) ((((uint32) (x)) >= IOPAGEBASE) && \ - (((uint32) (x)) < (IOPAGEBASE + IOPAGESIZE))) - -/* Read only memory - appears twice */ - -#define ROMAWIDTH 17 /* ROM addr width */ -#define ROMSIZE (1u << ROMAWIDTH) /* ROM length */ -#define ROMAMASK (ROMSIZE - 1) /* ROM addr mask */ -#define ROMBASE 0x20040000 /* ROM base */ -#define ADDR_IS_ROM(x) ((((uint32) (x)) >= ROMBASE) && \ - (((uint32) (x)) < (ROMBASE + ROMSIZE + ROMSIZE))) - -/* Local register space */ - -#define REGAWIDTH 19 /* REG addr width */ -#define REGSIZE (1u << REGAWIDTH) /* REG length */ -#define REGBASE 0x20080000 /* REG addr base */ - -/* KA655 board registers */ - -#define KAAWIDTH 3 /* KA reg width */ -#define KASIZE (1u << KAAWIDTH) /* KA reg length */ -#define KABASE (REGBASE + 0x4000) /* KA650 addr base */ - -/* CQBIC registers */ - -#define CQBICSIZE (5 << 2) /* 5 registers */ -#define CQBICBASE (REGBASE) /* CQBIC addr base */ -#define CQMAPASIZE 15 /* map addr width */ -#define CQMAPSIZE (1u << CQMAPASIZE) /* map length */ -#define CQMAPAMASK (CQMAPSIZE - 1) /* map addr mask */ -#define CQMAPBASE (REGBASE + 0x8000) /* map addr base */ -#define CQIPCSIZE 2 /* 2 bytes only */ -#define CQIPCBASE (REGBASE + 0x1F40) /* ipc reg addr */ - -/* CMCTL registers */ - -#define CMCTLSIZE (18 << 2) /* 18 registers */ -#define CMCTLBASE (REGBASE + 0x100) /* CMCTL addr base */ - -/* SSC registers */ - -#define SSCSIZE 0x150 /* SSC size */ -#define SSCBASE 0x20140000 /* SSC base */ - -/* Non-volatile RAM - 1KB long */ - -#define NVRAWIDTH 10 /* NVR addr width */ -#define NVRSIZE (1u << NVRAWIDTH) /* NVR length */ -#define NVRAMASK (NVRSIZE - 1) /* NVR addr mask */ -#define NVRBASE 0x20140400 /* NVR base */ -#define ADDR_IS_NVR(x) ((((uint32) (x)) >= NVRBASE) && \ - (((uint32) (x)) < (NVRBASE + NVRSIZE))) - -/* CQBIC Qbus memory space (seen from CVAX) */ - -#define CQMAWIDTH 22 /* Qmem addr width */ -#define CQMSIZE (1u << CQMAWIDTH) /* Qmem length */ -#define CQMAMASK (CQMSIZE - 1) /* Qmem addr mask */ -#define CQMBASE 0x30000000 /* Qmem base */ - -/* Qbus I/O modes */ - -#define READ 0 /* PDP-11 compatibility */ -#define WRITE (L_WORD) -#define WRITEB (L_BYTE) - -/* Common CSI flags */ - -#define CSR_V_GO 0 /* go */ -#define CSR_V_IE 6 /* interrupt enable */ -#define CSR_V_DONE 7 /* done */ -#define CSR_V_BUSY 11 /* busy */ -#define CSR_V_ERR 15 /* error */ -#define CSR_GO (1u << CSR_V_GO) -#define CSR_IE (1u << CSR_V_IE) -#define CSR_DONE (1u << CSR_V_DONE) -#define CSR_BUSY (1u << CSR_V_BUSY) -#define CSR_ERR (1u << CSR_V_ERR) - -/* Timers */ - -#define TMR_CLK 0 /* 100Hz clock */ - -/* I/O system definitions */ - -#define DZ_MUXES 4 /* max # of muxes */ -#define DZ_LINES 4 /* (DZV) lines per mux */ -#define MT_MAXFR (1 << 16) /* magtape max rec */ -#define AUTO_LNT 34 /* autoconfig ranks */ -#define DIB_MAX 100 /* max DIBs */ - -#define DEV_V_UBUS (DEV_V_UF + 0) /* Unibus */ -#define DEV_V_QBUS (DEV_V_UF + 1) /* Qbus */ -#define DEV_V_FLTA (DEV_V_UF + 2) /* flt addr */ -#define DEV_UBUS (1u << DEV_V_UBUS) -#define DEV_QBUS (1u << DEV_V_QBUS) -#define DEV_FLTA (1u << DEV_V_FLTA) - -#define UNIBUS FALSE /* 22b only */ - -#define DEV_RDX 16 /* default device radix */ - -/* Device information block */ - -#define VEC_DEVMAX 4 /* max device vec */ - -struct pdp_dib { - uint32 ba; /* base addr */ - uint32 lnt; /* length */ - t_stat (*rd)(int32 *dat, int32 ad, int32 md); - t_stat (*wr)(int32 dat, int32 ad, int32 md); - int32 vnum; /* vectors: number */ - int32 vloc; /* locator */ - int32 vec; /* value */ - int32 (*ack[VEC_DEVMAX])(void); /* ack routine */ -}; - -typedef struct pdp_dib DIB; - -/* I/O page layout - RQB,RQC,RQD float based on number of DZ's */ - -#define IOBA_DZ (IOPAGEBASE + 000100) /* DZ11 */ -#define IOLN_DZ 010 -#define IOBA_RQB (IOPAGEBASE + 000334 + (020 * (DZ_MUXES / 2))) -#define IOLN_RQB 004 -#define IOBA_RQC (IOPAGEBASE + IOBA_RQB + IOLN_RQB) -#define IOLN_RQC 004 -#define IOBA_RQD (IOPAGEBASE + IOBA_RQC + IOLN_RQC) -#define IOLN_RQD 004 -#define IOBA_RQ (IOPAGEBASE + 012150) /* RQDX3 */ -#define IOLN_RQ 004 -#define IOBA_TS (IOPAGEBASE + 012520) /* TS11 */ -#define IOLN_TS 004 -#define IOBA_RL (IOPAGEBASE + 014400) /* RL11 */ -#define IOLN_RL 012 -#define IOBA_XQ (IOPAGEBASE + 014440) /* DEQNA/DELQA */ -#define IOLN_XQ 020 -#define IOBA_XQB (IOPAGEBASE + 014460) /* 2nd DEQNA/DELQA */ -#define IOLN_XQB 020 -#define IOBA_TQ (IOPAGEBASE + 014500) /* TMSCP */ -#define IOLN_TQ 004 -#define IOBA_RP (IOPAGEBASE + 016700) /* RP/RM */ -#define IOLN_RP 054 -#define IOBA_DBL (IOPAGEBASE + 017500) /* doorbell */ -#define IOLN_DBL 002 -#define IOBA_LPT (IOPAGEBASE + 017514) /* LP11 */ -#define IOLN_LPT 004 -#define IOBA_PTR (IOPAGEBASE + 017550) /* PC11 reader */ -#define IOLN_PTR 004 -#define IOBA_PTP (IOPAGEBASE + 017554) /* PC11 punch */ -#define IOLN_PTP 004 - -/* The KA65x maintains 4 separate hardware IPL levels, IPL 17 to IPL 14 - Within each IPL, priority is right to left -*/ - -/* IPL 17 */ - -/* IPL 16 */ - -#define INT_V_CLK 0 /* clock */ - -/* IPL 15 */ - -#define INT_V_RQ 0 /* RQDX3 */ -#define INT_V_RL 1 /* RLV12/RL02 */ -#define INT_V_DZRX 2 /* DZ11 */ -#define INT_V_DZTX 3 -#define INT_V_RP 4 /* RP,RM drives */ -#define INT_V_TS 5 /* TS11/TSV05 */ -#define INT_V_TQ 6 /* TMSCP */ -#define INT_V_XQ 7 /* DEQNA/DELQA */ - -/* IPL 14 */ - -#define INT_V_TTI 0 /* console */ -#define INT_V_TTO 1 -#define INT_V_PTR 2 /* PC11 */ -#define INT_V_PTP 3 -#define INT_V_LPT 4 /* LP11 */ -#define INT_V_CSI 5 /* SSC cons UART */ -#define INT_V_CSO 6 -#define INT_V_TMR0 7 /* SSC timers */ -#define INT_V_TMR1 8 - -#define INT_CLK (1u << INT_V_CLK) -#define INT_RQ (1u << INT_V_RQ) -#define INT_RL (1u << INT_V_RL) -#define INT_DZRX (1u << INT_V_DZRX) -#define INT_DZTX (1u << INT_V_DZTX) -#define INT_RP (1u << INT_V_RP) -#define INT_TS (1u << INT_V_TS) -#define INT_TQ (1u << INT_V_TQ) -#define INT_XQ (1u << INT_V_XQ) -#define INT_TTI (1u << INT_V_TTI) -#define INT_TTO (1u << INT_V_TTO) -#define INT_PTR (1u << INT_V_PTR) -#define INT_PTP (1u << INT_V_PTP) -#define INT_LPT (1u << INT_V_LPT) -#define INT_CSI (1u << INT_V_CSI) -#define INT_CSO (1u << INT_V_CSO) -#define INT_TMR0 (1u << INT_V_TMR0) -#define INT_TMR1 (1u << INT_V_TMR1) - -#define IPL_CLK (0x16 - IPL_HMIN) /* relative IPL */ -#define IPL_RQ (0x15 - IPL_HMIN) -#define IPL_RL (0x15 - IPL_HMIN) -#define IPL_DZRX (0x15 - IPL_HMIN) -#define IPL_DZTX (0x15 - IPL_HMIN) -#define IPL_RP (0x15 - IPL_HMIN) -#define IPL_TS (0x15 - IPL_HMIN) -#define IPL_TQ (0x15 - IPL_HMIN) -#define IPL_XQ (0x15 - IPL_HMIN) -#define IPL_TTI (0x14 - IPL_HMIN) -#define IPL_TTO (0x14 - IPL_HMIN) -#define IPL_PTR (0x14 - IPL_HMIN) -#define IPL_PTP (0x14 - IPL_HMIN) -#define IPL_LPT (0x14 - IPL_HMIN) -#define IPL_CSI (0x14 - IPL_HMIN) -#define IPL_CSO (0x14 - IPL_HMIN) -#define IPL_TMR0 (0x14 - IPL_HMIN) -#define IPL_TMR1 (0x14 - IPL_HMIN) - -#define IPL_HMAX 0x17 /* highest hwre level */ -#define IPL_HMIN 0x14 /* lowest hwre level */ -#define IPL_HLVL (IPL_HMAX - IPL_HMIN + 1) /* # hardware levels */ -#define IPL_SMAX 0xF /* highest swre level */ - -/* Device vectors */ - -#define VEC_Q 0x200 /* Qbus vector offset */ -#define VEC_PTR (VEC_Q + 0070) -#define VEC_PTP (VEC_Q + 0074) -#define VEC_XQ (VEC_Q + 0120) -#define VEC_RQ (VEC_Q + 0154) -#define VEC_RL (VEC_Q + 0160) -#define VEC_LPT (VEC_Q + 0200) -#define VEC_TS (VEC_Q + 0224) -#define VEC_RP (VEC_Q + 0254) -#define VEC_TQ (VEC_Q + 0260) -#define VEC_DZRX (VEC_Q + 0300) -#define VEC_DZTX (VEC_Q + 0304) - -/* Autoconfigure ranks */ - -#define RANK_DZ 8 -#define RANK_RL 14 -#define RANK_RQ 26 -#define RANK_TQ 30 - -/* Interrupt macros */ - -#define IVCL(dv) ((IPL_##dv * 32) + INT_V_##dv) -#define IREQ(dv) int_req[IPL_##dv] -#define SET_INT(dv) int_req[IPL_##dv] = int_req[IPL_##dv] | (INT_##dv) -#define CLR_INT(dv) int_req[IPL_##dv] = int_req[IPL_##dv] & ~(INT_##dv) -#define IORETURN(f,v) ((f)? (v): SCPE_OK) /* cond error return */ - -/* Logging */ - -#define LOG_CPU_I 0x0001 /* intexc */ -#define LOG_CPU_R 0x0002 /* REI */ -#define LOG_CPU_P 0x0004 /* context */ -#define LOG_CPU_H 0x0008 /* history */ -#define LOG_RP 0x0010 -#define LOG_TS 0x0020 -#define LOG_RQ 0x0040 -#define LOG_TQ 0x0080 -#define LOG_XQ0 0x0100 -#define LOG_XQ1 0x0200 -#define LOG_XQ2 0x0400 -#define LOG_XQ3 0x0800 - -#define DBG_LOG(x) (sim_log && (cpu_log & (x))) - -/* Function prototypes for I/O */ - -t_bool map_addr (uint32 qa, uint32 *ma); -int32 map_readB (uint32 ba, int32 bc, uint8 *buf); -int32 map_readW (uint32 ba, int32 bc, uint16 *buf); -int32 map_readL (uint32 ba, int32 bc, uint32 *buf); -int32 map_writeB (uint32 ba, int32 bc, uint8 *buf); -int32 map_writeW (uint32 ba, int32 bc, uint16 *buf); -int32 map_writeL (uint32 ba, int32 bc, uint32 *buf); - -#define Map_Addr(a,b) map_addr (a, b) -#define Map_ReadB(a,b,c,d) map_readB (a, b, c) -#define Map_ReadW(a,b,c,d) map_readW (a, b, c) -#define Map_WriteB(a,b,c,d) map_writeB (a, b, c) -#define Map_WriteW(a,b,c,d) map_writeW (a, b, c) - -t_stat set_addr (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat show_addr (FILE *st, UNIT *uptr, int32 val, void *desc); -t_stat set_addr_flt (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat set_vec (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat show_vec (FILE *st, UNIT *uptr, int32 val, void *desc); -t_stat auto_config (uint32 rank, uint32 num); diff --git a/build_mingw.bat b/build_mingw.bat deleted file mode 100644 index eaad7353..00000000 --- a/build_mingw.bat +++ /dev/null @@ -1,14 +0,0 @@ -@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 -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 deleted file mode 100644 index 6d7b9282..00000000 --- a/build_mingw_ether.bat +++ /dev/null @@ -1,15 +0,0 @@ -@echo off -rem 12-Nov-02 rms Ethernet support -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 -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/descrip.mms b/descrip.mms deleted file mode 100644 index 81c7c01e..00000000 --- a/descrip.mms +++ /dev/null @@ -1,1023 +0,0 @@ -# -# DESCRIP.MMS -# Written By: Robert Alan Byer -# byer@mail.ourservers.net -# -# Modified By: Mark Pizzolato -# mark@infocomm.com -# -# 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. -# CLEAN Will Clean Files Back To Base Kit. -# -# To build with debugging enabled (which will also enable traceback -# information) use.. -# -# MMK/FORCE/MACRO=(DEBUG=1) -# -# This will produce an executable named {Simulator}-{VAX|AXP}-DBG.EXE -# - -# -# 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=ALL -LINK_DEBUG = /DEBUG/TRACEBACK -CC_OPTIMIZE = /NOOPTIMIZE -.IFDEF __ALPHA__ -CC_FLAGS = /PREFIX=ALL -ARCH = AXP-DBG -.ELSE -ARCH = VAX-DBG -CC_FLAGS = $(CC_FLAGS) -.ENDIF -.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 -CC_FLAGS = $(CC_FLAGS) -.ENDIF -.ENDIF - -# -# Define Our Compiler Flags -# -CC_FLAGS = $(CC_FLAGS)$(CC_DEBUG)$(CC_OPTIMIZE)/NEST=PRIMARY/NAME=(AS_IS,SHORTENED) - -# -# Define The Compile Command. -# -CC = CC/DECC$(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_DIR)SIM_TAPE.C -SIMH_OBJS = $(SIMH_DIR)SCP_TTY.OBJ,$(SIMH_DIR)SIM_SOCK.OBJ,\ - $(SIMH_DIR)SIM_TMXR.OBJ,$(SIMH_DIR)SIM_ETHER.OBJ,\ - $(SIMH_DIR)SIM_TAPE.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.OBJ,\ - $(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_DIR)IBM1130_FMT.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_DIR)IBM1130_FMT.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_DIR)PDP18B_RB.C,$(PDP18B_DIR)PDP18B_FPP.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,\ - $(PDP18B_DIR)PDP18B_RB.OBJ,$(PDP18B_DIR)PDP18B_FPP.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))/DEFINE=("VM_PDP11=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_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_XTND.C,\ - $(PDP10_DIR)PDP10_RP.C,$(PDP10_DIR)PDP10_SYS.C,\ - $(PDP10_DIR)PDP10_TIM.C,$(PDP10_DIR)PDP10_TU.C,\ - $(PDP11_DIR)PDP11_PT.C,$(PDP11_DIR)PDP11_DZ.C,\ - $(PDP11_DIR)PDP11_RY.C,$(PDP11_DIR)PDP11_XU.C -PDP10_OBJS = $(PDP10_DIR)PDP10_FE.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_XTND.OBJ,\ - $(PDP10_DIR)PDP10_RP.OBJ,$(PDP10_DIR)PDP10_SYS.OBJ,\ - $(PDP10_DIR)PDP10_TIM.OBJ,$(PDP10_DIR)PDP10_TU.OBJ,\ - $(PDP10_DIR)PDP11_PT.OBJ,$(PDP10_DIR)PDP11_DZ.OBJ,\ - $(PDP10_DIR)PDP11_RY.OBJ,$(PDP10_DIR)PDP11_XU.OBJ -PDP10_OPTIONS = /INCLUDE=($(SIMH_DIR),$(PDP10_DIR),$(PDP11_DIR))/DEFINE=("USE_INT64=1","VM_PDP10=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 -# -# If On Alpha, Define "USE_INT64" As We Have INT64. -# -.IFDEF __ALPHA__ -VAX_OPTIONS = /INCLUDE=($(SIMH_DIR),$(VAX_DIR),$(PDP11_DIR))/DEFINE=("USE_INT64=1","VM_VAX=1") -.ELSE -# -# We Are On A VAX Platform So Don't Define "USE_INT64" As We Don't Have -# INT64. -# -VAX_OPTIONS = /INCLUDE=($(SIMH_DIR),$(VAX_DIR),$(PDP11_DIR))/DEFINE=("VM_VAX=1") -.ENDIF - -# -# 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 VAX SDS -.ELSE -# -# Else We Are On VAX And Build Everything EXCEPT The PDP-10 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 VAX SDS -.ENDIF - -CLEAN : - $! - $! Clean out all targets and building Remnants - $! - $ IF (F$SEARCH("$(BIN_DIR)*.EXE;*").NES."") THEN - - DELETE/NOLOG/NOCONFIRM $(BIN_DIR)*.EXE;* - $ IF (F$SEARCH("$(LIB_DIR)*.EXE;*").NES."") THEN - - DELETE/NOLOG/NOCONFIRM $(LIB_DIR)*.OLB;* - $ IF (F$SEARCH("SYS$DISK:[...]*.OBJ;*").NES."") THEN - - DELETE/NOLOG/NOCONFIRM SYS$DISK:[...]*.OBJ;* - -# -# 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. -# -$(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;* - -# -# 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;* - -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;* diff --git a/makefile b/makefile deleted file mode 100644 index f3c30c92..00000000 --- a/makefile +++ /dev/null @@ -1,340 +0,0 @@ -# CC Command -# -# Note: -O2 is sometimes broken in GCC when setjump/longjump is being -# used. Try -O2 only with released simulators. -# -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 - - -# -# Common Libraries -# -BIN = BIN/ -SIM = scp.c scp_tty.c sim_sock.c sim_tmxr.c sim_ether.c sim_tape.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 ${PDP1D}pdp1_drm.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_rb.c ${PDP18BD}pdp18b_tt1.c ${PDP18BD}pdp18b_fpp.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 ${PDP11D}pdp11_xu.c -PDP11_OPT = -DVM_PDP11 -I ${PDP11D} ${NETWORK_OPT} - - - -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 = -DVM_VAX -DUSE_INT64 -I ${VAXD} -I ${PDP11D} ${NETWORK_OPT} - - - -PDP10D = PDP10/ -PDP10 = ${PDP10D}pdp10_fe.c ${PDP11D}pdp11_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 \ - ${PDP11D}pdp11_pt.c ${PDP11D}pdp11_ry.c ${PDP11D}pdp11_xu.c -PDP10_OPT = -DVM_PDP10 -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 \ - ${HP2100D}hp2100_ipl.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 \ - ${IBM1130D}ibm1130_fmt.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 ${ID16D}id16_dboot.c ${ID16D}id_ttp.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 ${ID32D}id32_dboot.c ${ID32D}id_ttp.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${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} - -all : ${ALL} - -clean : -ifeq ($(WIN32),) - ${RM} ${ALL} -else - if exist BIN\*.exe del /q BIN\*.exe -endif -# -# Individual builds -# -${BIN}pdp1${EXE} : ${PDP1} ${SIM} - ${CC} ${PDP1} ${SIM} ${PDP1_OPT} -o $@ ${LDFLAGS} - - - -${BIN}pdp4${EXE} : ${PDP18B} ${SIM} - ${CC} ${PDP18B} ${SIM} ${PDP4_OPT} -o $@ ${LDFLAGS} - - - -${BIN}pdp7${EXE} : ${PDP18B} ${SIM} - ${CC} ${PDP18B} ${SIM} ${PDP7_OPT} -o $@ ${LDFLAGS} - - - -${BIN}pdp8${EXE} : ${PDP8} ${SIM} - ${CC} ${PDP8} ${SIM} ${PDP8_OPT} -o $@ ${LDFLAGS} - - - -${BIN}pdp9${EXE} : ${PDP18B} ${SIM} - ${CC} ${PDP18B} ${SIM} ${PDP9_OPT} -o $@ ${LDFLAGS} - - - -${BIN}pdp15${EXE} : ${PDP18B} ${SIM} - ${CC} ${PDP18B} ${SIM} ${PDP15_OPT} -o $@ ${LDFLAGS} - - - -${BIN}pdp10${EXE} : ${PDP10} ${SIM} - ${CC} ${PDP10} ${SIM} ${PDP10_OPT} -o $@ ${LDFLAGS} - - - -${BIN}pdp11${EXE} : ${PDP11} ${SIM} - ${CC} ${PDP11} ${SIM} ${PDP11_OPT} -o $@ ${LDFLAGS} - - - -${BIN}vax${EXE} : ${VAX} ${SIM} - ${CC} ${VAX} ${SIM} ${VAX_OPT} -o $@ ${LDFLAGS} - - - -${BIN}nova${EXE} : ${NOVA} ${SIM} - ${CC} ${NOVA} ${SIM} ${NOVA_OPT} -o $@ ${LDFLAGS} - - - -${BIN}eclipse${EXE} : ${ECLIPSE} ${SIM} - ${CC} ${ECLIPSE} ${SIM} ${ECLIPSE_OPT} -o $@ ${LDFLAGS} - - - -${BIN}h316${EXE} : ${H316} ${SIM} - ${CC} ${H316} ${SIM} ${H316_OPT} -o $@ ${LDFLAGS} - - - -${BIN}hp2100${EXE} : ${HP2100} ${SIM} - ${CC} ${HP2100} ${SIM} ${HP2100_OPT} -o $@ ${LDFLAGS} - - - -${BIN}i1401${EXE} : ${I1401} ${SIM} - ${CC} ${I1401} ${SIM} ${I1401_OPT} -o $@ ${LDFLAGS} - - - -${BIN}i1620${EXE} : ${I1620} ${SIM} - ${CC} ${I1620} ${SIM} ${I1620_OPT} -o $@ ${LDFLAGS} - - -${BIN}ibm1130${EXE} : ${IBM1130} - ${CC} ${IBM1130} ${SIM} ${IBM1130_OPT} -o $@ ${LDFLAGS} - - -${BIN}s3${EXE} : ${S3} ${SIM} - ${CC} ${S3} ${SIM} ${S3_OPT} -o $@ ${LDFLAGS} - - -${BIN}altair${EXE} : ${ALTAIR} ${SIM} - ${CC} ${ALTAIR} ${SIM} ${ALTAIR_OPT} -o $@ ${LDFLAGS} - - -${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/scp.c b/scp.c deleted file mode 100644 index 52e5bdeb..00000000 --- a/scp.c +++ /dev/null @@ -1,3773 +0,0 @@ -/* scp.c: simulator control program - - 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. - - 01-Sep-03 RMS Fixed end-of-file problem in dep, idep - Fixed error on trailing spaces in dep, idep - 15-Jul-03 RMS Removed unnecessary test in reset_all - 15-Jun-03 RMS Added register flag REG_VMIO - 25-Apr-03 RMS Added extended address support (V3.0) - Fixed bug in SAVE (found by Peter Schorn) - Added u5, u6 fields - Added logical name support - 03-Mar-03 RMS Added sim_fsize - 27-Feb-03 RMS Fixed bug in multiword deposits to files - 08-Feb-03 RMS Changed sim_os_sleep to void, match_ext to char* - Added multiple actions, .ini file support - Added multiple switch evaluations per line - 07-Feb-03 RMS Added VMS support for ! (from Mark Pizzolato) - 01-Feb-03 RMS Added breakpoint table extension, actions - 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) - Added support for fixed buffer devices - Added support for Telnet console, removed VT support - Added help - Added VMS file optimizations (from Robert Alan Byer) - Added quiet mode, DO with parameters, GUI interface, - extensible commands (from Brian Knittel) - Added device enable/disable commands - 14-Jul-02 RMS Fixed exit bug in do, added -v switch (from Brian Knittel) - 17-May-02 RMS Fixed bug in fxread/fxwrite error usage (found by - Norm Lastovic) - 02-May-02 RMS Added VT emulation interface, changed {NO}LOG to SET {NO}LOG - 22-Apr-02 RMS Fixed laptop sleep problem in clock calibration, added - magtape record length error (found by Jonathan Engdahl) - 26-Feb-02 RMS Fixed initialization bugs in do_cmd, get_aval - (found by Brian Knittel) - 10-Feb-02 RMS Fixed problem in clock calibration - 06-Jan-02 RMS Moved device enable/disable to simulators - 30-Dec-01 RMS Generalized timer packaged, added circular arrays - 19-Dec-01 RMS Fixed DO command bug (found by John Dundas) - 07-Dec-01 RMS Implemented breakpoint package - 05-Dec-01 RMS Fixed bug in universal register logic - 03-Dec-01 RMS Added read-only units, extended SET/SHOW, universal registers - 24-Nov-01 RMS Added unit-based registers - 16-Nov-01 RMS Added DO command - 28-Oct-01 RMS Added relative range addressing - 08-Oct-01 RMS Added SHOW VERSION - 30-Sep-01 RMS Relaxed attach test in BOOT - 27-Sep-01 RMS Added queue count routine, fixed typo in ex/mod - 17-Sep-01 RMS Removed multiple console support - 07-Sep-01 RMS Removed conditional externs on function prototypes - Added special modifier print - 31-Aug-01 RMS Changed int64 to t_int64 for Windoze (V2.7) - 18-Jul-01 RMS Minor changes for Macintosh port - 12-Jun-01 RMS Fixed bug in big-endian I/O (found by Dave Conroy) - 27-May-01 RMS Added multiple console support - 16-May-01 RMS Added logging - 15-May-01 RMS Added features from Tim Litt - 12-May-01 RMS Fixed missing return in disable_cmd - 25-Mar-01 RMS Added ENABLE/DISABLE - 14-Mar-01 RMS Revised LOAD/DUMP interface (again) - 05-Mar-01 RMS Added clock calibration support - 05-Feb-01 RMS Fixed bug, DETACH buffered unit with hwmark = 0 - 04-Feb-01 RMS Fixed bug, RESTORE not using device's attach routine - 21-Jan-01 RMS Added relative time - 22-Dec-00 RMS Fixed find_device for devices ending in numbers - 08-Dec-00 RMS V2.5a changes - 30-Oct-00 RMS Added output file option to examine - 11-Jul-99 RMS V2.5 changes - 13-Apr-99 RMS Fixed handling of 32b addresses - 04-Oct-98 RMS V2.4 changes - 20-Aug-98 RMS Added radix commands - 05-Jun-98 RMS Fixed bug in ^D handling for UNIX - 10-Apr-98 RMS Added switches to all commands - 26-Oct-97 RMS Added search capability - 25-Jan-97 RMS Revised data types - 23-Jan-97 RMS Added bi-endian I/O - 06-Sep-96 RMS Fixed bug in variable length IEXAMINE - 16-Jun-96 RMS Changed interface to parse/print_sym - 06-Apr-96 RMS Added error checking in reset all - 07-Jan-96 RMS Added register buffers in save/restore - 11-Dec-95 RMS Fixed ordering bug in save/restore - 22-May-95 RMS Added symbolic input - 13-Apr-95 RMS Added symbolic printouts -*/ - -/* Macros and data structures */ - -#include "sim_defs.h" -#include "sim_rev.h" -#include "sim_sock.h" -#include "sim_tmxr.h" -#include -#include - -#define EX_D 0 /* deposit */ -#define EX_E 1 /* examine */ -#define EX_I 2 /* interactive */ -#define SCH_OR 0 /* search logicals */ -#define SCH_AND 1 -#define SCH_XOR 2 -#define SCH_E 0 /* search booleans */ -#define SCH_N 1 -#define SCH_G 2 -#define SCH_L 3 -#define SCH_EE 4 -#define SCH_NE 5 -#define SCH_GE 6 -#define SCH_LE 7 -#define SSH_ST 0 /* set */ -#define SSH_SH 1 /* show */ -#define SSH_CL 2 /* clear */ -#define RU_RUN 0 /* run */ -#define RU_GO 1 /* go */ -#define RU_STEP 2 /* step */ -#define RU_CONT 3 /* continue */ -#define RU_BOOT 4 /* boot */ - -#define SRBSIZ 1024 /* save/restore buffer */ -#define SIM_BRK_INILNT 4096 /* bpt tbl length */ -#define SIM_BRK_ALLTYP 0xFFFFFFFF -#define SIM_NTIMERS 8 /* # timers */ -#define SIM_TMAX 500 /* max timer makeup */ -#define UPDATE_SIM_TIME(x) sim_time = sim_time + (x - sim_interval); \ - sim_rtime = sim_rtime + ((uint32) (x - sim_interval)); \ - x = sim_interval - -#define print_val(a,b,c,d) fprint_val (stdout, (a), (b), (c), (d)) -#define SZ_D(dp) (size_map[((dp)->dwidth + CHAR_BIT - 1) / CHAR_BIT]) -#define SZ_R(rp) \ - (size_map[((rp)->width + (rp)->offset + CHAR_BIT - 1) / CHAR_BIT]) -#if defined (t_int64) -#define SZ_LOAD(sz,v,mb,j) \ - if (sz == sizeof (uint8)) v = *(((uint8 *) mb) + ((uint32) j)); \ - else if (sz == sizeof (uint16)) v = *(((uint16 *) mb) + ((uint32) j)); \ - else if (sz == sizeof (uint32)) v = *(((uint32 *) mb) + ((uint32) j)); \ - else v = *(((t_uint64 *) mb) + ((uint32) j)); -#define SZ_STORE(sz,v,mb,j) \ - if (sz == sizeof (uint8)) *(((uint8 *) mb) + j) = (uint8) v; \ - else if (sz == sizeof (uint16)) *(((uint16 *) mb) + ((uint32) j)) = (uint16) v; \ - else if (sz == sizeof (uint32)) *(((uint32 *) mb) + ((uint32) j)) = (uint32) v; \ - else *(((t_uint64 *) mb) + ((uint32) j)) = v; -#else -#define SZ_LOAD(sz,v,mb,j) \ - if (sz == sizeof (uint8)) v = *(((uint8 *) mb) + ((uint32) j)); \ - else if (sz == sizeof (uint16)) v = *(((uint16 *) mb) + ((uint32) j)); \ - else v = *(((uint32 *) mb) + ((uint32) j)); -#define SZ_STORE(sz,v,mb,j) \ - if (sz == sizeof (uint8)) *(((uint8 *) mb) + ((uint32) j)) = (uint8) v; \ - else if (sz == sizeof (uint16)) *(((uint16 *) mb) + ((uint32) j)) = (uint16) v; \ - else *(((uint32 *) mb) + ((uint32) j)) = v; -#endif -#define GET_SWITCHES(cp) \ - if ((cp = get_sim_sw (cp)) == NULL) return SCPE_INVSW -#define GET_RADIX(val,dft) \ - if (sim_switches & SWMASK ('O')) val = 8; \ - else if (sim_switches & SWMASK ('D')) val = 10; \ - else if (sim_switches & SWMASK ('H')) val = 16; \ - else val = dft; - -#if defined(VMS) -#define FOPEN(file_spec, mode) fopen (file_spec, mode, "ALQ=32", "DEQ=4096", \ - "MBF=6", "MBC=127", "FOP=cbt,tef", "ROP=rah,wbh", "CTX=stm") -#else -#define FOPEN(file_spec, mode) fopen (file_spec, mode) -#endif - -/* VM interface */ - -extern char sim_name[]; -extern DEVICE *sim_devices[]; -extern REG *sim_PC; -extern char *sim_stop_messages[]; -extern t_stat sim_instr (void); -extern t_stat sim_load (FILE *ptr, char *cptr, char *fnam, int32 flag); -extern int32 sim_emax; -extern t_stat fprint_sym (FILE *ofile, t_addr addr, t_value *val, - UNIT *uptr, int32 sw); -extern t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, - int32 sw); - -/* The per-simulator init routine is a weak global that defaults to NULL - The other per-simulator pointers can be overrriden by the init routine */ - -void (*sim_vm_init) (void); -char* (*sim_vm_read) (char *ptr, int32 size, FILE *stream) = NULL; -void (*sim_vm_post) (t_bool from_scp) = NULL; -CTAB *sim_vm_cmd = NULL; - -/* External routines */ - -extern t_stat ttinit (void); -extern t_stat ttrunstate (void); -extern t_stat ttcmdstate (void); -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); - -/* Prototypes */ - -/* Command processors */ - -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); -t_stat detach_cmd (int32 flag, char *ptr); -t_stat assign_cmd (int32 flag, char *ptr); -t_stat deassign_cmd (int32 flag, char *ptr); -t_stat save_cmd (int32 flag, char *ptr); -t_stat restore_cmd (int32 flag, char *ptr); -t_stat exit_cmd (int32 flag, char *ptr); -t_stat set_cmd (int32 flag, char *ptr); -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); - -/* Set and show command processors */ - -t_stat set_telnet (int32 flg, char *cptr); -t_stat set_notelnet (int32 flg, char *cptr); -t_stat set_logon (int32 flag, char *cptr); -t_stat set_logoff (int32 flag, char *cptr); -t_stat set_radix (DEVICE *dptr, UNIT *uptr, int32 flag); -t_stat set_devenbdis (DEVICE *dptr, UNIT *uptr, int32 flag); -t_stat set_onoff (DEVICE *dptr, UNIT *uptr, int32 flag); -t_stat ssh_break (FILE *st, char *cptr, int32 flg); -t_stat show_config (FILE *st, int32 flag, char *cptr); -t_stat show_queue (FILE *st, int32 flag, char *cptr); -t_stat show_time (FILE *st, int32 flag, char *cptr); -t_stat show_mod_names (FILE *st, int32 flag, char *cptr); -t_stat show_log_names (FILE *st, int32 flag, char *cptr); -t_stat show_log (FILE *st, int32 flag, char *cptr); -t_stat show_telnet (FILE *st, int32 flag, char *cptr); -t_stat show_version (FILE *st, int32 flag, char *cptr); -t_stat show_break (FILE *st, int32 flag, char *cptr); -t_stat show_device (FILE *st, DEVICE *dptr, int32 flag); -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); -t_stat sim_save (FILE *sfile); -t_stat sim_rest (FILE *rfile); - -/* Breakpoint package */ - -t_stat sim_brk_init (void); -t_stat sim_brk_set (t_addr loc, int32 sw, int32 ncnt, char *act); -t_stat sim_brk_clr (t_addr loc, int32 sw); -t_stat sim_brk_clrall (int32 sw); -t_stat sim_brk_show (FILE *st, t_addr loc, int32 sw); -t_stat sim_brk_showall (FILE *st, int32 sw); -char *sim_brk_getact (char *buf, int32 size); -void sim_brk_clract (void); -void sim_brk_npc (void); -BRKTAB *sim_brk_new (t_addr loc); - -/* Commands support routines */ - -SCHTAB *get_search (char *cptr, DEVICE *dptr, SCHTAB *schptr); -int32 test_search (t_value val, SCHTAB *schptr); -char *get_glyph_gen (char *iptr, char *optr, char mchar, t_bool uc); -int32 get_switches (char *cptr); -char *get_sim_sw (char *cptr); -t_stat get_aval (t_addr addr, DEVICE *dptr, UNIT *uptr); -t_value get_rval (REG *rptr, uint32 idx); -void put_rval (REG *rptr, uint32 idx, t_value val); -t_value strtotv (char *inptr, char **endptr, uint32 radix); -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); -C1TAB *find_c1tab (C1TAB *tab, char *gbuf); -CTAB *find_cmd (char *gbuf); -DEVICE *find_dev (char *ptr); -DEVICE *find_unit (char *ptr, UNIT **uptr); -REG *find_reg_glob (char *ptr, char **optr, DEVICE **gdptr); - -/* Forward references within commands */ - -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 assign_device (DEVICE *dptr, char *cptr); -t_stat deassign_device (DEVICE *dptr); -t_stat exdep_reg_loop (FILE *ofile, SCHTAB *schptr, int32 flag, char *cptr, - REG *lowr, REG *highr, uint32 lows, uint32 highs); -t_stat ex_reg (FILE *ofile, t_value val, int32 flag, REG *rptr, uint32 idx); -t_stat dep_reg (int32 flag, char *cptr, REG *rptr, uint32 idx); -t_stat exdep_addr_loop (FILE *ofile, SCHTAB *schptr, int32 flag, char *cptr, - t_addr low, t_addr high, DEVICE *dptr, UNIT *uptr); -t_stat ex_addr (FILE *ofile, int32 flag, t_addr addr, DEVICE *dptr, UNIT *uptr); -t_stat dep_addr (int32 flag, char *cptr, t_addr addr, DEVICE *dptr, - UNIT *uptr, int32 dfltinc); -t_stat step_svc (UNIT *ptr); -void sub_args (char *instr, char *tmpbuf, int32 maxstr, int32 nargs, char *do_arg[]); - -/* Global data */ - -UNIT *sim_clock_queue = NULL; -int32 sim_interval = 0; -int32 sim_switches = 0; -int32 sim_is_running = 0; -uint32 sim_brk_summ = 0; -uint32 sim_brk_types = 0; -uint32 sim_brk_dflt = 0; -char *sim_brk_act = NULL; -BRKTAB *sim_brk_tab = NULL; -int32 sim_brk_ent = 0; -int32 sim_brk_lnt = 0; -int32 sim_brk_ins = 0; -t_bool sim_brk_pend = FALSE; -t_addr sim_brk_ploc = 0; -int32 sim_quiet = 0; -static double sim_time; -static uint32 sim_rtime; -static int32 noqueue_time; -volatile int32 stop_cpu = 0; -t_value *sim_eval = NULL; -int32 sim_end = 1; /* 1 = little */ -FILE *sim_log = NULL; /* log file */ -unsigned char sim_flip[FLIP_SIZE]; - -TMLN sim_con_ldsc = { 0 }; /* console line descr */ -TMXR sim_con_tmxr = { 1, 0, 0, &sim_con_ldsc }; /* console line mux */ -UNIT step_unit = { UDATA (&step_svc, 0, 0) }; - -/* Tables and strings */ - -const char save_vercur[] = "V3.0"; -const char save_ver210[] = "V2.10"; -const char save_ver26[] = "V2.6"; -const char *scp_error_messages[] = { - "Address space exceeded", - "Unit not attached", - "I/O error", - "Checksum error", - "Format error", - "Unit not attachable", - "File open error", - "Memory exhausted", - "Invalid argument", - "Step expired", - "Unknown command", - "Read only argument", - "Command not completed", - "Simulation stopped", - "Goodbye", - "Console input I/O error", - "Console output I/O error", - "End of file", - "Relocation error", - "No settable parameters", - "Unit already attached", - "Hardware timer error", - "SIGINT handler setup error", - "Console terminal setup error", - "Subscript out of range", - "Command not allowed", - "Unit disabled", - "Read only operation not allowed", - "Invalid switch", - "Missing value", - "Too few arguments", - "Too many arguments", - "Non-existent device", - "Non-existent unit", - "Non-existent register", - "Non-existent parameter", - "Nested DO commands", - "Internal error", - "Invalid magtape record length", - "Console Telnet connection lost", - "Console Telnet connection timed out" -}; - -const size_t size_map[] = { sizeof (int8), - sizeof (int8), sizeof (int16), sizeof (int32), sizeof (int32) -#if defined (t_int64) - , sizeof (t_int64), sizeof (t_int64), sizeof (t_int64), sizeof (t_int64) -#endif -}; - -const t_value width_mask[] = { 0, - 0x1, 0x3, 0x7, 0xF, - 0x1F, 0x3F, 0x7F, 0xFF, - 0x1FF, 0x3FF, 0x7FF, 0xFFF, - 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF, - 0x1FFFF, 0x3FFFF, 0x7FFFF, 0xFFFFF, - 0x1FFFFF, 0x3FFFFF, 0x7FFFFF, 0xFFFFFF, - 0x1FFFFFF, 0x3FFFFFF, 0x7FFFFFF, 0xFFFFFFF, - 0x1FFFFFFF, 0x3FFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF -#if defined (t_int64) - , 0x1FFFFFFFF, 0x3FFFFFFFF, 0x7FFFFFFFF, 0xFFFFFFFFF, - 0x1FFFFFFFFF, 0x3FFFFFFFFF, 0x7FFFFFFFFF, 0xFFFFFFFFFF, - 0x1FFFFFFFFFF, 0x3FFFFFFFFFF, 0x7FFFFFFFFFF, 0xFFFFFFFFFFF, - 0x1FFFFFFFFFFF, 0x3FFFFFFFFFFF, 0x7FFFFFFFFFFF, 0xFFFFFFFFFFFF, - 0x1FFFFFFFFFFFF, 0x3FFFFFFFFFFFF, 0x7FFFFFFFFFFFF, 0xFFFFFFFFFFFFF, - 0x1FFFFFFFFFFFFF, 0x3FFFFFFFFFFFFF, 0x7FFFFFFFFFFFFF, 0xFFFFFFFFFFFFFF, - 0x1FFFFFFFFFFFFFF, 0x3FFFFFFFFFFFFFF, - 0x7FFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFF, - 0x1FFFFFFFFFFFFFFF, 0x3FFFFFFFFFFFFFFF, - 0x7FFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF -#endif -}; - -static CTAB cmd_table[] = { - { "RESET", &reset_cmd, 0, - "r{eset} {ALL|} reset simulator\n" }, - { "EXAMINE", &exdep_cmd, EX_E, - "e{xamine} examine memory or registers\n" }, - { "IEXAMINE", &exdep_cmd, EX_E+EX_I, - "ie{xamine} interactive examine memory or registers\n" }, - { "DEPOSIT", &exdep_cmd, EX_D, - "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, - "go {new PC} start simulation\n" }, - { "STEP", &run_cmd, RU_STEP, - "s{tep} {n} simulate n instructions\n" }, - { "CONT", &run_cmd, RU_CONT, - "c{ont} continue simulation\n" }, - { "BOOT", &run_cmd, RU_BOOT, - "b{oot} bootstrap unit\n" }, - { "BREAK", &brk_cmd, SSH_ST, - "br{eak} set breakpoints\n" }, - { "NOBREAK", &brk_cmd, SSH_CL, - "nobr{eak} clear breakpoints\n" }, - { "ATTACH", &attach_cmd, 0, - "at{tach} attach file to simulated unit\n" }, - { "DETACH", &detach_cmd, 0, - "det{ach} detach file from simulated unit\n" }, - { "ASSIGN", &assign_cmd, 0, - "as{sign} assign logical name for device\n" }, - { "DEASSIGN", &deassign_cmd, 0, - "dea{ssign} deassign logical name for device\n" }, - { "SAVE", &save_cmd, 0, - "sa{ve} save simulator to file\n" }, - { "RESTORE", &restore_cmd, 0, - "rest{ore}|ge{t} restore simulator from file\n" }, - { "GET", &restore_cmd, 0, NULL }, - { "LOAD", &load_cmd, 0, - "l{oad} {} load binary file\n" }, - { "DUMP", &load_cmd, 1, - "du(mp) {} dump binary file\n" }, - { "EXIT", &exit_cmd, 0, - "exi{t}|q{uit}|by{e} exit from simulation\n" }, - { "QUIT", &exit_cmd, 0, NULL }, - { "BYE", &exit_cmd, 0, NULL }, - { "SET", &set_cmd, 0, - "set log enable logging to file\n" - "set nolog disable logging\n" - "set telnet enable Telnet port for console\n" - "set notelnet disable Telnet for console\n" - "set OCT|DEC|HEX set device display radix\n" - "set ENABLED enable device\n" - "set DISABLED disable device\n" - "set ONLINE enable unit\n" - "set OFFLINE disable unit\n" - "set | set device/unit parameter\n" - }, - { "SHOW", &show_cmd, 0, - "sh{ow} br{eak} show breakpoints on address list\n" - "sh{ow} c{onfiguration} show configuration\n" - "sh{ow} d{evices} show devices\n" - "sh{ow} l{og} show log\n" - "sh{ow} m{odifiers} show modifiers\n" - "sh{ow} n{ames} show logical names\n" - "sh{ow} q{ueue} show event queue\n" - "sh{ow} te{lnet} show console Telnet status\n" - "sh{ow} ti{me} show simulated time\n" - "sh{ow} ve{rsion} show simulator version\n" - "sh{ow} | show device parameters\n" }, - { "DO", &do_cmd, 0, - "do {arg,arg...} process command file\n" }, - { "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 */ - -int main (int argc, char *argv[]) -{ -char cbuf[CBUFSIZE], gbuf[CBUFSIZE], *cptr; -int32 i, sw; -t_bool lookswitch; -t_stat stat; -CTAB *cmdp; -union {int32 i; char c[sizeof (int32)]; } end_test; - -#if defined (__MWERKS__) && defined (macintosh) -argc = ccommand (&argv); -#endif - -*cbuf = 0; /* init arg buffer */ -sim_switches = 0; /* init switches */ -lookswitch = TRUE; -for (i = 1; i < argc; i++) { /* loop thru args */ - if (argv[i] == NULL) continue; /* paranoia */ - if ((*argv[i] == '-') && lookswitch) { /* switch? */ - if ((sw = get_switches (argv[i])) < 0) { - fprintf (stderr, "Invalid switch %s\n", argv[i]); - return 0; } - sim_switches = sim_switches | sw; } - else { if ((strlen (argv[i]) + strlen (cbuf) + 1) >= CBUFSIZE) { - fprintf (stderr, "Argument string too long\n"); - return 0; } - if (*cbuf) strcat (cbuf, " "); /* concat args */ - strcat (cbuf, argv[i]); - lookswitch = FALSE; } /* no more switches */ - } /* end for */ -sim_quiet = sim_switches & SWMASK ('Q'); /* -q means quiet */ - -if (sim_vm_init != NULL) (*sim_vm_init)(); /* call once only */ -end_test.i = 1; /* test endian-ness */ -sim_end = end_test.c[0]; -stop_cpu = 0; -sim_interval = 0; -sim_time = sim_rtime = 0; -noqueue_time = 0; -sim_clock_queue = NULL; -sim_is_running = 0; -sim_log = NULL; -if (sim_emax <= 0) sim_emax = 1; - -if ((stat = ttinit ()) != SCPE_OK) { - fprintf (stderr, "Fatal terminal initialization error\n%s\n", - scp_error_messages[stat - SCPE_BASE]); - return 0; } -if ((sim_eval = calloc (sim_emax, sizeof (t_value))) == NULL) { - fprintf (stderr, "Unable to allocate examine buffer\n"); - return 0; }; -if ((stat = reset_all (0)) != SCPE_OK) { - fprintf (stderr, "Fatal simulator initialization error\n%s\n", - scp_error_messages[stat - SCPE_BASE]); - return 0; } -if ((stat = sim_brk_init ()) != SCPE_OK) { - fprintf (stderr, "Fatal breakpoint table initialization error\n%s\n", - scp_error_messages[stat - SCPE_BASE]); - return 0; } -if (!sim_quiet) { - printf ("\n"); - show_version (stdout, 0, NULL); } - -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); } -else if (*argv[0]) { /* sim name arg? */ - char nbuf[PATH_MAX + 7], *np; /* "path.ini" */ - nbuf[0] = '"'; /* starting " */ - strncpy (nbuf + 1, argv[0], PATH_MAX + 1); /* copy sim name */ - if (np = match_ext (nbuf, "EXE")) *np = 0; /* remove .exe */ - strcat (nbuf, ".ini\""); /* add .ini" */ - stat = do_cmd (1, nbuf); } /* proc cmd file */ - -while (stat != SCPE_EXIT) { /* in case exit */ - printf ("sim> "); /* prompt */ - if (cptr = sim_brk_getact (cbuf, CBUFSIZE)) /* pending action? */ - printf ("%s\n", cptr); /* echo */ - else if (sim_vm_read != NULL) /* sim routine? */ - 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", cptr); /* log cmd */ - cptr = get_glyph (cptr, gbuf, 0); /* get command glyph */ - sim_switches = 0; /* init switches */ - if (cmdp = find_cmd (gbuf)) /* lookup command */ - 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]); } - if (sim_vm_post != NULL) (*sim_vm_post) (TRUE); - } /* end while */ - -detach_all (0, TRUE); /* close files */ -set_logoff (0, NULL); /* close log */ -set_notelnet (0, NULL); /* close Telnet */ -ttclose (); /* close console */ -return 0; -} - -/* Find command routine */ - -CTAB *find_cmd (char *gbuf) -{ -CTAB *cmdp = NULL; - -if (sim_vm_cmd) cmdp = find_ctab (sim_vm_cmd, gbuf); /* try ext commands */ -if (cmdp == NULL) cmdp = find_ctab (cmd_table, gbuf); /* try regular cmds */ -return cmdp; -} - -/* Exit command */ - -t_stat exit_cmd (int32 flag, char *cptr) -{ -return SCPE_EXIT; -} - -/* Help command */ - -void fprint_help (FILE *st) -{ -CTAB *cmdp; - -for (cmdp = cmd_table; cmdp && (cmdp->name != NULL); cmdp++) { - if (cmdp->help) fprintf (st, cmdp->help); } -for (cmdp = sim_vm_cmd; cmdp && (cmdp->name != NULL); cmdp++) { - if (cmdp->help) fprintf (st, cmdp->help); } -return; -} - -t_stat help_cmd (int32 flag, char *cptr) -{ -char gbuf[CBUFSIZE]; -CTAB *cmdp; - -GET_SWITCHES (cptr); -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); } - 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"); -#if defined (VMS) -if ((cptr == NULL) || (strlen (cptr) == 0)) cptr = "SPAWN/INPUT=SYS$COMMAND:"; -#endif -fflush(stdout); /* flush stdout */ -if (sim_log) fflush (sim_log); /* flush log if enabled */ -system (cptr); -#if defined (VMS) -printf ("\n"); -#endif - -return SCPE_OK; -} - -/* Do command */ - -t_stat do_cmd (int32 flag, char *fcptr) -{ -char *cptr, cbuf[CBUFSIZE], gbuf[CBUFSIZE], *c, quote, *do_arg[10]; -FILE *fpin; -CTAB *cmdp; -int32 echo, nargs; -t_stat stat = SCPE_OK; - -if (flag == 0) { GET_SWITCHES (fcptr); } /* get switches */ -echo = sim_switches & SWMASK ('V'); /* -v means echo */ - -c = fcptr; -for (nargs = 0; nargs < 10; ) { /* extract arguments */ - while (isspace (*c)) c++; /* skip blanks */ - if (*c == 0) break; /* all done */ - if (*c == '\'' || *c == '"') quote = *c++; /* quoted string? */ - else quote = 0; - do_arg[nargs++] = c; /* save start */ - while (*c && (quote? (*c != quote): !isspace (*c))) c++; - if (*c) *c++ = 0; /* term at quote/spc */ - } /* end for */ -if (nargs <= 0) return SCPE_2FARG; /* need at least 1 */ -if ((fpin = fopen (do_arg[0], "r")) == NULL) /* cmd file failed to open? */ - return SCPE_OPENERR; - -do { cptr = read_line (cbuf, CBUFSIZE, fpin); /* get cmd line */ - sub_args (cbuf, gbuf, CBUFSIZE, nargs, do_arg); - if (cptr == NULL) break; /* exit on eof */ - if (*cptr == 0) continue; /* ignore blank */ - if (echo) printf("do> %s\n", cptr); /* echo if -v */ - if (sim_log) fprintf (sim_log, "do> %s\n", cptr); - cptr = get_glyph (cptr, gbuf, 0); /* get command glyph */ - sim_switches = 0; /* init switches */ - if (strcmp (gbuf, "DO") == 0) { /* don't recurse */ - fclose (fpin); - return SCPE_NEST; } - if (cmdp = find_cmd (gbuf)) /* lookup command */ - 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_vm_post != NULL) (*sim_vm_post) (TRUE); -} while (stat != SCPE_EXIT); - -fclose (fpin); /* close file */ -return (stat == SCPE_EXIT)? SCPE_EXIT: SCPE_OK; -} - -/* Substitute_args - replace %n tokens in 'instr' with the do command's arguments - - Calling sequence - instr = input string - tmpbuf = temp buffer - maxstr = min (len (instr), len (tmpbuf)) - nargs = number of arguments - do_arg[10] = arguments -*/ - -void sub_args (char *instr, char *tmpbuf, int32 maxstr, int32 nargs, char *do_arg[]) -{ -char *ip, *op, *ap, *oend = tmpbuf + maxstr - 2; - -for (ip = instr, op = tmpbuf; *ip && (op < oend); ) { - if ((*ip == '\\') && (ip[1] == '%')) { /* \% = literal % */ - ip++; /* skip \ */ - if (*ip) *op++ = *ip++; } /* copy next */ - else if ((*ip == '%') && /* %n = sub */ - ((ip[1] >= '1') && (ip[1] <= ('0'+ nargs - 1)))) { - ap = do_arg[ip[1] - '0']; - ip = ip + 2; - while (*ap && (op < oend)) *op++ = *ap++; }/* copy the argument */ - else *op++ = *ip++; } /* literal character */ -*op = 0; /* term buffer */ -strcpy (instr, tmpbuf); -return; -} - -/* Set command */ - -t_stat set_cmd (int32 flag, char *cptr) -{ -int32 lvl; -t_stat r; -char gbuf[CBUFSIZE], *cvptr, *svptr; -DEVICE *dptr; -UNIT *uptr; -MTAB *mptr; -CTAB *gcmdp; -C1TAB *ctbr, *glbr; -static CTAB set_glob_tab[] = { - { "TELNET", &set_telnet, 0 }, - { "NOTELNET", &set_notelnet, 0 }, - { "LOG", &set_logon, 0 }, - { "NOLOG", &set_logoff, 0 }, - { "BREAK", &brk_cmd, SSH_ST }, - { NULL, NULL, 0 } }; -static C1TAB set_dev_tab[] = { - { "OCTAL", &set_radix, 8 }, - { "DECIMAL", &set_radix, 10 }, - { "HEX", &set_radix, 16 }, - { "ENABLED", &set_devenbdis, 1 }, - { "DISABLED", &set_devenbdis, 0 }, - { NULL, NULL, 0 } }; -static C1TAB set_unit_tab[] = { - { "ONLINE", &set_onoff, 1 }, - { "OFFLINE", &set_onoff, 0 }, - { NULL, NULL, 0 } }; - -GET_SWITCHES (cptr); /* get switches */ -if (*cptr == 0) return SCPE_2FARG; /* must be more */ -cptr = get_glyph (cptr, gbuf, 0); /* get glob/dev/unit */ - -if (dptr = find_dev (gbuf)) { /* device match? */ - uptr = dptr->units; /* first unit */ - ctbr = set_dev_tab; /* global table */ - lvl = MTAB_VDV; } /* device match */ -else if (dptr = find_unit (gbuf, &uptr)) { /* unit match? */ - if (uptr == NULL) return SCPE_NXUN; /* invalid unit */ - ctbr = set_unit_tab; /* global table */ - lvl = MTAB_VUN; } /* unit match */ -else if (gcmdp = find_ctab (set_glob_tab, gbuf)) /* global? */ - return gcmdp->action (gcmdp->arg, cptr); /* do the rest */ -else return SCPE_NXDEV; /* no match */ -if (*cptr == 0) return SCPE_2FARG; /* must be more */ - -while (*cptr != 0) { /* do all mods */ - 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 */ - (MATCH_CMD (gbuf, mptr->mstring) == 0)) { /* matches option? */ - if (mptr->mask & MTAB_XTD) { /* extended? */ - if ((lvl & mptr->mask) == 0) return SCPE_ARG; - 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? */ - else if (mptr->mask & MTAB_VAL) { /* take a value? */ - if (!cvptr) return SCPE_MISVAL; /* none? error */ - r = dep_reg (0, cvptr, (REG *) mptr->desc, 0); - if (r != SCPE_OK) return r; } - else if (cvptr) return SCPE_ARG; /* = value? */ - else *((int32 *) mptr->desc) = mptr->match; - } /* end if xtd */ - else { /* old style */ - if (cvptr) return SCPE_ARG; /* = value? */ - if (uptr->flags & UNIT_DIS) /* disabled? */ - return SCPE_UDIS; - if ((mptr->valid) && ((r = mptr->valid - (uptr, mptr->match, cvptr, mptr->desc)) - != SCPE_OK)) return r; /* invalid? */ - uptr->flags = (uptr->flags & ~(mptr->mask)) | - (mptr->match & mptr->mask); /* set new value */ - } /* end else xtd */ - break; /* terminate for */ - } /* end if match */ - } /* end for */ - if (!mptr || (mptr->mask == 0)) { /* no match? */ - if (glbr = find_c1tab (ctbr, gbuf)) { /* global match? */ - r = glbr->action (dptr, uptr, glbr->arg); /* do global */ - if (r != SCPE_OK) return r; } - else if (!dptr->modifiers) return SCPE_NOPARAM; /* no modifiers? */ - else return SCPE_NXPAR; } /* end if no mat */ - } /* end while */ -return SCPE_OK; /* done all */ -} - -/* Match CTAB/CTAB1 name */ - -CTAB *find_ctab (CTAB *tab, char *gbuf) -{ -for (; tab->name != NULL; tab++) { - if (MATCH_CMD (gbuf, tab->name) == 0) return tab; } -return NULL; -} - -C1TAB *find_c1tab (C1TAB *tab, char *gbuf) -{ -for (; tab->name != NULL; tab++) { - if (MATCH_CMD (gbuf, tab->name) == 0) return tab; } -return NULL; -} - -/* Log on routine */ - -t_stat set_logon (int32 flag, char *cptr) -{ -char gbuf[CBUFSIZE]; - -if (*cptr == 0) return SCPE_2FARG; /* need arg */ -cptr = get_glyph_nc (cptr, gbuf, 0); /* get file name */ -if (*cptr != 0) return SCPE_2MARG; /* now eol? */ -set_logoff (0, NULL); /* close cur log */ -sim_log = FOPEN (gbuf, "a"); /* open log */ -if (sim_log == NULL) return SCPE_OPENERR; /* error? */ -if (!sim_quiet) printf ("Logging to file \"%s\"\n", gbuf); -fprintf (sim_log, "Logging to file \"%s\"\n", gbuf); /* start of log */ -return SCPE_OK; -} - -/* Log off routine */ - -t_stat set_logoff (int32 flag, char *cptr) -{ -if (cptr && (*cptr != 0)) return SCPE_2MARG; /* now eol? */ -if (sim_log == NULL) return SCPE_OK; /* no log? */ -if (!sim_quiet) printf ("Log file closed\n"); -fprintf (sim_log, "Log file closed\n"); /* close log */ -fclose (sim_log); -sim_log = NULL; -return SCPE_OK; -} - -/* Set controller data radix routine */ - -t_stat set_radix (DEVICE *dptr, UNIT *uptr, int32 flag) -{ -dptr->dradix = flag & 037; -return SCPE_OK; -} - -/* Set controller enabled/disabled routine */ - -t_stat set_devenbdis (DEVICE *dptr, UNIT *uptr, int32 flag) -{ -UNIT *up; -uint32 i; - -if ((dptr->flags & DEV_DISABLE) == 0) return SCPE_NOFNC;/* allowed? */ -if (flag) { /* enable? */ - if ((dptr->flags & DEV_DIS) == 0) return SCPE_OK; /* already enb? ok */ - dptr->flags = dptr->flags & ~DEV_DIS; } /* no, enable */ -else { /* disable */ - if (dptr->flags & DEV_DIS) return SCPE_OK; /* already dsb? ok */ - for (i = 0; i < dptr->numunits; i++) { /* check units */ - up = (dptr->units) + i; /* att or active? */ - if ((up->flags & UNIT_ATT) || sim_is_active (up)) - return SCPE_NOFNC; } /* can't do it */ - dptr->flags = dptr->flags | DEV_DIS; } /* disable */ -if (dptr->reset) return dptr->reset (dptr); /* reset device */ -else return SCPE_OK; -} - -/* Set unit online/offline routine */ - -t_stat set_onoff (DEVICE *dptr, UNIT *uptr, int32 flag) -{ -if (!(uptr->flags & UNIT_DISABLE)) return SCPE_NOFNC; /* allowed? */ -if (flag) uptr->flags = uptr->flags & ~UNIT_DIS; /* onl? enable */ -else { /* offline? */ - if ((uptr->flags & UNIT_ATT) || sim_is_active (uptr)) - return SCPE_NOFNC; /* more tests */ - uptr->flags = uptr->flags | UNIT_DIS; } /* disable */ -return SCPE_OK; -} - -/* Show command */ - -t_stat show_cmd (int32 flag, char *cptr) -{ -int32 i, lvl; -t_stat r; -char gbuf[CBUFSIZE]; -DEVICE *dptr; -UNIT *uptr; -MTAB *mptr; - -static SHTAB show_table[] = { - { "CONFIGURATION", &show_config, 0 }, - { "DEVICES", &show_config, 1 }, - { "QUEUE", &show_queue, 0 }, - { "TIME", &show_time, 0 }, - { "MODIFIERS", &show_mod_names, 0 }, - { "NAMES", &show_log_names, 0 }, - { "VERSION", &show_version, 0 }, - { "LOG", &show_log, 0 }, - { "TELNET", &show_telnet, 0 }, - { "BREAK", &show_break, 0 }, - { NULL, NULL, 0 } }; - -GET_SWITCHES (cptr); /* get switches */ -if (*cptr == 0) return SCPE_2FARG; /* must be more */ -cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */ -for (i = 0; show_table[i].name != NULL; i++) { /* find command */ - if (MATCH_CMD (gbuf, show_table[i].name) == 0) { - r = show_table[i].action (stdout, show_table[i].arg, cptr); - if (sim_log) show_table[i].action (sim_log, show_table[i].arg, cptr); - return r; } } - -if (dptr = find_dev (gbuf)) { /* device match? */ - uptr = dptr->units; /* first unit */ - lvl = MTAB_VDV; } /* device match */ -else if (dptr = find_unit (gbuf, &uptr)) { /* unit match? */ - if (uptr == NULL) return SCPE_NXUN; /* invalid unit */ - if (uptr->flags & UNIT_DIS) return SCPE_UDIS; /* disabled? */ - lvl = MTAB_VUN; } /* unit match */ -else return SCPE_NXDEV; /* no match */ - -if (*cptr == 0) { /* now eol? */ - if (lvl == MTAB_VDV) { /* show dev? */ - r = show_device (stdout, dptr, 0); - if (sim_log) show_device (sim_log, dptr, 0); - return r; } - else { - r = show_unit (stdout, dptr, uptr, -1); - if (sim_log) show_unit (sim_log, dptr, uptr, -1); - return r; } } -if (dptr->modifiers == NULL) return SCPE_NOPARAM; /* any modifiers? */ - -while (*cptr != 0) { /* do all mods */ - cptr = get_glyph (cptr, gbuf, ','); /* get modifier */ - for (mptr = dptr->modifiers; mptr->mask != 0; mptr++) { - if (((mptr->mask & MTAB_XTD)? /* right level? */ - (mptr->mask & lvl): (MTAB_VUN & lvl)) && - ((mptr->disp && mptr->pstring && /* named disp? */ - (MATCH_CMD (gbuf, mptr->pstring) == 0)) || - ((mptr->mask & MTAB_VAL) && /* named value? */ - mptr->mstring && - (MATCH_CMD (gbuf, mptr->mstring) == 0)))) { - show_one_mod (stdout, dptr, uptr, mptr, 1); - if (sim_log) show_one_mod (sim_log, dptr, uptr, mptr, 1); - break; - } /* end if */ - } /* end for */ - if (mptr->mask == 0) return SCPE_ARG; /* any match? */ - } /* end while */ -return SCPE_OK; -} - -/* Show device and unit */ - -t_stat show_device (FILE *st, DEVICE *dptr, int32 flag) -{ -uint32 j, ucnt; -UNIT *uptr; - -fprintf (st, "%s", sim_dname (dptr)); /* print dev name */ -if (qdisable (dptr)) { /* disabled? */ - fprintf (st, ", disabled\n"); - return SCPE_OK; } -for (j = ucnt = 0; j < dptr->numunits; j++) { /* count units */ - uptr = dptr->units + j; - if (!(uptr->flags & UNIT_DIS)) ucnt++; } -show_all_mods (st, dptr, dptr->units, MTAB_VDV); /* show dev mods */ -if (dptr->numunits == 0) fprintf (st, "\n"); -else { if (ucnt == 0) fprintf (st, ", all units disabled\n"); - else if (ucnt > 1) fprintf (st, ", %d units\n", ucnt); - else if (flag) fprintf (st, "\n"); } -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); } -return SCPE_OK; -} - -t_stat show_unit (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag) -{ -int32 u = uptr - dptr->units; - -if (flag > 1) fprintf (st, " %s%d", sim_dname (dptr), u); -else if (flag < 0) fprintf (st, "%s%d", sim_dname (dptr), u); -if (uptr->flags & UNIT_FIX) { - 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"); } -else if (uptr->flags & UNIT_ATTABLE) - fprintf (st, ", not attached"); -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; -t_addr mval = kval * kval; -t_addr psize = uptr->capac; -char scale, width; - -if ((dptr->dwidth / dptr->aincr) > 8) width = 'W'; -else width = 'B'; -if (uptr->capac < (kval * 10)) scale = 0; -else if (uptr->capac < (mval * 10)) { - scale = 'K'; - psize = psize / kval; } -else { scale = 'M'; - psize = psize / mval; } -fprint_val (st, (t_value) psize, 10, T_ADDR_W, PV_LEFT); -if (scale) fputc (scale, st); -fputc (width, st); -return; -} - -/* Show processors */ - -t_stat show_version (FILE *st, int32 flag, char *cptr) -{ -int32 vmaj = SIM_MAJOR, vmin = SIM_MINOR, vpat = SIM_PATCH; - -if (cptr && (*cptr != 0)) return SCPE_2MARG; -fprintf (st, "%s simulator V%d.%d-%d\n", sim_name, vmaj, vmin, vpat); -return SCPE_OK; -} - -t_stat show_config (FILE *st, int32 flag, char *cptr) -{ -int32 i; -DEVICE *dptr; - -if (cptr && (*cptr != 0)) return SCPE_2MARG; -fprintf (st, "%s simulator configuration\n\n", sim_name); -for (i = 0; (dptr = sim_devices[i]) != NULL; i++) - show_device (st, dptr, flag); -return SCPE_OK; -} - -t_stat show_log_names (FILE *st, int32 flag, char *cptr) -{ -int32 i; -DEVICE *dptr; - -for (i = 0; (dptr = sim_devices[i]) != NULL; i++) { - if (dptr->lname) fprintf (st, "%s -> %s\n", - dptr->lname, dptr->name); } -return SCPE_OK; -} - -t_stat show_queue (FILE *st, int32 flag, char *cptr) -{ -DEVICE *dptr; -UNIT *uptr; -int32 accum; - -if (cptr && (*cptr != 0)) return SCPE_2MARG; -if (sim_clock_queue == NULL) { - fprintf (st, "%s event queue empty, time = %.0f\n", - sim_name, sim_time); - return SCPE_OK; } -fprintf (st, "%s event queue status, time = %.0f\n", - sim_name, sim_time); -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", sim_dname (dptr)); - 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; } -return SCPE_OK; -} - -t_stat show_time (FILE *st, int32 flag, char *cptr) -{ -if (cptr && (*cptr != 0)) return SCPE_2MARG; -fprintf (st, "Time: %.0f\n", sim_time); -return SCPE_OK; -} - -t_stat show_log (FILE *st, int32 flag, char *cptr) -{ -if (cptr && (*cptr != 0)) return SCPE_2MARG; -if (sim_log) fprintf (st, "Logging enabled\n"); -else fprintf (st, "Logging disabled\n"); -return SCPE_OK; -} - -t_stat show_break (FILE *st, int32 flag, char *cptr) -{ -t_stat r; - -if (cptr && (*cptr != 0)) { /* more? */ - r = ssh_break (stdout, cptr, 1); - if (sim_log) ssh_break (sim_log, cptr, SSH_SH); } -else { r = sim_brk_showall (stdout, sim_switches); - if (sim_log) sim_brk_showall (sim_log,sim_switches); } -return r; -} - -/* Show modifiers */ - -t_stat show_mod_names (FILE *st, int32 flag, char *cptr) -{ -int32 i, any, enb; -DEVICE *dptr; -MTAB *mptr; - -if (cptr && (*cptr != 0)) return SCPE_2MARG; /* now eol? */ -for (i = 0; (dptr = sim_devices[i]) != NULL; i++) { - any = enb = 0; - if (dptr->modifiers) { - for (mptr = dptr->modifiers; mptr->mask != 0; mptr++) { - if (mptr->mstring) { - if (strcmp (mptr->mstring, "ENABLED") == 0) enb = 1; - if (any++) fprintf (st, ", %s", mptr->mstring); - else fprintf (st, "%s\t%s", sim_dname (dptr), mptr->mstring); } } } - if (!enb && (dptr->flags & DEV_DISABLE)) { - if (any++) fprintf (st, ", ENABLED, DISABLED"); - else fprintf (st, "%s\tENABLED, DISABLED", sim_dname (dptr)); } - if (any) fprintf (st, "\n"); } -return SCPE_OK; -} - -t_stat show_all_mods (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag) -{ -MTAB *mptr; - -if (dptr->modifiers == NULL) return SCPE_OK; -for (mptr = dptr->modifiers; mptr->mask != 0; mptr++) { - if (mptr->pstring && ((mptr->mask & MTAB_XTD)? - ((mptr->mask & flag) && !(mptr->mask & MTAB_NMO)): - ((MTAB_VUN & flag) && ((uptr->flags & mptr->mask) == mptr->match)))) { - fputs (", ", st); - show_one_mod (st, dptr, uptr, mptr, 0); } } -return SCPE_OK; -} - -t_stat show_one_mod (FILE *st, DEVICE *dptr, UNIT *uptr, MTAB *mptr, int32 flag) -{ -t_value val; - -if (mptr->disp) mptr->disp (st, uptr, mptr->match, mptr->desc); -else if ((mptr->mask & MTAB_XTD) && (mptr->mask & MTAB_VAL)) { - REG *rptr = (REG *) mptr->desc; - fprintf (st, "%s=", mptr->pstring); - val = get_rval (rptr, 0); - fprint_val (st, val, rptr->radix, rptr->width, - rptr->flags & REG_FMT); } -else fputs (mptr->pstring, st); -if (flag && !((mptr->mask & MTAB_XTD) && - (mptr->mask & MTAB_NMO))) fputc ('\n', st); -return SCPE_OK; -} - -/* Breakpoint commands */ - -t_stat brk_cmd (int32 flg, char *cptr) -{ -GET_SWITCHES (cptr); /* get switches */ -return ssh_break (NULL, cptr, flg); /* call common code */ -} - -t_stat ssh_break (FILE *st, char *cptr, int32 flg) -{ -char gbuf[CBUFSIZE], *tptr, *t1ptr, *aptr; -DEVICE *dptr = sim_devices[0]; -UNIT *uptr = dptr->units; -t_stat r; -t_addr lo, hi, max = uptr->capac - dptr->aincr; -int32 cnt; - -if (*cptr == 0) return SCPE_2FARG; -if (sim_brk_types == 0) return SCPE_NOFNC; -if ((dptr == NULL) || (uptr == NULL)) return SCPE_IERR; -if (aptr = strchr (cptr, ';')) { /* ;action? */ - if (flg != SSH_ST) return SCPE_ARG; /* only on SET */ - *aptr++ = 0; } /* separate strings */ -while (*cptr) { - cptr = get_glyph (cptr, gbuf, ','); - tptr = get_range (gbuf, &lo, &hi, dptr->aradix, max, 0); - if (tptr == NULL) return SCPE_ARG; - if (*tptr == '[') { - cnt = (int32) strtotv (tptr + 1, &t1ptr, 10); - if ((tptr == t1ptr) || (*t1ptr != ']') || - (flg != SSH_ST)) return SCPE_ARG; - tptr = t1ptr + 1; } - else cnt = 0; - if (*tptr != 0) return SCPE_ARG; - if ((lo == 0) && (hi == max)) { - if (flg == SSH_CL) sim_brk_clrall (sim_switches); - else if (flg == SSH_SH) sim_brk_showall (st, sim_switches); - else return SCPE_ARG; } - else { - for ( ; lo <= hi; lo = lo + dptr->aincr) { - if (flg == SSH_ST) r = sim_brk_set (lo, sim_switches, cnt, aptr); - else if (flg == SSH_CL) r = sim_brk_clr (lo, sim_switches); - else if (flg == SSH_SH) r = sim_brk_show (st, lo, sim_switches); - else return SCPE_ARG; - if (r != SCPE_OK) return r; - } - } - } -return SCPE_OK; -} - -/* Reset command and routines - - re[set] reset all devices - re[set] all reset all devices - re[set] device reset specific device -*/ - -t_stat reset_cmd (int32 flag, char *cptr) -{ -char gbuf[CBUFSIZE]; -DEVICE *dptr; - -GET_SWITCHES (cptr); /* get switches */ -if (*cptr == 0) return (reset_all (0)); /* reset(cr) */ -cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */ -if (*cptr != 0) return SCPE_2MARG; /* now eol? */ -if (strcmp (gbuf, "ALL") == 0) return (reset_all (0)); -dptr = find_dev (gbuf); /* locate device */ -if (dptr == NULL) return SCPE_NXDEV; /* found it? */ -if (dptr->reset != NULL) return dptr->reset (dptr); -else return SCPE_OK; -} - -/* Reset devices start..end - - Inputs: - start = number of starting device - Outputs: - status = error status -*/ - -t_stat reset_all (uint32 start) -{ -DEVICE *dptr; -uint32 i; -t_stat reason; - -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; } } -return SCPE_OK; -} - -/* Load and dump commands - - lo[ad] filename {arg} load specified file - du[mp] filename {arg} dump to specified file -*/ - -t_stat load_cmd (int32 flag, char *cptr) -{ -char gbuf[CBUFSIZE]; -FILE *loadfile; -t_stat reason; - -GET_SWITCHES (cptr); /* get switches */ -if (*cptr == 0) return SCPE_2FARG; /* must be more */ -cptr = get_glyph_nc (cptr, gbuf, 0); /* get file name */ -loadfile = FOPEN (gbuf, flag? "wb": "rb"); /* open for wr/rd */ -if (loadfile == NULL) return SCPE_OPENERR; -GET_SWITCHES (cptr); /* get switches */ -reason = sim_load (loadfile, cptr, gbuf, flag); /* load or dump */ -fclose (loadfile); -return reason; -} - -/* Attach command - - at[tach] unit file attach specified unit to file -*/ - -t_stat attach_cmd (int32 flag, char *cptr) -{ -char gbuf[CBUFSIZE]; -DEVICE *dptr; -UNIT *uptr; - -GET_SWITCHES (cptr); /* get switches */ -if (*cptr == 0) return SCPE_2FARG; /* must be more */ -cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */ -GET_SWITCHES (cptr); /* get switches */ -if (*cptr == 0) return SCPE_2FARG; /* now eol? */ -dptr = find_unit (gbuf, &uptr); /* locate unit */ -if (dptr == NULL) return SCPE_NXDEV; /* found dev? */ -if (uptr == NULL) return SCPE_NXUN; /* valid unit? */ -if (dptr->attach != NULL) return dptr->attach (uptr, cptr); -return attach_unit (uptr, cptr); -} - -t_stat attach_unit (UNIT *uptr, char *cptr) -{ -DEVICE *dptr; -t_stat reason; - -if (uptr->flags & UNIT_DIS) return SCPE_UDIS; /* disabled? */ -if (!(uptr->flags & UNIT_ATTABLE)) return SCPE_NOATT; /* not attachable? */ -if ((dptr = find_dev_from_unit (uptr)) == NULL) return SCPE_NOATT; -if (uptr->flags & UNIT_ATT) { /* already attached? */ - reason = detach_unit (uptr); - if (reason != SCPE_OK) return reason; } -uptr->filename = calloc (CBUFSIZE, sizeof (char)); -if (uptr->filename == NULL) return SCPE_MEM; -strncpy (uptr->filename, cptr, CBUFSIZE); -if (sim_switches & SWMASK ('R')) { /* read only? */ - if ((uptr->flags & UNIT_ROABLE) == 0) /* allowed? */ - return attach_err (uptr, SCPE_NORO); /* no, error */ - uptr->fileref = FOPEN (cptr, "rb"); /* open rd only */ - if (uptr->fileref == NULL) /* open fail? */ - return attach_err (uptr, SCPE_OPENERR); /* yes, error */ - uptr->flags = uptr->flags | UNIT_RO; /* set rd only */ - if (!sim_quiet) printf ("%s: unit is read only\n", sim_dname (dptr)); } -else { /* normal */ - uptr->fileref = FOPEN (cptr, "rb+"); /* open r/w */ - if (uptr->fileref == NULL) { /* open fail? */ - if (errno == EROFS) { /* read only? */ - if ((uptr->flags & UNIT_ROABLE) == 0) /* allowed? */ - return attach_err (uptr, SCPE_NORO); /* no error */ - uptr->fileref = FOPEN (cptr, "rb"); /* open rd only */ - if (uptr->fileref == NULL) /* open fail? */ - return attach_err (uptr, SCPE_OPENERR); /* yes, error */ - uptr->flags = uptr->flags | UNIT_RO; /* set rd only */ - if (!sim_quiet) printf ("%s: unit is read only\n", sim_dname (dptr)); } - else { /* doesn't exist */ - if (sim_switches & SWMASK ('E')) /* must exist? */ - return attach_err (uptr, SCPE_OPENERR); /* yes, error */ - uptr->fileref = FOPEN (cptr, "wb+"); /* open new file */ - if (uptr->fileref == NULL) /* open fail? */ - return attach_err (uptr, SCPE_OPENERR); /* yes, error */ - if (!sim_quiet) printf ("%s: creating new file\n", sim_dname (dptr)); } - } /* end if null */ - } /* end else */ -if (uptr->flags & UNIT_BUFABLE) { /* buffer? */ - uint32 cap = ((uint32) uptr->capac) / dptr->aincr; /* effective size */ - if (uptr->flags & UNIT_MUSTBUF) /* dyn alloc? */ - uptr->filebuf = calloc (cap, SZ_D (dptr)); /* allocate */ - if (uptr->filebuf == NULL) /* no buffer? */ - return attach_err (uptr, SCPE_MEM); /* error */ - if (!sim_quiet) printf ("%s: buffering file in memory\n", sim_dname (dptr)); - uptr->hwmark = fxread (uptr->filebuf, SZ_D (dptr), /* read file */ - cap, uptr->fileref); - uptr->flags = uptr->flags | UNIT_BUF; } /* set buffered */ -uptr->flags = uptr->flags | UNIT_ATT; -uptr->pos = 0; -return SCPE_OK; -} - -t_stat attach_err (UNIT *uptr, t_stat stat) -{ -free (uptr->filename); -uptr->filename = NULL; -return stat; -} - -/* Detach command - - det[ach] all detach all units - det[ach] unit detach specified unit -*/ - -t_stat detach_cmd (int32 flag, char *cptr) -{ -char gbuf[CBUFSIZE]; -DEVICE *dptr; -UNIT *uptr; - -GET_SWITCHES (cptr); /* get switches */ -if (*cptr == 0) return SCPE_2FARG; /* must be more */ -cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */ -if (*cptr != 0) return SCPE_2MARG; /* now eol? */ -if (strcmp (gbuf, "ALL") == 0) return (detach_all (0, FALSE)); -dptr = find_unit (gbuf, &uptr); /* locate unit */ -if (dptr == NULL) return SCPE_NXDEV; /* found dev? */ -if (uptr == NULL) return SCPE_NXUN; /* valid unit? */ -if (!(uptr->flags & UNIT_ATTABLE)) return SCPE_NOATT; -if (dptr->detach != NULL) return dptr->detach (uptr); -return detach_unit (uptr); -} - -/* Detach devices start..end - - Inputs: - start = number of starting device - shutdown = TRUE if simulator shutting down - Outputs: - status = error status -*/ - -t_stat detach_all (int32 start, t_bool shutdown) -{ -uint32 i, j; -t_stat reason; -DEVICE *dptr; -UNIT *uptr; - -if ((start < 0) || (start > 1)) return SCPE_IERR; -for (i = start; (dptr = sim_devices[i]) != NULL; i++) { - for (j = 0; j < dptr->numunits; j++) { - uptr = (dptr->units) + j; - if ((uptr->flags & UNIT_ATTABLE) || shutdown) { - if (dptr->detach != NULL) reason = dptr->detach (uptr); - else reason = detach_unit (uptr); - if (reason != SCPE_OK) return reason; } } } -return SCPE_OK; -} - -t_stat detach_unit (UNIT *uptr) -{ -DEVICE *dptr; - -if (uptr == NULL) return SCPE_IERR; -if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; -if ((dptr = find_dev_from_unit (uptr)) == NULL) return SCPE_OK; -if (uptr->flags & UNIT_BUF) { - uint32 cap = (uptr->hwmark + dptr->aincr - 1) / dptr->aincr; - if (uptr->hwmark && ((uptr->flags & UNIT_RO) == 0)) { - if (!sim_quiet) printf ("%s: writing buffer to file\n", sim_dname (dptr)); - rewind (uptr->fileref); - fxwrite (uptr->filebuf, SZ_D (dptr), cap, uptr->fileref); - if (ferror (uptr->fileref)) perror ("I/O error"); } - if (uptr->flags & UNIT_MUSTBUF) { /* dyn alloc? */ - free (uptr->filebuf); /* free buf */ - uptr->filebuf = NULL; } - uptr->flags = uptr->flags & ~UNIT_BUF; } -uptr->flags = uptr->flags & ~(UNIT_ATT | UNIT_RO); -free (uptr->filename); -uptr->filename = NULL; -return (fclose (uptr->fileref) == EOF)? SCPE_IOERR: SCPE_OK; -} - -/* Assign command - - as[sign] device name assign logical name to device -*/ - -t_stat assign_cmd (int32 flag, char *cptr) -{ -char gbuf[CBUFSIZE]; -DEVICE *dptr; - -GET_SWITCHES (cptr); /* get switches */ -if (*cptr == 0) return SCPE_2FARG; /* must be more */ -cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */ -GET_SWITCHES (cptr); /* get switches */ -if (*cptr == 0) return SCPE_2FARG; /* now eol? */ -dptr = find_dev (gbuf); /* locate device */ -if (dptr == NULL) return SCPE_NXDEV; /* found dev? */ -cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */ -if (*cptr != 0) return SCPE_2MARG; /* must be eol */ -if (find_dev (gbuf)) return SCPE_ARG; /* name in use */ -deassign_device (dptr); /* release current */ -return assign_device (dptr, gbuf); -} - -t_stat assign_device (DEVICE *dptr, char *cptr) -{ -dptr->lname = calloc (CBUFSIZE, sizeof (char)); -if (dptr->lname == NULL) return SCPE_MEM; -strncpy (dptr->lname, cptr, CBUFSIZE); -return SCPE_OK; -} - -/* Deassign command - - dea[ssign] device deassign logical name -*/ - -t_stat deassign_cmd (int32 flag, char *cptr) -{ -char gbuf[CBUFSIZE]; -DEVICE *dptr; - -GET_SWITCHES (cptr); /* get switches */ -if (*cptr == 0) return SCPE_2FARG; /* must be more */ -cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */ -if (*cptr != 0) return SCPE_2MARG; /* now eol? */ -dptr = find_dev (gbuf); /* locate device */ -if (dptr == NULL) return SCPE_NXDEV; /* found dev? */ -return deassign_device (dptr); -} - -t_stat deassign_device (DEVICE *dptr) -{ -if (dptr->lname) free (dptr->lname); -dptr->lname = NULL; -return SCPE_OK; -} - -/* Get device display name */ - -char *sim_dname (DEVICE *dptr) -{ -return (dptr->lname? dptr->lname: dptr->name); -} - -/* Save command - - sa[ve] filename save state to specified file -*/ - -t_stat save_cmd (int32 flag, char *cptr) -{ -FILE *sfile; -t_stat r; -GET_SWITCHES (cptr); /* get switches */ -if (*cptr == 0) return SCPE_2FARG; /* must be more */ -if ((sfile = FOPEN (cptr, "wb")) == NULL) return SCPE_OPENERR; -r = sim_save (sfile); -fclose (sfile); -return r; -} - -t_stat sim_save (FILE *sfile) -{ -void *mbuf; -int32 l, t; -uint32 i, j; -t_addr k, high; -t_value val; -t_stat r; -t_bool zeroflg; -size_t sz; -DEVICE *dptr; -UNIT *uptr; -REG *rptr; - -#define WRITE_I(xx) fxwrite (&(xx), sizeof (xx), 1, sfile) - -fputs (save_vercur, sfile); /* [V2.5] save format */ -fputc ('\n', sfile); -fputs (sim_name, sfile); /* sim name */ -fputc ('\n', sfile); -WRITE_I (sim_time); /* sim time */ -WRITE_I (sim_rtime); /* [V2.6] sim rel time */ - -for (i = 0; (dptr = sim_devices[i]) != NULL; i++) { /* loop thru devices */ - fputs (dptr->name, sfile); /* device name */ - fputc ('\n', sfile); - if (dptr->lname) fputs (dptr->lname, sfile); /* [V3.0] logical name */ - fputc ('\n', sfile); - WRITE_I (dptr->flags); /* [V2.10] flags */ - for (j = 0; j < dptr->numunits; j++) { - uptr = dptr->units + j; - t = sim_is_active (uptr); - WRITE_I (j); /* unit number */ - WRITE_I (t); /* activation time */ - WRITE_I (uptr->u3); /* unit specific */ - WRITE_I (uptr->u4); - WRITE_I (uptr->u5); /* [V3.0] more unit */ - WRITE_I (uptr->u6); - WRITE_I (uptr->flags); /* [V2.10] flags */ - if (uptr->flags & UNIT_ATT) fputs (uptr->filename, sfile); - fputc ('\n', sfile); - if (((uptr->flags & (UNIT_FIX + UNIT_ATTABLE)) == UNIT_FIX) && - (dptr->examine != NULL) && - ((high = uptr->capac) != 0)) { /* memory-like unit? */ - WRITE_I (high); /* [V2.5] write size */ - sz = SZ_D (dptr); - if ((mbuf = calloc (SRBSIZ, sz)) == NULL) { - fclose (sfile); - return SCPE_MEM; } - for (k = 0; k < high; ) { /* loop thru mem */ - zeroflg = TRUE; - for (l = 0; (l < SRBSIZ) && (k < high); l++, - k = k + (dptr->aincr)) { /* check for 0 block */ - r = dptr->examine (&val, k, uptr, 0); - if (r != SCPE_OK) return r; - if (val) zeroflg = FALSE; - SZ_STORE (sz, val, mbuf, l); - } /* end for l */ - if (zeroflg) { /* all zero's? */ - l = -l; /* invert block count */ - WRITE_I (l); } /* write only count */ - else { - WRITE_I (l); /* block count */ - fxwrite (mbuf, sz, l, sfile); } - } /* end for k */ - free (mbuf); /* dealloc buffer */ - } /* end if mem */ - else { /* no memory */ - high = 0; /* write 0 */ - WRITE_I (high); - } /* end else mem */ - } /* end unit loop */ - t = -1; /* end units */ - WRITE_I (t); /* write marker */ - for (rptr = dptr->registers; (rptr != NULL) && /* loop thru regs */ - (rptr->name != NULL); rptr++) { - fputs (rptr->name, sfile); /* name */ - fputc ('\n', sfile); - WRITE_I (rptr->depth); /* [V2.10] depth */ - for (j = 0; j < rptr->depth; j++) { /* loop thru values */ - val = get_rval (rptr, j); /* get value */ - WRITE_I (val); } } /* store */ - fputc ('\n', sfile); } /* end registers */ -fputc ('\n', sfile); /* end devices */ -return (ferror (sfile))? SCPE_IOERR: SCPE_OK; /* error during save? */ -} - -/* Restore command - - re[store] filename restore state from specified file -*/ - -t_stat restore_cmd (int32 flag, char *cptr) -{ -FILE *rfile; -t_stat r; - -GET_SWITCHES (cptr); /* get switches */ -if (*cptr == 0) return SCPE_2FARG; /* must be more */ -if ((rfile = FOPEN (cptr, "rb")) == NULL) return SCPE_OPENERR; -r = sim_rest (rfile); -fclose (rfile); -return r; -} - -t_stat sim_rest (FILE *rfile) -{ -char buf[CBUFSIZE]; -void *mbuf; -int32 j, blkcnt, limit, unitno, time, flg; -uint32 us, depth; -t_addr k, high; -t_value val, mask; -t_stat r; -size_t sz; -t_bool v30 = FALSE, v210 = FALSE; -DEVICE *dptr; -UNIT *uptr; -REG *rptr; - -#define READ_S(xx) if (read_line ((xx), CBUFSIZE, rfile) == NULL) \ - return SCPE_IOERR; -#define READ_I(xx) if (fxread (&xx, sizeof (xx), 1, rfile) == 0) \ - return SCPE_IOERR; - -READ_S (buf); /* [V2.5+] read version */ -if (strcmp (buf, save_vercur) == 0) v30 = v210 = TRUE; /* version 2.11? */ -else if (strcmp (buf, save_ver210) == 0) v210 = TRUE; /* version 2.10? */ -else if (strcmp (buf, save_ver26) != 0) { /* version 2.6? */ - printf ("Invalid file version: %s\n", buf); /* no, unknown */ - return SCPE_INCOMP; } -READ_S (buf); /* read sim name */ -if (strcmp (buf, sim_name)) { /* name match? */ - printf ("Wrong system type: %s\n", buf); - return SCPE_INCOMP; } -READ_I (sim_time); /* sim time */ -READ_I (sim_rtime); /* [V2.6+] sim rel time */ - -for ( ;; ) { /* device loop */ - READ_S (buf); /* read device name */ - if (buf[0] == 0) break; /* last? */ - if ((dptr = find_dev (buf)) == NULL) { /* locate device */ - printf ("Invalid device name: %s\n", buf); - return SCPE_INCOMP; } - if (v30) { /* [V3.0+] */ - READ_S (buf); /* read logical name */ - deassign_device (dptr); /* delete old name */ - if ((buf[0] != 0) && - ((r = assign_device (dptr, buf)) != SCPE_OK)) return r; } - if (v210) { /* [V2.10+] */ - READ_I (flg); /* cont flags */ - dptr->flags = (dptr->flags & ~DEV_RFLAGS) | /* restore */ - (flg & DEV_RFLAGS); } - for ( ;; ) { /* unit loop */ - READ_I (unitno); /* unit number */ - if (unitno < 0) break; /* end units? */ - if ((uint32) unitno >= dptr->numunits) { /* too big? */ - printf ("Invalid unit number: %s%d\n", sim_dname (dptr), unitno); - return SCPE_INCOMP; } - READ_I (time); /* event time */ - uptr = (dptr->units) + unitno; - sim_cancel (uptr); - if (time > 0) sim_activate (uptr, time - 1); - READ_I (uptr->u3); /* device specific */ - READ_I (uptr->u4); - if (v30) { /* [V3.0+] */ - READ_I (uptr->u5); /* more dev specific */ - READ_I (uptr->u6); } - if (v210) { /* [V2.10+] */ - READ_I (flg); /* unit flags */ - uptr->flags = (uptr->flags & ~UNIT_RFLAGS) | - (flg & UNIT_RFLAGS); } /* restore */ - READ_S (buf); /* attached file */ - if (!(dptr->flags & DEV_NET) || /* if not net dev or */ - !(uptr->flags & UNIT_ATT) || /* not currently att */ - (buf[0] == 0)) { /* or will not be att */ - if (dptr->detach) r = dptr->detach (uptr); /* detach old */ - else r = detach_unit (uptr); - if (r != SCPE_OK) return r; - 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 */ - 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) || - (dptr->deposit == NULL)) { - printf ("Can't restore memory: %s%d\n", sim_dname (dptr), unitno); - return SCPE_INCOMP; } - if (high != uptr->capac) { - if ((dptr->flags & DEV_DYNM) && - ((dptr->msize == NULL) || - (dptr->msize (uptr, (int32) high, NULL, NULL) != SCPE_OK))) { - printf ("Can't change memory size: %s%d\n", - sim_dname (dptr), unitno); - return SCPE_INCOMP; } - uptr->capac = high; - printf ("Memory size changed: %s%d = ", sim_dname (dptr), unitno); - fprint_capac (stdout, dptr, uptr); - printf ("\n"); } - sz = SZ_D (dptr); /* allocate buffer */ - if ((mbuf = calloc (SRBSIZ, sz)) == NULL) - return SCPE_MEM; - for (k = 0; k < high; ) { /* loop thru mem */ - READ_I (blkcnt); /* block count */ - if (blkcnt < 0) limit = -blkcnt; /* compressed? */ - else limit = fxread (mbuf, sz, blkcnt, rfile); - if (limit <= 0) return SCPE_IOERR; /* invalid or err? */ - for (j = 0; j < limit; j++, k = k + (dptr->aincr)) { - if (blkcnt < 0) val = 0; /* compressed? */ - else SZ_LOAD (sz, val, mbuf, j);/* saved value */ - r = dptr->deposit (val, k, uptr, 0); - if (r != SCPE_OK) return r; - } /* end for j */ - } /* end for k */ - free (mbuf); /* dealloc buffer */ - } /* end if high */ - } /* end unit loop */ - for ( ;; ) { /* register loop */ - READ_S (buf); /* read reg name */ - if (buf[0] == 0) break; /* last? */ - if (v210) { READ_I (depth); } /* [V2.10+] depth */ - if ((rptr = find_reg (buf, NULL, dptr)) == NULL) { - printf ("Invalid register name: %s %s\n", sim_dname (dptr), buf); - if (v210) { /* [V2.10]+ */ - for (us = 0; us < depth; us++) { /* skip values */ - READ_I (val); } } - else { - READ_I (val); /* must be one val */ - if (!restore_skip_val (rfile)) /* grope for next reg */ - return SCPE_INCOMP; } /* err or eof? */ - continue; } /* pray! */ - if (v210 && (depth != rptr->depth)) /* [V2.10+] mismatch? */ - printf ("Register depth mismatch: %s %s, file = %d, sim = %d\n", - sim_dname (dptr), buf, depth, rptr->depth); - else depth = rptr->depth; /* depth validated */ - mask = width_mask[rptr->width]; /* get mask */ - for (us = 0; us < depth; us++) { /* loop thru values */ - READ_I (val); /* read value */ - if (val > mask) /* value ok? */ - printf ("Invalid register value: %s %s\n", sim_dname (dptr), buf); - else if (us < rptr->depth) /* in range? */ - put_rval (rptr, us, val); } } - } /* end device loop */ -return SCPE_OK; -} - -/* Restore skip values (pre V2.10) - - To find the next register name, sift through bytes looking for valid - upper case ASCII characters terminated by \n */ - -t_bool restore_skip_val (FILE *rfile) -{ -t_bool instr = FALSE; -char c; -int32 ic, pos; - -if ((ic = fgetc (rfile)) == EOF) return FALSE; /* one char */ -fseek (rfile, ftell (rfile) - 1, SEEK_SET); /* back up over */ -if ((ic & 0377) == '\n') return TRUE; /* immediate nl? */ -while ((ic = fgetc (rfile)) != EOF) { /* get char */ - c = ic & 0377; /* cut to 8b */ - if (isalnum (c) || (c == '*') || (c == '_')) { /* valid reg char? */ - if (!instr) pos = ftell (rfile) - 1; /* new? save pos */ - instr = TRUE; } - else { /* not ASCII */ - if ((c == '\n') && instr) { /* nl & in string? */ - fseek (rfile, pos, SEEK_SET); /* rewind file */ - return TRUE; } - instr = FALSE; } /* not in string */ - } /* end while */ -return FALSE; /* error */ -} - -/* Run, go, cont, step commands - - ru[n] [new PC] reset and start simulation - go [new PC] start simulation - co[nt] start simulation - s[tep] [step limit] start simulation for 'limit' instructions - b[oot] device bootstrap from device and start simulation -*/ - -t_stat run_cmd (int32 flag, char *cptr) -{ -char gbuf[CBUFSIZE]; -uint32 i, j; -int32 step, unitno; -t_stat r; -DEVICE *dptr; -UNIT *uptr; -void int_handler (int signal); - -GET_SWITCHES (cptr); /* get switches */ -step = 0; -if (((flag == RU_RUN) || (flag == RU_GO)) && (*cptr != 0)) { /* run or go */ - cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */ - if ((r = dep_reg (0, gbuf, sim_PC, 0)) != SCPE_OK) return r; } - -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; } } - -if (flag == RU_BOOT) { /* boot */ - if (*cptr == 0) return SCPE_2FARG; /* must be more */ - cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */ - dptr = find_unit (gbuf, &uptr); /* locate unit */ - if (dptr == NULL) return SCPE_NXDEV; /* found dev? */ - if (uptr == NULL) return SCPE_NXUN; /* valid unit? */ - if (dptr->boot == NULL) return SCPE_NOFNC; /* can it boot? */ - if (uptr->flags & UNIT_DIS) return SCPE_UDIS; /* disabled? */ - if ((uptr->flags & UNIT_ATTABLE) && - !(uptr->flags & UNIT_ATT)) return SCPE_UNATT; - unitno = uptr - dptr->units; /* recover unit# */ - if ((r = dptr->boot (unitno, dptr)) != SCPE_OK) return r; } - -if (*cptr != 0) return SCPE_2MARG; /* now eol? */ - -if ((flag == RU_RUN) || (flag == RU_BOOT)) { /* run or boot */ - sim_interval = 0; /* reset queue */ - sim_time = sim_rtime = 0; - noqueue_time = 0; - sim_clock_queue = NULL; - 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_ext (uptr->fileref, uptr->pos, SEEK_SET); } } -stop_cpu = 0; -if (signal (SIGINT, int_handler) == SIG_ERR) { /* set WRU */ - return SCPE_SIGERR; } -if (ttrunstate () != SCPE_OK) { /* set console mode */ - ttcmdstate (); - return SCPE_TTYERR; } -if ((r = sim_check_console (30)) != SCPE_OK) { /* check console, error? */ - ttcmdstate (); - return r; } -if (step) sim_activate (&step_unit, step); /* set step timer */ -sim_is_running = 1; /* flag running */ -sim_brk_clract (); /* defang actions */ -r = sim_instr(); - -sim_is_running = 0; /* flag idle */ -ttcmdstate (); /* restore console */ -signal (SIGINT, SIG_DFL); /* cancel WRU */ -sim_cancel (&step_unit); /* cancel step timer */ -if (sim_clock_queue != NULL) { /* update sim time */ - UPDATE_SIM_TIME (sim_clock_queue->time); } -else { UPDATE_SIM_TIME (noqueue_time); } -#if defined (VMS) -printf ("\n"); -#endif -fprint_stopped (stdout, r); /* print msg */ -if (sim_log) fprint_stopped (sim_log, r); /* log if enabled */ -return SCPE_OK; -} - -/* Print stopped message */ - -void fprint_stopped (FILE *stream, t_stat v) -{ -int32 i; -t_stat r; -t_addr k; -t_value pcval; -DEVICE *dptr; - -if (v >= SCPE_BASE) fprintf (stream, "\n%s, %s: ", - scp_error_messages[v - SCPE_BASE], sim_PC->name); -else fprintf (stream, "\n%s, %s: ", sim_stop_messages[v], sim_PC->name); -pcval = get_rval (sim_PC, 0); -fprint_val (stream, pcval, sim_PC->radix, sim_PC->width, - sim_PC->flags & REG_FMT); -if (((dptr = sim_devices[0]) != NULL) && (dptr->examine != NULL)) { - for (i = 0; i < sim_emax; i++) sim_eval[i] = 0; - for (i = 0, k = (t_addr) pcval; i < sim_emax; i++, k = k + dptr->aincr) { - if ((r = dptr->examine (&sim_eval[i], k, dptr->units, - SWMASK ('V'))) != SCPE_OK) break; } - if ((r == SCPE_OK) || (i > 0)) { - fprintf (stream, " ("); - if (fprint_sym (stream, (t_addr) pcval, sim_eval, NULL, SWMASK('M')) > 0) - fprint_val (stream, sim_eval[0], dptr->dradix, - dptr->dwidth, PV_RZRO); - fprintf (stream, ")"); } } -fprintf (stream, "\n"); -return; -} - -/* Unit service for step timeout, originally scheduled by STEP n command - - Return step timeout SCP code, will cause simulation to stop -*/ - -t_stat step_svc (UNIT *uptr) -{ -return SCPE_STEP; -} - -/* Signal handler for ^C signal - - Set stop simulation flag -*/ - -void int_handler (int sig) -{ -stop_cpu = 1; -return; -} - -/* Examine/deposit commands - - ex[amine] [modifiers] list examine - de[posit] [modifiers] list val deposit - ie[xamine] [modifiers] list interactive examine - id[eposit] [modifiers] list interactive deposit - - modifiers - @filename output file - -letter(s) switches - devname'n device name and unit number - [{&|^}value]{=|==|!|!=|>|>=|<|<=} value search specification - - list list of addresses and registers - addr[:addr|-addr] address range - ALL all addresses - register[:register|-register] register range - STATE all registers -*/ - -t_stat exdep_cmd (int32 flag, char *cptr) -{ -char gbuf[CBUFSIZE], *gptr, *tptr; -int32 t; -t_bool exd2f; -t_addr low, high; -t_stat reason; -DEVICE *dptr, *tdptr; -UNIT *uptr, *tuptr; -REG *lowr, *highr; -SCHTAB stab, *schptr; -FILE *ofile; - -ofile = NULL; /* no output file */ -exd2f = FALSE; -sim_switches = 0; /* no switches */ -schptr = NULL; /* no search */ -stab.logic = SCH_OR; /* default search params */ -stab.bool = SCH_GE; -stab.mask = stab.comp = 0; -dptr = sim_devices[0]; /* default device, unit */ -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 */ - 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 */ - else if (get_search (gbuf, dptr, &stab) != NULL) { /* try for 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; } - 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? */ - -if (ofile == NULL) ofile = stdout; /* no file? stdout */ -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 | 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, (uint32) low, (uint32) high); - continue; } - - tptr = get_range (gptr, &low, &high, dptr->aradix, - (((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); - } /* end for */ -if (exd2f) fclose (ofile); /* close output file */ -return reason; -} - -/* Loop controllers for examine/deposit - - exdep_reg_loop examine/deposit range of registers - exdep_addr_loop examine/deposit range of addresses -*/ - -t_stat exdep_reg_loop (FILE *ofile, SCHTAB *schptr, int32 flag, char *cptr, - REG *lowr, REG *highr, uint32 lows, uint32 highs) -{ -t_stat reason; -uint32 idx; -t_value val; -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 & SIM_SW_HIDE) && - (rptr->flags & REG_HIDDEN)) continue; - for (idx = lows; idx <= highs; idx++) { - if (idx >= 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; -} - -t_stat exdep_addr_loop (FILE *ofile, SCHTAB *schptr, int32 flag, char *cptr, - t_addr low, t_addr high, DEVICE *dptr, UNIT *uptr) -{ -t_addr i, mask; -t_stat reason; - -if (uptr->flags & UNIT_DIS) return SCPE_UDIS; /* disabled? */ -mask = (t_addr) width_mask[dptr->awidth]; -if ((low > mask) || (high > mask) || (low > high)) return SCPE_ARG; -for (i = low; i <= high; i = i + (dptr->aincr)) { - if ((flag & EX_E) || schptr) { /* examine or search? */ - reason = get_aval (i, dptr, uptr); /* get data */ - 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); } - if (flag != EX_E) { - 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; -} - -/* Examine register routine - - Inputs: - ofile = output stream - val = current register value - flag = type of ex/mod command (ex, iex, idep) - rptr = pointer to register descriptor - idx = index - Outputs: - return = error status -*/ - -t_stat ex_reg (FILE *ofile, t_value val, int32 flag, REG *rptr, uint32 idx) -{ -int32 rdx; - -if (rptr == NULL) return SCPE_IERR; -if (rptr->depth > 1) fprintf (ofile, "%s[%d]: ", rptr->name, idx); -else fprintf (ofile, "%s: ", rptr->name); -if (!(flag & EX_E)) return SCPE_OK; -GET_RADIX (rdx, rptr->radix); -if (rptr->flags & REG_VMIO) - fprint_sym (ofile, rdx, &val, NULL, REG_VMIO); -else fprint_val (ofile, val, rdx, rptr->width, rptr->flags & REG_FMT); -if (flag & EX_I) fprintf (ofile, " "); -else fprintf (ofile, "\n"); -return SCPE_OK; -} - -/* Get register value - - Inputs: - rptr = pointer to register descriptor - idx = index - Outputs: - return = register value -*/ - -t_value get_rval (REG *rptr, uint32 idx) -{ -size_t sz; -t_value val; -UNIT *uptr; - -sz = SZ_R (rptr); -if ((rptr->depth > 1) && (rptr->flags & REG_CIRC)) { - idx = idx + rptr->qptr; - if (idx >= rptr->depth) idx = idx - rptr->depth; } -if ((rptr->depth > 1) && (rptr->flags & REG_UNIT)) { - uptr = ((UNIT *) rptr->loc) + idx; -#if defined (t_int64) - if (sz <= sizeof (uint32)) val = *((uint32 *) uptr); - else val = *((t_uint64 *) uptr); } -#else - val = *((uint32 *) uptr); } -#endif -else if ((rptr->depth > 1) && (sz == sizeof (uint8))) - val = *(((uint8 *) rptr->loc) + idx); -else if ((rptr->depth > 1) && (sz == sizeof (uint16))) - val = *(((uint16 *) rptr->loc) + idx); -#if defined (t_int64) -else if (sz <= sizeof (uint32)) - val = *(((uint32 *) rptr->loc) + idx); -else val = *(((t_uint64 *) rptr->loc) + idx); -#else -else val = *(((uint32 *) rptr->loc) + idx); -#endif -val = (val >> rptr->offset) & width_mask[rptr->width]; -return val; -} - -/* Deposit register routine - - Inputs: - flag = type of deposit (normal/interactive) - cptr = pointer to input string - rptr = pointer to register descriptor - idx = index - Outputs: - return = error status -*/ - -t_stat dep_reg (int32 flag, char *cptr, REG *rptr, uint32 idx) -{ -t_stat r; -t_value val, mask; -int32 rdx; -char gbuf[CBUFSIZE]; - -if ((cptr == NULL) || (rptr == NULL)) return SCPE_IERR; -if (rptr->flags & REG_RO) return SCPE_RO; -if (flag & EX_I) { - cptr = read_line (gbuf, CBUFSIZE, stdin); - if (sim_log) fprintf (sim_log, (cptr? "%s\n": "\n"), cptr); - if (cptr == NULL) return 1; /* force exit */ - if (*cptr == 0) return SCPE_OK; } /* success */ -mask = width_mask[rptr->width]; -GET_RADIX (rdx, rptr->radix); -if (rptr->flags & REG_VMIO) - r = parse_sym (cptr, rdx, NULL, &val, REG_VMIO); -else val = get_uint (cptr, rdx, mask, &r); -if (r != SCPE_OK) return SCPE_ARG; -if ((rptr->flags & REG_NZ) && (val == 0)) return SCPE_ARG; -put_rval (rptr, idx, val); -return SCPE_OK; -} - -/* Put register value - - Inputs: - rptr = pointer to register descriptor - idx = index - val = new value - mask = mask - Outputs: - none -*/ - -void put_rval (REG *rptr, uint32 idx, t_value val) -{ -size_t sz; -t_value mask; -UNIT *uptr; - -#define PUT_RVAL(sz,rp,id,v,m) \ - *(((sz *) rp->loc) + id) = \ - (*(((sz *) rp->loc) + id) & \ - ~((m) << (rp)->offset)) | ((v) << (rp)->offset) - -if (rptr == sim_PC) sim_brk_npc (); -sz = SZ_R (rptr); -mask = width_mask[rptr->width]; -if ((rptr->depth > 1) && (rptr->flags & REG_CIRC)) { - idx = idx + rptr->qptr; - if (idx >= rptr->depth) idx = idx - rptr->depth; } -if ((rptr->depth > 1) && (rptr->flags & REG_UNIT)) { - uptr = ((UNIT *) rptr->loc) + idx; -#if defined (t_int64) - if (sz <= sizeof (uint32)) - *((uint32 *) uptr) = (*((uint32 *) uptr) & - ~(((uint32) mask) << rptr->offset)) | - (((uint32) val) << rptr->offset); - else *((t_uint64 *) uptr) = (*((t_uint64 *) uptr) - & ~(mask << rptr->offset)) | (val << rptr->offset); } -#else - *((uint32 *) uptr) = (*((uint32 *) uptr) & - ~(((uint32) mask) << rptr->offset)) | - (((uint32) val) << rptr->offset); } -#endif -else if ((rptr->depth > 1) && (sz == sizeof (uint8))) - PUT_RVAL (uint8, rptr, idx, (uint32) val, (uint32) mask); -else if ((rptr->depth > 1) && (sz == sizeof (uint16))) - PUT_RVAL (uint16, rptr, idx, (uint32) val, (uint32) mask); -#if defined (t_int64) -else if (sz <= sizeof (uint32)) - PUT_RVAL (uint32, rptr, idx, (int32) val, (uint32) mask); -else PUT_RVAL (t_uint64, rptr, idx, val, mask); -#else -else PUT_RVAL (uint32, rptr, idx, val, mask); -#endif -return; -} - -/* Examine address routine - - Inputs: (sim_eval is an implicit argument) - ofile = output stream - flag = type of ex/mod command (ex, iex, idep) - addr = address to examine - dptr = pointer to device - uptr = pointer to unit - Outputs: - return = if >= 0, error status - if < 0, number of extra words retired -*/ - -t_stat ex_addr (FILE *ofile, int32 flag, t_addr addr, DEVICE *dptr, UNIT *uptr) -{ -t_stat reason; -int32 rdx; - -fprint_val (ofile, addr, dptr->aradix, dptr->awidth, PV_LEFT); -fprintf (ofile, ": "); -if (!(flag & EX_E)) return SCPE_OK; - -GET_RADIX (rdx, dptr->dradix); -if ((reason = fprint_sym (ofile, addr, sim_eval, uptr, sim_switches)) > 0) - reason = fprint_val (ofile, sim_eval[0], rdx, dptr->dwidth, PV_RZRO); -if (flag & EX_I) fprintf (ofile, " "); -else fprintf (ofile, "\n"); -return reason; -} - -/* Get address routine - - Inputs: - flag = type of ex/mod command (ex, iex, idep) - addr = address to examine - dptr = pointer to device - uptr = pointer to unit - Outputs: (sim_eval is an implicit output) - return = error status -*/ - -t_stat get_aval (t_addr addr, DEVICE *dptr, UNIT *uptr) -{ -int32 i; -t_value mask; -t_addr j, loc; -size_t sz; -t_stat reason = SCPE_OK; - -if ((dptr == NULL) || (uptr == NULL)) return SCPE_IERR; -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_ext (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; -} - -/* Deposit address routine - - Inputs: - flag = type of deposit (normal/interactive) - cptr = pointer to input string - addr = address to examine - dptr = pointer to device - uptr = pointer to unit - dfltinc = value to return on cr input - Outputs: - return = if >= 0, error status - if < 0, number of extra words retired -*/ - -t_stat dep_addr (int32 flag, char *cptr, t_addr addr, DEVICE *dptr, - UNIT *uptr, int32 dfltinc) -{ -int32 i, count, rdx; -t_addr j, loc; -t_stat r, reason; -t_value mask; -size_t sz; -char gbuf[CBUFSIZE]; - -if (dptr == NULL) return SCPE_IERR; -if (flag & EX_I) { - cptr = read_line (gbuf, CBUFSIZE, stdin); - if (sim_log) fprintf (sim_log, (cptr? "%s\n": "\n"), cptr); - if (cptr == NULL) return 1; /* force exit */ - if (*cptr == 0) return dfltinc; } /* success */ -if (uptr->flags & UNIT_RO) return SCPE_RO; /* read only? */ -mask = width_mask[dptr->dwidth]; - -GET_RADIX (rdx, dptr->dradix); -if ((reason = parse_sym (cptr, addr, uptr, sim_eval, sim_switches)) > 0) { - sim_eval[0] = get_uint (cptr, rdx, mask, &reason); - if (reason != SCPE_OK) return reason; } -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 = (uint32) loc + 1; } - else { - fseek_ext (uptr->fileref, sz * loc, SEEK_SET); - fxwrite (&sim_eval[i], 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) -{ -DEVICE *dptr = sim_devices[0]; -int32 i, count, rdx; -t_stat r; - -GET_SWITCHES (cptr); -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 - - Inputs: - cptr = pointer to buffer - size = maximum size - stream = pointer to input stream - Outputs: - optr = pointer to first non-blank character - NULL if EOF -*/ - -char *read_line (char *cptr, int32 size, FILE *stream) -{ -char *tptr; - -cptr = fgets (cptr, size, stream); /* get cmd line */ -if (cptr == NULL) { - clearerr (stream); /* clear error */ - return NULL; } /* ignore EOF */ -for (tptr = cptr; tptr < (cptr + size); tptr++) /* remove cr or nl */ - if ((*tptr == '\n') || (*tptr == '\r')) *tptr = 0; -while (isspace (*cptr)) cptr++; /* absorb spaces */ -if (*cptr == ';') *cptr = 0; /* ignore comment */ -return cptr; -} - -/* get_glyph get next glyph (force upper case) - get_glyph_nc get next glyph (no conversion) - get_glyph_gen get next glyph (general case) - - Inputs: - iptr = pointer to input string - optr = pointer to output string - mchar = optional end of glyph character - flag = TRUE for convert to upper case (_gen only) - Outputs - result = pointer to next character in input string -*/ - -char *get_glyph_gen (char *iptr, char *optr, char mchar, t_bool uc) -{ -while ((isspace (*iptr) == 0) && (*iptr != 0) && (*iptr != mchar)) { - if (islower (*iptr) && uc) *optr = toupper (*iptr); - else *optr = *iptr; - iptr++; optr++; } -*optr = 0; -if (mchar && (*iptr == mchar)) iptr++; /* skip terminator */ -while (isspace (*iptr)) iptr++; /* absorb spaces */ -return iptr; -} - -char *get_glyph (char *iptr, char *optr, char mchar) -{ -return get_glyph_gen (iptr, optr, mchar, TRUE); -} - -char *get_glyph_nc (char *iptr, char *optr, char mchar) -{ -return get_glyph_gen (iptr, optr, mchar, FALSE); -} - -/* get_yn yes/no question - - Inputs: - cptr = pointer to question - deflt = default answer - Outputs: - result = true if yes, false if no -*/ - -t_stat get_yn (char *ques, t_stat deflt) -{ -char cbuf[CBUFSIZE], *cptr; - -printf ("%s ", ques); -cptr = read_line (cbuf, CBUFSIZE, stdin); -if ((cptr == NULL) || (*cptr == 0)) return deflt; -if ((*cptr == 'Y') || (*cptr == 'y')) return TRUE; -return FALSE; -} - -/* get_uint unsigned number - - Inputs: - cptr = pointer to input string - radix = input radix - max = maximum acceptable value - *status = pointer to error status - Outputs: - val = value -*/ - -t_value get_uint (char *cptr, uint32 radix, t_value max, t_stat *status) -{ -t_value val; -char *tptr; - -*status = SCPE_OK; -val = strtotv (cptr, &tptr, radix); -if ((cptr == tptr) || (val > max)) *status = SCPE_ARG; -else { while (isspace (*tptr)) tptr++; - if (*tptr != 0) *status = SCPE_ARG; } -return val; -} - -/* get_range range specification - - Inputs: - cptr = pointer to input string - *lo = pointer to low result - *hi = pointer to high result - aradix = address radix - max = default high value - term = terminating character, 0 if none - Outputs: - tptr = input pointer after processing - NULL if error -*/ - -char *get_range (char *cptr, t_addr *lo, t_addr *hi, uint32 rdx, - t_addr max, char term) -{ -char *tptr; - -if (max && strncmp (cptr, "ALL", strlen ("ALL")) == 0) { /* ALL? */ - tptr = cptr + strlen ("ALL"); - *lo = 0; - *hi = max; } -else { *lo = (t_addr) strtotv (cptr, &tptr, rdx); /* get low */ - if (cptr == tptr) return NULL; /* error? */ - if ((*tptr == '-') || (*tptr == ':')) { /* range? */ - cptr = tptr + 1; - *hi = (t_addr) strtotv (cptr, &tptr, rdx); /* get high */ - if (cptr == tptr) return NULL; - if (*lo > *hi) return NULL; } - else if (*tptr == '/') { /* relative? */ - cptr = tptr + 1; - *hi = (t_addr) strtotv (cptr, &tptr, rdx); /* get high */ - if ((cptr == tptr) || (*hi == 0)) return NULL; - *hi = *lo + *hi - 1; } - 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 - - Inputs: - cptr = pointer to input string - Outputs: - result = pointer to device -*/ - -DEVICE *find_dev (char *cptr) -{ -int32 i; -DEVICE *dptr; - -for (i = 0; (dptr = sim_devices[i]) != NULL; i++) { - if ((strcmp (cptr, dptr->name) == 0) || - (dptr->lname && - (strcmp (cptr, dptr->lname) == 0))) return dptr; } -return NULL; -} - -/* Find_unit find unit matching input string - - Inputs: - cptr = pointer to input string - uptr = pointer to unit pointer - Outputs: - result = pointer to device (null if no dev) - *iptr = pointer to unit (null if nx unit) -*/ - -DEVICE *find_unit (char *cptr, UNIT **uptr) -{ -uint32 i, u; -char *nptr, *tptr; -t_stat r; -DEVICE *dptr; - -if (uptr == NULL) return NULL; /* arg error? */ -if (dptr = find_dev (cptr)) { /* exact match? */ - 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 && /* any units? */ - (((nptr = dptr->name) && - (strncmp (cptr, nptr, strlen (nptr)) == 0)) || - ((nptr = dptr->lname) && - (strncmp (cptr, nptr, strlen (nptr)) == 0)))) { - tptr = cptr + strlen (nptr); - if (isdigit (*tptr)) { - if (qdisable (dptr)) return NULL; /* disabled? */ - u = (uint32) get_uint (tptr, 10, dptr->numunits - 1, &r); - if (r != SCPE_OK) *uptr = NULL; /* error? */ - else *uptr = dptr->units + u; - return dptr; } } } -return NULL; -} - -/* Find_dev_from_unit find device for unit - - Inputs: - uptr = pointer to unit - Outputs: - result = pointer to device -*/ - -DEVICE *find_dev_from_unit (UNIT *uptr) -{ -DEVICE *dptr; -uint32 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; } } -return NULL; -} - -/* Test for disabled device */ - -t_bool qdisable (DEVICE *dptr) -{ -return (dptr->flags & DEV_DIS? TRUE: FALSE); -} - -/* find_reg_glob find globally unique register - - Inputs: - cptr = pointer to input string - optr = pointer to output pointer (can be null) - gdptr = pointer to global device - Outputs: - result = pointer to register, NULL if error - *optr = pointer to next character in input string - *gdptr = pointer to device where found -*/ - -REG *find_reg_glob (char *cptr, char **optr, DEVICE **gdptr) -{ -int32 i; -DEVICE *dptr; -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 */ -return srptr; -} - -/* find_reg find register matching input string - - Inputs: - cptr = pointer to input string - optr = pointer to output pointer (can be null) - dptr = pointer to device - Outputs: - result = pointer to register, NULL if error - *optr = pointer to next character in input string -*/ - -REG *find_reg (char *cptr, char **optr, DEVICE *dptr) -{ -char *tptr; -REG *rptr; -uint32 slnt; - -if ((cptr == NULL) || (dptr == NULL) || - (dptr->registers == NULL)) return NULL; -tptr = cptr; -do { tptr++; } - while (isalnum (*tptr) || (*tptr == '*') || (*tptr == '_')); -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; } } -return NULL; -} - -/* get_switches get switches from input string - - Inputs: - cptr = pointer to input string - Outputs: - sw = switch bit mask - 0 if no switches, -1 if error -*/ - -int32 get_switches (char *cptr) -{ -int32 sw; - -if (*cptr != '-') return 0; -sw = 0; -for (cptr++; (isspace (*cptr) == 0) && (*cptr != 0); cptr++) { - if (isalpha (*cptr) == 0) return -1; - sw = sw | SWMASK (toupper (*cptr)); } -return sw; -} - -/* get_sim_sw accumulate sim_switches - - Inputs: - cptr = pointer to input string - Outputs: - ptr = pointer to first non-string glyph - NULL if error -*/ - -char *get_sim_sw (char *cptr) -{ -int32 lsw; -char gbuf[CBUFSIZE]; - -while (*cptr == '-') { /* while switches */ - cptr = get_glyph (cptr, gbuf, 0); /* get switch glyph */ - lsw = get_switches (gbuf); /* parse */ - if (lsw <= 0) return NULL; /* invalid? */ - sim_switches = sim_switches | lsw; } /* accumulate */ -return cptr; -} - -/* Match file extension - - Inputs: - fnam = file name - ext = extension, without period - Outputs: - cp = pointer to final '.' if match, NULL if not -*/ - -char *match_ext (char *fnam, char *ext) -{ -char *pptr, *fptr, *eptr; - -if ((fnam == NULL) || (ext == NULL)) return NULL; -pptr = strrchr (fnam, '.'); -if (pptr) { - for (fptr = pptr + 1, eptr = ext; *fptr; fptr++, eptr++) { - if (toupper (*fptr) != toupper (*eptr)) return NULL; } - if (*eptr) return NULL; } -return pptr; -} - -/* Get search specification - - Inputs: - cptr = pointer to input string - dptr = pointer to device - schptr = pointer to search table - Outputs: - return = NULL if error - schptr if valid search specification -*/ - -SCHTAB *get_search (char *cptr, DEVICE *dptr, SCHTAB *schptr) -{ -int32 c, logop, cmpop; -t_value logval, cmpval; -char *sptr, *tptr; -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; } - 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; } - else return NULL; } /* end while */ -if (logop >= 0) { - schptr->logic = logop; - schptr->mask = logval; } -if (cmpop >= 0) { - schptr->bool = cmpop; - schptr->comp = cmpval; } -return schptr; -} - -/* Test value against search specification - - Inputs: - val = value to test - schptr = pointer to search table - Outputs: - return = 1 if value passes search criteria, 0 if not -*/ - -int32 test_search (t_value val, SCHTAB *schptr) -{ -if (schptr == NULL) return 0; -switch (schptr->logic) { /* case on logical */ -case SCH_OR: - val = val | schptr->mask; - break; -case SCH_AND: - val = val & schptr->mask; - break; -case SCH_XOR: - val = val ^ schptr->mask; - break; } -switch (schptr->bool) { /* case on comparison */ -case SCH_E: case SCH_EE: - return (val == schptr->comp); -case SCH_N: case SCH_NE: - return (val != schptr->comp); -case SCH_G: - return (val > schptr->comp); -case SCH_GE: - return (val >= schptr->comp); -case SCH_L: - return (val < schptr->comp); -case SCH_LE: - return (val <= schptr->comp); } -return 0; -} - -/* Radix independent input/output package - - strtotv - general radix input routine - - Inputs: - inptr = string to convert - endptr = pointer to first unconverted character - radix = radix for input - Outputs: - value = converted value - - On an error, the endptr will equal the inptr. -*/ - -t_value strtotv (char *inptr, char **endptr, uint32 radix) -{ -int32 nodigit; -t_value val; -uint32 c, digit; - -*endptr = inptr; /* assume fails */ -if ((radix < 2) || (radix > 36)) return 0; -while (isspace (*inptr)) inptr++; /* bypass white space */ -val = 0; -nodigit = 1; -for (c = *inptr; isalnum(c); c = *++inptr) { /* loop through char */ - if (islower (c)) c = toupper (c); - if (isdigit (c)) digit = c - (uint32) '0'; /* digit? */ - else digit = c + 10 - (uint32) 'A'; /* no, letter */ - if (digit >= radix) return 0; /* valid in radix? */ - val = (val * radix) + digit; /* add to value */ - nodigit = 0; } -if (nodigit) return 0; /* no digits? */ -*endptr = inptr; /* result pointer */ -return val; -} - -/* fprint_val - general radix printing routine - - Inputs: - stream = stream designator - val = value to print - radix = radix to print - width = width to print - format = leading zeroes format - Outputs: - status = error status -*/ - -t_stat fprint_val (FILE *stream, t_value val, uint32 radix, - uint32 width, uint32 format) -{ -#define MAX_WIDTH ((int) (CHAR_BIT * sizeof (t_value))) -t_value owtest, wtest; -int32 d, digit, ndigits; -char dbuf[MAX_WIDTH + 1]; - -for (d = 0; d < MAX_WIDTH; d++) dbuf[d] = (format == PV_RZRO)? '0': ' '; -dbuf[MAX_WIDTH] = 0; -d = MAX_WIDTH; -do { d = d - 1; - digit = (int32) (val % radix); - val = val / radix; - dbuf[d] = (digit <= 9)? '0' + digit: 'A' + (digit - 10); - } while ((d > 0) && (val != 0)); - -if (format != PV_LEFT) { - wtest = owtest = radix; - ndigits = 1; - while ((wtest < width_mask[width]) && (wtest >= owtest)) { - 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; -} - -/* Event queue package - - sim_activate add entry to event queue - sim_cancel remove entry from event queue - sim_process_event process entries on event queue - sim_is_active see if entry is on event queue - sim_atime return absolute time for an entry - sim_gtime return global time - sim_qcount return event queue entry count - - Asynchronous events are set up by queueing a unit data structure - to the event queue with a timeout (in simulator units, relative - to the current time). Each simulator 'times' these events by - counting down interval counter sim_interval. When this reaches - zero the simulator calls sim_process_event to process the event - and to see if further events need to be processed, or sim_interval - reset to count the next one. - - The event queue is maintained in clock order; entry timeouts are - RELATIVE to the time in the previous entry. - - sim_process_event - process event - - Inputs: - none - Outputs: - reason reason code returned by any event processor, - or 0 (SCPE_OK) if no exceptions -*/ - -t_stat sim_process_event (void) -{ -UNIT *uptr; -t_stat reason; - -if (stop_cpu) return SCPE_STOP; /* stop CPU? */ -if (sim_clock_queue == NULL) { /* queue empty? */ - UPDATE_SIM_TIME (noqueue_time); /* update sim time */ - sim_interval = noqueue_time = NOQUEUE_WAIT; /* flag queue empty */ - return SCPE_OK; } -UPDATE_SIM_TIME (sim_clock_queue->time); /* update sim time */ -do { uptr = sim_clock_queue; /* get first */ - sim_clock_queue = uptr->next; /* remove first */ - uptr->next = NULL; /* hygiene */ - uptr->time = 0; - if (sim_clock_queue != NULL) sim_interval = sim_clock_queue->time; - else sim_interval = noqueue_time = NOQUEUE_WAIT; - if (uptr->action != NULL) reason = uptr->action (uptr); - else reason = SCPE_OK; - } while ((reason == SCPE_OK) && (sim_interval == 0)); - -/* Empty queue forces sim_interval != 0 */ - -return reason; -} - -/* sim_activate - activate (queue) event - - Inputs: - uptr = pointer to unit - event_time = relative timeout - Outputs: - reason = result (SCPE_OK if ok) -*/ - -t_stat sim_activate (UNIT *uptr, int32 event_time) -{ -UNIT *cptr, *prvptr; -int32 accum; - -if (event_time < 0) return SCPE_IERR; -if (sim_is_active (uptr)) return SCPE_OK; /* already active? */ -if (sim_clock_queue == NULL) { UPDATE_SIM_TIME (noqueue_time); } -else { UPDATE_SIM_TIME (sim_clock_queue->time); } /* update sim time */ - -prvptr = NULL; -accum = 0; -for (cptr = sim_clock_queue; cptr != NULL; cptr = cptr->next) { - if (event_time < (accum + cptr->time)) break; - accum = accum + cptr->time; - prvptr = cptr; } -if (prvptr == NULL) { /* insert at head */ - cptr = uptr->next = sim_clock_queue; - sim_clock_queue = uptr; } -else { cptr = uptr->next = prvptr->next; /* insert at prvptr */ - prvptr->next = uptr; } -uptr->time = event_time - accum; -if (cptr != NULL) cptr->time = cptr->time - uptr->time; -sim_interval = sim_clock_queue->time; -return SCPE_OK; -} - -/* sim_cancel - cancel (dequeue) event - - Inputs: - uptr = pointer to unit - Outputs: - reason = result (SCPE_OK if ok) - -*/ - -t_stat sim_cancel (UNIT *uptr) -{ -UNIT *cptr, *nptr; - -if (sim_clock_queue == NULL) return SCPE_OK; -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 (nptr != NULL) nptr->time = nptr->time + uptr->time; -uptr->next = NULL; /* hygiene */ -uptr->time = 0; -if (sim_clock_queue != NULL) sim_interval = sim_clock_queue->time; -else sim_interval = noqueue_time = NOQUEUE_WAIT; -return SCPE_OK; -} - -/* sim_is_active - test for entry in queue, return activation time - - Inputs: - uptr = pointer to unit - Outputs: - result = absolute activation time + 1, 0 if inactive -*/ - -int32 sim_is_active (UNIT *uptr) -{ -UNIT *cptr; -int32 accum; - -accum = 0; -for (cptr = sim_clock_queue; cptr != NULL; cptr = cptr->next) { - accum = accum + cptr->time; - if (cptr == uptr) return accum + 1; } -return 0; -} - -/* sim_gtime - return global time - sim_grtime - return global time with rollover - - Inputs: none - Outputs: - time = global time -*/ - -double sim_gtime (void) -{ -if (sim_clock_queue == NULL) { UPDATE_SIM_TIME (noqueue_time); } -else { UPDATE_SIM_TIME (sim_clock_queue->time); } -return sim_time; -} - -uint32 sim_grtime (void) -{ -if (sim_clock_queue == NULL) { UPDATE_SIM_TIME (noqueue_time); } -else { UPDATE_SIM_TIME (sim_clock_queue->time); } -return sim_rtime; -} - -/* sim_qcount - return queue entry count - - Inputs: none - Outputs: - count = number of entries on the queue -*/ - -int32 sim_qcount (void) -{ -int32 cnt; -UNIT *uptr; - -cnt = 0; -for (uptr = sim_clock_queue; uptr != NULL; uptr = uptr->next) cnt++; -return cnt; -} - -/* Endian independent binary I/O package - - For consistency, all binary data read and written by the simulator - is stored in little endian data order. That is, in a multi-byte - data item, the bytes are written out right to left, low order byte - to high order byte. On a big endian host, data is read and written - from high byte to low byte. Consequently, data written on a little - endian system must be byte reversed to be usable on a big endian - system, and vice versa. - - These routines are analogs of the standard C runtime routines - fread and fwrite. If the host is little endian, or the data items - are size char, then the calls are passed directly to fread or - fwrite. Otherwise, these routines perform the necessary byte swaps - using an intermediate buffer. -*/ - -size_t fxread (void *bptr, size_t size, size_t count, FILE *fptr) -{ -size_t c, j, nelem, nbuf, lcnt, total; -int32 i, k; -unsigned char *sptr, *dptr; - -if (sim_end || (size == sizeof (char))) - return fread (bptr, size, count, fptr); -if ((size == 0) || (count == 0)) return 0; -nelem = FLIP_SIZE / size; /* elements in buffer */ -nbuf = count / nelem; /* number buffers */ -lcnt = count % nelem; /* count in last buf */ -if (lcnt) nbuf = nbuf + 1; -else lcnt = nelem; -total = 0; -dptr = bptr; /* init output ptr */ -for (i = nbuf; i > 0; i--) { - c = fread (sim_flip, size, (i == 1? lcnt: nelem), fptr); - 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; } } -return total; -} - -size_t fxwrite (void *bptr, size_t size, size_t count, FILE *fptr) -{ -size_t c, j, nelem, nbuf, lcnt, total; -int32 i, k; -unsigned char *sptr, *dptr; - -if (sim_end || (size == sizeof (char))) - return fwrite (bptr, size, count, fptr); -if ((size == 0) || (count == 0)) return 0; -nelem = FLIP_SIZE / size; /* elements in buffer */ -nbuf = count / nelem; /* number buffers */ -lcnt = count % nelem; /* count in last buf */ -if (lcnt) nbuf = nbuf + 1; -else lcnt = nelem; -total = 0; -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; } - c = fwrite (sim_flip, size, c, fptr); - if (c == 0) return total; - total = total + c; } -return total; -} - -/* Get file size */ - -uint32 sim_fsize (char *cptr) -{ -FILE *fp; -uint32 sz; - -fp = fopen (cptr, "rb"); -if (fp == NULL) return 0; -fseek (fp, 0, SEEK_END); -sz = ftell (fp); -fclose (fp); -return sz; -} - -/* OS independent clock calibration package - - sim_rtc_init initialize calibration - sim_rtc_calb calibrate clock -*/ - -static int32 rtc_ticks[SIM_NTIMERS] = { 0 }; /* ticks */ -static uint32 rtc_rtime[SIM_NTIMERS] = { 0 }; /* real time */ -static uint32 rtc_vtime[SIM_NTIMERS] = { 0 }; /* virtual time */ -static uint32 rtc_nxintv[SIM_NTIMERS] = { 0 }; /* next interval */ -static int32 rtc_based[SIM_NTIMERS] = { 0 }; /* base delay */ -static int32 rtc_currd[SIM_NTIMERS] = { 0 }; /* current delay */ -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]; -rtc_nxintv[tmr] = 1000; -rtc_ticks[tmr] = 0; -rtc_based[tmr] = time; -rtc_currd[tmr] = time; -return time; -} - -int32 sim_rtcn_calb (int32 ticksper, int32 tmr) -{ -uint32 new_rtime, delta_rtime; -int32 delta_vtime; - -if ((tmr < 0) || (tmr >= SIM_NTIMERS)) return 10000; -rtc_ticks[tmr] = rtc_ticks[tmr] + 1; /* count ticks */ -if (rtc_ticks[tmr] < ticksper) return rtc_currd[tmr]; /* 1 sec yet? */ -rtc_ticks[tmr] = 0; /* reset ticks */ -if (!rtc_avail) return rtc_currd[tmr]; /* no timer? */ -new_rtime = sim_os_msec (); /* wall time */ -if (new_rtime < rtc_rtime[tmr]) { /* time running backwards? */ - rtc_rtime[tmr] = new_rtime; /* reset wall time */ - return rtc_currd[tmr]; } /* can't calibrate */ -delta_rtime = new_rtime - rtc_rtime[tmr]; /* elapsed wtime */ -rtc_rtime[tmr] = new_rtime; /* adv wall time */ -if ((delta_rtime == 0) || (delta_rtime > 30000)) /* gap 0 or too big? */ - return rtc_currd[tmr]; /* can't calibr */ -rtc_based[tmr] = (int32) (((double) rtc_based[tmr] * (double) rtc_nxintv[tmr]) / - ((double) delta_rtime)); /* new base rate */ -rtc_vtime[tmr] = rtc_vtime[tmr] + 1000; /* adv sim time */ -delta_vtime = rtc_vtime[tmr] - rtc_rtime[tmr]; /* gap */ -if (delta_vtime > SIM_TMAX) delta_vtime = SIM_TMAX; /* limit gap */ -else if (delta_vtime < -SIM_TMAX) delta_vtime = -SIM_TMAX; -rtc_nxintv[tmr] = 1000 + delta_vtime; /* next wtime */ -rtc_currd[tmr] = (int32) (((double) rtc_based[tmr] * (double) rtc_nxintv[tmr]) / - 1000.0); /* next delay */ -if (rtc_currd[tmr] <= 0) rtc_currd[tmr] = 1; /* never negative or zero! */ -return rtc_currd[tmr]; -} - -/* Prior interfaces - default to timer 0 */ - -int32 sim_rtc_init (int32 time) -{ -return sim_rtcn_init (time, 0); -} - -int32 sim_rtc_calb (int32 ticksper) -{ -return sim_rtcn_calb (ticksper, 0); -} - -/* Breakpoint package. This module replaces the VM-implemented one - instruction breakpoint capability. - - Breakpoints are stored in table sim_brk_tab, which is ordered by address for - efficient binary searching. A breakpoint consists of a four entry structure: - - addr address of the breakpoint - type types of breakpoints set on the address - a bit mask representing letters A-Z - cnt number of iterations before breakp is taken - action pointer command string to be executed - when break is taken - - sim_brk_summ is a summary of the types of breakpoints that are currently set (it - is the bitwise OR of all the type fields). A simulator need only check for - a breakpoint of type X if bit SWMASK('X') is set in sim_brk_sum. - - The package contains the following public routines: - - sim_brk_init initialize - sim_brk_set set breakpoint - sim_brk_clr clear breakpoint - sim_brk_clrall clear all breakpoints - sim_brk_show show breakpoint - sim_brk_showall show all breakpoints - sim_brk_test test for breakpoint - sim_brk_npc PC has been changed - sim_brk_getact get next action - sim_brk_clract clear pending actions - - Initialize breakpoint system. -*/ - -t_stat sim_brk_init (void) -{ -sim_brk_lnt = SIM_BRK_INILNT; -sim_brk_tab = calloc (sim_brk_lnt, sizeof (BRKTAB)); -if (sim_brk_tab == NULL) return SCPE_MEM; -sim_brk_ent = sim_brk_ins = 0; -sim_brk_pend = FALSE; -sim_brk_act = NULL; -return SCPE_OK; -} - -/* Search for a breakpoint in the sorted breakpoint table */ - -BRKTAB *sim_brk_fnd (t_addr loc) -{ -int32 lo, hi, p; -BRKTAB *bp; - -if (sim_brk_ent == 0) { /* table empty? */ - sim_brk_ins = 0; /* insrt at head */ - return NULL; } /* sch fails */ -lo = 0; /* initial bounds */ -hi = sim_brk_ent - 1; -do { p = (lo + hi) >> 1; /* probe */ - bp = sim_brk_tab + p; /* table addr */ - if (loc == bp->addr) return bp; /* match? */ - else if (loc < bp->addr) hi = p - 1; /* go down? p is upper */ - else lo = p + 1; } /* go up? p is lower */ -while (lo <= hi); -if (loc < bp->addr) sim_brk_ins = p; /* insrt before or */ -else sim_brk_ins = p + 1; /* after last sch */ -return NULL; -} - -/* Insert a breakpoint */ - -BRKTAB *sim_brk_new (t_addr loc) -{ -int32 i, t; -BRKTAB *bp, *newp; - -if (sim_brk_ins < 0) return NULL; -if (sim_brk_ent >= sim_brk_lnt) { /* out of space? */ - t = sim_brk_lnt + SIM_BRK_INILNT; /* new size */ - newp = calloc (t, sizeof (BRKTAB)); /* new table */ - if (newp == NULL) return NULL; /* can't extend */ - for (i = 0; i < sim_brk_lnt; i++) /* copy table */ - *(newp + i) = *(sim_brk_tab + i); - free (sim_brk_tab); /* free old table */ - sim_brk_tab = newp; /* new base, lnt */ - sim_brk_lnt = t; } -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 = sim_brk_tab + sim_brk_ins; -bp->addr = loc; -bp->typ = 0; -bp->cnt = 0; -bp->act = NULL; -sim_brk_ent = sim_brk_ent + 1; -return bp; -} - -/* Set a breakpoint of type sw */ - -t_stat sim_brk_set (t_addr loc, int32 sw, int32 ncnt, char *act) -{ -BRKTAB *bp; - -if (sw == 0) sw = sim_brk_dflt; -if ((sim_brk_types & sw) == 0) return SCPE_NOFNC; -bp = sim_brk_fnd (loc); /* present? */ -if (!bp) bp = sim_brk_new (loc); /* no, allocate */ -if (!bp) return SCPE_MEM; /* still no? mem err */ -bp->typ = sw; /* set type */ -bp->cnt = ncnt; /* set count */ -if ((bp->act != NULL) && (act != NULL)) { /* replace old action? */ - free (bp->act); /* deallocate */ - bp->act = NULL; } /* now no action */ -if ((act != NULL) && (*act != 0)) { /* new action? */ - char *newp = calloc (CBUFSIZE, sizeof (char)); /* allocate buffer */ - if (newp == NULL) return SCPE_MEM; /* mem err? */ - strncpy (newp, act, CBUFSIZE); /* copy action */ - bp->act = newp; } /* set pointer */ -sim_brk_summ = sim_brk_summ | sw; -return SCPE_OK; -} - -/* Clear a breakpoint */ - -t_stat sim_brk_clr (t_addr loc, int32 sw) -{ -BRKTAB *bp = sim_brk_fnd (loc); - -if (!bp) return SCPE_OK; /* not there? ok */ -if (sw == 0) sw = SIM_BRK_ALLTYP; -bp->typ = bp->typ & ~sw; -if (bp->typ) return SCPE_OK; /* clear all types? */ -if (bp->act != NULL) free (bp->act); /* deallocate action */ -for ( ; bp < (sim_brk_tab + sim_brk_ent - 1); bp++) /* erase entry */ - *bp = *(bp + 1); -sim_brk_ent = sim_brk_ent - 1; /* decrement count */ -sim_brk_summ = 0; /* recalc summary */ -for (bp = sim_brk_tab; bp < (sim_brk_tab + sim_brk_ent); bp++) - sim_brk_summ = sim_brk_summ | bp->typ; -return SCPE_OK; -} - -/* Clear all breakpoints */ - -t_stat sim_brk_clrall (int32 sw) -{ -BRKTAB *bp; - -if (sw == 0) sw = SIM_BRK_ALLTYP; -for (bp = sim_brk_tab; bp < (sim_brk_tab + sim_brk_ent); ) { - if (bp->typ & sw) sim_brk_clr (bp->addr, sw); - else bp++; } -return SCPE_OK; -} - -/* Show a breakpoint */ - -t_stat sim_brk_show (FILE *st, t_addr loc, int32 sw) -{ -BRKTAB *bp = sim_brk_fnd (loc); -DEVICE *dptr; -int32 i, any; - -if (sw == 0) sw = SIM_BRK_ALLTYP; -if (!bp || (!(bp->typ & sw))) return SCPE_OK; -dptr = sim_devices[0]; -if (dptr == NULL) return SCPE_OK; -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 (bp->cnt > 0) fprintf (st, " [%d]", bp->cnt); -if (bp->act != NULL) fprintf (st, "; %s", bp->act); -fprintf (st, "\n"); -return SCPE_OK; -} - -/* Show all breakpoints */ - -t_stat sim_brk_showall (FILE *st, int32 sw) -{ -BRKTAB *bp; - -if (sw == 0) sw = SIM_BRK_ALLTYP; -for (bp = sim_brk_tab; bp < (sim_brk_tab + sim_brk_ent); bp++) { - if (bp->typ & sw) sim_brk_show (st, bp->addr, sw); } -return SCPE_OK; -} - -/* Test for breakpoint */ - -t_bool sim_brk_test (t_addr loc, int32 btyp) -{ -BRKTAB *bp; - -if ((bp = sim_brk_fnd (loc)) && /* entry in table? */ - (btyp & bp->typ) && /* type match? */ - (!sim_brk_pend || (loc != sim_brk_ploc)) && /* new location? */ - (--(bp->cnt) <= 0)) { /* count reach 0? */ - bp->cnt = 0; /* reset count */ - sim_brk_ploc = loc; /* save location */ - sim_brk_act = bp->act; /* set up actions */ - sim_brk_pend = TRUE; /* don't do twice */ - return TRUE; } -sim_brk_pend = FALSE; -return FALSE; -} - -/* Get next pending action, if any */ - -char *sim_brk_getact (char *buf, int32 size) -{ -char *ep; -size_t lnt; - -if (sim_brk_act == NULL) return NULL; /* any action? */ -while (isspace (*sim_brk_act)) sim_brk_act++; /* skip spaces */ -if (*sim_brk_act == 0) return (sim_brk_act = NULL); /* now empty? */ -if (ep = strchr (sim_brk_act, ';')) { /* cmd delimiter? */ - lnt = ep - sim_brk_act; /* cmd length */ - memcpy (buf, sim_brk_act, lnt + 1); /* copy with ; */ - buf[lnt] = 0; /* erase ; */ - sim_brk_act = sim_brk_act + lnt + 1; } /* adv ptr */ -else { strncpy (buf, sim_brk_act, size); /* copy action */ - sim_brk_act = NULL; } /* no more */ -return buf; -} - -/* Clear pending actions */ - -void sim_brk_clract (void) -{ -sim_brk_act = NULL; -} - -/* New PC */ - -void sim_brk_npc (void) -{ -sim_brk_pend = FALSE; -return; -} - -/* Telnet console package. - - The console terminal can be attached to the controlling window - or to a Telnet connection. If attached to a Telnet connection, - the console is described by internal terminal multiplexor - sim_con_tmxr and internal terminal line description sim_con_ldsc. -*/ - -/* Set console to Telnet port */ - -t_stat set_telnet (int32 flg, char *cptr) -{ -if (*cptr == 0) return SCPE_2FARG; /* too few arguments? */ -if (sim_con_tmxr.master) return SCPE_ALATT; /* already open? */ -return tmxr_open_master (&sim_con_tmxr, cptr); /* open master socket */ -} - -/* Close console Telnet port */ - -t_stat set_notelnet (int32 flag, char *cptr) -{ -if (cptr && (*cptr != 0)) return SCPE_2MARG; /* too many arguments? */ -if (sim_con_tmxr.master == 0) return SCPE_OK; /* ignore if already closed */ -return tmxr_close_master (&sim_con_tmxr); /* close master socket */ -} - -/* Show console Telnet status */ - -t_stat show_telnet (FILE *st, int32 flag, char *cptr) -{ -if (cptr && (*cptr != 0)) return SCPE_2MARG; -if (sim_con_tmxr.master == 0) - fprintf (st, "Connected to console window\n"); -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); - tmxr_fconns (st, &sim_con_ldsc, -1); - tmxr_fstats (st, &sim_con_ldsc, -1); } -return SCPE_OK; -} - -/* Check connection before executing */ - -t_stat sim_check_console (int32 sec) -{ -int32 c, i; - -if (sim_con_tmxr.master == 0) return SCPE_OK; /* not Telnet? done */ -if (sim_con_ldsc.conn) { /* connected? */ - tmxr_poll_rx (&sim_con_tmxr); /* poll (check disconn) */ - 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 */ - 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 connection\n"); - fflush (stdout); } - sim_os_sleep (1); /* wait 1 second */ - } -return SCPE_TTMO; /* timed out */ -} - -/* Poll for character */ - -t_stat sim_poll_kbd (void) -{ -int32 c; - -c = sim_os_poll_kbd (); /* get character */ -if ((c == SCPE_STOP) || (sim_con_tmxr.master == 0)) /* ^E or not Telnet? */ - return c; /* in-window */ -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 & (SCPE_BREAK | 0377)) | SCPE_KFLAG; -return SCPE_OK; -} - -/* Output character */ - -t_stat sim_putchar (int32 c) -{ -if (sim_con_tmxr.master == 0) /* not Telnet? */ - return sim_os_putchar (c); /* in-window version */ -if (sim_con_ldsc.conn == 0) return SCPE_LOST; /* no Telnet conn? */ -tmxr_putc_ln (&sim_con_ldsc, c); /* output char */ -tmxr_poll_tx (&sim_con_tmxr); /* poll xmt */ -return SCPE_OK; -} diff --git a/scp_tty.c b/scp_tty.c deleted file mode 100644 index fe4b7e19..00000000 --- a/scp_tty.c +++ /dev/null @@ -1,884 +0,0 @@ -/* scp_tty.c: operating system-dependent I/O routines - - 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. - - 25-Apr-03 RMS Added long seek support from Mark Pizzolato - Added Unix priority control from Mark Pizzolato - 24-Sep-02 RMS Removed VT support, added Telnet console support - Added CGI support (from Brian Knittel) - Added MacOS sleep (from Peter Schorn) - 14-Jul-02 RMS Added Windows priority control from Mark Pizzolato - 20-May-02 RMS Added Windows VT support from Fischer Franz - 01-Feb-02 RMS Added VAX fix from Robert Alan Byer - 19-Sep-01 RMS More Mac changes - 31-Aug-01 RMS Changed int64 to t_int64 for Windoze - 20-Jul-01 RMS Added Macintosh support (from Louis Chretien, Peter Schorn, - and Ben Supnik) - 15-May-01 RMS Added logging support - 05-Mar-01 RMS Added clock calibration support - 08-Dec-00 BKR Added OS/2 support (from Bruce Ray) - 18-Aug-98 RMS Added BeOS support - 13-Oct-97 RMS Added NetBSD terminal support - 25-Jan-97 RMS Added POSIX terminal I/O support - 02-Jan-97 RMS Fixed bug in sim_poll_kbd - - This module implements the following routines to support terminal I/O: - - ttinit - called once to get initial terminal state - ttrunstate - called to put terminal into run state - ttcmdstate - called to return terminal to command state - ttclose - called once before the simulator exits - sim_os_poll_kbd - poll for keyboard input - sim_os_putchar - output character to terminal - - This module implements the following routines to support clock calibration: - - sim_os_msec - return elapsed time in msec - sim_os_sleep - sleep specified number of seconds - - Versions are included for VMS, Windows, OS/2, Macintosh, BSD UNIX, and POSIX UNIX. - The POSIX UNIX version works with LINUX. -*/ - -#include "sim_defs.h" -int32 sim_int_char = 005; /* interrupt character */ -extern FILE *sim_log; - -/* VMS routines, from Ben Thomas, with fixes from Robert Alan Byer */ - -#if defined (VMS) -#define _SIM_IO_TTY_ 0 -#if defined(__VAX) -#define sys$assign SYS$ASSIGN -#define sys$qiow SYS$QIOW -#define sys$gettim SYS$GETTIM -#endif - -#include -#include -#include -#include -#include -#include -#include -#define EFN 0 -unsigned int32 tty_chan = 0; -typedef struct { - unsigned short sense_count; - unsigned char sense_first_char; - unsigned char sense_reserved; - unsigned int32 stat; - unsigned int32 stat2; } SENSE_BUF; -typedef struct { - unsigned int16 status; - unsigned int16 count; - unsigned int32 dev_status; } IOSB; -SENSE_BUF cmd_mode = { 0 }; -SENSE_BUF run_mode = { 0 }; - -t_stat ttinit (void) -{ -unsigned int32 status; -IOSB iosb; -$DESCRIPTOR (terminal_device, "tt"); - -status = sys$assign (&terminal_device, &tty_chan, 0, 0); -if (status != SS$_NORMAL) return SCPE_TTIERR; -status = sys$qiow (EFN, tty_chan, IO$_SENSEMODE, &iosb, 0, 0, - &cmd_mode, sizeof (cmd_mode), 0, 0, 0, 0); -if ((status != SS$_NORMAL) || (iosb.status != SS$_NORMAL)) return SCPE_TTIERR; -run_mode = cmd_mode; -run_mode.stat = cmd_mode.stat | TT$M_NOECHO & ~(TT$M_HOSTSYNC | TT$M_TTSYNC); -run_mode.stat2 = cmd_mode.stat2 | TT2$M_PASTHRU; -return SCPE_OK; -} - -t_stat ttrunstate (void) -{ -unsigned int status; -IOSB iosb; - -status = sys$qiow (EFN, tty_chan, IO$_SETMODE, &iosb, 0, 0, - &run_mode, sizeof (run_mode), 0, 0, 0, 0); -if ((status != SS$_NORMAL) || (iosb.status != SS$_NORMAL)) return SCPE_TTIERR; -return SCPE_OK; -} - -t_stat ttcmdstate (void) -{ -unsigned int status; -IOSB iosb; - -status = sys$qiow (EFN, tty_chan, IO$_SETMODE, &iosb, 0, 0, - &cmd_mode, sizeof (cmd_mode), 0, 0, 0, 0); -if ((status != SS$_NORMAL) || (iosb.status != SS$_NORMAL)) return SCPE_TTIERR; -return SCPE_OK; -} - -t_stat ttclose (void) -{ -return ttcmdstate (); -} - -t_stat sim_os_poll_kbd (void) -{ -unsigned int status, term[2]; -unsigned char buf[4]; -IOSB iosb; -SENSE_BUF sense; - -term[0] = 0; term[1] = 0; -status = sys$qiow (EFN, tty_chan, IO$_SENSEMODE | IO$M_TYPEAHDCNT, &iosb, - 0, 0, &sense, 8, 0, term, 0, 0); -if ((status != SS$_NORMAL) || (iosb.status != SS$_NORMAL)) return SCPE_TTIERR; -if (sense.sense_count == 0) return SCPE_OK; -term[0] = 0; term[1] = 0; -status = sys$qiow (EFN, tty_chan, - IO$_READLBLK | IO$M_NOECHO | IO$M_NOFILTR | IO$M_TIMED | IO$M_TRMNOECHO, - &iosb, 0, 0, buf, 1, 0, term, 0, 0); -if ((status != SS$_NORMAL) || (iosb.status != SS$_NORMAL)) return SCPE_OK; -if (buf[0] == sim_int_char) return SCPE_STOP; -return (buf[0] | SCPE_KFLAG); -} - -t_stat sim_os_putchar (int32 out) -{ -unsigned int status; -char c; -IOSB iosb; - -c = out; -status = sys$qiow (EFN, tty_chan, IO$_WRITELBLK | IO$M_NOFORMAT, - &iosb, 0, 0, &c, 1, 0, 0, 0, 0); -if (sim_log) fputc (c, sim_log); -if ((status != SS$_NORMAL) || (iosb.status != SS$_NORMAL)) return SCPE_TTOERR; -return SCPE_OK; -} - -const t_bool rtc_avail = TRUE; - -uint32 sim_os_msec () -{ -uint32 quo, htod, tod[2]; -int32 i; - -sys$gettim (tod); /* time 0.1usec */ - -/* To convert to msec, must divide a 64b quantity by 10000. This is actually done - by dividing the 96b quantity 0'time by 10000, producing 64b of quotient, the - high 32b of which are discarded. This can probably be done by a clever multiply... -*/ - -quo = htod = 0; -for (i = 0; i < 64; i++) { /* 64b quo */ - htod = (htod << 1) | ((tod[1] >> 31) & 1); /* shift divd */ - tod[1] = (tod[1] << 1) | ((tod[0] >> 31) & 1); - 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 */ -return quo; -} - -void sim_os_sleep (unsigned int sec) -{ -sleep (sec); -return; -} - -#endif - -/* Win32 routines */ - -#if defined (_WIN32) -#define _SIM_IO_TTY_ 0 -#include -#include -#include -#include -static volatile int sim_win_ctlc = 0; - -void win_handler (int sig) -{ -sim_win_ctlc = 1; -return; -} - -t_stat ttinit (void) -{ -return SCPE_OK; -} - -t_stat ttrunstate (void) -{ -if (signal (SIGINT, win_handler) == SIG_ERR) return SCPE_SIGERR; -SetThreadPriority (GetCurrentThread(), THREAD_PRIORITY_BELOW_NORMAL); -return SCPE_OK; -} - -t_stat ttcmdstate (void) -{ -SetThreadPriority (GetCurrentThread(), THREAD_PRIORITY_NORMAL); -return SCPE_OK; -} - -t_stat ttclose (void) -{ -return SCPE_OK; -} - -t_stat sim_os_poll_kbd (void) -{ -int c; - -if (sim_win_ctlc) { - sim_win_ctlc = 0; - signal (SIGINT, win_handler); - return 003 | SCPE_KFLAG; } -if (!kbhit ()) return SCPE_OK; -c = _getch (); -if ((c & 0177) == '\b') c = 0177; -if ((c & 0177) == sim_int_char) return SCPE_STOP; -return c | SCPE_KFLAG; -} - -t_stat sim_os_putchar (int32 c) -{ -if (c != 0177) { - _putch (c); - if (sim_log) fputc (c, sim_log); } -return SCPE_OK; -} - -const t_bool rtc_avail = TRUE; - -uint32 sim_os_msec () -{ -return GetTickCount (); -} - -void sim_os_sleep (unsigned int sec) -{ -Sleep (sec * 1000); -return; -} - -#endif - -/* OS/2 routines, from Bruce Ray */ - -#if defined (__OS2__) -#define _SIM_IO_TTY_ 0 -#include - -t_stat ttinit (void) -{ -return SCPE_OK; -} - -t_stat ttrunstate (void) -{ -return SCPE_OK; -} - -t_stat ttcmdstate (void) -{ -return SCPE_OK; -} - -t_stat ttclose (void) -{ -return SCPE_OK; -} - -t_stat sim_os_poll_kbd (void) -{ -int c; - -if (!kbhit ()) return SCPE_OK; -c = getch(); -if ((c & 0177) == '\b') c = 0177; -if ((c & 0177) == sim_int_char) return SCPE_STOP; -return c | SCPE_KFLAG; -} - -t_stat sim_os_putchar (int32 c) -{ -if (c != 0177) { - putch (c); - fflush (stdout) ; - if (sim_log) fputc (c, sim_log); } -return SCPE_OK; -} - -const t_bool rtc_avail = FALSE; - -uint32 sim_os_msec () -{ -return 0; -} - -#endif - -/* Metrowerks CodeWarrior Macintosh routines, from Louis Chretien, - Peter Schorn, and Ben Supnik -*/ - -#if defined (__MWERKS__) && defined (macintosh) -#define _SIM_IO_TTY_ 0 - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* function prototypes */ - -Boolean SIOUXIsAppWindow(WindowPtr window); -void SIOUXDoMenuChoice(long menuValue); -void SIOUXUpdateMenuItems(void); -void SIOUXUpdateScrollbar(void); -int ps_kbhit(void); -int ps_getch(void); -t_stat ttinit (void); -t_stat ttrunstate (void); -t_stat ttcmdstate (void); -t_stat ttclose (void); -uint32 sim_os_msec (void); -t_stat sim_os_poll_kbd (void); -t_stat sim_os_putchar (int32 c); - -extern char sim_name[]; -extern pSIOUXWin SIOUXTextWindow; -static CursHandle iBeamCursorH = NULL; /* contains the iBeamCursor */ - -static void updateCursor(void) { - WindowPtr window; - window = FrontWindow(); - if (SIOUXIsAppWindow(window)) { - GrafPtr savePort; - Point localMouse; - GetPort(&savePort); - SetPort(window); -#if TARGET_API_MAC_CARBON - GetGlobalMouse(&localMouse); -#else - localMouse = LMGetMouseLocation(); -#endif - 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); - } - return; -} - -int ps_kbhit(void) { - EventRecord event; - int c; - updateCursor(); - SIOUXUpdateScrollbar(); - while (GetNextEvent(updateMask | osMask | mDownMask | mUpMask | activMask | - highLevelEventMask | diskEvt, &event)) { - SIOUXHandleOneEvent(&event); - } - if (SIOUXQuitting) { - 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; - } - return true; - } - else { - return false; - } -} - -int ps_getch(void) { - int c; - EventRecord event; - fflush(stdout); - updateCursor(); - while(!GetNextEvent(keyDownMask,&event)) { - if (GetNextEvent(updateMask | osMask | mDownMask | mUpMask | activMask | - highLevelEventMask | diskEvt, &event)) { - SIOUXUpdateScrollbar(); - SIOUXHandleOneEvent(&event); - } - } - if (SIOUXQuitting) { - exit(1); - } - c = event.message&charCodeMask; - if ((event.modifiers & cmdKey) && (c > 0x20)) { - SIOUXUpdateMenuItems(); - SIOUXDoMenuChoice(MenuKey(c)); - } - if (SIOUXQuitting) { - exit(1); - } - return c; -} - -t_stat ttinit (void) { -/* Note that this only works if the call to ttinit comes before any output to the console */ - int i; - char title[50] = " "; /* this blank will later be replaced by the number of characters */ - unsigned char ptitle[50]; - SIOUXSettings.autocloseonquit = TRUE; - SIOUXSettings.asktosaveonclose = FALSE; - SIOUXSettings.showstatusline = FALSE; - SIOUXSettings.columns = 80; - SIOUXSettings.rows = 40; - SIOUXSettings.toppixel = 42; - SIOUXSettings.leftpixel = 6; - iBeamCursorH = GetCursor(iBeamCursor); - strcat(title, sim_name); - 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]; - } - SIOUXSetTitle(ptitle); - return SCPE_OK; -} - -t_stat ttrunstate (void) -{ -return SCPE_OK; -} - -t_stat ttcmdstate (void) -{ -return SCPE_OK; -} - -t_stat ttclose (void) -{ -return SCPE_OK; -} - -t_stat sim_os_poll_kbd (void) -{ -int c; - -if (!ps_kbhit ()) return SCPE_OK; -c = ps_getch(); -if ((c & 0177) == '\b') c = 0177; -if ((c & 0177) == sim_int_char) return SCPE_STOP; -return c | SCPE_KFLAG; -} - -t_stat sim_os_putchar (int32 c) -{ -if (c != 0177) { - putchar (c); - fflush (stdout) ; - if (sim_log) fputc (c, sim_log); } -return SCPE_OK; -} - -const t_bool rtc_avail = TRUE; - -uint32 sim_os_msec (void) -{ -unsigned long long micros; -UnsignedWide macMicros; -unsigned long millis; - -Microseconds (&macMicros); -micros = *((unsigned long long *) &macMicros); -millis = micros / 1000LL; -return (uint32) millis; -} - -void sim_os_sleep (unsigned int sec) -{ -sleep (sec); -return; -} - -#endif - -/* BSD UNIX routines */ - -#if defined (BSDTTY) -#define _SIM_IO_TTY_ 0 -#include -#include -#include -#include - -struct sgttyb cmdtty,runtty; /* V6/V7 stty data */ -struct tchars cmdtchars,runtchars; /* V7 editing */ -struct ltchars cmdltchars,runltchars; /* 4.2 BSD editing */ -int cmdfl,runfl; /* TTY flags */ - -t_stat ttinit (void) -{ -cmdfl = fcntl (0, F_GETFL, 0); /* get old flags and status */ -runfl = cmdfl | FNDELAY; -if (ioctl (0, TIOCGETP, &cmdtty) < 0) return SCPE_TTIERR; -if (ioctl (0, TIOCGETC, &cmdtchars) < 0) return SCPE_TTIERR; -if (ioctl (0, TIOCGLTC, &cmdltchars) < 0) return SCPE_TTIERR; -runtty = cmdtty; /* initial run state */ -runtty.sg_flags = cmdtty.sg_flags & ~(ECHO|CRMOD) | CBREAK; -runtchars.t_intrc = sim_int_char; /* interrupt */ -runtchars.t_quitc = 0xFF; /* no quit */ -runtchars.t_startc = 0xFF; /* no host sync */ -runtchars.t_stopc = 0xFF; -runtchars.t_eofc = 0xFF; -runtchars.t_brkc = 0xFF; -runltchars.t_suspc = 0xFF; /* no specials of any kind */ -runltchars.t_dsuspc = 0xFF; -runltchars.t_rprntc = 0xFF; -runltchars.t_flushc = 0xFF; -runltchars.t_werasc = 0xFF; -runltchars.t_lnextc = 0xFF; -return SCPE_OK; /* return success */ -} - -t_stat ttrunstate (void) -{ -runtchars.t_intrc = sim_int_char; /* in case changed */ -fcntl (0, F_SETFL, runfl); /* non-block mode */ -if (ioctl (0, TIOCSETP, &runtty) < 0) return SCPE_TTIERR; -if (ioctl (0, TIOCSETC, &runtchars) < 0) return SCPE_TTIERR; -if (ioctl (0, TIOCSLTC, &runltchars) < 0) return SCPE_TTIERR; -nice (10); /* lower priority */ -return SCPE_OK; -} - -t_stat ttcmdstate (void) -{ -nice (-10); /* restore priority */ -fcntl (0, F_SETFL, cmdfl); /* block mode */ -if (ioctl (0, TIOCSETP, &cmdtty) < 0) return SCPE_TTIERR; -if (ioctl (0, TIOCSETC, &cmdtchars) < 0) return SCPE_TTIERR; -if (ioctl (0, TIOCSLTC, &cmdltchars) < 0) return SCPE_TTIERR; -return SCPE_OK; -} - -t_stat ttclose (void) -{ -return ttcmdstate (); -} - -t_stat sim_os_poll_kbd (void) -{ -int status; -unsigned char buf[1]; - -status = read (0, buf, 1); -if (status != 1) return SCPE_OK; -else return (buf[0] | SCPE_KFLAG); -} - -t_stat sim_os_putchar (int32 out) -{ -char c; - -c = out; -write (1, &c, 1); -if (sim_log) fputc (c, sim_log); -return SCPE_OK; -} - -const t_bool rtc_avail = TRUE; - -uint32 sim_os_msec () -{ -struct timeval cur; -struct timezone foo; -uint32 msec; - -gettimeofday (&cur, &foo); -msec = (((uint32) cur.tv_sec) * 1000) + (((uint32) cur.tv_usec) / 1000); -return msec; -} - -void sim_os_sleep (unsigned int sec) -{ -sleep (sec); -return; -} - -#endif - -/* POSIX UNIX routines, from Leendert Van Doorn */ - -#if !defined (_SIM_IO_TTY_) -#include -#include -#include - -struct termios cmdtty, runtty; -static int prior_norm = 1; - -t_stat ttinit (void) -{ -if (!isatty (fileno (stdin))) return SCPE_OK; /* skip if !tty */ -if (tcgetattr (0, &cmdtty) < 0) return SCPE_TTIERR; /* get old flags */ -runtty = cmdtty; -runtty.c_lflag = runtty.c_lflag & ~(ECHO | ICANON); /* no echo or edit */ -runtty.c_oflag = runtty.c_oflag & ~OPOST; /* no output edit */ -runtty.c_iflag = runtty.c_iflag & ~ICRNL; /* no cr conversion */ -runtty.c_cc[VINTR] = sim_int_char; /* interrupt */ -runtty.c_cc[VQUIT] = 0; /* no quit */ -runtty.c_cc[VERASE] = 0; -runtty.c_cc[VKILL] = 0; -runtty.c_cc[VEOF] = 0; -runtty.c_cc[VEOL] = 0; -runtty.c_cc[VSTART] = 0; /* no host sync */ -runtty.c_cc[VSUSP] = 0; -runtty.c_cc[VSTOP] = 0; -#if defined (VREPRINT) -runtty.c_cc[VREPRINT] = 0; /* no specials */ -#endif -#if defined (VDISCARD) -runtty.c_cc[VDISCARD] = 0; -#endif -#if defined (VWERASE) -runtty.c_cc[VWERASE] = 0; -#endif -#if defined (VLNEXT) -runtty.c_cc[VLNEXT] = 0; -#endif -runtty.c_cc[VMIN] = 0; /* no waiting */ -runtty.c_cc[VTIME] = 0; -#if defined (VDSUSP) -runtty.c_cc[VDSUSP] = 0; -#endif -#if defined (VSTATUS) -runtty.c_cc[VSTATUS] = 0; -#endif -return SCPE_OK; -} - -t_stat ttrunstate (void) -{ -if (!isatty (fileno (stdin))) return SCPE_OK; /* skip if !tty */ -runtty.c_cc[VINTR] = sim_int_char; /* in case changed */ -if (tcsetattr (0, TCSAFLUSH, &runtty) < 0) return SCPE_TTIERR; -if (prior_norm) { /* at normal pri? */ - errno = 0; - nice (10); /* try to lower pri */ - prior_norm = errno; } /* if no error, done */ -return SCPE_OK; -} - -t_stat ttcmdstate (void) -{ -if (!isatty (fileno (stdin))) return SCPE_OK; /* skip if !tty */ -if (!prior_norm) { /* priority down? */ - errno = 0; - nice (-10); /* try to raise pri*/ - prior_norm = (errno == 0); } /* if no error, done */ -if (tcsetattr (0, TCSAFLUSH, &cmdtty) < 0) return SCPE_TTIERR; -return SCPE_OK; -} - -t_stat ttclose (void) -{ -return ttcmdstate (); -} - -t_stat sim_os_poll_kbd (void) -{ -int status; -unsigned char buf[1]; - -status = read (0, buf, 1); -if (status != 1) return SCPE_OK; -else return (buf[0] | SCPE_KFLAG); -} - -t_stat sim_os_putchar (int32 out) -{ -char c; - -c = out; -write (1, &c, 1); -if (sim_log) fputc (c, sim_log); -return SCPE_OK; -} - -const t_bool rtc_avail = TRUE; - -uint32 sim_os_msec () -{ -struct timeval cur; -uint32 msec; - -gettimeofday (&cur, NULL); -msec = (((uint32) cur.tv_sec) * 1000) + (((uint32) cur.tv_usec) / 1000); -return msec; -} - -void sim_os_sleep (unsigned int sec) -{ -sleep (sec); -return; -} - -#endif - -/* Long seek routines */ - -#if defined (USE_INT64) && defined (USE_ADDR64) - -/* Alpha VMS */ - -#if defined (__ALPHA) && defined (VMS) /* Alpha VMS */ -#define _SIM_IO_FSEEK_EXT_ 0 - -static t_int64 fpos_t_to_int64 (fpos_t *pos) -{ -unsigned short *w = (unsigned short *) pos; /* endian dep! */ -t_int64 result; - -result = w[1]; -result <<= 16; -result += w[0]; -result <<= 9; -result += w[2]; -return result; -} - -static void int64_to_fpos_t (t_int64 ipos, fpos_t *pos, size_t mbc) -{ -unsigned short *w = (unsigned short *) pos; -int bufsize = mbc << 9; - -w[3] = 0; -w[2] = (unsigned short) (ipos % bufsize); -ipos -= w[2]; -ipos >>= 9; -w[0] = (unsigned short) ipos; -ipos >>= 16; -w[1] = (unsigned short) ipos; -if ((w[2] == 0) && (w[0] || w[1])) { - w[2] = bufsize; - w[0] -= mbc; } -} - -int fseek_ext (FILE *st, t_addr offset, int whence) -{ -t_addr fileaddr; -fpos_t filepos; - -switch (whence) { - case SEEK_SET: - fileaddr = offset; - break; - case SEEK_CUR: - if (fgetpos (st, &filepos)) return (-1); - fileaddr = fpos_t_to_int64 (&filepos); - fileaddr = fileaddr + offset; - break; - default: - errno = EINVAL; - return (-1); } -int64_to_fpos_t (fileaddr, &filepos, 127); -return fsetpos (st, &filepos); -} - -#endif - -/* Alpha UNIX - natively 64b */ - -#if defined (__ALPHA) && defined (__unix__) /* Alpha UNIX */ -#define _SIM_IO_FSEEK_EXT_ 0 - -int fseek_ext (FILE *st, t_addr offset, int whence) -{ -return fseek (st, offset, whence); -} - -#endif - -/* Windows */ - -#if defined (_WIN32) -#define _SIM_IO_FSEEK_EXT_ 0 - -int fseek_ext (FILE *st, t_addr offset, int whence) -{ -fpos_t fileaddr; - -switch (whence) { - case SEEK_SET: - fileaddr = offset; - break; - case SEEK_CUR: - if (fgetpos (st, &fileaddr)) return (-1); - fileaddr = fileaddr + offset; - break; - default: - errno = EINVAL; - return (-1); } -return fsetpos (st, &fileaddr); -} - -#endif /* end Windows */ - -#endif /* end 64b seek defs */ - -/* Default: no OS-specific routine has been defined */ - -#if !defined (_SIM_IO_FSEEK_EXT_) -#define _SIM_IO_FSEEK_EXT_ 0 - -int fseek_ext (FILE *st, t_addr xpos, int origin) -{ -return fseek (st, (int32) xpos, origin); -} - -uint32 sim_taddr_64 = 0; -#else -uint32 sim_taddr_64 = 1; -#endif diff --git a/sim_defs.h b/sim_defs.h deleted file mode 100644 index 7bdbbd62..00000000 --- a/sim_defs.h +++ /dev/null @@ -1,482 +0,0 @@ -/* sim_defs.h: simulator definitions - - 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. - - 15-Jun-03 RMS Added register flag REG_VMIO - 23-Apr-03 RMS Revised for 32b/64b t_addr - 14-Mar-03 RMS Lengthened default serial output wait - 31-Mar-03 RMS Added u5, u6 fields - 18-Mar-03 RMS Added logical name support - Moved magtape definitions to sim_tape.h - Moved breakpoint definitions from scp.c - 03-Mar-03 RMS Added sim_fsize - 08-Feb-03 RMS Changed sim_os_sleep to void, added match_ext - 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 end of medium support - Added help messages to CTAB - Added flag and context fields to DEVICE - Added restore flag masks - Revised 64b definitions - 02-May-02 RMS Removed log status codes - 22-Apr-02 RMS Added magtape record length error - 30-Dec-01 RMS Generalized timer package, added circular arrays - 07-Dec-01 RMS Added breakpoint package - 01-Dec-01 RMS Added read-only unit support, extended SET/SHOW features, - improved error messages - 24-Nov-01 RMS Added unit-based registers - 27-Sep-01 RMS Added queue count prototype - 17-Sep-01 RMS Removed multiple console support - 07-Sep-01 RMS Removed conditional externs on function prototypes - 31-Aug-01 RMS Changed int64 to t_int64 for Windoze - 17-Jul-01 RMS Added additional function prototypes - 27-May-01 RMS Added multiple console support - 15-May-01 RMS Increased string buffer size - 25-Feb-01 RMS Revisions for V2.6 - 15-Oct-00 RMS Editorial revisions for V2.5 - 11-Jul-99 RMS Added unsigned int data types - 14-Apr-99 RMS Converted t_addr to unsigned - 04-Oct-98 RMS Additional definitions for V2.4 - - The interface between the simulator control package (SCP) and the - simulator consists of the following routines and data structures - - sim_name simulator name string - sim_devices[] array of pointers to simulated devices - sim_PC pointer to saved PC register descriptor - sim_interval simulator interval to next event - sim_stop_messages[] array of pointers to stop messages - sim_instr() instruction execution routine - sim_load() binary loader routine - sim_emax maximum number of words in an instruction - - In addition, the simulator must supply routines to print and parse - architecture specific formats - - print_sym print symbolic output - parse_sym parse symbolic input -*/ - -#ifndef _SIM_DEFS_H_ -#define _SIM_DEFS_H_ 0 - -#include -#include -#include -#include -#include -#include - -#ifndef TRUE -#define TRUE 1 -#define FALSE 0 -#endif - -/* Length specific integer declarations */ - -#define int8 char -#define int16 short -#define int32 int -typedef int t_stat; /* status */ -typedef int t_bool; /* boolean */ -typedef unsigned int8 uint8; -typedef unsigned int16 uint16; -typedef unsigned int32 uint32; - -#if defined (USE_INT64) /* 64b data */ -#if defined (_WIN32) /* Windows */ -#define t_int64 __int64 -#elif defined (__ALPHA) && defined (VMS) /* Alpha VMS */ -#define t_int64 __int64 -#elif defined (__ALPHA) && defined (__unix__) /* Alpha UNIX */ -#define t_int64 long -#else /* default GCC */ -#define t_int64 long long -#endif /* end OS's */ -typedef unsigned t_int64 t_uint64, t_value; /* value */ -typedef t_int64 t_svalue; /* signed value */ -#else /* 32b data */ -typedef unsigned int32 t_value; -typedef int32 t_svalue; -#endif /* end 64b data */ - -#if defined (USE_INT64) && defined (USE_ADDR64) /* 64b address */ -typedef unsigned t_int64 t_addr; -#define T_ADDR_W 64 -#else /* 32b address */ -typedef unsigned int32 t_addr; -#define T_ADDR_W 32 -#endif /* end 64b address */ - -/* System independent definitions */ - -#define FLIP_SIZE (1 << 16) /* flip buf size */ -#if !defined (PATH_MAX) /* usually in limits */ -#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 */ -#define SIM_SW_REG (1u << 28) /* register value */ - -/* Simulator status codes - - 0 ok - 1 - (SCPE_BASE - 1) simulator specific - SCPE_BASE - n general -*/ - -#define SCPE_OK 0 /* normal return */ -#define SCPE_BASE 64 /* base for messages */ -#define SCPE_NXM (SCPE_BASE + 0) /* nxm */ -#define SCPE_UNATT (SCPE_BASE + 1) /* no file */ -#define SCPE_IOERR (SCPE_BASE + 2) /* I/O error */ -#define SCPE_CSUM (SCPE_BASE + 3) /* loader cksum */ -#define SCPE_FMT (SCPE_BASE + 4) /* loader format */ -#define SCPE_NOATT (SCPE_BASE + 5) /* not attachable */ -#define SCPE_OPENERR (SCPE_BASE + 6) /* open error */ -#define SCPE_MEM (SCPE_BASE + 7) /* alloc error */ -#define SCPE_ARG (SCPE_BASE + 8) /* argument error */ -#define SCPE_STEP (SCPE_BASE + 9) /* step expired */ -#define SCPE_UNK (SCPE_BASE + 10) /* unknown command */ -#define SCPE_RO (SCPE_BASE + 11) /* read only */ -#define SCPE_INCOMP (SCPE_BASE + 12) /* incomplete */ -#define SCPE_STOP (SCPE_BASE + 13) /* sim stopped */ -#define SCPE_EXIT (SCPE_BASE + 14) /* sim exit */ -#define SCPE_TTIERR (SCPE_BASE + 15) /* console tti err */ -#define SCPE_TTOERR (SCPE_BASE + 16) /* console tto err */ -#define SCPE_EOF (SCPE_BASE + 17) /* end of file */ -#define SCPE_REL (SCPE_BASE + 18) /* relocation error */ -#define SCPE_NOPARAM (SCPE_BASE + 19) /* no parameters */ -#define SCPE_ALATT (SCPE_BASE + 20) /* already attached */ -#define SCPE_TIMER (SCPE_BASE + 21) /* hwre timer err */ -#define SCPE_SIGERR (SCPE_BASE + 22) /* signal err */ -#define SCPE_TTYERR (SCPE_BASE + 23) /* tty setup err */ -#define SCPE_SUB (SCPE_BASE + 24) /* subscript err */ -#define SCPE_NOFNC (SCPE_BASE + 25) /* func not imp */ -#define SCPE_UDIS (SCPE_BASE + 26) /* unit disabled */ -#define SCPE_NORO (SCPE_BASE + 27) /* rd only not ok */ -#define SCPE_INVSW (SCPE_BASE + 28) /* invalid switch */ -#define SCPE_MISVAL (SCPE_BASE + 29) /* missing value */ -#define SCPE_2FARG (SCPE_BASE + 30) /* too few arguments */ -#define SCPE_2MARG (SCPE_BASE + 31) /* too many arguments */ -#define SCPE_NXDEV (SCPE_BASE + 32) /* nx device */ -#define SCPE_NXUN (SCPE_BASE + 33) /* nx unit */ -#define SCPE_NXREG (SCPE_BASE + 34) /* nx register */ -#define SCPE_NXPAR (SCPE_BASE + 35) /* nx parameter */ -#define SCPE_NEST (SCPE_BASE + 36) /* nested DO */ -#define SCPE_IERR (SCPE_BASE + 37) /* internal error */ -#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 0010000 /* tti data flag */ -#define SCPE_BREAK 0020000 /* tti break flag */ - -/* Print value format codes */ - -#define PV_RZRO 0 /* right, zero fill */ -#define PV_RSPC 1 /* right, space fill */ -#define PV_LEFT 2 /* left justify */ - -/* Default timing parameters */ - -#define KBD_POLL_WAIT 5000 /* keyboard poll */ -#define SERIAL_IN_WAIT 100 /* serial in time */ -#define SERIAL_OUT_WAIT 100 /* serial output */ -#define NOQUEUE_WAIT 10000 /* min check time */ - -/* Convert switch letter to bit mask */ - -#define SWMASK(x) (1u << (((int) (x)) - ((int) 'A'))) - -/* String match */ - -#define MATCH_CMD(ptr,cmd) strncmp ((ptr), (cmd), strlen (ptr)) - -/* Device data structure */ - -struct sim_device { - char *name; /* name */ - struct sim_unit *units; /* units */ - struct sim_reg *registers; /* registers */ - struct sim_mtab *modifiers; /* modifiers */ - uint32 numunits; /* #units */ - uint32 aradix; /* address radix */ - uint32 awidth; /* address width */ - uint32 aincr; /* addr increment */ - uint32 dradix; /* data radix */ - uint32 dwidth; /* data width */ - t_stat (*examine)(t_value *v, t_addr a, struct sim_unit *up, - int32 sw); /* examine routine */ - t_stat (*deposit)(t_value v, t_addr a, struct sim_unit *up, - int32 sw); /* deposit routine */ - t_stat (*reset)(struct sim_device *dp);/* reset routine */ - t_stat (*boot)(int32 u, struct sim_device *dp); - /* boot routine */ - t_stat (*attach)(struct sim_unit *up, char *cp); - /* attach routine */ - t_stat (*detach)(struct sim_unit *up); /* detach routine */ - void *ctxt; /* context */ - uint32 flags; /* flags */ - t_stat (*msize)(struct sim_unit *up, int32 v, char *cp, void *dp); - /* mem size routine */ - char *lname; /* logical name */ -}; - -/* 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_NET 3 /* network attach */ -#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_NET (1 << DEV_V_NET) - -#define DEV_UFMASK (((1u << DEV_V_RSV) - 1) & ~((1u << DEV_V_UF) - 1)) -#define DEV_RFLAGS (DEV_UFMASK|DEV_DIS) /* restored flags */ - -/* Unit data structure - - Parts of the unit structure are device specific, that is, they are - not referenced by the simulator control package and can be freely - used by device simulators. Fields starting with 'buf', and flags - starting with 'UF', are device specific. The definitions given here - are for a typical sequential device. -*/ - -struct sim_unit { - struct sim_unit *next; /* next active */ - t_stat (*action)(struct sim_unit *up); /* action routine */ - char *filename; /* open file name */ - FILE *fileref; /* file reference */ - void *filebuf; /* memory buffer */ - uint32 hwmark; /* high water mark */ - int32 time; /* time out */ - uint32 flags; /* flags */ - t_addr capac; /* capacity */ - t_addr pos; /* file position */ - int32 buf; /* buffer */ - int32 wait; /* wait */ - int32 u3; /* device specific */ - int32 u4; /* device specific */ - int32 u5; /* device specific */ - int32 u6; /* device specific */ -}; - -/* Unit flags */ - -#define UNIT_V_UF 12 /* device specific */ -#define UNIT_V_RSV 31 /* reserved!! */ - -#define UNIT_ATTABLE 000001 /* attachable */ -#define UNIT_RO 000002 /* read only */ -#define UNIT_FIX 000004 /* fixed capacity */ -#define UNIT_SEQ 000010 /* sequential */ -#define UNIT_ATT 000020 /* attached */ -#define UNIT_BINK 000040 /* K = power of 2 */ -#define UNIT_BUFABLE 000100 /* bufferable */ -#define UNIT_MUSTBUF 000200 /* must buffer */ -#define UNIT_BUF 000400 /* buffered */ -#define UNIT_ROABLE 001000 /* read only ok */ -#define UNIT_DISABLE 002000 /* disable-able */ -#define UNIT_DIS 004000 /* disabled */ - -#define UNIT_UFMASK (((1u << UNIT_V_RSV) - 1) & ~((1u << UNIT_V_UF) - 1)) -#define UNIT_RFLAGS (UNIT_UFMASK|UNIT_DIS) /* restored flags */ - -/* Register data structure */ - -struct sim_reg { - char *name; /* name */ - void *loc; /* location */ - uint32 radix; /* radix */ - uint32 width; /* width */ - uint32 offset; /* starting bit */ - uint32 depth; /* save depth */ - uint32 flags; /* flags */ - uint32 qptr; /* circ q ptr */ -}; - -#define REG_FMT 0003 /* see PV_x */ -#define REG_RO 0004 /* read only */ -#define REG_HIDDEN 0010 /* hidden */ -#define REG_NZ 0020 /* must be non-zero */ -#define REG_UNIT 0040 /* in unit struct */ -#define REG_CIRC 0100 /* circular array */ -#define REG_VMIO 0200 /* use VM print/parse */ -#define REG_HRO (REG_RO | REG_HIDDEN) /* hidden, read only */ - -/* Command tables, base and alternate formats */ - -struct sim_ctab { - char *name; /* name */ - t_stat (*action)(int32 flag, char *cptr); - /* action routine */ - int32 arg; /* argument */ - char *help; /* help string */ -}; - -struct sim_c1tab { - char *name; /* name */ - t_stat (*action)(struct sim_device *dptr, struct sim_unit *uptr, - int32 flag); /* action routine */ - int32 arg; /* argument */ - char *help; /* help string */ -}; - -struct sim_shtab { - char *name; /* name */ - t_stat (*action)(FILE *st, int32 flag, char *cptr); - int32 arg; /* argument */ - char *help; /* help string */ -}; - -/* Modifier table - only extended entries have disp, reg, or flags */ - -struct sim_mtab { - uint32 mask; /* mask */ - uint32 match; /* match */ - char *pstring; /* print string */ - char *mstring; /* match string */ - t_stat (*valid)(struct sim_unit *up, int32 v, char *cp, void *dp); - /* validation routine */ - t_stat (*disp)(FILE *st, struct sim_unit *up, int32 v, void *dp); - /* display routine */ - void *desc; /* value descriptor */ - /* REG * if MTAB_VAL */ - /* int * if not */ -}; - -#define MTAB_XTD (1u << UNIT_V_RSV) /* ext entry flag */ -#define MTAB_VDV 001 /* valid for dev */ -#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 */ - -struct sim_schtab { - int32 logic; /* logical operator */ - int32 bool; /* boolean operator */ - t_value mask; /* mask for logical */ - t_value comp; /* comparison for boolean */ -}; - -/* Breakpoint table */ - -struct sim_brktab { - t_addr addr; /* address */ - int32 typ; /* mask of types */ - int32 cnt; /* proceed count */ - char *act; /* action string */ -}; - -/* The following macros define structure contents */ - -#define UDATA(act,fl,cap) NULL,act,NULL,NULL,NULL,0,0,(fl),(cap),0,0 - -#if defined (__STDC__) || defined (_WIN32) -#define ORDATA(nm,loc,wd) #nm, &(loc), 8, (wd), 0, 1 -#define DRDATA(nm,loc,wd) #nm, &(loc), 10, (wd), 0, 1 -#define HRDATA(nm,loc,wd) #nm, &(loc), 16, (wd), 0, 1 -#define FLDATA(nm,loc,pos) #nm, &(loc), 2, 1, (pos), 1 -#define GRDATA(nm,loc,rdx,wd,pos) #nm, &(loc), (rdx), (wd), (pos), 1 -#define BRDATA(nm,loc,rdx,wd,dep) #nm, (loc), (rdx), (wd), 0, (dep) -#define URDATA(nm,loc,rdx,wd,off,dep,fl) \ - #nm, &(loc), (rdx), (wd), (off), (dep), ((fl) | REG_UNIT) -#else -#define ORDATA(nm,loc,wd) "nm", &(loc), 8, (wd), 0, 1 -#define DRDATA(nm,loc,wd) "nm", &(loc), 10, (wd), 0, 1 -#define HRDATA(nm,loc,wd) "nm", &(loc), 16, (wd), 0, 1 -#define FLDATA(nm,loc,pos) "nm", &(loc), 2, 1, (pos), 1 -#define GRDATA(nm,loc,rdx,wd,pos) "nm", &(loc), (rdx), (wd), (pos), 1 -#define BRDATA(nm,loc,rdx,wd,dep) "nm", (loc), (rdx), (wd), 0, (dep) -#define URDATA(nm,loc,rdx,wd,off,dep,fl) \ - "nm", &(loc), (rdx), (wd), (off), (dep), ((fl) | REG_UNIT) -#endif - -/* Typedefs for principal structures */ - -typedef struct sim_device DEVICE; -typedef struct sim_unit UNIT; -typedef struct sim_reg REG; -typedef struct sim_ctab CTAB; -typedef struct sim_c1tab C1TAB; -typedef struct sim_shtab SHTAB; -typedef struct sim_mtab MTAB; -typedef struct sim_schtab SCHTAB; -typedef struct sim_brktab BRKTAB; - -/* Function prototypes */ - -t_stat sim_process_event (void); -t_stat sim_activate (UNIT *uptr, int32 interval); -t_stat sim_cancel (UNIT *uptr); -int32 sim_is_active (UNIT *uptr); -double sim_gtime (void); -uint32 sim_grtime (void); -int32 sim_qcount (void); -t_stat attach_unit (UNIT *uptr, char *cptr); -t_stat detach_unit (UNIT *uptr); -t_stat reset_all (uint32 start_device); -size_t fxread (void *bptr, size_t size, size_t count, FILE *fptr); -size_t fxwrite (void *bptr, size_t size, size_t count, FILE *fptr); -int fseek_ext (FILE *st, t_addr xpos, int origin); -uint32 sim_fsize (char *cptr); -char *sim_dname (DEVICE *dptr); -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, uint32 radix, t_value max, t_stat *status); -char *get_range (char *cptr, t_addr *lo, t_addr *hi, uint32 rdx, - t_addr max, char term); -t_stat get_ipaddr (char *cptr, uint32 *ipa, uint32 *ipp); -t_value strtotv (char *cptr, char **endptr, uint32 radix); -t_stat fprint_val (FILE *stream, t_value val, uint32 rdx, uint32 wid, uint32 fmt); -DEVICE *find_dev_from_unit (UNIT *uptr); -REG *find_reg (char *ptr, char **optr, DEVICE *dptr); -int32 sim_rtc_init (int32 time); -int32 sim_rtc_calb (int32 ticksper); -int32 sim_rtcn_init (int32 time, int32 tmr); -int32 sim_rtcn_calb (int32 time, int32 tmr); -t_stat sim_poll_kbd (void); -t_stat sim_putchar (int32 out); -BRKTAB *sim_brk_fnd (t_addr loc); -t_bool sim_brk_test (t_addr bloc, int32 btyp); -void sim_os_sleep (unsigned int sec); -char *match_ext (char *fnam, char *ext); - -#endif diff --git a/sim_ether.c b/sim_ether.c deleted file mode 100644 index 48a4280f..00000000 --- a/sim_ether.c +++ /dev/null @@ -1,631 +0,0 @@ -/* sim_ether.c: OS-dependent network routines - ------------------------------------------------------------------------------ - - Copyright (c) 2002-2003, David T. Hittner - - 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 - THE AUTHOR 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 the author shall not be - used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from the author. - - ------------------------------------------------------------------------------ - - 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: - - 30-May-03 DTH Changed WIN32 to _WIN32 for consistency - 07-Mar-03 MP Fixed Linux implementation of PacketGetAdapterNames to also - work on Red Hat 6.2-sparc and Debian 3.0r1-sparc. - 03-Mar-03 MP Changed logging to be consistent on stdout and sim_log - 01-Feb-03 MP Changed type of local variables in eth_packet_trace to - conform to the interface needs of eth_mac_fmt wich produces - char data instead of unsigned char data. Suggested by the - DECC compiler. - 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) - Added ethX detection simplification (from Megan Gentry) - Removed sections of temporary code - Added parameter validation - 23-Oct-02 DTH Beta 5 released - 22-Oct-02 DTH Added all_multicast and promiscuous support - Fixed not attached behavior - 21-Oct-02 DTH Added NetBSD support (from Jason Thorpe) - Patched buffer size to make sure entire packet is read in - Made 'ethX' check characters passed as well as length - Corrected copyright again - 16-Oct-02 DTH Beta 4 released - Corrected copyright - 09-Oct-02 DTH Beta 3 released - Added pdp11 write acceleration (from Patrick Caulfield) - 08-Oct-02 DTH Beta 2 released - Integrated with 2.10-0p4 - Added variable vector and copyrights - 04-Oct-02 DTH Added linux support (from Patrick Caulfield) - 03-Oct-02 DTH Beta version of xq/sim_ether released for SIMH 2.09-11 - 24-Sep-02 DTH Finished eth_devices, eth_getname - 18-Sep-02 DTH Callbacks implemented - 13-Sep-02 DTH Basic packet read/write written - 20-Aug-02 DTH Created Sim_Ether for O/S independant ethernet implementation - - ------------------------------------------------------------------------------ - - Work left to do: - 1) Addition of other host Operating Systems (VMS, MAC, etc..) - 2) Possible efficiency increase by using BPF filtering - - ------------------------------------------------------------------------------ -*/ - - -#include "sim_ether.h" - -extern FILE *sim_log; - -/*============================================================================*/ -/* OS-independant ethernet routines */ -/*============================================================================*/ - -void eth_mac_fmt(ETH_MAC* mac, char* buff) -{ - uint8* m = (uint8*) mac; - sprintf(buff, "%02X-%02X-%02X-%02X-%02X-%02X", m[0], m[1], m[2], m[3], m[4], m[5]); - 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) -{ - char src[20]; - 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("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) -{ -#define ETH_SUPPORTED_DEVICES 10 - ETH_LIST list[ETH_SUPPORTED_DEVICES]; - int count = eth_devices(ETH_SUPPORTED_DEVICES, list); - - if (count < number) return 0; - strcpy(name, list[number].name); - return name; -} - -void eth_zero(ETH_DEV* dev) -{ - /* set all members to NULL OR 0 */ - memset(dev, 0, sizeof(ETH_DEV)); -} - -/*============================================================================*/ -/* Non-implemented versions */ -/*============================================================================*/ - -#if !defined (_WIN32) && !defined(linux) && !defined(__NetBSD__) && \ - !defined (__OpenBSD__) || !defined (USE_NETWORK) -t_stat eth_open (ETH_DEV* dev, char* name) - {return SCPE_NOFNC;} -t_stat eth_close (ETH_DEV* dev) - {return SCPE_NOFNC;} -t_stat eth_write (ETH_DEV* dev, ETH_PACK* packet, ETH_PCALLBACK routine) - {return SCPE_NOFNC;} -t_stat eth_read (ETH_DEV* dev, ETH_PACK* packet, ETH_PCALLBACK routine) - {return SCPE_NOFNC;} -t_stat eth_filter (ETH_DEV* dev, int addr_count, ETH_MAC* addresses, - ETH_BOOL all_multicast, ETH_BOOL promiscuous) - {return SCPE_NOFNC;} -int eth_devices (int max, ETH_LIST* dev) - {return 0;} -#else /* endif unimplemented */ - -/*============================================================================*/ -/* WIN32, Linux, NetBSD, and OpenBSD routines */ -/* Uses WinPcap and libpcap packages */ -/*============================================================================*/ - -#include -#include -#ifdef _WIN32 -#include -#endif /* _WIN32 */ -#if defined (__NetBSD__) || defined (__OpenBSD__) -#include -#include -#endif /* __NetBSD__ || __OpenBSD__*/ -#if defined (linux) || defined(__NetBSD__) || defined (__OpenBSD__) -#include -#endif /* linux || __NetBSD__ || __OpenBSD__ */ - -t_stat eth_open(ETH_DEV* dev, char* name) -{ - const int bufsz = (BUFSIZ < ETH_MAX_PACKET) ? ETH_MAX_PACKET : BUFSIZ; - char errbuf[PCAP_ERRBUF_SIZE]; - char temp[1024]; - char* savname = name; - int num; - - /* initialize device */ - eth_zero(dev); - - /* translate name of type "ethX" to real device name */ - if ((strlen(name) == 4) - && (tolower(name[0]) == 'e') - && (tolower(name[1]) == 't') - && (tolower(name[2]) == 'h') - && isdigit(name[3]) - ) { - num = atoi(&name[3]); - savname = eth_getname(num, temp); - } - - /* 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 */ - printf ("Eth: pcap_open_live error - %s\n", errbuf); - if (sim_log) fprintf (sim_log, "Eth: pcap_open_live error - %s\n", errbuf); - return SCPE_OPENERR; - } else { - printf ("Eth: opened %s\n", savname); - if (sim_log) fprintf (sim_log, "Eth: opened %s\n", savname); - } - - /* save name of device */ - dev->name = malloc(strlen(savname)+1); - 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. - 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__) - /* set file non-blocking */ - fcntl(pcap_fileno(dev->handle), F_SETFL, fcntl(pcap_fileno(dev->handle), F_GETFL, 0) | O_NONBLOCK); -#endif /* linux || __NetBSD__ || __OpenBSD__ */ - - return SCPE_OK; -} - -t_stat eth_close(ETH_DEV* dev) -{ - /* make sure device exists */ - if (!dev) return SCPE_UNATT; - - /* 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); - eth_zero(dev); - - return SCPE_OK; -} - -t_stat eth_write(ETH_DEV* dev, ETH_PACK* packet, ETH_PCALLBACK routine) -{ - int status = 1; /* default to failure */ - - /* make sure device exists */ - if (!dev) return SCPE_UNATT; - - /* make sure packet exists */ - if (!packet) return SCPE_ARG; - - /* 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 ETH_DEBUG - eth_packet_trace (packet, "writing"); -#endif - status = pcap_sendpacket((pcap_t*)dev->handle, (u_char*)packet->msg, packet->len); - } /* if packet->len */ - - /* call optional write callback function */ - if (routine) - (routine)(status); - - return SCPE_OK; -} - -void eth_callback(u_char* info, const struct pcap_pkthdr* header, const u_char* data) -{ - ETH_DEV* dev = (ETH_DEV*) info; - - /* 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? */ - if (dev->all_multicast && (data[0] & 0x01)) to_me = 1; - - /* promiscuous mode? */ - if (dev->promiscuous) to_me = 1; - - if (to_me && !from_me) { - - /* set data in passed read packet */ - dev->read_packet->len = header->len; - memcpy(dev->read_packet->msg, data, header->len); - -#ifdef ETH_DEBUG - eth_packet_trace (dev->read_packet, "reading"); -#endif - - /* 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) -{ - int status; - - /* make sure device exists */ - if (!dev) return SCPE_UNATT; - - /* make sure packet exists */ - if (!packet) return SCPE_ARG; - - /* set read packet */ - dev->read_packet = packet; - packet->len = 0; - - /* set optional callback routine */ - dev->read_callback = routine; - - /* 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; -} - -t_stat eth_filter(ETH_DEV* dev, int addr_count, ETH_MAC* addresses, - ETH_BOOL all_multicast, ETH_BOOL promiscuous) -{ - int i; - - /* make sure device exists */ - if (!dev) return SCPE_UNATT; - - /* filter count OK? */ - if ((addr_count < 0) || (addr_count > ETH_FILTER_MAX)) - return SCPE_ARG; - else - if (!addresses) return SCPE_ARG; - - /* clear filter array */ - memset(dev->filter_address, 0, sizeof(ETH_MAC) * ETH_FILTER_MAX); - - /* set new filter addresses */ - for (i = 0; i < addr_count; i++) - memcpy(dev->filter_address[i], addresses[i], sizeof(ETH_MAC)); - - /* store other flags */ - dev->all_multicast = all_multicast; - dev->promiscuous = promiscuous; - - return SCPE_OK; -} - -int eth_devices(int max, ETH_LIST* list) -{ - int i, index, len; - uint8 buffer[2048]; - uint8 buffer2[2048]; - uint8* cptr = buffer2; - unsigned long size = sizeof(buffer); - unsigned long ret; - - /* get names of devices from packet driver */ - ret = PacketGetAdapterNames(buffer, &size); - - /* device names in ascii or unicode format? */ - if ((buffer[1] == 0) && (buffer[3] == 0)) { /* unicode.. */ - int i = 0; - int cptr_inc = 2; - /* want to use buffer for scanning, so copy to buffer2 */ - memcpy (buffer2, buffer, sizeof(buffer)); - /* convert unicode to ascii (assuming every other byte is zero) */ - while (cptr < (buffer2 + sizeof(buffer2))) { - buffer[i] = *cptr; - if ((buffer[i] == 0) && (buffer[i-1] == 0)) { /* end of unicode devices */ - /* descriptions are in ascii, so change increment */ - cptr_inc = 1; - } - cptr += cptr_inc; - i++; - } - } - - /* scan ascii string and load list*/ - index = 0; - cptr = buffer; - /* extract device names and numbers */ - while (len = strlen(cptr)) { - list[index].num = index; - strcpy(list[index].name, cptr); - cptr += len + 1; - index++; - } - cptr += 2; - /* extract device descriptions */ - for (i=0; i < index; i++) { - len = strlen(cptr); - strcpy(list[i].desc, cptr); - cptr += len + 1; - } - return index; /* count of devices */ -} - -#endif /* (_WIN32 || linux || __NetBSD__ || __OpenBSD__) && USE_NETWORK */ - -/*============================================================================*/ -/* linux-specific code */ -/*============================================================================*/ - -#if defined (linux) && defined (USE_NETWORK) -#include -#include -#include /* for the glibc version number */ -#if (__GLIBC__ >= 2 && __GLIBC_MINOR >= 1) || __GLIBC__ >= 3 -#include -#include /* the L2 protocols */ -#else /*__GLIBC__*/ -#include -#include -#include -#include -#include /* The L2 protocols */ -#endif /*__GLIBC__*/ - -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, unsigned long* size) -{ - struct ifreq ifr; - int iindex = 1; - int sock = socket(PF_PACKET, SOCK_RAW, 0); - int ptr = 0; - - ifr.ifr_ifindex = iindex; - - while (ioctl(sock, SIOCGIFNAME, &ifr) == 0) { - /* Only use ethernet interfaces */ - if ((0 == ioctl(sock, SIOCGIFHWADDR, &ifr)) && - (ifr.ifr_hwaddr.sa_family == ARPHRD_ETHER)) { - strcpy(buffer+ptr, ifr.ifr_name); - ptr += strlen(buffer+ptr)+1; - } - ifr.ifr_ifindex = ++iindex; - } - if (ptr == 0) { /* Found any Ethernet Interfaces? */ - /* No, so try some good guesses since the SIOCGIFNAME ioctl - doesn't always return the ethernet interfaces, at least not - Debian or Red Hat running on sparc boxes. */ - - for (iindex=0; iindex < 10; ++iindex) { - sprintf(ifr.ifr_name, "eth%d", iindex); - if ((0 == ioctl(sock, SIOCGIFHWADDR, &ifr)) && - (ifr.ifr_hwaddr.sa_family == ARPHRD_ETHER)) { - strcpy(buffer+ptr, ifr.ifr_name); - ptr += strlen(buffer+ptr)+1; - } - } - } - - close(sock); - - buffer[ptr++] = '\0'; - buffer[ptr++] = '\0'; - *size = ptr; -} - -#endif /* linux && USE_NETWORK */ - -/*============================================================================*/ -/* NetBSD/OpenBSD-specific code */ -/*============================================================================*/ - -#if (defined (__NetBSD__) || defined(__OpenBSD__)) && defined (USE_NETWORK) -#include -#include -#include -#include -#include -#include - -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, unsigned long* size) -{ - const struct sockaddr_dl *sdl; - struct ifaddrs *ifap, *ifa; - char *p; - int ptr = 0; - - if (getifaddrs(&ifap) != 0) { - *size = 0; - return (0); - } - - p = NULL; - for (ifa = ifap; ifa; ifa = ifa->ifa_next) { - if (ifa->ifa_addr->sa_family != AF_LINK) - continue; - if (p && strcmp(p, ifa->ifa_name) == 0) - continue; - sdl = (const struct sockaddr_dl *) ifa->ifa_addr; - if (sdl->sdl_type != IFT_ETHER) - continue; - - strcpy(buffer+ptr, ifa->ifa_name); - ptr += strlen(ifa->ifa_name)+1; - } - - freeifaddrs(ifap); - - buffer[ptr++] = '\0'; - buffer[ptr++] = '\0'; - *size = ptr; - - return (ptr); -} - -#endif /* (__NetBSD__ || __OpenBSD__) && USE_NETWORK */ - diff --git a/sim_ether.h b/sim_ether.h deleted file mode 100644 index b0471f57..00000000 --- a/sim_ether.h +++ /dev/null @@ -1,122 +0,0 @@ -/* sim_ether.h: OS-dependent network information - ------------------------------------------------------------------------------ - - Copyright (c) 2002-2003, David T. Hittner - - 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 - THE AUTHOR 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 the author shall not be - used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from the author. - - ------------------------------------------------------------------------------ - - Modification history: - - 05-Jun-03 DTH Added used to struct eth_packet - 01-Feb-03 MP Changed some uint8 strings to char* to reflect usage - 22-Oct-02 DTH Added all_multicast and promiscuous support - 21-Oct-02 DTH Corrected copyright again - 16-Oct-02 DTH Fixed copyright - 08-Oct-02 DTH Integrated with 2.10-0p4, added variable vector and copyrights - 03-Oct-02 DTH Beta version of xq/sim_ether released for SIMH 2.09-11 - 15-Aug-02 DTH Started XQ simulation - - ------------------------------------------------------------------------------ -*/ - -#ifndef _SIM_ETHER_H -#define _SIM_ETHER_H - -#include "sim_defs.h" - -/* structure declarations */ - -#define ETH_PROMISC 1 /* promiscuous mode = true */ -#define ETH_TIMEOUT -1 /* read timeout in milliseconds (immediate) */ -#define ETH_FILTER_MAX 20 /* maximum address filters */ -#define ETH_BPF_INS_MAX 500 /* maximum bpf instructions */ -#define ETH_DEV_NAME_MAX 256 /* maximum device name size */ -#define ETH_DEV_DESC_MAX 256 /* maximum device description size */ -#define ETH_MIN_PACKET 60 /* minimum ethernet packet size */ -#define ETH_MAX_PACKET 1514 /* maximum ethernet packet size */ - -struct eth_packet { - uint8 msg[1518]; - int len; - int used; -}; - -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; - char name[ETH_DEV_NAME_MAX]; - char desc[ETH_DEV_DESC_MAX]; -}; - -typedef int ETH_BOOL; -typedef unsigned char ETH_MAC[6]; -typedef struct eth_packet ETH_PACK; -typedef void (*ETH_PCALLBACK)(int status); -typedef struct eth_list ETH_LIST; - -struct eth_device { - char* name; /* name of ethernet device */ - void* handle; /* handle of implementation-specific device */ - ETH_PCALLBACK read_callback; /* read callback function */ - ETH_PCALLBACK write_callback; /* write callback function */ - ETH_PACK* read_packet; /* read packet */ - ETH_PACK* write_packet; /* write packet */ - ETH_MAC filter_address[ETH_FILTER_MAX]; /* filtering addresses */ - ETH_BOOL promiscuous; /* promiscuous mode flag */ - ETH_BOOL all_multicast; /* receive all multicast messages */ -}; - -typedef struct eth_device ETH_DEV; - -/* prototype declarations*/ - -t_stat eth_open (ETH_DEV* dev, char* name); /* open ethernet interface */ -t_stat eth_close (ETH_DEV* dev); /* close ethernet interface */ -t_stat eth_write (ETH_DEV* dev, ETH_PACK* packet,/* write sychronous packet; */ - ETH_PCALLBACK routine); /* callback when done */ -t_stat eth_read (ETH_DEV* dev, ETH_PACK* packet,/* read single packet; */ - ETH_PCALLBACK routine); /* callback when done*/ -t_stat eth_filter (ETH_DEV* dev, int addr_count, /* set filter on incoming packets */ - ETH_MAC* addresses, - ETH_BOOL all_multicast, - ETH_BOOL promiscuous); -int eth_devices (int max, ETH_LIST* dev); /* get ethernet devices on host */ - -void eth_mac_fmt (ETH_MAC* add, char* buffer); /* format ethernet mac address */ -void eth_packet_trace (ETH_PACK* packet, char* msg); /* trace ethernet packet */ - -#endif /* _SIM_ETHER_H */ diff --git a/sim_rev.h b/sim_rev.h deleted file mode 100644 index 73702935..00000000 --- a/sim_rev.h +++ /dev/null @@ -1,832 +0,0 @@ -/* sim_rev.h: simulator revisions and current rev level - - 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. -*/ - -#ifndef _SIM_REV_H_ -#define _SIM_REV_H_ 0 - -#define SIM_MAJOR 3 -#define SIM_MINOR 0 -#define SIM_PATCH 2 - -/* V3.0 revision history - -patch date module(s) and fix(es) - - 2 tbd scp.c: - -- fixed end-of-file problem in dep, idep - -- fixed error on trailing spaces in dep, idep - - pdp1_stddev.c - -- fixed system hang if continue after PTR error - -- added PTR start/stop functionality - -- added address switch functionality to PTR BOOT - - pdp1_sys.c: added multibank capability to LOAD - - pdp18b_cpu.c: - -- fixed priorities in PDP-15 API (PI between 3 and 4) - -- fixed sign handling in PDP-15 unsigned mul/div - -- fixed bug in CAF, must clear API subsystem - - i1401_mt.c: - -- fixed tape read end-of-record handling based on real 1401 - -- added diagnostic read (space forward) - - i1620_cpu.c - -- fixed bug in immediate index add (found by Michael Short) - - 1 27-Jul-03 pdp1_cpu.c: updated to detect indefinite I/O wait - - pdp1_drm.c: fixed incorrect logical, missing activate, break - - pdp1_lp.c: - -- fixed bugs in instruction decoding, overprinting - -- updated to detect indefinite I/O wait - - pdp1_stddev.c: - -- changed RIM loader to be "hardware" - -- updated to detect indefinite I/O wait - - pdp1_sys.c: added block loader format support to LOAD - - pdp10_rp.c: fixed bug in read header - - pdp11_rq: fixed bug in user disk size (found by Chaskiel M Grundman) - - pdp18b_cpu.c: - -- added FP15 support - -- added XVM support - -- added EAE support to the PDP-4 - -- added PDP-15 "re-entrancy ECO" - -- fixed memory protect/skip interaction - -- fixed CAF to only reset peripherals - - pdp18b_fpp.c: added FP15 - - pdp18b_lp.c: fixed bug in Type 62 overprinting - - pdp18b_rf.c: fixed bug in set size routine - - pdp18b_stddev.c: - -- increased PTP TIME for PDP-15 operating systems - -- added hardware RIM loader for PDP-7, PDP-9, PDP-15 - - pdp18b_sys.c: added FP15, KT15, XVM instructions - - pdp8b_df.c, pdp8_rf.c: fixed bug in set size routine - - hp2100_dr.c: - -- fixed drum sizes - -- fixed variable capacity interaction with SAVE/RESTORE - - i1401_cpu.c: revised fetch to model hardware more closely - - ibm1130: fixed bugs found by APL 1130 - - nova_dsk.c: fixed bug in set size routine - - altairz80: fixed bug in real-time clock on Windows host - - 0 15-Jun-03 scp.c: - -- added ASSIGN/DEASSIGN - -- changed RESTORE to detach files - -- added u5, u6 unit fields - -- added USE_ADDR64 support - -- changed some structure fields to unsigned - - scp_tty.c: added extended file seek - - sim_sock.c: fixed calling sequence in stubs - - sim_tape.c: - -- added E11 and TPC format support - -- added extended file support - - sim_tmxr.c: fixed bug in SHOW CONNECTIONS - - all magtapes: - -- added multiformat support - -- added extended file support - - i1401_cpu.c: - -- fixed mnemonic, instruction lengths, and reverse - scan length check bug for MCS - -- fixed MCE bug, BS off by 1 if zero suppress - -- fixed chaining bug, D lost if return to SCP - -- fixed H branch, branch occurs after continue - -- added check for invalid 8 character MCW, LCA - - i1401_mt.c: fixed load-mode end of record response - - nova_dsk.c: fixed variable size interaction with restore - - pdp1_dt.c: fixed variable size interaction with restore - - pdp10_rp.c: fixed ordering bug in attach - - pdp11_cpu.c: - -- fixed bug in MMR1 update (found by Tim Stark) - -- fixed bug in memory size table - - pdp11_lp.c, pdp11_rq.c: added extended file support - - pdp11_rl.c, pdp11_rp.c, pdp11_ry.c: fixed ordering bug in attach - - pdp11_tc.c: fixed variable size interaction with restore - - pdp11_xq.c: - -- corrected interrupts on IE state transition (code by Tom Evans) - -- added interrupt clear on soft reset (first noted by Bob Supnik) - -- removed interrupt when setting XL or RL (multiple people) - -- added SET/SHOW XQ STATS - -- added SHOW XQ FILTERS - -- added ability to split received packet into multiple buffers - -- added explicit runt & giant packet processing - - vax_fpa.c: - -- fixed integer overflow bug in CVTfi - -- fixed multiple bugs in EMODf - - vax_io.c: optimized byte and word DMA routines - - vax_sysdev.c: - -- added calibrated delay to ROM reads (from Mark Pizzolato) - -- fixed calibration problems in interval timer (from Mark Pizzolato) - - pdp1_dt.c: fixed variable size interaction with restore - - pdp18b_dt.c: fixed variable size interaction with restore - - pdp18b_mt.c: fixed bug in MTTR - - pdp18b_rf.c: fixed variable size interaction with restore - - pdp8_df.c, pdp8_rf.c: fixed variable size interaction - with restore - - pdp8_dt.c: fixed variable size interaction with restore - - pdp8_mt.c: fixed bug in SKTR - - hp2100_dp.c,hp2100_dq.c: - -- fixed bug in read status (13210A controller) - -- fixed bug in seek completion - - id_pt.c: fixed type declaration (found by Mark Pizzolato) - - gri_cpu.c: fixed bug in SC queue pointer management - -/* V2.10 revision history - - 4 03-Mar-03 scp.c - -- added .ini startup file capability - -- added multiple breakpoint actions - -- added multiple switch evaluation points - -- fixed bug in multiword deposits to file - - sim_tape.c: magtape simulation library - - h316_stddev.c: added set line frequency command - - hp2100_mt.c, hp2100_ms.c: revised to use magtape library - - i1401_mt.c: revised to use magtape library - - id_dp.c, id_idc.c: fixed cylinder overflow on writes - - id_mt.c: - -- fixed error handling to stop selector channel - -- revised to use magtape library - - id16_sys.c, id32_sys.c: added relative addressing support - - id_uvc.c: - -- added set frequency command to line frequency clock - -- improved calibration algorithm for precision clock - - nova_clk.c: added set line frequency command - - nova_dsk.c: fixed autosizing algorithm - - nova_mt.c: revised to use magtape library - - pdp10_tu.c: revised to use magtape library - - pdp11_cpu.c: fixed bug in MMR1 update (found by Tim Stark) - - pdp11_stddev.c - -- added set line frequency command - -- added set ctrl-c command - - pdp11_rq.c: - -- fixed ordering problem in queue process - -- fixed bug in vector calculation for VAXen - -- added user defined drive support - - pdp11_ry.c: fixed autosizing algorithm - - pdp11_tm.c, pdp11_ts.c: revised to use magtape library - - pdp11_tq.c: - -- fixed ordering problem in queue process - -- fixed overly restrictive test for bad modifiers - -- fixed bug in vector calculation for VAXen - -- added variable controller, user defined drive support - -- revised to use magtape library - - pdp18b_cpu.c: fixed three EAE bugs (found by Hans Pufal) - - pdp18b_mt.c: - -- fixed bugs in BOT error handling, interrupt handling - -- revised to use magtape library - - pdp18b_rf.c: - -- removed 22nd bit from disk address - -- fixed autosizing algorithm - - pdp18b_stddev.c: - -- added set line frequency command - -- added set ctrl-c command - - pdp18b_sys.c: fixed FMTASC printouts (found by Hans Pufal) - - pdp8_clk.c: added set line frequency command - - pdp8_df.c, pdp8_rf.c, pdp8_rx.c: fixed autosizing algorithm - - pdp8_mt.c: - -- fixed bug in BOT error handling - -- revised to use magtape library - - pdp8_tt.c: added set ctrl-c command - - sds_cpu.c: added set line frequency command - - sds_mt.c: revised to use magtape library - - vax_stddev.c: added set ctrl-c command - - 3 06-Feb-03 scp.c: - -- added dynamic extension of the breakpoint table - -- added breakpoint actions - - hp2100_cpu.c: fixed last cycle bug in DMA output (found by - Mike Gemeny) - - hp2100_ipl.c: individual links are full duplex (found by - Mike Gemeny) - - pdp11_cpu.c: changed R, SP to track PSW respectively - - pdp18b_defs.h, pdp18b_sys.c: added RB09 fixed head disk, - LP09 printer - - pdp18b_rf.c: - -- fixed IOT decoding (found by Hans Pufal) - -- fixed address overrun logic - -- added variable number of platters and autosizing - - pdp18b_rf.c: - -- fixed IOT decoding - -- fixed bug in command initiation - - pdp18b_rb.c: new RB09 fixed head disk - - pdp18b_lp.c: new LP09 line printer - - pdp8_df.c: added variable number of platters and autosizing - - pdp8_rf.c: added variable number of platters and autosizing - - nova_dsk.c: added variable number of platters and autosizing - - id16_cpu.c: fixed bug in SETM, SETMR (found by Mark Pizzolato) - - 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) - - pdp10_tu.c: - -- fixed bug in bootstrap (reported by Michael Thompson) - -- fixed bug in read (reported by Harris Newman) - - 0 15-Nov-02 SCP and libraries - scp.c: - -- added Telnet console support - -- removed VT emulation support - -- added support for statically buffered devices - -- added HELP - -- fixed bugs in set_logon, ssh_break (found by David Hittner) - -- added VMS file optimization (from Robert Alan Byer) - -- added quiet mode, DO with parameters, GUI interface, - extensible commands (from Brian Knittel) - -- added DEVICE context and flags - -- added central device enable/disable support - -- modified SAVE/GET to save and restore flags - -- modified boot routine calling sequence - scp_tty.c: - -- removed VT emulation support - -- added sim_os_sleep, renamed sim_poll_kbd, sim_putchar - sim_tmxr.c: - -- modified for Telnet console support - -- fixed bug in binary (8b) support - sim_sock.c: modified for Telnet console support - sim_ether.c: new library for Ethernet (from David Hittner) - - all magtapes: - -- added support for end of medium - -- cleaned up BOT handling - - all DECtapes: added support for RT11 image file format - - most terminals and multiplexors: - -- added support for 7b vs 8b character processing - - PDP-1 - pdp1_cpu.c, pdp1_sys.c, pdp1_dt.c: added PDP-1 DECtape support - - PDP-8 - pdp8_cpu.c, all peripherals: - -- added variable device number support - -- added new device enabled/disable support - pdp8_rx.c: added RX28/RX02 support - - PDP-11 - pdp11_defs.h, pdp11_io.c, pdp11_sys.c, all peripherals: - -- added variable vector support - -- added new device enable/disable support - -- added autoconfiguration support - all bootstraps: modified to support variable addresses - dec_mscp.h, pdp11_tq.c: added TK50 support - pdp11_rq.c: - -- added multicontroller support - -- fixed bug in HBE error log packet - -- fixed bug in ATP processing - pdp11_ry.c: added RX211/RX02 support - pdp11_hk.c: added RK611/RK06/RK07 support - pdp11_tq.c: added TMSCP support - pdp11_xq.c: added DEQNA/DELQA support (from David Hittner) - pdp11_pclk.c: added KW11P support - pdp11_ts.c: - -- fixed bug in CTL decoding - -- fixed bug in extended status XS0_MOT - pdp11_stddev.c: removed paper tape to its own module - - PDP-18b - pdp18b_cpu.c, all peripherals: - -- added variable device number support - -- added new device enabled/disabled support - - VAX - dec_dz.h: fixed bug in number of boards calculation - vax_moddefs.h, vax_io.c, vax_sys.c, all peripherals: - -- added variable vector support - -- added new device enable/disable support - -- added autoconfiguration support - vax_sys.c: - -- generalized examine/deposit - -- added TMSCP, multiple RQDX3, DEQNA/DELQA support - vax_stddev.c: removed paper tape, now uses PDP-11 version - vax_sysdev.c: - -- allowed NVR to be attached to file - -- removed unused variables (found by David Hittner) - - PDP-10 - pdp10_defs.h, pdp10_ksio.c, all peripherals: - -- added variable vector support - -- added new device enable/disable support - pdp10_defs.h, pdp10_ksio.c: added support for standard PDP-11 - peripherals, added RX211 support - pdp10_pt.c: rewritten to reference common implementation - - Nova, Eclipse: - nova_cpu.c, eclipse_cpu.c, all peripherals: - -- added new device enable/disable support - - HP2100 - hp2100_cpu: - -- fixed bugs in the EAU, 21MX, DMS, and IOP instructions - -- fixed bugs in the memory protect and DMS functions - -- created new options to enable/disable EAU, MPR, DMS - -- added new device enable/disable support - hp2100_fp.c: - -- recoded to conform to 21MX microcode algorithms - hp2100_stddev.c: - -- fixed bugs in TTY reset, OTA, time base generator - -- revised BOOT support to conform to RBL loader - -- added clock calibration - hp2100_dp.c: - -- changed default to 13210A - -- added BOOT support - hp2100_dq.c: - -- finished incomplete functions, fixed head switching - -- added BOOT support - hp2100_ms.c: - -- fixed bugs found by diagnostics - -- added 13183 support - -- added BOOT support - hp2100_mt.c: - -- fixed bugs found by diagnostics - -- disabled by default - hp2100_lpt.c: implemented 12845A controller - hp2100_lps.c: - -- renamed 12653A controller - -- added diagnostic mode for MPR, DCPC diagnostics - -- disabled by default - - IBM 1620: first release - -/* V2.9 revision history - - 11 20-Jul-02 i1401_mt.c: on read, end of record stores group mark - without word mark (found by Van Snyder) - - i1401_dp.c: reworked address generation and checking - - vax_cpu.c: added infinite loop detection and halt to - boot ROM option (from Mark Pizzolato) - - vax_fpa.c: changed function names to prevent conflict - with C math library - - pdp11_cpu.c: fixed bug in MMR0 update logic (from - John Dundas) - - pdp18b_stddev.c: added "ASCII mode" for reader and - punch (from Hans Pufal) - - gri_*.c: added GRI-909 simulator - - scp.c: added DO echo, DO exit (from Brian Knittel) - - scp_tty.c: added Windows priority hacking (from - Mark Pizzolato) - - 10 15-Jun-02 scp.c: fixed error checking on calls to fxread/fxwrite - (found by Norm Lastovic) - - scp_tty.c, sim_vt.h, sim_vt.c: added VTxxx emulation - support for Windows (from Fischer Franz) - - sim_sock.c: added OS/2 support (from Holger Veit) - - pdp11_cpu.c: fixed bugs (from John Dundas) - -- added special case for PS<15:12> = 1111 to MFPI - -- removed special case from MTPI - -- added masking of relocation adds - - i1401_cpu.c: - -- added multiply/divide - -- fixed bugs (found by Van Snyder) - o 5 and 7 character H, 7 character doesn't branch - o 8 character NOP - o 1401-like memory dump - - i1401_dp.c: added 1311 disk - - 9 04-May-02 pdp11_rq: fixed bug in polling routine - - 8 03-May-02 scp.c: - -- changed LOG/NOLOG to SET LOG/NOLOG - -- added SHOW LOG - -- added SET VT/NOVT and SHOW VT for VT emulation - - sim_sock.h: changed VMS stropt.h include to ioctl.h - - vax_cpu.c - -- added TODR powerup routine to set date, time on boot - -- fixed exception flows to clear trap request - -- fixed register logging in autoincrement indexed - - vax_stddev.c: added TODR powerup routine - - vax_cpu1.c: fixed exception flows to clear trap request - - 7 30-Apr-02 scp.c: fixed bug in clock calibration when (real) clock - jumps forward due too far (found by Jonathan Engdahl) - - pdp11_cpu.c: fixed bugs, added features (from John Dundas - and Wolfgang Helbig) - -- added HTRAP and BPOK to maintenance register - -- added trap on kernel HALT if MAINT set - -- fixed red zone trap, clear odd address and nxm traps - -- fixed RTS SP, don't increment restored SP - -- fixed TSTSET, write dst | 1 rather than prev R0 | 1 - -- fixed DIV, set N=0,Z=1 on div by zero (J11, 11/70) - -- fixed DIV, set set N=Z=0 on overfow (J11, 11/70) - -- fixed ASH, ASHC, count = -32 used implementation- - dependent 32 bit right shift - -- fixed illegal instruction test to detect 000010 - -- fixed write-only page test - - pdp11_rp.c: fixed SHOW ADDRESS command - - vaxmod_defs.h: fixed DZ vector base and number of lines - - dec_dz.h: - -- fixed interrupt acknowledge routines - -- fixed SHOW ADDRESS command - - all magtape routines: added test for badly formed - record length (suggested by Jonathan Engdahl) - - 6 18-Apr-02 vax_cpu.c: fixed CASEL condition codes - - vax_cpu1.c: fixed vfield pos > 31 test to be unsigned - - vax_fpu.c: fixed EDIV overflow test for 0 quotient - - 5 14-Apr-02 vax_cpu1.c: - -- fixed interrupt, prv_mode set to 0 (found by Tim Stark) - -- fixed PROBEx to mask mode to 2b (found by Kevin Handy) - - 4 1-Apr-02 pdp11_rq.c: fixed bug, reset cleared write protect status - - pdp11_ts.c: fixed bug in residual frame count after space - - 3 15-Mar-02 pdp11_defs.h: changed default model to KDJ11A (11/73) - - pdp11_rq.c: adjusted delays for M+ timing bugs - - hp2100_cpu.c, pdp10_cpu.c, pdp11_cpu.c: tweaked abort - code for ANSI setjmp/longjmp compliance - - hp2100_cpu.c, hp2100_fp.c, hp2100_stddev.c, hp2100_sys.c: - revised to allocate memory dynamically - - 2 01-Mar-02 pdp11_cpu.c: - -- fixed bugs in CPU registers - -- fixed double operand evaluation order for M+ - - pdp11_rq.c: added delays to initialization for - RSX11M+ prior to V4.5 - - 1 20-Feb-02 scp.c: fixed bug in clock calibration when (real) - time runs backwards - - pdp11_rq.c: fixed bug in host timeout logic - - pdp11_ts.c: fixed bug in message header logic - - pdp18b_defs.h, pdp18b_dt.c, pdp18b_sys.c: added - PDP-7 DECtape support - - hp2100_cpu.c: - -- added floating point and DMS - -- fixed bugs in DIV, ASL, ASR, LBT, SBT, CBT, CMW - - hp2100_sys.c: added floating point, DMS - - hp2100_fp.c: added floating point - - ibm1130: added Brian Knittel's IBM 1130 simulator - - 0 30-Jan-02 scp.c: - -- generalized timer package for multiple timers - -- added circular register arrays - -- fixed bugs, line spacing in modifier display - -- added -e switch to attach - -- moved device enable/disable to simulators - - scp_tty.c: VAX specific fix (from Robert Alan Byer) - - sim_tmxr.c, sim_tmxr.h: - -- added tmxr_fstats, tmxr_dscln - -- renamed tmxr_fstatus to tmxr_fconns - - sim_sock.c, sim_sock.h: added VMS support (from - Robert Alan Byer) - - pdp_dz.h, pdp18b_tt1.c, nova_tt1.c: - -- added SET DISCONNECT - -- added SHOW STATISTICS - - pdp8_defs.h: fixed bug in interrupt enable initialization - - pdp8_ttx.c: rewrote as unified multiplexor - - pdp11_cpu.c: fixed calc_MMR1 macro (found by Robert Alan Byer) - - pdp11_stddev.c: fixed bugs in KW11L (found by John Dundas) - - pdp11_rp.c: fixed bug in 18b mode boot - - pdp11 bootable I/O devices: fixed register setup at boot - exit (found by Doug Carman) - - hp2100_cpu.c: - -- fixed DMA register tables (found by Bill McDermith) - -- fixed SZx,SLx,RSS bug (found by Bill McDermith) - -- fixed flop restore logic (found by Bill McDermith) - - hp2100_mt.c: fixed bug on write of last character - - hp2100_dq,dr,ms,mux.c: added new disk, magtape, and terminal - multiplexor controllers - - i1401_cd.c, i1401_mt.c: new zero footprint bootstraps - (from Van Snyder) - - i1401_sys.c: fixed symbolic display of H, NOP with no trailing - word mark (found by Van Snyder) - - most CPUs: - -- replaced OLDPC with PC queue - -- implemented device enable/disable locally - - V2.8 revision history - -5 25-Dec-01 scp.c: fixed bug in DO command (found by John Dundas) - - pdp10_cpu.c: - -- moved trap-in-progress to separate variable - -- cleaned up declarations - -- cleaned up volatile state for GNU C longjmp - - pdp11_cpu.c: cleaned up declarations - - pdp11_rq.c: added RA-class disks - -4 17-Dec-01 pdp11_rq.c: added delayed processing of packets - -3 16-Dec-01 pdp8_cpu.c: - -- mode A EAE instructions didn't clear GTF - -- ASR shift count > 24 mis-set GTF - -- effective shift count == 32 didn't work - -2 07-Dec-01 scp.c: added breakpoint package - - all CPU's: revised to use new breakpoint package - -1 05-Dec-01 scp.c: fixed bug in universal register name logic - -0 30-Nov-01 Reorganized simh source and documentation tree - - scp: Added DO command, universal registers, extended - SET/SHOW logic - - pdp11: overhauled PDP-11 for DMA map support, shared - sources with VAX, dynamic buffer allocation - - 18b pdp: overhauled interrupt structure - - pdp8: added RL8A - - pdp10: fixed two ITS-related bugs (found by Dave Conroy) - - V2.7 revision history - -patch date module(s) and fix(es) - -15 23-Oct-01 pdp11_rp.c, pdp10_rp.c, pdp10_tu.c: fixed bugs - error interrupt handling - - pdp10_defs.h, pdp10_ksio.c, pdp10_fe.c, pdp10_fe.c, - pdp10_rp.c, pdp10_tu.c: reworked I/O page interface - to use symbolic base addresses and lengths - -14 20-Oct-01 dec_dz.h, sim_tmxr_h, sim_tmxr.c: fixed bug in Telnet - state handling (found by Thord Nilson), removed - tmxr_getchar, added tmxr_rqln and tmxr_tqln - -13 18-Oct-01 pdp11_tm.c: added stub diagnostic register clock - for RSTS/E (found by Thord Nilson) - -12 15-Oct-01 pdp11_defs.h, pdp11_cpu.c, pdp11_tc.c, pdp11_ts.c, - pdp11_rp.c: added operations logging - -11 8-Oct-01 scp.c: added sim_rev.h include and version print - - pdp11_cpu.c: fixed bug in interrupt acknowledge, - multiple outstanding interrupts caused the lowest - rather than the highest to be acknowledged - -10 7-Oct-01 pdp11_stddev.c: added monitor bits (CSR<7>) for full - KW11L compatibility, needed for RSTS/E autoconfiguration - -9 6-Oct-01 pdp11_rp.c, pdp10_rp.c, pdp10_tu.c: rewrote interrupt - logic from RH11/RH70 schematics, to mimic hardware quirks - - dec_dz.c: fixed bug in carrier detect logic, carrier - detect was being cleared on next modem poll - -8 4-Oct-01 pdp11_rp.c, pdp10_rp.c, pdp10_tu.c: undid edit of - 28-Sep-01; real problem was level-sensitive nature of - CS1_SC, but CS1_SC can only trigger an interrupt if - DONE is set - -7 2-Oct-01 pdp11_rp.c, pdp10_rp.c: CS1_SC is evaluated as a level- - sensitive, rather than an edge-sensitive, input to - interrupt request - -6 30-Sep-01 pdp11_rp.c, pdp10_rp.c: separated out CS1<5:0> to per- - drive registers - - pdp10_tu.c: based on above, cleaned up handling of - non-existent formatters, fixed non-data transfer - commands clearing DONE - -5 28-Sep-01 pdp11_rp.c, pdp10_rp.c, pdp10_tu.c: controller should - interrupt if ATA or SC sets when IE is set, was - interrupting only if DON = 1 as well - -4 27-Sep-01 pdp11_ts.c: - -- NXM errors should return TC4 or TC5; were returning TC3 - -- extended features is part of XS2; was returned in XS3 - -- extended characteristics (fifth) word needed for RSTS/E - - pdp11_tc.c: stop, stop all do cause an interrupt - - dec_dz.h: scanner should find a ready output line, even - if there are no connections; needed for RSTS/E autoconfigure - - scp.c: - -- added routine sim_qcount for 1130 - -- added "simulator exit" detach routine for 1130 - - sim_defs.h: added header for sim_qcount - -3 20-Sep-01 pdp11_ts.c: boot code binary was incorrect - -2 19-Sep-01 pdp18b_cpu.c: EAE should interpret initial count of 00 - as 100 - - scp.c: modified Macintosh support - -1 17-Sep-01 pdp8_ttx.c: new module for PDP-8 multi-terminal support - - pdp18b_tt1.c: modified to use sim_tmxr library - - nova_tt1.c: modified to use sim_tmxr library - - dec_dz.h: added autodisconnect support - - scp.c: removed old multiconsole support - - sim_tmxr.c: modified calling sequence for sim_putchar_ln - - sim_sock.c: added Macintosh sockets support -*/ - -#endif diff --git a/sim_sock.c b/sim_sock.c deleted file mode 100644 index e79380b3..00000000 --- a/sim_sock.c +++ /dev/null @@ -1,296 +0,0 @@ -/* sim_sock.c: OS-dependent socket routines - - 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. - - 17-Apr-03 RMS Fixed non-implemented version of sim_close_sock - (found by Mark Pizzolato) - 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 - 06-Feb-02 RMS Added VMS support from Robert Alan Byer - 16-Sep-01 RMS Added Macintosh support from Peter Schorn - 02-Sep-01 RMS Fixed UNIX bugs found by Mirian Lennox and Tom Markson -*/ - -#include "sim_defs.h" -#include "sim_sock.h" -#include - -/* OS dependent routines - - sim_master_sock create master socket - sim_accept_conn accept connection - sim_read_sock read from socket - sim_write_sock write from socket - sim_close_sock close socket - sim_setnonblock set socket non-blocking - sim_msg_sock send message to socket -*/ - -int32 sim_sock_cnt = 0; - -/* First, all the non-implemented versions */ - -#if defined (__OS2__) && !defined (__EMX__) - -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; -} - -int32 sim_read_sock (SOCKET sock, char *buf, int32 nbytes) -{ -return -1; -} - -int32 sim_write_sock (SOCKET sock, char *msg, int32 nbytes) -{ -return 0; -} - -void sim_close_sock (SOCKET sock, t_bool master) -{ -return; -} - -SOCKET sim_setnonblock (SOCKET sock) -{ -return SOCKET_ERROR; -} - -#else /* endif unimpl */ - -/* 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; - -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); /* insert addr */ - -sta = bind (newsock, (struct sockaddr *) &name, sizeof (name)); -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? */ - 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); - -return newsock; /* got it! */ -} - -SOCKET sim_accept_conn (SOCKET master, uint32 *ipaddr) -{ -int32 sta, err; -#if defined (macintosh) -socklen_t size; -#elif defined (_WIN32) || defined (__EMX__) -int size; -#else -size_t size; -#endif -SOCKET newsock; -struct sockaddr_in clientname; - -if (master == 0) return INVALID_SOCKET; /* not attached? */ -size = sizeof (clientname); -newsock = accept (master, (struct sockaddr *) &clientname, &size); -if (newsock == INVALID_SOCKET) { /* 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? */ - 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; - -timerclear (&tz); -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, err; - -rbytes = recv (sock, buf, nbytes, 0); -if (rbytes == 0) return -1; /* disconnect */ -if (rbytes == SOCKET_ERROR) { - err = WSAGetLastError (); - if (err == WSAEWOULDBLOCK) return 0; /* no data */ - printf ("Sockets: read error %d\n", err); - return -1; } -return rbytes; -} - -int32 sim_write_sock (SOCKET sock, char *msg, int32 nbytes) -{ -return send (sock, msg, nbytes, 0); -} - -void sim_close_sock (SOCKET sock, t_bool master) -{ -#if defined (_WIN32) -closesocket (sock); -if (master) { - sim_sock_cnt = sim_sock_cnt - 1; - if (sim_sock_cnt <= 0) { - WSACleanup (); - sim_sock_cnt = 0; } } -#else -close (sock); -#endif -return; -} - -#if defined (_WIN32) /* Windows */ -SOCKET sim_setnonblock (SOCKET sock) -{ -unsigned long non_block = 1; - -return ioctlsocket (sock, FIONBIO, &non_block); /* set nonblocking */ -} - -#elif defined (VMS) /* VMS */ -SOCKET sim_setnonblock (SOCKET sock) -{ -int non_block = 1; - -return ioctl (sock, FIONBIO, &non_block); /* set nonblocking */ -} - -#else /* Mac, Unix, OS/2 */ -int32 sim_setnonblock (SOCKET sock) -{ -int32 fl, sta; - -fl = fcntl (sock, F_GETFL,0); /* get flags */ -if (fl == -1) return SOCKET_ERROR; -sta = fcntl (sock, F_SETFL, fl | O_NONBLOCK); /* set nonblock */ -if (sta == -1) return SOCKET_ERROR; -#if !defined (macintosh) && !defined (__EMX__) /* Unix only */ -sta = fcntl (sock, F_SETOWN, getpid()); /* set ownership */ -if (sta == -1) return SOCKET_ERROR; -#endif -return 0; -} - -#endif /* endif !Win32 && !VMS */ - -#endif /* end else !implemented */ diff --git a/sim_sock.h b/sim_sock.h deleted file mode 100644 index c31ac676..00000000 --- a/sim_sock.h +++ /dev/null @@ -1,75 +0,0 @@ -/* sim_sock.h: OS-dependent socket routines header file - - 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. - - 20-Mar-03 RMS Added missing timerclear definition for VMS (from - Robert Alan Byer) - 15-Feb-03 RMS Added time.h for EMX (from Holger Veit) - 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 - 06-Feb-02 RMS Added VMS support from Robert Alan Byer - 16-Sep-01 RMS Added Macintosh support from Peter Schorn -*/ - -#ifndef _SIM_SOCK_H_ -#define _SIM_SOCK_H_ 0 - -#if defined (_WIN32) /* Windows */ -#undef INT_PTR /* hack, hack */ -#include - -#elif !defined (__OS2__) || defined (__EMX__) /* VMS, Mac, Unix, OS/2 EMX */ -#define WSAGetLastError() errno /* Windows macros */ -#define SOCKET int32 -#define WSAEWOULDBLOCK EWOULDBLOCK -#define INVALID_SOCKET -1 -#define SOCKET_ERROR -1 -#include /* for fcntl, getpid */ -#include /* for sockets */ -#include -#include -#include /* for sockaddr_in */ -#include -#include /* for EMX */ -#endif - -#if defined (VMS) /* VMS unique */ -#include /* for ioctl */ -#if !defined (timerclear) -#define timerclear(tvp) (tvp)->tv_sec = (tvp)->tv_usec = 0 -#endif -#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); -SOCKET sim_setnonblock (SOCKET sock); - -#endif diff --git a/sim_tape.c b/sim_tape.c deleted file mode 100644 index ecd38a58..00000000 --- a/sim_tape.c +++ /dev/null @@ -1,548 +0,0 @@ -/* sim_tape.c: simulator tape support library - - 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. - - Ultimately, this will be a place to hide processing of various tape formats, - as well as OS-specific direct hardware access. - - 25-Apr-03 RMS Added extended file support - 28-Mar-03 RMS Added E11 and TPC format support - - Public routines: - - sim_tape_attach attach tape unit - sim_tape_detach detach tape unit - sim_tape_rdrecf read tape record forward - sim_tape_rdrecr read tape record reverse - sim_tape_wrrecf write tape record forward - sim_tape_sprecf space tape record forward - sim_tape_sprecr space tape record reverse - sim_tape_wrtmk write tape mark - sim_tape_wreom erase remainder of tape - sim_tape_rewind rewind - sim_tape_reset reset unit - sim_tape_bot TRUE if at beginning of tape - sim_tape_eot TRUE if at or beyond end of tape - sim_tape_wrp TRUE if write protected - sim_tape_set_fmt set tape format - sim_tape_show_fmt show tape format -*/ - -#include "sim_defs.h" -#include "sim_tape.h" - -struct sim_tape_fmt { - char *name; /* name */ - int32 uflags; /* unit flags */ - t_addr bot; /* bot test */ -}; - -static struct sim_tape_fmt fmts[MTUF_N_FMT] = { - { "SIMH", 0, sizeof (t_mtrlnt) - 1 }, - { "E11", 0, sizeof (t_mtrlnt) - 1 }, - { "TPC", UNIT_RO, sizeof (t_tpclnt) - 1 }, -/* { "TPF", UNIT_RO, 0 }, */ - { NULL, 0, 0 } -}; - -extern int32 sim_switches; - -t_stat sim_tape_ioerr (UNIT *uptr); -t_stat sim_tape_wrdata (UNIT *uptr, uint32 dat); -uint32 sim_tape_tpc_map (UNIT *uptr, t_addr *map); -t_addr sim_tape_tpc_fnd (UNIT *uptr, t_addr *map); - -/* Attach tape unit */ - -t_stat sim_tape_attach (UNIT *uptr, char *cptr) -{ -uint32 objc; -char gbuf[CBUFSIZE]; -t_stat r; - -if (sim_switches & SWMASK ('F')) { /* format spec? */ - cptr = get_glyph (cptr, gbuf, 0); /* get spec */ - if (*cptr == 0) return SCPE_2FARG; /* must be more */ - if (sim_tape_set_fmt (uptr, 0, gbuf, NULL) != SCPE_OK) - return SCPE_ARG; } -r = attach_unit (uptr, cptr); /* attach unit */ -if (r != SCPE_OK) return r; /* error? */ - -switch (MT_GET_FMT (uptr)) { /* case on format */ -case MTUF_F_TPC: /* TPC */ - objc = sim_tape_tpc_map (uptr, NULL); /* get # objects */ - if (objc == 0) { /* tape empty? */ - sim_tape_detach (uptr); - return SCPE_FMT; } /* yes, complain */ - uptr->filebuf = calloc (objc + 1, sizeof (t_mtrlnt)); - if (uptr->filebuf == NULL) { /* map allocated? */ - sim_tape_detach (uptr); - return SCPE_MEM; } /* no, complain */ - uptr->hwmark = objc + 1; /* save map size */ - sim_tape_tpc_map (uptr, uptr->filebuf); /* fill map */ - break; -default: - break; } - -sim_tape_rewind (uptr); -return SCPE_OK; -} - -/* Detach tape unit */ - -t_stat sim_tape_detach (UNIT *uptr) -{ -uint32 f = MT_GET_FMT (uptr); -t_stat r; - -r = detach_unit (uptr); /* detach unit */ -if (r != SCPE_OK) return r; - -switch (f) { /* case on format */ -case MTUF_F_TPC: /* TPC */ - if (uptr->filebuf) free (uptr->filebuf); /* free map */ - uptr->filebuf = NULL; - uptr->hwmark = 0; - break; -default: - break; } - -sim_tape_rewind (uptr); -return SCPE_OK; -} - -/* Read record length forward (internal routine) - - Inputs: - uptr = pointer to tape unit - bc = pointer to returned record length - Outputs: - status = operation status - - exit condition position - - unit unattached unchanged - read error unchanged, PNU set - end of file/medium unchanged, PNU set - tape mark updated - data record updated, fxread will read record forward -*/ - -t_stat sim_tape_rdlntf (UNIT *uptr, t_mtrlnt *bc) -{ -uint32 f = MT_GET_FMT (uptr); -t_mtrlnt sbc; -t_tpclnt tpcbc; - -MT_CLR_PNU (uptr); -if ((uptr->flags & UNIT_ATT) == 0) return MTSE_UNATT; /* not attached? */ -fseek_ext (uptr->fileref, uptr->pos, SEEK_SET); /* set tape pos */ - -switch (f) { /* switch on fmt */ -case MTUF_F_STD: case MTUF_F_E11: - fxread (bc, sizeof (t_mtrlnt), 1, uptr->fileref); /* read rec lnt */ - sbc = MTR_L (*bc); /* save rec lnt */ - if (ferror (uptr->fileref)) { /* error? */ - MT_SET_PNU (uptr); /* pos not upd */ - return sim_tape_ioerr (uptr); } - if (feof (uptr->fileref) || (*bc == MTR_EOM)) { /* eof or eom? */ - MT_SET_PNU (uptr); /* pos not upd */ - return MTSE_EOM; } - uptr->pos = uptr->pos + sizeof (t_mtrlnt); /* spc over rec lnt */ - if (*bc == MTR_TMK) return MTSE_TMK; /* tape mark? */ - uptr->pos = uptr->pos + sizeof (t_mtrlnt) + /* spc over record */ - ((f == MTUF_F_STD)? ((sbc + 1) & ~1): sbc); - break; - -case MTUF_F_TPC: - fxread (&tpcbc, sizeof (t_tpclnt), 1, uptr->fileref); - *bc = tpcbc; /* save rec lnt */ - if (ferror (uptr->fileref)) { /* error? */ - MT_SET_PNU (uptr); /* pos not upd */ - return sim_tape_ioerr (uptr); } - if (feof (uptr->fileref)) { /* eof? */ - MT_SET_PNU (uptr); /* pos not upd */ - return MTSE_EOM; } - uptr->pos = uptr->pos + sizeof (t_tpclnt); /* spc over reclnt */ - if (tpcbc == TPC_TMK) return MTSE_TMK; /* tape mark? */ - uptr->pos = uptr->pos + ((tpcbc + 1) & ~1); /* spc over record */ - break; - -default: - return MTSE_FMT; } - -return MTSE_OK; -} - -/* Read record length reverse (internal routine) - - Inputs: - uptr = pointer to tape unit - bc = pointer to returned record length - Outputs: - status = operation status - - exit condition position - - unit unattached unchanged - beginning of tape unchanged - read error unchanged - end of file unchanged - end of medium updated - tape mark updated - data record updated, fxread will read record forward -*/ - -t_stat sim_tape_rdlntr (UNIT *uptr, t_mtrlnt *bc) -{ -uint32 f = MT_GET_FMT (uptr); -t_addr ppos; -t_mtrlnt sbc; -t_tpclnt tpcbc; - -MT_CLR_PNU (uptr); -if ((uptr->flags & UNIT_ATT) == 0) return MTSE_UNATT; /* not attached? */ -if (sim_tape_bot (uptr)) return MTSE_BOT; /* at BOT? */ - -switch (f) { /* switch on fmt */ -case MTUF_F_STD: case MTUF_F_E11: - fseek_ext (uptr->fileref, uptr->pos - sizeof (t_mtrlnt), SEEK_SET); - fxread (bc, sizeof (t_mtrlnt), 1, uptr->fileref); /* read rec lnt */ - sbc = MTR_L (*bc); - if (ferror (uptr->fileref)) /* error? */ - return sim_tape_ioerr (uptr); - if (feof (uptr->fileref)) return MTSE_EOM; /* eof? */ - uptr->pos = uptr->pos - sizeof (t_mtrlnt); /* spc over rec lnt */ - if (*bc == MTR_EOM) return MTSE_EOM; /* eom? */ - if (*bc == MTR_TMK) return MTSE_TMK; /* tape mark? */ - uptr->pos = uptr->pos - sizeof (t_mtrlnt) - /* spc over record */ - ((f == MTUF_F_STD)? ((sbc + 1) & ~1): sbc); - fseek_ext (uptr->fileref, uptr->pos + sizeof (t_mtrlnt), SEEK_SET); - break; - -case MTUF_F_TPC: - ppos = sim_tape_tpc_fnd (uptr, uptr->filebuf); /* find prev rec */ - fseek_ext (uptr->fileref, ppos, SEEK_SET); /* position */ - fxread (&tpcbc, sizeof (t_tpclnt), 1, uptr->fileref); - *bc = tpcbc; /* save rec lnt */ - if (ferror (uptr->fileref)) /* error? */ - return sim_tape_ioerr (uptr); - if (feof (uptr->fileref)) return MTSE_EOM; /* eof? */ - uptr->pos = ppos; /* spc over record */ - if (*bc == MTR_TMK) return MTSE_TMK; /* tape mark? */ - fseek_ext (uptr->fileref, uptr->pos + sizeof (t_tpclnt), SEEK_SET); - break; -default: - return MTSE_FMT; } -return MTSE_OK; -} - -/* Read record forward - - Inputs: - uptr = pointer to tape unit - buf = pointer to buffer - bc = pointer to returned record length - max = maximum record size - Outputs: - status = operation status - - exit condition position - - unit unattached unchanged - read error unchanged, PNU set - end of file/medium unchanged, PNU set - invalid record unchanged, PNU set - tape mark updated - data record updated - data record error updated -*/ - -t_stat sim_tape_rdrecf (UNIT *uptr, uint8 *buf, t_mtrlnt *bc, t_mtrlnt max) -{ -t_mtrlnt i, tbc, rbc; -t_addr opos; -t_stat st; - -opos = uptr->pos; /* old position */ -if (st = sim_tape_rdlntf (uptr, &tbc)) return st; /* read rec lnt */ -*bc = rbc = MTR_L (tbc); /* strip error flag */ -if (rbc > max) { /* rec out of range? */ - MT_SET_PNU (uptr); - uptr->pos = opos; - return MTSE_INVRL; } -i = fxread (buf, sizeof (uint8), rbc, uptr->fileref); /* read record */ -if (ferror (uptr->fileref)) { /* error? */ - MT_SET_PNU (uptr); - uptr->pos = opos; - return sim_tape_ioerr (uptr); } -for ( ; i < rbc; i++) buf[i] = 0; /* fill with 0's */ -return (MTR_F (tbc)? MTSE_RECE: MTSE_OK); -} - -/* Read record reverse - - Inputs: - uptr = pointer to tape unit - buf = pointer to buffer - bc = pointer to returned record length - max = maximum record size - Outputs: - status = operation status - - exit condition position - - unit unattached unchanged - read error unchanged - end of file unchanged - end of medium updated - invalid record unchanged - tape mark updated - data record updated - data record error updated -*/ - -t_stat sim_tape_rdrecr (UNIT *uptr, uint8 *buf, t_mtrlnt *bc, t_mtrlnt max) -{ -t_mtrlnt i, rbc, tbc; -t_stat st; - -if (st = sim_tape_rdlntr (uptr, &tbc)) return st; /* read rec lnt */ -*bc = rbc = MTR_L (tbc); /* strip error flag */ -if (rbc > max) return MTSE_INVRL; /* rec out of range? */ -i = fxread (buf, sizeof (uint8), rbc, uptr->fileref); /* read record */ -if (ferror (uptr->fileref)) /* error? */ - return sim_tape_ioerr (uptr); -for ( ; i < rbc; i++) buf[i] = 0; /* fill with 0's */ -return (MTR_F (tbc)? MTSE_RECE: MTSE_OK); -} - -/* Write record forward - - Inputs: - uptr = pointer to tape unit - buf = pointer to buffer - bc = record length - Outputs: - status = operation status - - exit condition position - - unit unattached unchanged - write protect unchanged - write error unchanged, PNU set - data record updated -*/ - -t_stat sim_tape_wrrecf (UNIT *uptr, uint8 *buf, t_mtrlnt bc) -{ -uint32 f = MT_GET_FMT (uptr); -t_mtrlnt sbc; - -MT_CLR_PNU (uptr); -if (f == MTUF_F_STD) sbc = (bc + 1) & ~1; -else sbc = bc; -if ((uptr->flags & UNIT_ATT) == 0) return MTSE_UNATT; /* not attached? */ -if (uptr->flags & MTUF_WRP) return MTSE_WRP; /* write prot? */ -fseek_ext (uptr->fileref, uptr->pos, SEEK_SET); /* set pos */ -fxwrite (&bc, sizeof (t_mtrlnt), 1, uptr->fileref); -fxwrite (buf, sizeof (uint8), sbc, uptr->fileref); -fxwrite (&bc, sizeof (t_mtrlnt), 1, uptr->fileref); -if (ferror (uptr->fileref)) { /* error? */ - MT_SET_PNU (uptr); - return sim_tape_ioerr (uptr); } -uptr->pos = uptr->pos + sbc + (2 * sizeof (t_mtrlnt)); /* move tape */ -return MTSE_OK; -} - -/* Write metadata forward (internal routine) */ - -t_stat sim_tape_wrdata (UNIT *uptr, uint32 dat) -{ -MT_CLR_PNU (uptr); -if ((uptr->flags & UNIT_ATT) == 0) return MTSE_UNATT; /* not attached? */ -if (uptr-> flags & MTUF_WRP) return MTSE_WRP; /* write prot? */ -fseek_ext (uptr->fileref, uptr->pos, SEEK_SET); /* set pos */ -fxwrite (&dat, sizeof (t_mtrlnt), 1, uptr->fileref); -if (ferror (uptr->fileref)) { /* error? */ - MT_SET_PNU (uptr); - return sim_tape_ioerr (uptr); } -uptr->pos = uptr->pos + sizeof (t_mtrlnt); /* move tape */ -return MTSE_OK; -} - -/* Write tape mark */ - -t_stat sim_tape_wrtmk (UNIT *uptr) -{ -return sim_tape_wrdata (uptr, MTR_TMK); -} - -/* Write end of medium */ - -t_stat sim_tape_wreom (UNIT *uptr) -{ -return sim_tape_wrdata (uptr, MTR_EOM); -} - -/* Space record forward */ - -t_stat sim_tape_sprecf (UNIT *uptr, t_mtrlnt *bc) -{ -t_stat st; - -st = sim_tape_rdlntf (uptr, bc); /* get record length */ -*bc = MTR_L (*bc); -return st; -} - -/* Space record reverse */ - -t_stat sim_tape_sprecr (UNIT *uptr, t_mtrlnt *bc) -{ -t_stat st; - -if (MT_TST_PNU (uptr)) { - MT_CLR_PNU (uptr); - *bc = 0; - return SCPE_OK; } -st = sim_tape_rdlntr (uptr, bc); /* get record length */ -*bc = MTR_L (*bc); -return st; -} - -/* Rewind tape */ - -t_stat sim_tape_rewind (UNIT *uptr) -{ -uptr->pos = 0; -MT_CLR_PNU (uptr); -return MTSE_OK; -} - -/* Reset tape */ - -t_stat sim_tape_reset (UNIT *uptr) -{ -MT_CLR_PNU (uptr); -return SCPE_OK; -} - -/* Test for BOT */ - -t_bool sim_tape_bot (UNIT *uptr) -{ -uint32 f = MT_GET_FMT (uptr); - -return (uptr->pos <= fmts[f].bot)? TRUE: FALSE; -} - -/* Test for end of tape */ - -t_bool sim_tape_eot (UNIT *uptr, t_addr cap) -{ -return (uptr->pos > cap)? TRUE: FALSE; -} - -/* Test for write protect */ - -t_bool sim_tape_wrp (UNIT *uptr) -{ -return (uptr->flags & MTUF_WRP)? TRUE: FALSE; -} - -/* Process I/O error */ - -t_stat sim_tape_ioerr (UNIT *uptr) -{ -perror ("Magtape library I/O error"); -clearerr (uptr->fileref); -return SCPE_IOERR; -} - -/* Set tape format */ - -t_stat sim_tape_set_fmt (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -int32 f; - -if (uptr == NULL) return SCPE_IERR; -if (cptr == NULL) return SCPE_ARG; -for (f = 0; f < MTUF_N_FMT; f++) { - if (fmts[f].name && (strcmp (cptr, fmts[f].name) == 0)) { - uptr->flags = (uptr->flags & ~MTUF_FMT) | - (f << MTUF_V_FMT) | fmts[f].uflags; - return SCPE_OK; } } -return SCPE_ARG; -} - -/* Show tape format */ - -t_stat sim_tape_show_fmt (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -int32 f = MT_GET_FMT (uptr); - -if (fmts[f].name) fprintf (st, "%s format", fmts[f].name); -else fprintf (st, "invalid format"); -return SCPE_OK; -} - -/* Map a TPC format tape image */ - -uint32 sim_tape_tpc_map (UNIT *uptr, t_addr *map) -{ -t_addr tpos; -t_tpclnt bc; -uint32 i, objc; - -if ((uptr == NULL) || (uptr->fileref == NULL)) return 0; -for (objc = 0, tpos = 0;; ) { - fseek_ext (uptr->fileref, tpos, SEEK_SET); - i = fxread (&bc, sizeof (t_tpclnt), 1, uptr->fileref); - if (i == 0) break; - if (map) map[objc] = tpos; - objc++; - tpos = tpos + ((bc + 1) & ~1) + sizeof (t_tpclnt); } -if (map) map[objc] = tpos; -return objc; -} - -/* Find the preceding record in a TPC file */ - -t_addr sim_tape_tpc_fnd (UNIT *uptr, t_addr *map) -{ -uint32 lo, hi, p; - - -if (map == NULL) return 0; -lo = 0; -hi = uptr->hwmark - 1; -do { p = (lo + hi) >> 1; - if (uptr->pos == map[p]) - return ((p == 0)? map[p]: map[p - 1]); - else if (uptr->pos < map[p]) hi = p - 1; - else lo = p + 1; } -while (lo <= hi); -return ((p == 0)? map[p]: map[p - 1]); -} diff --git a/sim_tape.h b/sim_tape.h deleted file mode 100644 index 74d3f363..00000000 --- a/sim_tape.h +++ /dev/null @@ -1,101 +0,0 @@ -/* sim_tape.h: simulator tape support library definitions - - 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. -*/ - -#ifndef _SIM_TAPE_H_ -#define _SIM_TAPE_H_ 0 - -/* SIMH/E11 tape format */ - -typedef uint32 t_mtrlnt; /* magtape rec lnt */ - -#define MTR_TMK 0x00000000 /* tape mark */ -#define MTR_EOM 0xFFFFFFFF /* end of medium */ -#define MTR_ERF 0x80000000 /* error flag */ -#define MTR_F(x) ((x) & MTR_ERF) /* record error flg */ -#define MTR_L(x) ((x) & ~MTR_ERF) /* record length */ - -/* TPC tape format */ - -typedef uint16 t_tpclnt; /* magtape rec lnt */ - -#define TPC_TMK 0x0000 /* tape mark */ - -/* Unit flags */ - -#define MTUF_V_PNU (UNIT_V_UF + 0) /* position not upd */ -#define MTUF_V_WLK (UNIT_V_UF + 1) /* write locked */ -#define MTUF_V_FMT (UNIT_V_UF + 2) /* tape file format */ -#define MTUF_W_FMT 3 /* 3b of formats */ -#define MTUF_N_FMT (1u << MTUF_W_FMT) /* number of formats */ -#define MTUF_M_FMT ((1u << MTUF_W_FMT) - 1) -#define MTUF_F_STD 0 /* SIMH format */ -#define MTUF_F_E11 1 /* E11 format */ -#define MTUF_F_TPC 2 /* TPC format */ -#define MUTF_F_TDF 3 /* TDF format */ -#define MTUF_V_UF (MTUF_V_FMT + MTUF_W_FMT) -#define MTUF_PNU (1u << MTUF_V_PNU) -#define MTUF_WLK (1u << MTUF_V_WLK) -#define MTUF_FMT (MTUF_M_FMT << MTUF_V_FMT) -#define MTUF_WRP (MTUF_WLK | UNIT_RO) - -#define MT_SET_PNU(u) (u)->flags = (u)->flags | MTUF_PNU -#define MT_CLR_PNU(u) (u)->flags = (u)->flags & ~MTUF_PNU -#define MT_TST_PNU(u) ((u)->flags & MTUF_PNU) -#define MT_GET_FMT(u) (((u)->flags >> MTUF_V_FMT) & MTUF_M_FMT) - -/* Return status codes */ - -#define MTSE_OK 0 /* no error */ -#define MTSE_TMK 1 /* tape mark */ -#define MTSE_UNATT 2 /* unattached */ -#define MTSE_IOERR 3 /* IO error */ -#define MTSE_INVRL 4 /* invalid rec lnt */ -#define MTSE_FMT 5 /* invalid format */ -#define MTSE_BOT 6 /* beginning of tape */ -#define MTSE_EOM 7 /* end of medium */ -#define MTSE_RECE 8 /* error in record */ -#define MTSE_WRP 9 /* write protected */ - -/* Prototypes */ - -t_stat sim_tape_attach (UNIT *uptr, char *cptr); -t_stat sim_tape_detach (UNIT *uptr); -t_stat sim_tape_rdrecf (UNIT *uptr, uint8 *buf, t_mtrlnt *bc, t_mtrlnt max); -t_stat sim_tape_rdrecr (UNIT *uptr, uint8 *buf, t_mtrlnt *bc, t_mtrlnt max); -t_stat sim_tape_wrrecf (UNIT *uptr, uint8 *buf, t_mtrlnt bc); -t_stat sim_tape_wrtmk (UNIT *uptr); -t_stat sim_tape_wreom (UNIT *uptr); -t_stat sim_tape_sprecf (UNIT *uptr, t_mtrlnt *bc); -t_stat sim_tape_sprecr (UNIT *uptr, t_mtrlnt *bc); -t_stat sim_tape_rewind (UNIT *uptr); -t_stat sim_tape_reset (UNIT *uptr); -t_bool sim_tape_bot (UNIT *uptr); -t_bool sim_tape_wrp (UNIT *uptr); -t_bool sim_tape_eot (UNIT *uptr, t_addr cap); -t_stat sim_tape_set_fmt (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat sim_tape_show_fmt (FILE *st, UNIT *uptr, int32 val, void *desc); - -#endif diff --git a/sim_tmxr.c b/sim_tmxr.c deleted file mode 100644 index e3f0f6a8..00000000 --- a/sim_tmxr.c +++ /dev/null @@ -1,496 +0,0 @@ -/* sim_tmxr.c: Telnet terminal multiplexor library - - 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. - - Based on the original DZ11 simulator by Thord Nilson, as updated by - Arthur Krewat. - - 09-Mar-03 RMS Fixed bug in SHOW CONN - 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 -*/ - -#include "sim_defs.h" -#include "sim_sock.h" -#include "sim_tmxr.h" -#include - -/* Telnet protocol constants - negatives are for init'ing signed char data */ - -#define TN_IAC -1 /* protocol delim */ -#define TN_DONT -2 /* dont */ -#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 */ -#define TN_LINE 34 /* line mode */ -#define TN_CR 015 /* carriage return */ - -/* Telnet line states */ - -#define TNS_NORM 000 /* normal */ -#define TNS_IAC 001 /* IAC seen */ -#define TNS_WILL 002 /* WILL seen */ -#define TNS_WONT 003 /* WONT seen */ -#define TNS_SKIP 004 /* skip next */ - -void tmxr_rmvrc (TMLN *lp, int32 p); -extern int32 sim_switches; -extern char sim_name[]; -extern FILE *sim_log; -extern uint32 sim_os_msec (void); - -/* Poll for new connection - - Called from unit service routine to test for new connection - - Inputs: - *mp = pointer to terminal multiplexor descriptor - Outputs: - line number activated, -1 if none -*/ - -int32 tmxr_poll_conn (TMXR *mp) -{ -SOCKET newsock; -TMLN *lp; -int32 i; -uint32 ipaddr; -static char mantra[] = { - TN_IAC, TN_WILL, TN_LINE, - TN_IAC, TN_WILL, TN_SGA, - TN_IAC, TN_WILL, TN_ECHO, - TN_IAC, TN_WILL, TN_BIN, - TN_IAC, TN_DO, TN_BIN }; - -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? */ - 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; } - } /* end if newsock */ -return -1; -} - -/* Reset line */ - -void tmxr_reset_ln (TMLN *lp) -{ -sim_close_sock (lp->conn, 0); /* reset conn */ -lp->conn = lp->tsta = 0; /* reset state */ -lp->rxbpr = lp->rxbpi = 0; -lp->txbpr = lp->txbpi = 0; -lp->xmte = 1; -lp->dstb = 0; -return; -} - -/* Get character from specific line - - Inputs: - *lp = pointer to terminal line descriptor - Output: - valid + char, 0 if line -*/ - -int32 tmxr_getc_ln (TMLN *lp) -{ -int32 j, val = 0; -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 */ - 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; -return val; -} - -/* Poll for input - - Inputs: - *mp = pointer to terminal multiplexor descriptor - Outputs: none -*/ - -void tmxr_poll_rx (TMXR *mp) -{ -int32 i, nbytes, j; -TMLN *lp; - -for (i = 0; i < mp->lines; i++) { /* loop thru lines */ - lp = mp->ldsc[i]; /* get line desc */ - if (!lp->conn || !lp->rcve) continue; /* skip if !conn */ - - nbytes = 0; - if (lp->rxbpi == 0) /* need input? */ - nbytes = sim_read_sock (lp->conn, /* yes, read */ - &(lp->rxb[lp->rxbpi]), /* leave spc for */ - TMXR_MAXBUF - TMXR_GUARD); /* Telnet cruft */ - else if (lp->tsta) /* in Telnet seq? */ - nbytes = sim_read_sock (lp->conn, /* yes, read to end */ - &(lp->rxb[lp->rxbpi]), - TMXR_MAXBUF - lp->rxbpi); - 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; - -/* Examine new data, remove TELNET cruft before making input available */ - - for (; j < lp->rxbpi; ) { /* loop thru char */ - char tmp = lp->rxb[j]; /* get char */ - switch (lp->tsta) { /* case tlnt state */ - case TNS_NORM: /* normal */ - if (tmp == TN_IAC) { /* IAC? */ - lp->tsta = TNS_IAC; /* change state */ - tmxr_rmvrc (lp, j); /* remove char */ - break; } - if ((tmp == TN_CR) && lp->dstb) /* CR, no bin */ - lp->tsta = TNS_SKIP; /* skip next */ - j = j + 1; /* advance j */ - break; - 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? */ - lp->tsta = TNS_WONT; - else lp->tsta = TNS_SKIP; /* IAC + other */ - tmxr_rmvrc (lp, j); /* remove char */ - break; - case TNS_WILL: case TNS_WONT: /* IAC+WILL/WONT prev */ - if (tmp == TN_BIN) { /* BIN? */ - if (lp->tsta == TNS_WILL) lp->dstb = 0; - else lp->dstb = 1; } - case TNS_SKIP: default: /* skip char */ - lp->tsta = TNS_NORM; /* next normal */ - tmxr_rmvrc (lp, j); /* remove char */ - break; } /* end case state */ - } /* end for char */ - } /* end else nbytes */ - } /* end for 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 */ - } /* end for */ -return; -} - -/* Return count of available characters for line */ - -int32 tmxr_rqln (TMLN *lp) -{ -return (lp->rxbpi - lp->rxbpr); -} - -/* 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]; - lp->rbr[p] = lp->rbr[p + 1]; } -lp->rxbpi = lp->rxbpi - 1; -return; -} - -/* Store character in line buffer - - Inputs: - *lp = pointer to line descriptor - chr = characters - Outputs: - none -*/ - -void tmxr_putc_ln (TMLN *lp, int32 chr) -{ -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 */ -else lp->xmte = 0; /* disable line */ -return; -} - -/* Poll for output - - Inputs: - *mp = pointer to terminal multiplexor descriptor - Outputs: - none -*/ - -void tmxr_poll_tx (TMXR *mp) -{ -int32 i, nbytes, sbytes; -TMLN *lp; - -for (i = 0; i < mp->lines; i++) { /* loop thru lines */ - lp = mp->ldsc[i]; /* get line desc */ - 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; } - } - if (nbytes == 0) { /* buf empty? */ - lp->xmte = 1; /* enable this line */ - lp->txbpr = lp->txbpi = 0; } - } /* end for */ -return; -} - -/* Return count of buffered characters for line */ - -int32 tmxr_tqln (TMLN *lp) -{ -return (lp->txbpi - lp->txbpr); -} - -/* Open master socket */ - -t_stat tmxr_open_master (TMXR *mp, char *cptr) -{ -int32 i, port; -SOCKET sock; -TMLN *lp; -t_stat r; - -port = (int32) get_uint (cptr, 10, 65535, &r); /* get port */ -if ((r != SCPE_OK) || (port == 0)) return SCPE_ARG; -sock = sim_master_sock (port); /* make master socket */ -if (sock == INVALID_SOCKET) return SCPE_OPENERR; /* open error */ -printf ("Listening on port %d (socket %d)\n", port, sock); -if (sim_log) fprintf (sim_log, - "Listening on port %d (socket %d)\n", port, sock); -mp->port = port; /* save port */ -mp->master = sock; /* save master socket */ -for (i = 0; i < mp->lines; i++) { /* initialize lines */ - lp = mp->ldsc[i]; - lp->conn = lp->tsta = 0; - lp->rxbpi = lp->rxbpr = 0; - lp->txbpi = lp->txbpr = 0; - lp->rxcnt = lp->txcnt = 0; - lp->xmte = 1; - lp->dstb = 0; } -return SCPE_OK; -} - -/* Attach unit to master socket */ - -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 */ -if (r != SCPE_OK) { /* error? */ - free (tptr); /* release buf */ - return SCPE_OPENERR; } -strcpy (tptr, cptr); /* copy port */ -uptr->filename = tptr; /* save */ -uptr->flags = uptr->flags | UNIT_ATT; /* no more errors */ -return SCPE_OK; -} - -/* Close master socket */ - -t_stat tmxr_close_master (TMXR *mp) -{ -int32 i; -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 */ - } /* end for */ -sim_close_sock (mp->master, 1); /* close master socket */ -mp->master = 0; -return SCPE_OK; -} - -/* Detach unit from master socket */ - -t_stat tmxr_detach (TMXR *mp, UNIT *uptr) -{ -if ((uptr->flags & UNIT_ATT) == 0) return SCPE_OK; /* attached? */ -tmxr_close_master (mp); /* close master socket */ -free (uptr->filename); /* free port string */ -uptr->filename = NULL; -uptr->flags = uptr->flags & ~UNIT_ATT; /* not attached */ -return SCPE_OK; -} - -/* Stub examine and deposit */ - -t_stat tmxr_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) -{ -return SCPE_NOFNC; -} - -t_stat tmxr_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw) -{ -return SCPE_NOFNC; -} - -/* Output message */ - -void tmxr_msg (SOCKET sock, char *msg) -{ -if (sock) sim_write_sock (sock, msg, strlen (msg)); -return; -} - -/* Print connections - used only in named SHOW command */ - -void tmxr_fconns (FILE *st, TMLN *lp, int32 ln) -{ -if (ln >= 0) fprintf (st, "line %d: ", ln); -if (lp->conn) { - int32 o1, o2, o3, o4, hr, mn, sc; - uint32 ctime; - - o1 = (lp->ipad >> 24) & 0xFF; - o2 = (lp->ipad >> 16) & 0xFF; - o3 = (lp->ipad >> 8) & 0xFF; - o4 = (lp->ipad) & 0xFF; - ctime = (sim_os_msec () - lp->cnms) / 1000; - hr = ctime / 3600; - mn = (ctime / 60) % 60; - sc = ctime % 60; - fprintf (st, "IP address %d.%d.%d.%d", o1, o2, o3, o4); - if (ctime) fprintf (st, ", connected %02d:%02d:%02d\n", hr, mn, sc); } -else fprintf (st, "line disconnected\n"); -return; -} - -/* Print statistics - used only in named SHOW command */ - -void tmxr_fstats (FILE *st, TMLN *lp, int32 ln) -{ -static const char *enab = "on"; -static const char *dsab = "off"; - -if (ln >= 0) fprintf (st, "line %d: ", ln); -if (lp->conn) { - fprintf (st, "input (%s) queued/total = %d/%d, ", - (lp->rcve? enab: dsab), - lp->rxbpi - lp->rxbpr, lp->rxcnt); - fprintf (st, "output (%s) queued/total = %d/%d\n", - (lp->xmte? enab: dsab), - lp->txbpi - lp->txbpr, lp->txcnt); } -else fprintf (st, "line disconnected\n"); -return; -} - -/* Disconnect line */ - -t_stat tmxr_dscln (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -TMXR *mp = (TMXR *) desc; -TMLN *lp; -int32 ln; -t_stat r; - -if ((mp == NULL) || (val && (cptr == NULL))) return SCPE_ARG; -if (cptr) { - ln = (int32) get_uint (cptr, 10, mp->lines - 1, &r); - if (r != SCPE_OK) return SCPE_ARG; } -else ln = 0; -lp = mp->ldsc[ln]; -if (lp->conn) { - tmxr_msg (lp->conn, "\r\nOperator disconnected line\r\n\n"); - tmxr_reset_ln (lp); } -return SCPE_OK; -} diff --git a/sim_tmxr.h b/sim_tmxr.h deleted file mode 100644 index 45ffa415..00000000 --- a/sim_tmxr.h +++ /dev/null @@ -1,95 +0,0 @@ -/* sim_tmxr.h: terminal multiplexor definitions - - 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. - - 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, - added tmxr_rqln, tmxr_tqln -*/ - -#ifndef _SIM_TMXR_H_ -#define _SIM_TMXR_H_ 0 - -#define TMXR_V_VALID 15 -#define TMXR_VALID (1 << TMXR_V_VALID) -#define TMXR_MAXBUF 128 /* buffer size */ -#define TMXR_GUARD 8 /* buffer guard */ -#define TMXR_MAXLIN 64 /* max lines */ - -struct tmln { - SOCKET conn; /* line conn */ - uint32 ipad; /* IP address */ - uint32 cnms; /* conn time */ - int32 tsta; /* Telnet state */ - int32 rcve; /* rcv enable */ - int32 xmte; /* xmt enable */ - int32 dstb; /* disable Tlnt bin */ - int32 rxbpr; /* rcv buf remove */ - int32 rxbpi; /* rcv buf insert */ - int32 rxcnt; /* rcv count */ - int32 txbpr; /* xmt buf remove */ - 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 */ - }; - -typedef struct tmln TMLN; - -struct tmxr { - int32 lines; /* # lines */ - int32 port; /* listening port */ - SOCKET master; /* master socket */ - TMLN *ldsc[TMXR_MAXLIN]; /* line descriptors */ - }; - -typedef struct tmxr TMXR; - -int32 tmxr_poll_conn (TMXR *mp); -void tmxr_reset_ln (TMLN *lp); -int32 tmxr_getc_ln (TMLN *lp); -void tmxr_poll_rx (TMXR *mp); -void tmxr_putc_ln (TMLN *lp, int32 chr); -void tmxr_poll_tx (TMXR *mp); -t_stat tmxr_open_master (TMXR *mp, char *cptr); -t_stat tmxr_close_master (TMXR *mp); -t_stat tmxr_attach (TMXR *mp, UNIT *uptr, char *cptr); -t_stat tmxr_detach (TMXR *mp, UNIT *uptr); -t_stat tmxr_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw); -t_stat tmxr_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw); -void tmxr_msg (SOCKET sock, char *msg); -void tmxr_fconns (FILE *st, TMLN *lp, int32 ln); -void tmxr_fstats (FILE *st, TMLN *lp, int32 ln); -t_stat tmxr_dscln (UNIT *uptr, int32 val, char *cptr, void *desc); -int32 tmxr_rqln (TMLN *lp); -int32 tmxr_tqln (TMLN *lp); - -#endif - diff --git a/simh_doc.txt b/simh_doc.txt deleted file mode 100644 index 63c75a98..00000000 --- a/simh_doc.txt +++ /dev/null @@ -1,1267 +0,0 @@ -To: Users -From: Bob Supnik -Subj: Simulator Usage, V3.0-2 -Date: 15-Sep-2003 - - COPYRIGHT NOTICE - -The following copyright notice applies to both the SIMH source and binary: - - 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"), - 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 SIMH simulators. These simulators are freeware; -refer to the license terms above for conditions of use. Support is not -available. The best way to fix problems or add features is to read and -modify the sources yourself. Alternately, you can send Internet mail to -bsupnik@us.inter.net, but a response is not guaranteed. - -The simulators use a common command interface. This memorandum describes -the features of the command interface. The details of each simulator are -documented in separate, machine-specific memoranda. - - -1. Compiling And Running A Simulator - -The simulators have been tested on VAX VMS, Alpha VMS, Alpha UNIX, -NetBSD, FreeBSD, OpenBSD, Linux, Solaris, Windows 9x/Me/NT/2000, MacOS -9 and X, and OS/2. Porting to other environments will require changes -to the operating system dependent code in scp_tty.c, scp_sock.c, and -sim_ether.c. - -The simulator sources are provided in a zip archive and are organized -hierarchically. Source files for the simulator libraries are in the -top level directory; source files for each simulator are in individual -subdirectories. Note that the include files in the top level directory -are referenced from the subdirectories, without path identifiers. Your -build tool needs to search the top level directory for include files not -found in the simulator-specific directory, or you will have to copy all -files from the subdirectories into the master directory. File manifests -for each simulator are given in that simulator's documentation. - -The simulators recognize or require a few compile-time #defines: - -- The 18b simulators require that the model name be defined as part - of the compilation command line (i.e., PDP4 for the PDP-4, PDP7 - for the PDP-7, PDP9 for the PDP-9, PDP15 for the PDP-15). - -- The PDP-10 simulator uses 64b integer variables, requiring that - USE_INT64 be defined as part of the compilation command line. - Since 64b integer declarations vary, sim_defs.h has conditional - declarations for Windows (_int64) and Digital UNIX (long). The - default is GNU C (long long). If your compiler uses a different - convention, you will have to modify sim_defs.h. - -- The PDP-10, PDP-11, and VAX simulators share common peripherals. - To distinguish the target system, one of three variables must be - defined on the command line: VM_PDP10 for the PDP-10; VM_PDP11 - for the PDP-11; or VM_VAX for the VAX. - -- The PDP-11 and VAX simulators optionally support Ethernet. To - include Ethernet emulation, USE_NETWORK must be defined as part - of the compilation command line. At present, Ethernet support is - available only on Windows, Linux, NetBSD, and OpenBSD. - -- The PDP-11 and VAX simulators optionally support disks and serial - devices files greater than 2GB. To include large device support, - both USE_INT64 and USE_ADDR64 must be defined as part of the - compilation command line. - -To start the simulator, simply type its name. (On version of VMS -prior to 6.2, the simulators must then be defined as foreign commands -in order to be be started by name.) The simulator recognizes one -switch, -Q; if specified, certain informational messages are suppressed. - -The simulator interprets the arguments on the command line, if any, -as the file name and arguments for a DO command: - - % pdp10 { {arg,arg,...}}(cr) - -If no file is specified on the command line, the simulator looks for -an startup file consisting of the simulator name (including its path -components) plus the extension .ini. If a startup file is specified, -either on the command line or implicitly via the .ini capability, it -ishould contain a series of non-interactive simulator command, one -per line. These command can be used to set up standard parameters, -for example, disk sizes. - -After initializing its internal structures and processing the startup -file (if any), the simulator types out its name and version and then -prompts for input with: - - sim> - -1.1 Compiling Under UNIX/Linux - -The sources originate on a Windows system and have cr-lf at the end of -every line. For use on UNIX or Mac, the sources must be converted to -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 can be compiled -with or without Ethernet support. To compile without Ethernet support: - - gmake {target|ALL|clean} - -To compile with Ethernet support: - - gmake USE_NETWORK=1 {target|ALL|clean} - -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. - If your UNIX only supports the BSD terminal interface, BSDTTY - must be defined as part of the compilation command line. - -- The PDP-8, PDP-11, 18b PDP, PDP-10, and Nova simulators use the - math library. If your UNIX does not link the math library - automatically, you must add -lm to the compilation command line. - -Examples: - -- PDP-11 under TERMIOS UNIX: - - % cc -DVM_PDP11 pdp11_*.c scp*.c sim_*.c -lm -o pdp11 - -- PDP-9 under TERMIOS UNIX: - - % cc -DPDP9 pdp18b_*.c scp*.c sim_*.c -lm -o pdp9 - -- PDP-10 under BSD terminal UNIX: - - % cc -DVM_PDP10 -DUSE_INT64 -DBSDTTY pdp10_*.c scp*.c sim_*.c -lm -o pdp10 - -1.2 Compiling Under Windows - -1.2.1 Compiling PDP-11 and VAX with Ethernet Support - -The Windows-specific Ethernet code uses the WinPCAP 3.0 package. -This package for windows simulates the libpcap package that is freely -available for Unix systems. - -WinPCAP must be installed prior to building the PDP-11 and VAX -simulators with Ethernet support. - -- Download V3.0 from http://winpcap.polito.it. -- Install the package as directed. -- Copy the required .h files (bittypes.h, devioctl.h, ip6_misc.h, - packet32.h, pcap.h, pcap-stdinc.h) from the WinPCAP 3.0 developer's - kit to the top level simulation directory. -- 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 standard library directory. -- Add -DUSE_NETWORK to the compilation command lines for the PDP-11 - and VAX. - -1.2.2 Compiling Under MinGW - -MinGW (Minimum GCC for Windows) is a free C compiler available from -http://www.mingw.org. The distribution includes a batch file -(build_mingw.bat) that will build all the simulators from source. -By default, the PDP-11 and VAX are built without Ethernet support. To -enable Ethernet support, install WinPCAP as described in the previous -section, and then use the alternative batch file (build_mingw_ether.bat). - -1.2.3 Compiling Under Visual C++ - -Each simulator must be organized as a separate Visual C++ project. -Starting from an empty console application, - -- Add all the files from the simulator file manifest to the project. -- Open the Project->Settings dialog box. -- On the C/C++ tab, Category: General, add any required preprocessor - definitions (for example, USE_INT64). -- On the C/C++ tab, Category: Preprocessor, add the top level - simulation directory to the Additional Include Directories. For - the VAX and PDP-10, you must also add the PDP-11 directory. -- On the Link tab, add wsock32.lib at the end of the list of - Object/Module Libraries. -- If you are building the PDP-11 and VAX with Ethernet support, you - must also add the WinPCAP libraries (packet.lib, wpcap.lib) to the - list of Object/Module libraries. - -If you are using Visual C++ .NET, you must turn off /Wp (warn about -potential 64b incompatibilities); otherwise, the compilations will -generate a lot of spurious conversion warnings. - -1.2.4 Compiling Under Borland C++ - -The Borland C++ compiler generates lots of spurious warnings about -missing function prototypes and conversions. All of these warnings -can be safely ignored. - -1.3 Compiling Under OpenVMS - -Compiling on OpenVMS requires DEC C. The simulators that require -64b (PDP-10 and VAX) will not compile on OpenVMS/VAX. The SIMH -distribution includes an MMS command file descrip.mms that will -build all the simulators from source. An example of hand compilation: - -- PDP-8 under VMS: - - $ cc scp*.c,sim_*.c,[.pdp8]pdp8*.c - $ link/exec=pdp8 scp*.obj,sim_*.obj,[.pdp8]pdp8*.obj - -1.4 Compiling Under MacOS - -The simulators have been tested on both MacOS 9 (with Codewarrior) -and MacOS/X (with Apple's tools). - -1.5 Compiling Under OS/2 - -Socket support requires the EMX compiler. - -2. Simulator Conventions - -A simulator consists of a series of devices, the first of which is -always the CPU. A device consists of named registers and one or more -numbered units. Registers correspond to device state, units to device -address spaces. Thus, the CPU device might have registers like PC, -ION, etc, and a unit corresponding to main memory; a disk device might -have registers like BUSY, DONE, etc, and units corresponding to individual -disk drives. Except for main memory, device address spaces are simulated -as unstructured binary disk files in the host file system. The SHOW -CONFIG command displays the simulator configuration. - -A simulator keeps time in terms of arbitrary units, usually one time unit -per instruction executed. Simulated events (such as completion of I/O) -are scheduled at some number of time units in the future. The simulator -executes synchronously, invoking event processors when simulated events -are scheduled to occur. Even asynchronous events, like keyboard input, -are handled by polling at synchronous intervals. The SHOW QUEUE command -displays the simulator event queue. - -3. Commands - -Simulator commands consist of a command verb, optional switches, and -optional arguments. Switches take the form: - - -{...} - -Multiple switches may be specified separately or together: -abcd or --a -b -c -d are treated identically. Verbs, switches, and other -input (except for file names) are case insensitive. - -Any command beginning with semicolon (;) is considered a comment and -ignored. - -3.1 Loading and Saving Programs - -The LOAD command (abbreviation LO) loads a file in binary paper-tape -loader format: - - sim> load {implementation options}(cr) - -The types of formats supported are implementation specific. Options -(such as load within range) are also implementation specific. - -The DUMP command (abbreviation DU) dumps memory in binary paper- -tape loader format: - - sim> dump {implementation options}(cr) - -The types of formats supported are implementation specific. Options -(such as dump within range) are also implementation specific. - -3.2 Saving and Restoring State - -The SAVE command (abbreviation SA) save the complete state of the -simulator to a file. This includes the contents of main memory and -all registers, and the I/O connections of devices: - - sim> save (cr) - -The RESTORE command (abbreviation REST, alternately GET) restores a -previously saved simulator state: - - sim> restore (cr) - -Note: SAVE file format compresses zeroes to minimize file size. - -3.3 Resetting Devices - -The RESET command (abbreviation RE) resets a device or the entire -simulator to a predefined condition: - - sim> RESET(cr) -- reset all devices - sim> RESET ALL(cr) -- reset all devices - sim> RESET (cr) -- reset specified device - -Typically, RESET stops any in-progress I/O operation, clears any -interrupt request, and returns the device to a quiescent state. It -does not clear main memory or affect I/O connections. - -3.4 Connecting and Disconnecting Devices - -Except for main memory, simulated unit address spaces are simulated -as unstructured binary disk files in the host file system. Before -using a simulated unit, the user must specify the file to be accessed -by that unit. The ATTACH (abbreviation AT) command associates a unit -and a file: - - sim> ATTACH (cr) - -If the file does not exist, and the -e switch was not specified, a -new file is created, and an appropriate message is printed. If the --e switch was specified, a new file is not created, and an error -message is printed. - -If the -r switch is specified, or the file is write protected, ATTACH -tries to open the file read only. If the file does not exist, or the -unit does not support read only operation, an error occurs. Input- -only devices, such as paper-tape readers, and devices with write lock -switches, such as disks and tapes, support read only operation; other -devices do not. If a file is ATTACHed read only, its contents can be -examined but not modified. - -For simulated magnetic tapes, the ATTACH command can specify the -format of the attached tape image file: - - sim> ATTACH -f (cr) - -The currently supported tape image file formats are: - - SIMH SIMH simulator format - E11 E11 simulator format - TPC TPC format - -The tape format can also be set with the SET command prior to ATTACH: - - sim> SET FORMAT=(cr) - sim> ATT (cr) - -The format of an attached file can be displayed with the SHOW command: - - sim> SHOW FORMAT(cr) - -For Telnet-based terminal emulators, the ATTACH command associates the -master unit with a TCP/IP port: - - sim> ATTACH (cr) - -The port is a decimal number between 1 and 65535 and should not used -by standard TCP/IP protocols. - -The DETACH (abbreviation DET) command breaks the association between -a unit and a file, or between a unit and a port: - - sim> DETACH ALL(cr) -- detach all units - sim> DETACH (cr) -- detach specified unit - -The EXIT command performs an automatic DETACH ALL. - -3.5 Examining and Changing State - -There are four commands to examine and change state: - - EXAMINE (abbreviated E) examines state - DEPOSIT (abbreviated D) changes state - IEXAMINE (interactive examine, abbreviated IE) examines state - and allows the user to interactively change it - IDEPOSIT (interactive deposit, abbreviated ID) allows the user - to interactively change state - -All four commands take the form - - command {modifiers} - -Deposit must also include a deposit value at the end of the command. - -There are four kinds of modifiers: switches, device/unit name, search -specifiers, and for EXAMINE, output file. Switches have been described -previously. A device/unit name identifies the device and unit whose -address space is to be examined or modified. If no device is specified, -the CPU (main memory)is selected; if a device but no unit is specified, -unit 0 of the device is selected. - -Search specifiers provide criteria for testing addresses or registers -to see if they should be processed. A specifier consists of a logical -operator, a relational operator, or both, optionally separated by spaces. - - { } - -where the logical operator is & (and), | (or), or ^ (xor), and the -relational operator is = or == (equal), ! or != (not equal), >= -(greater than or equal), > (greater than), <= (less than or equal), or -< (less than). If a logical operator is specified without a relational -operator, it is ignored. If a relational operator is specified without -a logical operator, no logical operation is performed. All comparisons -are unsigned. - -The output file modifier redirects command output to a file instead of -the console. An output file modifier consists of @ followed by a -valid file name. - -Modifiers may be specified in any order. If multiple modifiers of the -same time are specified, later modifiers override earlier modifiers. -Note that if the device/unit name comes after the search specifier, -the values will interpreted in the radix of the CPU, rather than of the -device/unit. - -The "state list" consists of one or more of the following, separated -by commas: - - register the specified register - register[sub1-sub2] the specified register array locations, - starting at location sub1 up to and - including location sub2 - register[sub1/length] the specified register array locations, - starting at location sub1 up to but - not including sub1+length - register[ALL] all locations in the specified register - array - register1-register2 all the registers starting at register1 - up to and including register2 - address the specified location - address1-address2 all locations starting at address1 up to - and including address2 - address/length all location starting at address up to - but not including address+length - STATE all registers in the device - ALL all locations in the unit - -Switches can be used to control the format of display information: - - -a display as ASCII - -c display as character string - -m display as instruction mnemonics - -o display as octal - -d display as decimal - -h display as hexidecimal - -The simulators typically accept symbolic input (see documentation with -each simulator). - -Examples: - - sim> ex 1000-1100 -- examine 1100:1100 - sim> de PC 1040 -- set PC to 1040 - sim> ie 40-50 -- interactively examine 40:50 - sim> ie >1000 40-50 -- interactively examine the subset - of locations 40:50 that are >1000 - sim> ex rx0 50060 -- examine 50060, RX unit 0 - sim> ex rx sbuf[3-6] -- examine SBUF[3] to SBUF[6] in RX - sim> de all 0 -- set main memory to 0 - sim> de &77>0 0 -- set all addresses whose low order - bits are non-zero to 0 - sim> ex -m @memdump.txt 0-7777 -- dump memory to file - -Note: to terminate an interactive command, simply type a bad value (eg, -XYZ) when input is requested. - -3.6 Running Programs - -The RUN command (abbreviated RU) resets all devices, deposits its argument -(if given) in the PC, and starts execution. If no argument is given, -execution starts at the current PC. - -The GO command does NOT reset devices, deposits its argument (if given) -in the PC, and starts execution. If no argument is given, execution -starts at the current PC. - -The CONT command (abbreviated CO) does NOT reset devices and resumes -execution at the current PC. - -The STEP command (abbreviated S) resumes execution at the current PC -for the number of instructions given by its argument. If no argument -is supplied, one instruction is executed. - -The BOOT command (abbreviated BO) bootstraps the device and unit given -by its argument. If no unit is supplied, unit 0 is bootstrapped. The -specified unit must be attached to a file. - -3.7 Stopping Programs - -Programs run until the simulator detects an error or stop condition, or -until the user forces a stop condition. - -3.7.1 Simulator Detected Stop Conditions - -These simulator-detected conditions stop simulation: - - - HALT instruction. If a HALT instruction is decoded, - simulation stops. - - - Breakpoint. The simulator may support breakpoints (see - below). - - - I/O error. If an I/O error occurs during simulation of an - I/O operation, and the device stop-on-I/O-error flag is set, - simulation usually stops. - - - Processor condition. Certain processor conditions can stop - simulation; these are described with the individual simulators. - -3.7.2 User Specified Stop Conditions - -Typing the interrupt character stops simulation. The interrupt character -is defined by the WRU (where are you) register and is initially set to -005 (^E). - -3.7.3 Breakpoints - -A simulator may offer breakpoint capability. A simulator may define -breakpoints of different types, identified by letter (for example, E -for execution, R for read, W for write, etc). At the moment, most -simulators support only E (execution) breakpoints. - -Associated with a breakpoint is a count and, optionally, one or more -actions. Each time the breakpoint is sprung, the associated count is -decremented. If the count is less than or equal to 0, the breakpoint -occurs; otherwise, it is deferred. When the breakpoint occurs, the -optional actions are automatically executed. - -A breakpoint is set by the BREAK command: - - sim> BREAK {-types} {[count]},{addr range...} - {;action;action...} - -If no type is specified, the simulator-specific default breakpoint -type (usually E for execution) is used. As with EXAMINE and DEPOSIT, -an address range may be a single address, a range of addresses low-high, -or a relative range of address/length. Examples of BREAK: - - sim> break -e 200 -- set E break at 200 - sim> break 2000/2[2] -- set E breaks at 2000,2001 - with count = 2 - sim> break 100;ex ac;d mq 0 -- set E break at 100 with - actions EX AC and D MQ 0 - sim> break 100; -- delete action on break at 100 - -Currently set breakpoints can be displayed with the SHOW BREAK command: - - sim> SHOW {-types} BREAK {ALL|{,...}} - -Locations with breakpoints of the specified type are displayed. - -Finally, breakpoints can be cleared by the NOBREAK command. - -3.8 Setting Device Parameters - -The SET command (abbreviated SE) changes the status of a device parameter: - - sim> SET {= SET {=} - -Most parameters are simulator and device specific. Disk drives, for -example, can usually be set WRITEENABLED or write LOCKED; if a device -supports multiple drive types, the SET command can be used to specify -the drive type. - -All devices recognize the following parameters: - - OCT sets the data radix = 8 - DEC sets the data radix = 10 - HEX sets the data radix = 16 - -3.9 Displaying Parameters and Status - -The SHOW CONFIGURATION command shows the simulator configuration and -the status of all simulated devices and units. - -The SHOW DEVICES command shows the configuration of all simulated -devices. - -The SHOW MODIFIERS command shows the modifiers available on all -simulated devices. - -The SHOW QUEUE command shows the state of the simulator event queue. -Times are in "simulation units", typically one unit per instruction -execution, relative to the current simulation time. - -The SHOW TIME command shows the number of time units elapsed since -the last RUN command. - -The SHOW command shows the status of the named simulated -device. SHOW shows the value of the named -parameter, if it can display a value. - -The SHOW command shows the status of the named simulated unit. -SHOW shows the value of the named parameter, if -it can display a value. - -3.10 Altering The Simulated Configuration - -In most simulators, the SET DISABLED command removes the -specified device from the configuration. A DISABLED device is -invisible to running programs. The device can still be RESET but -it cannot be ATTAChed, DETACHed, or BOOTed. SET ENABLED -restores a disabled device to a configuration. - -Most multi-unit devices allow units to be placed online or offline: - - sim> SET ONLINE - sim> SET OFFLINE - -When a unit is offline, it will not be displayed by SHOW DEVICE. - -The console terminal normally runs in the controlling window. -Optionally, the console terminal can be connected to a Telnet port. -This allows systems to emulate a VT100 using the built-in terminal -emulation of the Telnet client. - - sim> SET TELNET -- listen for console - Telnet connection on port - sim> SET NOTELNET -- disable console Telnet - sim> SHOW TELNET -- show console Telnet status - -The standard device names can be supplemented with logical names. -Logical names must be unique within a simulator (that is, they cannot -be the same as an existing device name). To assign a logical name -to a device: - - sim> ASSIGN device log-name -- assign log-name to device - -To remove a logical name: - - sim> DEASSIGN device -- remove logical name - -To show all logical names: - - sim> SHOW NAMES - -3.11 Logging Console Output - -Output to the console can be logged simultaneously to a file. Logging -is enabled by the LOG command: - - sim> SET LOG -- log console output to file - -Logging is disabled by the NOLOG command: - - sim> SET NOLOG -- disable logging - -SHOW LOG displays whether logging is enabled or disabled. - -3.12 Executing Command Files - -The simulator can execute command files with the DO command: - - sim> DO {arguments...} -- execute commands in file - -The DO command allows command files to contain substitutable arguments. -The string %n is recognized as meaning argument n from the DO command -line. The character \ has the usual UNIX meaning of an escape character; -the next character is interpreted literally, even if it is % or \. -Arguments with spaces can be enclosed in matching single or double -quotation marks. - -If the switch -V is specified, the commands in the file are echoed -before they are executed. - -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: - - sim> HELP -- print all HELP messages - sim> HELP -- print HELP for command - -3.15 Exiting The Simulator - -EXIT (synonyms QUIT and BYE) returns control to the operating system. - -Appendix 1: File Representations - -All file representations are little endian. On big endian hosts, the -simulator automatically performs any required byte swapping. - -1. Hard Disks - -Hard disks are represented as unstructured binary files of 16b data -items for the 12b and 16b simulators, of 32b data items for the 18b, -24b, and 32b simulators, and 64b for the 36b simulators. - -2. Floppy Disks - -PDP-8 and PDP-11 floppy disks are represented as unstructured binary -files of 8b data items. They are nearly identical to the floppy disk -images for Doug Jones' PDP-8 simulator but lack the initial 256 byte -header. A utility for converting between the two formats is easily -written. - -3. Magnetic Tapes - -Magnetic tapes are represented as unstructured binary files of 8b data -items. Each record consists of a 32b record header, in little endian -format. If the record header is not a special header, it is followed -by n 8b bytes of data, followed by a repeat of the 32b record header. -A 1 in the high order bit of the record header indicates an error in -the record. If the byte count is odd, the record is padded to even -length; the pad byte is undefined. - -Special record headers occur only once and have no data. The currently -defined special headers are: - - 0x00000000 file mark (not repeated) - 0xFFFFFFFF end of medium (not repeated) - -Magnetic tapes are endian independent and consistent across simulator -families. A magtape produced by the Nova simulator will appear to -have its 16b words byte swapped if read by the PDP-11 simulator. - -SIMH can read and write E11-format magtape images. E11 format differs -from SIMH format only for odd-length records; the data portion of E11 -records is not padded with an extra byte. - -SIMH can read TPC-format magtape images. TPC format uses a 16b record -header, with 0x0000 denoting file mark. The record header is not -repeated at the end of the record. Odd-length records are padded with -an extra byte. - -4. Line Printers - -Line printer output is represented by an ASCII file of lines separated -by the newline character. Overprinting is represented by a line ending -in return rather than newline. - -5. DECtapes - -DECtapes are structured as fixed length blocks. PDP-1/4/7/9/15 DECtapes -use 578 blocks of 256 32b words. Each 32b word contains 18b (6 lines) -of data. PDP-11 DECtapes use 578 blocks of 256 16b words. Each 16b word -contains 6 lines of data, with 2b omitted. This is compatible with native -PDP-11 DECtape dump facilities, and with John Wilson's PUTR Program. PDP-8 -DECtapes use 1474 blocks of 129 16b words. Each 16b word contains 12b -(4 lines) of data. PDP-8 OS/8 does not use the 129th word of each block, -and OS/8 DECtape dumps contain only 128 words per block. A utility, -DTOS8CVT.C, is provided to convert OS/8 DECtape dumps to simulator format. - -A known problem in DECtape format is that when a block is recorded in -one direction and read in the other, the bits in a word are scrambled -(to the complement obverse). The PDP-11 deals with this problem by -performing an automatic complement obverse on reverse writes and reads. -The other systems leave this problem to software. - -The simulator represents this difference as follows. On the PDP-11, all -data is represented in normal form. Data reads and writes are not direction -sensitive; read all and write all are direction sensitive. Real DECtapes -that are read forward will generate images with the correct representation -of the data. - -On the other systems, forward write creates data in normal form, while -reverse write creates data in complement obverse form. Forward read (and -read all) performs no transformations, while reverse read (and read all) -changes data to the complement obverse. Real DECtapes that are read forward -will generate data in normal form for blocks written forward, and complement -obverse data for blocks written in reverse, corresponding to the simulator -format. - -Appendix 2: Debug Status - -The debug status of each simulated CPU and device is as follows: - - system PDP-8 PDP-11 Nova PDP-1 18b PDP -device -CPU y y y y y -FPU - y - - h -EIS/CIS - h - - - -console y y y y y -paper tape y y y h y -card reader - - - - - -line printer y y y h y -clock y y y - y -extra terminal y y y - y -hard disk y y y - y -fixed disk y - h - y -floppy disk y y y - - -drum - - - h h -DECtape y y - h y -mag tape y y y - h - - system 1401 2100 PDP-10 H316 VAX -device -CPU y y y h y -FPU - y y - y -EIS/CIS - y y - - -console h y y h y -paper tape - y h h y -card reader y - - - - -line printer y y y h y -clock - y y h y -extra terminal - y y - y -hard disk - y y - y -fixed disk - n - - - -floppy disk - - h - - -drum - n - - - -DECtape - - - - - -mag tape y y y - y - - system GRI-909 1620 i16 i32 SDS940 -device -CPU h h d y d -FPU - - d y - -CIS - - - - - -console h h d y h -paper tape h h d y h -card reader - h - - - -line printer - h d y h -clock h - d y n -extra terminal - - h y h -hard disk - h d y h -fixed disk - - - - h -floppy disk - - d d - -drum - - - - h -DECtape - - - - - -mag tape - - d y h - -legend: y = runs operating system or sample program - d = runs diagnostics - h = runs hand-generated test cases - n = untested - - = not applicable - -Revision History (covering Rev 2.0 to present) - -Starting with Rev 2.7, detailed revision histories can be found -in file sim_rev.c. - -Rev 3.0, May, 03 - Added logical name support - Added multiple tape format support - Added 64b address support - Added PDP-4 EAE support - Added PDP-15 FP15 and XVM support - -Rev 2.10, Nov, 02 - Added Telnet console capability, removed VT emulation - Added DO with substitutable arguments (from Brian Knittel) - Added .ini initialization file (from Hans Pufal) - 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 hooks for input, output, commands - Added breakpoint actions - Added magtape simulation library - Added PDP-11 KW11P programmable clock - Added PDP-11 RK611/RK06/RK07 disk - Added PDP-11/VAX TMSCP tape - Added PDP-11/VAX DELQA Ethernet support (from David Hittner) - Added PDP-11/PDP-10 RX211/RX02 floppy disk - Added PDP-11/VAX autoconfiguration support - Added PDP-10/PDP-11/VAX variable vector support - Added PDP-1 DECtape - Added PDP-1, PDP-4 Type 24 serial drum support - Added PDP-8 RX28 support - Added PDP-9 RB09 fixed head disk, LP09 line printer - 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 50/60Hz support to line frequency clocks - Added 7B/8B support to terminals and multiplexors - Added BREAK support to terminals and multiplexors - -Rev 2.9, Jan, 02 - Added circular register arrays - Replaced ENABLE/DISABLE with SET ENABLED/DISABLED - Replaced LOG/NOLOG with SET LOG/NOLOG - Generalized the timer calibration package - Added additional routines to the multiplexor library - Added SET DISCONNECT, SHOW STATISTICS commands to multiplexors - Reimplemented PDP-8 TTX as a unified multiplexor - Implemented a PC queue in most simulators - Added VAX simulator - Added GRI-909 simulator - Added Peter Schorn's MITS 8080/Z80 simulator - Added Brian Knittel's IBM 1130 simulator - Added HP2100 DQ, DR, MS, MUX devices - Added SET VT/NOVT commands - -Rev 2.8, Dec, 01 - Added DO command - Added general breakpoint facility - Added extended SET/SHOW capability - Replaced ADD/REMOVE with SET ONLINE/OFFLINE - Added global register name recognition - Added unit-based register arrays - Added Charles Owen's System 3 simulator - Added PDP-11 I/O bus map - Added PDP-11/VAX RQDX3 - Added PDP-8 RL8A - Revised 18b PDP interrupt structure - Revised directory and documentation structure - Added support for MINGW environment - -Rev 2.7, Sep, 01 - Added DZ11 (from Thord Nilson and Art Krewat) to PDP-11, - PDP-10 - Added additional terminals to PDP-8 - Added TSS/8 packed character format to PDP-8 - Added sim_sock and sim_tmxr libraries - Added sim_qcount and simulator exit detach all facilities - Added Macintosh sim_sock support (from Peter Schorn) - Added simulator revision level, SHOW version - Changed int64/uint64 to t_int64/t_uint64 for Windoze - Fixed bug in PDP-11 interrupt acknowledge - Fixed bugs in PDP-11 TS NXM check, boot code, error status; - added extended characteristics and status - Fixed bug in PDP-11 TC stop, stop all functions - Fixed receive interrupt while disconnected bug in DZ11 - Fixed multi-unit operation bugs, interrupt bugs in PDP-11 - RP, PDP-10 RP, PDP-10 TU - Fixed carrier detect bug in PDP-11, PDP-10 DZ - Fixed bug in PDP-8 reset routine - Fixed conditional in PDP-18b CPU - Fixed SC = 0 bug in PDP-18b EAE - Fixed bug in PDP-7 LPT - Upgraded Nova second terminal to use sim_tmxr - Upgraded PDP-18b second terminal to use sim_tmxr - Upgraded PDP-11 LTC to full KW11-L - Removed hack multiple console support - -Rev 2.6b, Aug, 01 - Added H316/516 simulator - Added Macintosh support from Louis Chrétien, Peter Schorn, - and Ben Supnik - Added bad block table option to PDP-11 RL, RP - Removed register in declarations - Fixed bugs found by Peter Schorn - -- endian error in PDP-10, PDP-11 RP - -- space reverse error in PDP-11 TS - -- symbolic input in 1401 - Fixed bug in PDP-1 RIM loader found by Derek Peschel - Fixed bug in Nova fixed head disk - -Rev 2.6a, Jun, 01 - Added PDP-9, PDP-15 API option - Added PDP-9, PDP-15 second terminal - Added PDP-10 option for TOPS-20 V4.1 bug fix - Added PDP-10 FE CTRL-C option for Windoze - Added console logging - Added multiple console support - Added comment recognition - Increased size of string buffers for long path names - Fixed bug in big-endian I/O found by Dave Conroy - Fixed DECtape reset in PDP-8, PDP-11, PDP-9/15 - Fixed RIM loader PC handling in PDP-9/15 - Fixed indirect pointers in PDP-10 paging - Fixed SSC handling in PDP-10 TM02/TU45 - Fixed JMS to non-existent memory in PDP-8 - Fixed error handling on command file - -Rev 2.6, May, 01 - Added ENABLE/DISABLE devices - Added SHOW DEVICES - Added examination/modification of register arrays - Added PDP-10 simulator - Added clock autocalibration to SCP, Nova, PDP-8, PDP-11, - PDP-18b - Added PDP-8, PDP-11, PDP-9/15 DECtape - Added PDP-8 DF32 - Added 4k Disk Monitor boot to PDP-8 RF08 and DF32 - Added PDP-4/7 funny format loader support - Added extension handling to the PDP-8 and -9/15 loaders - Added PDP-11 TS11/TSV05 - Added integer interval timer to SCP - Added filename argument to LOAD/DUMP - Revised magtape and DECtape bootstraps to rewind before - first instruction - Fixed 3 cycle data break sequence in PDP-8 RF - Fixed 3 cycle data break sequence in 18b PDP LP, MT, RF - Fixed CS1.TRE write, CS2.MXF,UPE write, and CS2.UAI in - PDP-11 RP - Fixed 4M memory size definition in PDP-11 - Fixed attach bug in RESTORE - Fixed detach bug for buffered devices - Updated copyright notices, fixed comments - -Rev 2.5a, Dec, 00 - Added CMD flop to HP paper tape and line printer - Added status input for HP paper tape punch and TTY - Added Charles Owen's 1401 mag tape boot routine - Added Bruce Ray's Nova plotter and second terminal modules - Added Charles Owen's Eclipse CPU support - Added PDP-9/PDP-15 RIM/BIN loader support - Added PDP-9/PDP-15 extend/bank initial state registers - Added PDP-9/PDP-15 half/full duplex support - Moved software documentation to a separate file - Fixed SCP handling of devices without units - Fixed FLG, FBF initialization in many HP peripherals - Fixed 1401 bugs found by Charles Owen - -- 4, 7 char NOPs are legal - -- 1 char B is chained BCE - -- MCE moves whole character, not digit, after first - Fixed Nova bugs found by Bruce Ray - -- traps implemented on Nova 3 as well as Nova 4 - -- DIV and DIVS 0/0 set carry - -- RETN sets SP from FP at outset - -- IORST does not clear carry - -- Nova 4 implements two undocumented instructions - Fixed bugs in 18b PDP's - -- XCT indirect address calculation - -- missing index instructions in PDP-15 - -- bank mode handling in PDP-15 - -Rev 2.5, Nov, 00 - Removed Digital and Compaq from copyrights, as authorized - by Compaq Sr VP Bill Strecker - Revised save/restore format for 64b simulators - Added examine to file - Added unsigned integer data types to sim_defs - Added Nova 3 and Nova 4 instructions to Nova CPU - Added HP2100 - Fixed indirect loop through autoinc/dec in Nova CPU - Fixed MDV enabled test in Nova CPU - -Rev 2.4, Jan, 99 - Placed all sources under X11-like open source license - Added DUMP command, revised sim_load interface - Added SHOW MODIFIERS command - Revised magtape format to include record error flag - Fixed 64b problems in SCP - Fixed big endian problem in PDP-11 bad block routine - Fixed interrupt on error bug in PDP-11 RP/RM disks - Fixed ROL/ROR inversion in PDP-11 symbolic routines - -Rev 2.3d, Sep, 98 - Added BeOS support - Added radix commands and switches - Added PDP-11 CIS support - Added RT11 V5.3 to distribution kits - Fixed "shift 32" bugs in SCP, PDP-11 floating point - Fixed bug in PDP-11 paper tape reader - Fixed bug in ^D handling - -Rev 2.3c, May, 98 - Fixed bug in PDP-11 DIV overflow check - Fixed bugs in PDP-11 magtape bootstrap - Fixed bug in PDP-11 magtape unit select - Replaced UNIX V7 disk images - -Rev 2.3b, May, 98 - Added switch recognition to all simulator commands - Added RIM loader to PDP-8 paper tape reader and loader - Added second block bootstrap to PDP-11 magtape - Fixed bug in PDP-8 RF bootstrap - Fixed bug in PDP-11 symbolic display - Fixed bugs in PDP-11 floating point (LDEXP, STEXP, - MODf, STCfi, overflow handling) - -Rev 2.3a, Nov, 97 - Added search capability - Added bad block table command to PDP-11 disks - Added bootstrap to PDP-11 magtape - Added additional Nova moving head disks - Added RT-11 sample software - Fixed bugs in PDP-11 RM/RP disks - Fixed bugs in Nova moving head disks - Fixed endian dependence in 18b PDP RIM loader - -Rev 2.3, Mar, 97 - Added PDP-11 RP - Added PDP-1 - Changed UNIX terminal I/O to TERMIOS - Changed magtape format to double ended - Changed PDP-8 current page mnemonic from T to C - Added endian independent I/O routines - Added precise integer data types - Fixed bug in sim_poll_kbd - Fixed bug in PDP-8 binary loader - Fixed bugs in TM11 magtape - Fixed bug in RX11 bootstrap - Fixed bug in 18b PDP ADD - Fixed bug in 18b PDP paper tape reader - Fixed bug in PDP-4 console - Fixed bug in PDP-4,7 line printer - -Rev 2.2d, Dec, 96 - Added ADD/REMOVE commands - Added unit enable/disable support to device simulators - Added features for IBM 1401 project - Added switch recognition for symbolic input - Fixed bug in variable length IEXAMINE - Fixed LCD bug in RX8E - Initial changes for Win32 - Added IBM 1401 - -Rev 2.2b, Apr, 96 - Added PDP-11 dynamic memory size support - -Rev 2.2a, Feb, 96 - New endian independent magtape format - -Rev 2.2 Jan, 96 - Added register buffers for save/restore - Added 18b PDP's - Guaranteed TTI, CLK times are non-zero - Fixed breakpoint/RUN interaction bug - Fixed magnetic tape backspace to EOF bug - Fixed ISZ/DCA inversion in PDP-8 symbol table - Fixed sixbit conversion in PDP-8 examine/deposit - Fixed origin increment bug in PDP-11 binary loader - Fixed GCC longjmp optimization bug in PDP-11 CPU - Fixed unit number calculation bug in SCP and in Nova, - Nova, PDP-11, 18b PDP moving head disks - -Rev 2.1 Dec, 95 - Fixed PTR bug (setting done on EOF) in PDP-8, Nova - Fixed RX bug (setting error on INIT if drive 1 is - not attached) in PDP-8, PDP-11 - Fixed RF treatment of photocell flag in PDP-8 - Fixed autosize bug (always chose smallest disk if new - file) in PDP-11, Nova - Fixed not attached bug (reported as not attachable) in - most mass storage devices - Fixed Nova boot ROMs - Fixed bug in RESTORE (didn't requeue if delay = 0) - Fixed bug in RESTORE (clobbered device position) - Declared static constant arrays as static const - Added PDP-8, Nova magnetic tape simulators - Added Dasher mode to Nova terminal simulator - Added LINUX support - -Rev 2.0 May, 95 - Added symbolic assembly/disassembly - -Acknowledgements - -SIMH would not have been possible without help from around the world. I -would like to acknowledge the help of the following people, all of whom -donated their time and talent to this "computer archaeology" project: - -Bill Ackerman PDP-1 consulting -Alan Bawden ITS consulting -Winfried Bergmann Linux port testing -Phil Budne Solaris port testing -Max Burnet PDP information, documentation, and software -Robert Alan Byer VMS socket support and testing -James Carpenter LINUX port testing -Chip Charlot PDP-11 RT-11, RSTS/E, RSX-11M legal permissions -Louis Chrétien Macintosh porting -Dave Conroy HP 21xx documentation, PDP-10, PDP-18b debugging -L Peter Deutsch PDP-1 LISP software -Ethan Dicks PDP-11 2.9 BSD debugging -John Dundas PDP-11 CPU debugging, programmable clock simulator -Jonathan Engdahl PDP-11 device debugging -Carl Friend Nova and Interdata documentation, and RDOS software -Megan Gentry PDP-11 integer debugging -Dave Gesswein PDP-8 and PDP-9.15 documentation, PDP-8 DECtape, disk, - and paper tape images, PDP-9/15 DECtape images -Dick Greeley PDP-8 OS/8 and PDP-10 TOPS-10/20 legal permissions -Gordon Greene PDP-1 LISP machine readable source -Lynne Grettum PDP-11 RT-11, RSTS/E, RSX-11M legal permissions -Franc Grootjen PDP-11 2.11 BSD debugging -Doug Gwyn Portability debugging -Kevin Handy TS11/TSV05 documentation, make file -Ken Harrenstein KLH PDP-10 simulator -Bill Haygood PDP-8 information, simulator, and software -Wolfgang Helbig DZ11 implementation -Mark Hittinger PDP-10 debugging -Dave Hittner SCP debugging, DEQNA emulator and Ethernet library -Sellam Ismail GRI-909 documentation -Jay Jaeger IBM 1401 consulting -Doug Jones PDP-8 information, simulator, and software -Brian Knittel IBM 1130 simulator, SCP extensions for GUI support -Al Kossow HP 21xx, Varian 620, TI 990, Interdata, DEC - documentation and software -Arthur Krewat DZ11 changes for the PDP-10 -Mirian Crzig Lennox ITS and DZ11 debugging -Don Lewine Nova documentation and legal permissions -Tim Litt PDP-10 hardware documentation and schematics, - tape images, and software sources -Tim Markson DZ11 debugging -Bill McDermith HP 2100 debugging, 12565A simulator -Scott McGregor PDP-11 UNIX legal permissions -Jeff Moffatt HP 2100 information, documentation, and software -Alec Muffett Solaris port testing -Terry Newton HP 21MX debugging -Thord Nilson DZ11 implementation -Charles Owen Nova moving head disk debugging, Altair simulator, - Eclipse simulator, IBM System 3 simulator, - IBM 1401 diagnostics, debugging, and magtape boot -Sergio Pedraja MINGW environment debugging -Derek Peschel PDP-10 debugging -Paul Pierce IBM 1401 diagnostics, media recovery -Mark Pizzolato SCP, Ethernet, and VAX simulator improvements -Hans Pufal PDP-10 debugging, PDP-15 bootstrap, DOS-15 recovery, - DOS-15 documentation, PDP-9 restoration -Bruce Ray Software, documentation, bug fixes, and new devices - for the Nova, OS/2 porting -Craig St Clair DEC documentation -Richard Schedler Public repository maintenance -Peter Schorn Macintosh porting -Stephen Schultz PDP-11 2.11 BSD debugging -Olaf Seibert NetBSD port testing -Brian & Barry Silverman PDP-1 simulator and software -Tim Shoppa Nova documentation, RDOS software, PDP-10 and PDP-11 - software archive, hosting for SIMH site -Van Snyder IBM 1401 zero footprint bootstraps -Michael Somos PDP-1 debugging -Hans-Michael Stahl OS/2 port testing, TERMIOS implementation -Tim Stark TS10 PDP-10 simulator -Larry Stewart Initial suggestion for the project -Bill Strecker Permission to revert copyrights -Chris Suddick PDP-11 floating point debugging -Ben Supnik Macintosh timing routine -Bob Supnik SIMH simulators -Ben Thomas VMS character-by-character I/O routines -Warren Toomey PDP-11 UNIX software -Deb Toivonen DEC documentation -Mike Umbricht DEC documentation, H316 documentation and schematics -Leendert Van Doorn PDP-11 UNIX V6 debugging, TERMIOS implementation -Fred Van Kempen Ethernet code, RK611 emulator, PDP-11 debugging, - VAX/Ultrix debugging -Holger Veit OS/2 socket support -David Waks PDP-8 ESI-X and PDP-7 SIM8 software -Tom West Nova documentation -Adrian Wise H316 simulator, documentation, and software -John Wilson PDP-11 simulator and software -Joe Young RP debugging on Ultrix-11 and BSD - -In addition, the following companies have graciously licensed their -software at no cost for hobbyist use: - -Data General Corporation -Digital Equipment Corporation -Compaq Computer Corporation -Mentec Corporation -The Santa Cruz Operation -Caldera Corporation -Hewlett-Packard Corporation - - diff --git a/simh_faq.txt b/simh_faq.txt deleted file mode 100644 index b101617c..00000000 --- a/simh_faq.txt +++ /dev/null @@ -1,606 +0,0 @@ -SIMH FAQ, 15-Sep-2003 - -1 General - -1.1 What is SIMH? -1.2 Why was SIMH written? -1.3 What is the history of SIMH? -1.4 Who writes and maintains SIMH? -1.5 How is SIMH licensed? -1.6 How is SIMH distributed? -1.7 Which computer systems can SIMH simulate? -1.8 Which host systems does SIMH run on? -1.9 What software packages are available for use with the SIMH simulators? -1.10 Where can I get more information about SIMH? - --------------------------------------------------------------------------------- - -2 Operational - -2.1 How do I install SIMH on Windows? -2.2 How do I install SIMH with Ethernet support on Windows? -2.3 How do I install SIMH on Unix? -2.4 How do I install SIMH on VMS? -2.5 How do I transcribe a real CD for use with SIMH? -2.6 How do I transcribe other archival media for use with SIMH? -2.7 How can I get text files in and out of SIMH? -2.8 How can I get binary files in and out of SIMH? -2.9 Can I connect real devices on the host computer to SIMH? -2.10 My Windows host can't communicate with the PDP-11 or VAX over Ethernet; why? - --------------------------------------------------------------------------------- - -3 Writing and Debugging New Code - -3.1 What resources are available for writing new simulators? -3.2 What debugging facilities are available in SIMH? -3.3 When do I need to use the host debugger for debugging a simulator? -3.4 What is the release process for SIMH? - --------------------------------------------------------------------------------- - -4 VAX - -4.1 Where can I get software and hobbyist licenses for the VAX? -4.2 How do I install VMS? -4.3 How do I install NetBSD? -4.4 How do I install Ultrix? -4.5 What's the CPU serial number for my hobbyist license PAK? -4.6 How do I change the simulator from a VAXserver 3900 to a - MicroVAX 3900? -4.7 Is there an example of the simulator running VMS? -4.8 How can I import files into a simulated VMS environment? -4.9 How can I export files from a simulated VMS environment? - --------------------------------------------------------------------------------- - -5 PDP-11 - -5.1 When installing RSTS/E from simulated magtape, the installation process - hangs with no error message; why? - -================================================================================ -1. General Questions -================================================================================ - -1.1 What is SIMH? - -SIMH is the Computer History Simulation system. It consists of simulators -for approximately 20 different computers, all written around a common user -interface package and set of supporting libraries. SIMH can be used to -simulate any computer system for which sufficient detail is available, but -the focus to date has been on simulating computer systems of historic interest. - --------------------------------------------------------------------------------- - -1.2 Why was SIMH written? - -Significant portions of the computing past are being irretrievably lost, as -old systems are scrapped, documentation and software is thrown out, media -become obsolete or unreadable, and inventors and pioneers die. SIMH was -written as a vehicle to allow the computing past to be made accessible to -a wider audience, for recreational and educational purposes. SIMH preserves -historic computers as portable software, that can be run on any modern -system. SIMH also preserves representative software packages for these -systems. With SIMH, anyone with a desktop computer can call up and run -significant samples from the computing past, at any time. - --------------------------------------------------------------------------------- - -1.3 What is the history of SIMH? - -The SIMH project started in 1993, at the suggestion of Larry Stewart of DEC. -Its immediate purpose was to preserve the fading hardware and software -record of early minicomputers. Since then, the project has been expanded -to include other important systems, spanning the history of computing from -the late 50's to the late 80's. - -SIMH's core design is based on an earlier simulation system called MIMIC. -MIMIC was written in the late 1960's at Applied Data Research, by Mike -McCarthy, Len Feshkens, and Bob Supnik. MIMIC was a mini-computer simulator -that ran on the PDP-10. Its purpose was to facilitate the development and -debugging of real-time embedded systems by using the the PDP-10 timesharing -environment for program development, instead of the limited facilities of -the native minicomputer environments. Ironically, given SIMH's mission to -preserve the computing record, all machine-readable copies of MIMIC have -been lost. - --------------------------------------------------------------------------------- - -1.4 Who writes and maintains SIMH? - -Many people have contributed, and continue to contribute, to SIMH. The full -list of contributors can be found on the SIMH web site. Bob Supnik coordinates -SIMH development. - --------------------------------------------------------------------------------- - -1.5 How is SIMH licensed? - -SIMH is licensed under a modified X-Windows license. This license allows more -or less unrestricted use of the sources and binaries. The license is included -with the documentation and is also included in every source module. The -software packages are available under various terms and conditions; see the -documentation included with each software package. - --------------------------------------------------------------------------------- - -1.6 How is SIMH distributed? - -SIMH is distributed in source form from the SIMH web site, in the form of a -Zip archive. For Windows users, pre-compiled binaries are also available. - --------------------------------------------------------------------------------- - -1.7 Which computer systems does SIMH simulate? - -SIMH simulates the following computer systems: - - Manufacturer Model - - Digital Equipment Corporation PDP-1, PDP-4, PDP-7, PDP-8, PDP-9, - PDP-10, PDP-11, PDP-15, VAX - Data General Corporation Nova, Eclipse - IBM Corporation 1130, 1401, 1620, System 3 - GRI Corporation GRI-909 - Honeywell Corporation H316/516 - Hewlett Packard Corporation HP2116, HP2100, HP21MX - Interdata Corporation 16b systems, 7/32, 8/32 - Scientific Data Systems SDS-940 - MITS Altair 8080, Altair Z80 - -The documentation contains more details on supported models and peripherals. - --------------------------------------------------------------------------------- - -1.8 Which host systems does SIMH run on? - - Host System Compiler comments - - OpenVMS/VAX DEC C no 64b support; no Ethernet support - OpenVMS/Alpha DEC C no Ethernet support - - Windows 9x or Mingw/gcc or requires WinPcap for Ethernet support - Windows 2000 or Visual C++ or - Windows XP Borland C++ - - Mac OS/X no Ethernet support - - Linux gcc - Tru64 UNIX DEC C no Ethernet support - AIX no Ethernet support - Solaris no Ethernet support - HP/UX no Ethernet support - NetBSD gcc - OpenBSD gcc - FreeBSD gcc no Ethernet support - - OS/2 EMX no Ethernet support - --------------------------------------------------------------------------------- - -1.9 What software packages are available to run on SIMH? - -The list of available software packages can be found on the SIMH web site. - --------------------------------------------------------------------------------- - -1.10 Where can I get more information on SIMH? - -The SIMH web site is http://simh.trailing-edge.com. - -================================================================================ -2 Operational Questions -================================================================================ - -2.1 How do I install SIMH on Windows? - -The simplest way is to download the pre-compiled binaries. Unzip these into the -directory where you want to run SIMH. You can then run whichever binary that you -want. - -If you want to run the VAX emulator, you will also need the KA655.bin file from -the source kit. - --------------------------------------------------------------------------------- - -2.2 How do I install SIMH with Ethernet support on Windows? - -Separate pre-compiled binaries contain Ethernet support. Before running these -binaries, you must download download and install the WinPCAP AutoInstaller from - - http://winpcap.polito.it - -This creates a network packet driver in Windows for SIMH to attach to. - -To use network support, you must either be an administrator on the Windows -machine (implied in Windows 9X), or you must set the windows packet driver to -autostart when the system boots; see the WinPCAP FAQ page for detailed -information on how to do this. - --------------------------------------------------------------------------------- - -2.3 How do I install SIMH on Unix? - -- Unzip the archive of sources to a new directory. You must specify the - -a switch to unzip for proper conversion of Windows cr-lf sequences - to UNIX newline sequences. - -- If your system supports gmake, you can compile the simulators with - the command: - - % gmake all - -- If you want Ethernet support in the PDP-11 and VAX, you should compile - the simulators with the command: - - % gmake USE_NETWORK=1 all - - Note that Ethernet support is available ONLY on Linux, NetBSD, and - OpenBSD. - --------------------------------------------------------------------------------- - -2.4 How do I install SIMH on VMS? - -Download the SIMH source kit, and UNZIP it using the /TEXT=AUTO qualifier to -the directory that you want SIMH to reside in. Use MMK or MMS and the -descrip.mms file to build the binaries. - -UNZIP can be found on the VMS freeware CDs, or from www.info-zip.org -MMK can be found on the VMS freeware CDs, or from www.madgoat.com -MMS can be licensed from HP/Compaq/Digital. - -Note that the PDP-10 emulator cannot be built and used on VAX/VMS, because -the DEC C compiler for VAX/VMS does not support 64-bit integers. DEC C on -on Alpha VMS has the required 64-bit capability to build and run all of the -emulators. - --------------------------------------------------------------------------------- - -2.5 How do I transcribe a real CD for use with SIMH? - -- On UNIX, you can copy a CD to an ISO file with the dd command: - - % dd /if=/dev/raw_cd_device /out=/path/cdimage.iso - - Linux, and many Unix variants, support direct access to the CD ROM - from SIMH: - - sim> set rq1 cdrom - sim> att rq1 /dev/cdrom_drive - -- On Windows, there are quite a few products that can do this. The two most - common products are detailed below. Make sure to disable any antivirus - software before proceeding. Antivirus software tends to interfere with - the smooth flow of data from the CD and will occasionally transform the - data in strange and unexpected ways to 'protect' you. - - 1) Roxio EZ-CD Creator 5.x - Go to the the Disc menu and select Disc Info (there will be a delay). - Select the track shown, then click the Read Track button. - Enter the Save file name, then OK. - - 2) Nero 5.5 - Select Recorder|Save Track - Select the track, set the output filename - In Options, you may need to set the Read Speed down; - the VMS Hobbyist CD didn't work after a 52x read, but worked fine at 8x - Click GO - --------------------------------------------------------------------------------- - -2.6 How do I transcribe other archival media for use with SIMH? - -You must have access to a real system that can read the media to be -transcribed (e.g., a system with a working DECtape drive to read a -DECtape). Most systems have utilities to copy raw data to a disk -file; that file can then be transferred over the console serial -line to a system with an Internet link. Utility programs are -available to convert raw data streams to SIMH format. - --------------------------------------------------------------------------------- - -2.7 How can I get text files in and out of SIMH? - -Since SIMH supports the universal serial interface using TELNET, text can -be transferred using one of the serial line transfer protocols (X/Y/Zmodem, -Kermit) or using standard cut and paste techniques, if the host's TELNET -program supports it. - -To use the TELNET feature, connect to the SIMH machine using TELNET, and -set the target environment into a 'receive' mode. This is usually something -like running a text editor. Then tell the TELNET program to 'send', 'transfer', -or 'paste' the text that you want sent into the SIMH system. - -To get text out of the system, have the TELNET program either log the output, -or if the TELNET program supports a backscroll region you can use that. Tell -the SIMH system to 'type' or 'cat' the text file, sending the output to the -TELNET device, where you can edit it into a text file. - -Many TELNET programs also support transferring large files via X/Y/ZModem or -Kermit, which you can use as long as the SIMH system has the appropriate -matching program. - -C-Kermit from Columbia University (http://www.columbia.edu/kermit) is probably -the most universal way to transfer files in and out of SIMH systems. - -If the SIMH system supports Ethernet connectivity (PDP-11, VAX), you can also -use the various network copy programs (FTP, DECNET) to transfer files. - -Finally, you can "print" text files to the simulated line printer. Printer -output is automatically formatted as an ASCII text file. - --------------------------------------------------------------------------------- - -2.8 How can I get binary files in and out of SIMH? - -Since SIMH supports the universal serial interface using TELNET, binary -files can be transferred using one of the serial line transfer protocols -(X/Y/ZModem, Kermit) or by converting the binary to a text-encoded file -(HEXify, UUENCODE, VMShare, etc.) and transferred in text mode (see section -2.7). - -Many TELNET programs also support transferring large files via X/Y/ZModem or -Kermit, which you can use as long as the SIMH system has the appropriate -matching program. - -C-Kermit from Columbia University (http://www.columbia.edu/kermit) is probably -the most universal way to transfer files in and out of SIMH systems. - -If the SIMH system supports Ethernet connectivity (PDP-11, VAX), you can also -use the various network copy programs (FTP, DECNET) to transfer files. - --------------------------------------------------------------------------------- - -2.9 Can I connect real devices on the host computer to SIMH? - -No. - --------------------------------------------------------------------------------- - -2.10 My Windows host can't communicate with the PDP-11 or VAX over Ethernet; why? - -Due to the inherent limitations of WinPCAP, the SIMH system _CANNOT_ communicate -with the host on the primary interface. To establish communications between SIMH -and a PC host, add a second Ethernet controller, attach both controllers to the -same hub, and attach SIMH to the second controller. The host and SIMH will now -be able to communicate across the physical network connection. - -================================================================================ -3 Writing and Debugging New Code -================================================================================ - -3.1 What resources are available for writing new simulators? - -The SIMH web site contains documentation on the internals of SIMH, as well -as specific help for writing new peripherals for several of the popular -simulators. - --------------------------------------------------------------------------------- - -3.2 What debugging facilities are available in SIMH? - -Most simulators provide the following debugging capabilities: - -- Symbolic assembly and disassembly of memory contents. -- Numeric examination and modification of the data store of any simulated - device. -- Numeric search on both memory and device data. -- Visibility to simulator internal structures, such as the event queue. -- An unlimited number of instruction breakpoints. -- Proceed counts on breakpoints. -- Automatic execution of simulator commands on a breakpoint. -- Stepped execution (from single step to 'n' steps). -- A PC change queue, usually 64 instructions deep. - -Specific simulators may provide additional features, such as an instruction -history buffer, CPU and/or device logging, and breakpoints on memory reads -and writes. - --------------------------------------------------------------------------------- - -3.3 When do I need to use the host debugger for debugging a simulator? - -While a simulator is being debugged, its execution of instructions -or debugging support code may be unreliable. During this process, -the programmer may need to use the host debugger to stop in the -middle of an instruction execution, or to trap an error condition. -Host debugger breakpoints should be invisible to the simulator; with -the exception of clock calibration, all simulator events are driven -off the event queue rather than real-world events. - -If the programmer needs to force a simulator stop from the host -debugger, most simulators provide an "address stop" global variable. -Setting this variable to 1 will cause the simulator to stop after -completing the current instruction. - --------------------------------------------------------------------------------- - -3.4 What is the release process for SIMH? - -SIMH is released whenever a significant number of new features, or -important bug fixes, has accumulated. This has averaged every 4-8 -weeks. The major version number has not been changed since the -addition of symbolic debugging and won't be changed unless the -internals of SCP change dramatically. The minor version number -is changed when the format of the save/restore file must be updated. - -================================================================================ -4 VAX -================================================================================ - -4.1 Where can I get software and hobbyist licenses for the VAX? - -HP (formerly Compaq formerly DEC) provides licenses to OpenVMS for -hobbyist use. A description of the hobbyist license program can be -found on http://www.montagar.com/hobbyist/. - --------------------------------------------------------------------------------- - -4.2 How do I install VMS? - -To install VMS, you will need a distribution CD ROM. Any version -after VMS 5.5-2 should run on the simulator. - -- Transcribe the distribution CD ROM to an ISO-format CD image file. - (See question 2.5 for information on how to do this.) -- Set drive RQ1 to be a CD ROM. -- Attach the CD ROM image file to simulated drive RQ1. -- Set drive RQ0 to be the type of disk you want. Be sure that the - disk is large enough to hold VMS. -- Attach a blank disk image file to simulated drive RQ0. -- Boot the CPU. -- When the self-test code completes, boot the CD ROM. -- Use standalone backup to restore the CD ROM contents to the simulated - disk. - - sim> set rq0 rd54 - sim> set rq1 cdrom - sim> att rq0 new_vms.dsk - sim> att rq1 cd_rom_image.iso - sim> boot cpu - : - >>> boot rq1 - - $ (prompt from standalone backup) - -A writeup on the procedure can be found on the VMS hobbyist site. - --------------------------------------------------------------------------------- - -4.3 How do I install NetBSD? - -Directions for installing NetBSD on the NetBSD web site, at -http://www.netbsd.org/Ports/vax/emulator-howto.html. - --------------------------------------------------------------------------------- - -4.4 How do I install Ultrix? - -Ultrix is not presently licensed for hobbyist use. If you have a -valid license for Ultrix, and distribution tapes for a version that -supports the MicroVAX 3900 series (V4 or later), then you should -be able to install Ultrix on the simulator. - -- Transcribe the distribution tapes to SIMH-format tape image files. - (See question 2.6 for information on how to do this.) -- Mount the installation tape image on simulated drive TQ0. -- Set drive RQ0 to be the type of disk you want. Be sure that the - disk is large enough to hold Ultrix. -- Mount a blank disk image file on simulated drive RQ0. -- Boot the CPU. -- When the self-test code completes, boot the installation tape. -- The installation tape will guide you through the installation of - Ultrix. - - sim> set rq0 rd54 - sim> att rq0 new_vms.dsk - sim> att tq0 ultrix_install.tap - sim> boot cpu - : - >>> boot mua0 - - (Ultrix installation dialog) - ---------------------------------------------------------------------------------- - -4.5 What's the CPU serial number for my hobbyist license PAK? - -On a MicroVAX 3900, the CPU serial number is not readable and can -be an arbitrary value. 12345 will work fine. - ---------------------------------------------------------------------------------- - -4.6 How do I change the simulator from a VAXserver 3900 to a MicroVAX 3900? - -The system type is controlled by a "magic byte" in the CPU's boot ROM. -By default, the system type is a VAXserver 3900. To change the type -to a MicroVAX 3900, patch the boot ROM as follows: - - sim> set ptr ena - sim> att ptr ka655.bin - sim> ie ptr 4 - 4: 2 1 - sim> det ptr - -and reboot the simulated VAX. - ---------------------------------------------------------------------------------- - -4.7 Is there an example of the simulator running VMS? - -This example assumes you are trying to emulate a MicroVAX 3900 with 64MB of -memory, with a single 1GB disk drive, a CDROM, and an Ethernet controller. - -The host OS is Windows NT/2000/XP, and you have previously dumped the contents -of the VMS Hobbyist CD to a disk file as detailed in 2.5, and have loaded -WinPCAP on the system for Ethernet support. Other host OS's will look -similar but will have different file name syntax. - -c:\simh> vax ; run VAX emulator -sim> set cpu 64m ; set memory size to 64MB -sim> load -r vax\ka655.bin ; load the MicroVAX 3900 console ROM -sim> attach NVR vax\ka655.nvr ; create/load a Non-Volatile RAM file -sim> set LPT disable ; disable devices we don't want/need -sim> set TQ disable ; " -sim> set rq0 ra90 ; set disk 0 to 1GB (RA90 size) -sim> attach rq0 vax\vaxsys.dsk ; create/use disk file -sim> set rq1 rrd40 ; set disk 1 as a cdrom -sim> attach -r rq1 vax\hobbyist.dsk ; attach cdrom dump file as read-only -sim> set rq2 offline ; turn off disk rq2 -sim> set rq3 offline ; turn off disk rq3 -sim> attach xq eth0 ; attach to host ethernet controller -sim> b cpu ; start (boot) VAX console - -KA655-B V5.3, VMB 2.7 - 1) Dansk ; will not appear if the controlling - .. ; keyboard doesn't support multi- -15) Svenska ; national characters! - (1..15): 5 -Performing normal system tests. -40..39..38..37..36..35..34..33..32..31..30..29..28..27..26..25.. -24..23..22..21..20..19..18..17..16..15..14..13..12..11..10..9.. -8..7..6..5..4..3.. -Tests completed. ->>> show device ; tell console to show all devices -UQSSP Disk Controller 0 (772150) --DUA0 (RA90) --DUA1 (RRD40) - -Ethernet Adapter 0 (774440) --XQA0 (08-00-2B-AA-BB-CC) ->>> b dua1 ; tell console to boot cdrom -(BOOT/R5:1 DUA1) - -2..1..0 - ---------------------------------------------------------------------------------- - -4.8 How can I import files to a simulated VMS environment? - -- Use a CD burner program, like Easy CD Creator or Nero, to create an ISO 9660 - CD image containing the files you want to import. Note that file names are - limite to DOS '8.3' conventions. -- Attach the simulated CD image to a simulated CD drive. -- Mount the simulated CD as an ISO 9660 file system under VMS. -- Copy the files you need from the simulated CD to the simulated disk. - -(Thanks to Tim Stark for this suggestion.) - ---------------------------------------------------------------------------------- - -4.9 How can I export files from a simulated VMS environment? - -- Utility ODS2 (available on the Web) can read an ODS-2 disk image and copy files - from that image to the host file system. -- Text files can be printed to the simulated line printer, as described above. - -================================================================================ -5 PDP-11 -================================================================================ - -5.1 When installing RSTS/E from simulated magtape, the installation process - hangs with no error message; why? - -- RSTS/E installation from magnetic tape requires that the tape be write locked. \ No newline at end of file diff --git a/simh_swre.txt b/simh_swre.txt deleted file mode 100644 index 662a0cc5..00000000 --- a/simh_swre.txt +++ /dev/null @@ -1,703 +0,0 @@ -To: Users -From: Bob Supnik -Subj: Sample Software Packages -Date: 15-Sep-2003 - -This memorandum documents the sample software packages available to run -with the SIMH simulators. Many of these packages are available under -limited use licenses; please read the license terms included with the -software. - -The following copyright notice applies to both the SIMH source and binary: - - 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"), - 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. - -1. PDP-8 - -1.1 ESI-X - -ESI-X is an interactive program for technical computation. It can -execute both immediate commands and stored programs (like BASIC). ESI-X -is provided as both source and as a binary loader format paper-tape -image. For more information see the documentation included with the -program. My thanks to Dave Waks, who wrote the program, and to Paul -Pierce and Tim Litt, who recovered the source from its archival medium. - -To load and run ESI-X: - - sim> load esix.bin - sim> run 5400 - _TYPE 2+2. - 2+2 = 4 - -1.2 FOCAL69 - -FOCAL69 is an interactive program for technical computations. It can -execute both immediate commands and stored programs (like BASIC). FOCAL69 -is provided as a binary loader format paper-tape image. To load and -run FOCAL69: - - sim> load focal69.bin - sim> run 200 - *TYPE 2+2 - = 4.000* - -1.3 PDP-8 OS/8 - -OS/8 is the PDP-8's mass storage-based operating system. It provides a -program development and execution environment for assembler, BASIC, and -FORTRAN programs. OS/8 is provided under license, as is, without fee, by -Digital Equipment Corporation, for non-commercial use only. Please read -the enclosed license agreement for full terms and conditions. This license -agreement must be reproduced with any copy of the OS/8 disk images. My -thanks to Doug Jones of the University of Iowa, who provided the disk -images, and to Digital Equipment Corporation, which provided the license. - -To boot and run OS/8: - - sim> att rx0 os8sys_rx.dsk - sim> att rx1 os8f4_rx.dsk - sim> boot rx0 - - .DA dd-mmm-yy - . - -Note that OS/8 only recognizes upper case characters. The first disk -(drive 0) is the system disk; it also includes BASIC. The second disk -(drive 1) includes FORTRAN. - -1.4 PDP-8 TSS/8 - -TSS/8 is the PDP-8's timesharing system. It provides a program development -and execution environment for assembler, BASIC, and FORTRAN programs. TSS/8 -is provided as is, without fee, by Digital Equipment Corporation, for non- -commercial use only. My thanks to John Wilson of Dbit Inc, who provided -the disk image and the initialization tape source. - -Loading TSS/8 -------------- - -Note: your environment must have a functioning second Teletype; that is, you -cannot at present run TSS if your host system does not support the SIMH -sockets library. - -- Load the paper-tape bootstrap: - - sim> load tss8_init.bin - -- Mount the TSS/8 disk image of the RF08: - - sim> attach rf tss8_rf.dsk - -- Assign a TCP/IP port to the Telnet listener for the extra terminals: - - sim> attach ttix -- 4000 typically works - -- Run the bootstrap: - - sim> run 24200 - -- TSS/8 will boot and go through its startup dialog - - LOAD, DUMP, START, ETC? START - MONTH-DAY-YEAR: mm:dd:yy -- numeric, yy in range [74:85] - HR:MIN - hh:mm -- numeric, 24 hour format - (type cr to get attention) - - . - - and is now ready for login. The list of accounts and passwords: - - PPN Password - [0,1] VH3M - [0,2] LXHE - [0,3] SHUG - [77,77] - [1,10] WBCN - [20,1] DT - [20,2] PT - [20,3] TSS8 - [20,4] EDIT - [20,5] 4TH - [1,50] JERK - -- Login using one of the existing accounts. The login command won't echo: - - .LOGIN 2 LXHE -- privileged library account - - TSS/8.24 JOB 01 [00,02] K00 23:23:06 - - SYSTEM IS DOWN, INC. - -- The system is now ready for commands. To get a directory listing: - - .R CAT - -- Other users can log in by connecting, from a Telnet client, to localhost - on the port specified in the ATTACH TTIX command. - -2. PDP-11 - -2.1 UNIX V5, V6, V7 - -UNIX was first developed on the PDP-7; its first widespread usage was on -the PDP-11. UNIX provides a program development and execution environment -for assembler and C programs. UNIX V5, V6, V7 for the PDP-11 is provided -under license, as is, without fee, by Caldera Corportion, for non-commercial -use only. Please read the enclosed license agreement for full terms and -conditions. This license must be reproduced with any copy of the UNIX V5, -V6, V7 disk images. My thanks to PUPS, the PDP-11 UNIX Preservation Society -of Australia, which provided the disk images, and to Caldera, which provided -the license. - -2.1.1 UNIX V5 - -UNIX V5 is contained on a single RK05 disk image. To boot UNIX: - - sim> set cpu 18b - sim> att rk0 unix_v5_rk.dsk - sim> boot rk - @unix - login: root - #ls -l - -2.1.2 UNIX V6 - -UNIX V6 is contained on four RK05 disk images. To boot UNIX: - - sim> set cpu 18b - sim> att rk0 unix0_v6_rk.dsk - sim> att rk1 unix1_v6_rk.dsk - sim> att rk2 unix2_v6_rk.dsk - sim> att rk3 unix3_v6_rk.dsk - sim> boot rk0 - @unix - login: root - # ls -l - -2.1.3 UNIX V7 - -UNIX V7 is contained on a single RL02 disk image. To boot UNIX: - - sim> set cpu 18b - sim> set rl0 RL02 - sim> att rl0 unix_v7_rl.dsk - sim> boot rl0 - @boot - New Boot, known devices are hp ht rk rl rp tm vt - : rl(0,0)rl2unix - # - -A smaller image is contained on a single RK05 disk image. To boot UNIX: - - sim> set cpu 18b - sim> att rk0 unix_v7_rk.dsk - sim> boot rk0 - @boot - New Boot, known devices are hp ht rk rl rp tm vt - : rk(0,0)rkunix - # STTY -LCASE - # - -2.2 RT-11 - -RT-11 is the PDP-11's single user operating system. It provides a program -development and execution environment for assembler, BASIC, and FORTRAN -programs. RT-11 is provided under license, as is, without fee, by Mentec -Corporation, for non-commercial use ONLY ON THIS SIMULATOR. Please read -the enclosed license agreement for full terms and conditions. This license -agreement must be reproduced with any copy of the RT-11 disk image. My -thanks to John Wilson, a private collector, who provided the disk image -for RT-11 V4; to Megan Gentry, of Digital Equipment Corporation, who -provided the disk image for RT-11 V5.3; and to Mentec Corporation, which -provided the license. - -2.2.1 RT-11 V4 - -RT-11 is contained in a single RK05 disk image. To boot and run RT-11: - - sim> att rk0 rtv4_rk.dsk - sim> boot rk0 - -For RL, HK, RM, and RP series disks, RT-11 expects to find a manufacturer's -bad block table in the last track of the disk. Therefore, INITialization of -a new (all zero's) disk fails, because there is no valid bad block table. To -create a minimal bad block table, use the SET BADBLOCK command. - -2.2.2 RT-11 V5.3 - -RT-11 is contained in a single RL02 disk image. To boot and run RT-11: - - sim> set rl0 rl02 - sim> att rl0 rtv53_rl.dsk - sim> boot rl0 - -This is a full RT-11 distribution kit. It expects the user to copy the -distribution pack and generate a new system. This requires mounting a -blank pack on RL1. When a blank pack is attached to the simulator, a -bad block table must be created with the SET BADBLOCK command. - -3. Nova and Eclipse RDOS - -RDOS is the Nova's real-time mass storage operating system. It provides a -program development and execution environment for assembler, BASIC, and -FORTRAN programs. RDOS is provided under license, as is, without fee, by -Data General Corporation, for non-commercial use only. Please read the -enclosed license agreement for full terms and conditions. This license -agreement must be reproduced with any copy of the RDOS disk image. My -thanks to Carl Friend, a private collector, who provided the disk image, -and to Data General Corporation, which provided the license. - -To boot and run RDOS for the Nova: - - sim> att dp0 rdos_d31.dsk - sim> set tti dasher - sim> boot dp0 - FILENAME? (cr) - DATE (mm/dd/yy)? xx/yy/zz - TIME (hh:mm:ss)? hh:mm:ss - R - list/e - -To boot and run RDOS for the Eclipse: - - sim> att dp0 zrdos75.dsk - sim> set tti dasher - sim> boot dp0 - FILENAME? (cr) - DATE (mm/dd/yy)? xx/yy/zz - TIME (hh:mm:ss)? hh:mm:ss - R - list/e - -4. PDP-1 - -4.1 PDP-1 LISP - -PDP-1 LISP is an interactive interpreter for the Lisp language. It can -execute both interactive commands and stored programs. The startup -instructions for LISP are complicated; see the documentation included -with the program for details. My thanks to Peter Deutsch, who wrote the -program, to Gordon Greene, who typed it in from a printed listing, and -to Paul McJones, who helped with the final debug process. - -4.2 PDP-1 DDT - -PDP-1 DDT is an interactive debugging tool for the PDP-1. It provides -symbolic debugging capabilities for PDP-1 programs. The documentation -included with the program provides information on loading and operating -DDT. My thanks to Derek Peschel, who transcribed and debugged DDT. - -5. PDP-7 SIM8 - -PDP-7 SIM8 is a PDP-8 simulator for the PDP-7. It implements an 8K -PDP-8/I with keyboard, teleprinter, reader, punch, and line printer. -It provides an interactive console environment for control and debug -of the simulated PDP-8. For more information see the documentation -included with the program. My thanks to Dave Waks, who wrote the -program, and to Paul Pierce and Tim Litt, who recovered the source -from its archival medium. - -To load and run SIM8: - - sim> load sim8.rim - sim> run - AC/ 0000 - -6. PDP-9/PDP-15 - -6.1 FOCAL - -FOCAL15 is an interactive program for technical computations. It can -execute both immediate commands and stored programs (like BASIC). -FOCAL15 is provided as a binary loader format paper-tape image. My -thanks to Al Kossow, who provided the binary image. To load and run -FOCAL15: - - sim> load focal15.bin - sim> run - *TYPE FSQT(2),! - = 1.4142 - * - -6.2 Advanced Software System/Keyboard Monitor - -The Advanced Software System Keyboard Monitor is the simplest mass -storage monitor for the PDP-15. It offers single-user program -development and execution capabilities. To load and run ADSS/KM-15: - -- On the PDP-9 (only), initialize extend mode to on: - - sim> d extm_init 1 - -- Load the paper-tape bootstrap into upper memory: - - sim> load dec-15u.rim 77637 - - You specify the load address. - -- Verify that the bootstrap loaded correctly: - - sim> ex pc - PC: 077646 - -- Change the default line printer to be the LP09 rather than the Type - 647 (PDP-9) or LP15 (PDP-15): - - sim> set lpt disa - sim> set lp9 ena - -- Mount the Advanced Software System DECtape image on DECtape unit 0: - - sim> attach dt adss15_32k.dtp - -- Run the bootstrap: - - sim> run - -- The DECtape will boot and print out - - KMS9-15 V5B000 - $ - - and is now ready for commands. Recognized commands include: - - D list system device directory - I list available commands - R list device assignments - SCOM list systems communication region - -- To run Focal, assign unused DAT slot 10 and then load Focal - - $A LPA0 10 - $GLOAD - LOADER V5B000 - >_FOCAL - FOCAL V9A - *TYPE 2+2,! - 4.0000 - * - -6.3 Advanced Software System/Foreground Background - -Note: your environment must have a functioning second Teletype; that is, -you cannot at present run Foreground/Background if your host system -does not support the SIMH sockets library. - -- Load the paper-tape bootstrap into upper memory: - - sim> load dec-15u.rim 77637 - - You specify the load address. - -- Verify that the bootstrap loaded correctly: - - sim> ex pc - PC: 077646 - -- Mount the Foregorund/Background DECtape image on DECtape unit 0: - - sim> attach dt fb15_32k.dtp - -- Turn on the API option: - - sim> set cpu api - -- Assign a TCP/IP port to the Telnet listener for the second terminal: - - sim> assign tti1 -- 4000 typically works - -- Start a Telnet client to act as the second terminal and connect to - localhost on the specified port. - -- Run the bootstrap: - - sim> run - -- The DECtape will boot, and the Foreground/Background Monitor will print - on the second terminal - - F9/15 V4A - $ - - and is now ready for commands. Recognized commands include: - - D 0 list system device directory - R list device assignments - -- To activate the background, load IDLE into the foreground: - - $A DTA0 -4 - $GLOAD - FGLOAD V2A - >_IDLE - - Background terminal responds with - - B9/15 V4A - $ - - and is now ready for commands. - -6.4 DOS-15 - -DOS-15 is a more polished version of ADSS-15 using the RF15 or RP15 -as its system device. To load and run DOS-15: - -- Load the DOS-15 paper tape bootstrap into upper memory: - - sim> load rfsboot.rim 77637 - -- Mount the DOS-15 RF disk image on the RF15: - - sim> att rf dosv2a_4p.rf - -- Run the bootstrap: - - sim> run - -- The RF disk will boot and print out - - DOS-15 V2A - ENTER DATE (MM/DD/YY) - - - Enter the date (the year must be between 70 and 99). DOS-15 will - print its prompt and is now ready for commands. Recognized commands - include: - - I system information - S system configuration - R system device assignments - - -7. IBM 1401 - -7.1 Single Card "Koans" - -One of the art forms for the IBM 1401 was packing useful programs into a -single punched card. Three samples are included: - -i1401_ctolp.cd prints a card deck on the line printer -i1401_ctopu.cd copies a card deck to the card punch -i1401_hello.cd prints "HELLO WORLD" on the line printer and stops - -To use the reproduction cards, simply insert them at the beginning of a -text file, terminated by newline. Attach the modified file to the card -reader, attach a blank file to the output device, and boot the card reader. - -7.2 Diagnostic Tape - -The software and writeup were provided by Charles Owens. - -This 1401 Diagnostics tape is a bootable tape containing a series of 1401 -diagnostics dating from about 1962. The 1407 Inquiry console is not used; -all control is via the front panel. - -To run in the simulator, attach thusly: - - sim> attach mt1 1401diag.mt - sim> attach lpt errorlist.txt - sim> boot mt1 - -The simulator will halt with IS = 433. At this point, you can set options -through the sense switches and memory. - -D 1252 "1" Will cause headings to print for each test run. - Otherwise no printing will occur unless there are errors. - -D SSB 1 Loop if an error is detected. - -D SSC 1 Prints all test cases not just errors. - -D SSD 1 Repeat the test run over and over. - -D SSE 1 Halt if any error is detected, otherwise continue. - -When you continue from this halt (use C to CON), the simulator will halt -at 3001. Enter C again and the tape will spin thru a series of basic -CPU diagnostics. - -7.3 SPS - -The software and writeup were provided by Charles Owens. - -sps1.obj and sps2.obj are the object card decks for the "Symbolic -Programming System", a primitive assembler for the 1401 that predates -the better known and more functional Autocoder. - -To use SPS, write an SPS program using your favourite editor (two -examples are provided, hello.sps and diaglist.sps). SPS decks are -not free-format, but operands must be placed in columns: - - 1 - 5 Line Count (optional) - 6 - 7 Count (number of characters when defining a constant). - 8 - 13 Label (six characters must start with alphabetic). -14 - 16 Opcode: Examples: - A = Add - B = Branch (must be d-mod for conditional) - BWZ = Branch if Wordmark or Zone - C = Compare - CC = Carriage Control (printer) - CS = CLear Storage - CU = Control Unit (e.g. tape) - CW = Clear Workmark - D = Divide - DC = Define Constant (no wordmark) - DCW = Define Constant (starts in 24, length in 6-7) - END = End of program - LCA = Load Characters - H = Halt - M = Multiply - MCE = Move and Edit - MCS = Move and Supress Zeros - MCW = Move Characters - MN = Move Numeric - MZ = Move Zone - ORG = Define Origin Point - P = Punch Card - R = Read Card - S = Subtract - SS = Stacker Select - SW = Set Wordmark - W = Write Line - ZA = Zero and Add - ZS = Zero and Subtract - Tape: - MCW %UX YYY W Write Tape from addr YYY w/o wordmarks) - LCA %UX YYY W Write Tape, Unit X from addr YYY w/wordmarks) - MCW %UX YYY R Read Tape from addr YYY w/o wordmarks) - LCA %UX YYY R Read Tape, Unit X from addr YYY w/wordmarks) - CU %UX M Write Tape Mark - CU %UX E Skip and Blank Tape - CU %UX B Backspace Record - CU %UX R Rewind Tape - CU %UX U Rewind and Unlaod tape -17 - 22 Address for A-operand (label or 4-digit actual address) -23 - 23 blank, + or - to adjust A-operand by a constant -24 - 26 3-digit number to adjust A-operand by if 23 is + or - -27 - 27 Index (?) -28 - 33 Address for B-operand -34 - 34 Blank, + or - -35 - 37 3-digit number of adjust B-address by if 34 is + or - -38 - 38 Index (?) -39 - 39 D-modifier for this instruction. Notes: - / = Compare is unequal - S = Branch if Compare Equal - T = B is less than A - U = B is greater than A - L = Tape read error - K = Tape end of reel -40 - 55 Comments - -The SPS deck should start with an ORG operation to specify where in storage -the program starts, and end with an END card, with an optional A-operand -showing where to start execution. - -To assemble an SPS program, place the SPS source between the SPS1.OBJ and -the SPS2.OBJ deck, and another copy of the same source after the SPS2.OBJ -deck (SPS is a two-pass assembler). SPS prints a listing on LPT and punches -an object deck on CDP, ready to run. - -A UNIX command script to assemble an SPS deck painlessly is in "sps". To -use the script, enter "sps programname". The script creates programname.lst -for the listing and programname.obj for the object deck. Windows users -are out of luck, for now. - -8. HP2116 16K BASIC - -HP BASIC is a paper-tape centric implementation of BASIC for a 16KW -HP2116. Device numbers correspond to the default simulator settings: - - PTR = 10 - TTY = 11 - PTP = 12 - -The program is a complete but early BASIC and has one unsual requirement: -all programs must include a valid END statement to run correctly. My -thanks to Jeff Moffatt for providing the program. - -To load and run BASIC: - - sim> load basic1.abs - sim> run 100 - READY - 10 PRINT SQR(2) - 20 END - RUN - 1.41421 - - -9. PDP-10 TOPS-10 7.03, TOPS-10 7.04, TOPS-20 V4.1 - -TOPS-10 was the primary time-shared operating system for the PDP-10. -TOPS-20 was a popular alternative derived from the BBN TENEX system. -Installation and distribution tapes for TOPS-10 7.03, TOPS-10 7.04, -and TOPS-20 4.1 are available at http://pdp-10.trailing-edge.com. - -10. Interdata 32b Systems - -10.1 Interdata 7/32 UNIX - -Interdata UNIX V6 was the first port of UNIX from its native environment -on the PDP-11. The port was done by Richard Miller and his colleagues -at the University of Wollongong, Australia, in 1976-77. UNIX V6 and V7 -for the Interdata 7/32 is provided under license, as is, without fee, by -Caldera Corportion, for non-commercial use only. Please read the enclosed -license agreement for full terms and conditions. This license must be -reproduced with any copy of the UNIX V6 and V7 disk images. My thanks to -Richard Miller, without whose guidance, knowledge, and patience the -recreation of Interdata UNIX would not have been possible, and to Caldera, -which provided the license. - -10.1.1 UNIX V6 - -UNIX V6 is contained on a single 10MB disk image. To boot UNIX V6: - - sim> set ttp ena - sim> set pas dev=12 - sim> set mt dev=85 - sim> att -e dp0 iu6_dp0.dsk - sim> boot dp0 - ?unix - login: root - # ls -l - -10.1.2 UNIX V7 - -UNIX V7 is contained on two 10MB disk images. To boot UNIX V7: - - sim> set ttp ena - sim> set pas dev=12 - sim> set mt dev=85 - sim> att -e dp0 iu6_dp0.dsk - sim> att -e dp1 iu6_dp1.dsk - sim> boot dp0 - Boot - : dsk(1,0)unix - # - -Type ^D to enable multiuser mode. The root password is root. - -[end simh_swre.txt]