diff --git a/0readme_30.txt b/0readme_31.txt similarity index 61% rename from 0readme_30.txt rename to 0readme_31.txt index e1a623cf..0725c3c4 100644 --- a/0readme_30.txt +++ b/0readme_31.txt @@ -1,43 +1,110 @@ -Notes For V3.0-2 +Notes For V3.1-0 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. New Features in 3.1-0 -1.1 PDP-1 +1.1 SCP and libraries -- 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. +- Added simulated Ethernet support for VMS, FreeBSD, Mac OS/X. +- Added status return to tmxr_putc_ln. +- Added sim_putchar_s to handle possible output stalls. -2. Bugs Fixed in 3.0-2 +1.2 All DECtapes + +- Added "DECtape off reel" error stop. + +1.3 All Asynchronous Consoles + +- Added support for output congestion stall if using a Telnet connection. + +1.4 PDP-1 + +- Added Type 23 parallel drum support. + +1.5 PDP-8 + +- Added instruction history. +- Added TSC8-75 option support for ETOS. +- Added TD8E DECtape support. + +1.6 PDP-18b + +- Added instruction history. +- Changed PDP-9, PDP-15 API default to enabled. + +1.7 PDP-11 + +- Added support for 18b only Qbus devices. +- Formalized bus and addressing definitions. +- Added control to enable/disable autoconfiguration. +- Added stub support for second Unibus Ethernet controller. + +1.7 Interdata 32b + +- Added instruction history. + +1.8 Eclipse + +- Added floating point support. +- Added programmable interval timer support. + +1.9 H316 + +- Added DMA/DMC support. +- Added fixed head disk support. +- Added moving head disk support. +- Added magtape support. + +1.10 IBM 1130 (Brian Knittel) + +- Added support for physical card reader, using the Cardread +interface (www.ibm1130.org/sim/downloads). +- Added support for physical printer (flushes output buffer after +each line). + +2. Bugs Fixed in 3.1-0 2.1 SCP and libraries -- Fixed end of file problem in dep, idep. -- Fixed handling of trailing spaces in dep, idep. +- Fixed numerous bugs in Ethernet library. -2.2 PDP-1 +2.2 All DECtapes -- Fixed system hang if continue after PTR error. -- Fixed PTR to start/stop on successive rpa instructions. +- Fixed reverse checksum value in 'read all' mode. +- Simplified (and sped up) timing. -2.3 PDP 18b family +2.3 PDP-8 -- 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. +- Fixed bug in RX28 read status (found by Charles Dickman). +- Fixed RX28 double density write. -2.4 1401 +2.4 PDP-18b -- Fixed tape read end-of-record handling based on real 1401. -- Added diagnostic read (space forward). +- Fixed autoincrement bug in PDP-4, PDP-7, PDP-9. -2.5 1620 +2.5 PDP-11/VAX -- Fixed bug in immediate index add (found by Michael Short). +- Revised RQ MB->LBN conversion for greater accuracy. +- Fixed bug in IO configuration (found by David Hittner). +- Fixed bug with multiple RQ RAUSER drives. +- Fixed bug in second Qbus Ethernet controller interrupts. + +2.6 Nova/Eclipse + +- Fixed bugs in DKP flag clear, map setup, map usage (Charles Owen). +- Fixed bug in MT, reset completes despite I/O reset (Charles Owen). +- Fixed bug in MT, space operations return word count (Charles Owen). + +2.7 IBM 1130 (Brian Knittel) + +- Fixed bug in setting carry bit in subtract and subtract double. +- Fixed timing problem in console printer simulation. + +2.8 1620 + +- Fixed bug in branch digit (found by Dave Babcock). 3. New Features in 3.0 vs prior releases @@ -47,7 +114,7 @@ debugged. Do NOT enable these features for normal operations. - Changed RESTORE to unconditionally detach files. - Added E11 and TPC format support to magtape library. - Fixed bug in SHOW CONNECTIONS. -- Added USE_ADDR64 support +- Added USE_ADDR64 support. 3.2 All magtapes @@ -68,6 +135,10 @@ debugged. Do NOT enable these features for normal operations. - Added block loader format support to LOAD. - Changed BOOT PTR to allow loading of all of the first bank of memory. +- 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. 3.5 PDP-18b Family @@ -79,7 +150,12 @@ debugged. Do NOT enable these features for normal operations. 4. Bugs Fixed in 3.0 vs prior releases -4.1 VAX +4.1 SCP and Libraries + +- Fixed end of file problem in dep, idep. +- Fixed handling of trailing spaces in dep, idep. + +4.2 VAX - Fixed CVTfi bug: integer overflow not set if exponent out of range - Fixed EMODx bugs: @@ -91,7 +167,7 @@ debugged. Do NOT enable these features for normal operations. fast host processors (fixes from Mark Pizzolato). - Fixed bug in user disk size (found by Chaskiel M Grundman). -4.2 1401 +4.3 1401 - Fixed mnemonic, instruction lengths, and reverse scan length check bug for MCS. - Fixed MCE bug, BS off by 1 if zero suppress. @@ -100,20 +176,24 @@ debugged. Do NOT enable these features for normal operations. - Added check for invalid 8 character MCW, LCA. - Fixed magtape load-mode end of record response. - Revised fetch to model hardware more closely. +- Fixed tape read end-of-record handling based on real 1401. +- Added diagnostic read (space forward). -4.3 Nova +4.4 Nova - Fixed DSK variable size interaction with restore. - Fixed bug in DSK set size routine. -4.4 PDP-1 +4.5 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. +- Fixed system hang if continue after PTR error. +- Fixed PTR to start/stop on successive rpa instructions. -4.5 PDP-11 +4.6 PDP-11 - Fixed DT variable size interaction with restore. - Fixed bug in MMR1 update (found by Tim Stark). @@ -127,7 +207,7 @@ debugged. Do NOT enable these features for normal operations. o Added explicit runt and giant packet processing. - Fixed bug in user disk size (found by Chaskiel M Grundman). -4.6 PDP-18B +4.7 PDP-18B - Fixed DT, RF variable size interaction with restore. - Fixed MT bug in MTTR. @@ -135,32 +215,40 @@ debugged. Do NOT enable these features for normal operations. - Fixed bug in PDP-15 memory protect/skip interaction. - Fixed bug in RF set size routine. - Increased PTP TIME for PDP-15 operating systems. +- 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. -4.7 PDP-8 +4.8 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 +4.9 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 +4.10 GRI - Fixed bug in SC queue pointer management. -4.10 PDP-10 +4.11 PDP-10 - Fixed bug in RP read header. -4.11 Ibm1130 +4.12 Ibm1130 - Fixed bugs found by APL 1130. -4.12 Altairz80 +4.13 Altairz80 - Fixed bug in real-time clock on Windows host. + +4.14 1620 + +- Fixed bug in immediate index add (found by Michael Short). + diff --git a/0readme_ethernet.txt b/0readme_ethernet.txt index 938fcf71..6ffc7a84 100644 --- a/0readme_ethernet.txt +++ b/0readme_ethernet.txt @@ -8,7 +8,7 @@ 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. +supports Windows, Linux, NetBSD, OpenBSD, FreeBSD, OS/X, and Alpha VMS. Currently, the Sim_Ether module sets the selected ethernet card into promiscuous mode to gather all packets, then filters out the packets that it @@ -20,53 +20,138 @@ 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. +Using the libpcap/WinPcap interface, the simulated computer cannot "talk" to +the host computer via the selected interface, since the packets are not +reflected back to the host. The workaround for this is to use a second NIC in +the host and connect them both into the same network; then the host and the +simulator can communicate over the physical LAN. + +Universal TUN/TAP support provides another solution for the above dual-NIC +problem for systems that support Universal TUN/TAP. Since the TUN/TAP interface +is at a different network level, the host can create a TAP device for the +simulator and then bridge or route packets between the TAP device and the real +network interface. Note that the TAP device and any bridging or routing must be +established before running the simulator; SIMH does not create, bridge, or +route TAP devices for you. + ------------------------------------------------------------------------------- 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. + package that is freely available for un*x 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. + the WinPCAP documentation for details on the static loading workaround. + + 4. If you want to use TAP devices, they must be created before running SIMH. + (TAP component from the OpenVPN project; http://openvpn.sourceforge.net) + + 5. Compaq PATHWORKS 32 v7.2 also enabled bridging for the ethernet adapters + when the DECNET and LAT drivers were installed; TAP was not needed. + Building on Windows: - 1. Install WinPCAP 3.0. + 1. Install WinPCAP 3.0 runtime and the WinPCAP Developer's kit. + 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: +Linux, {Free|Net|Open}BSD, OS/X, and Un*x 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. + 2. If you want to use TAP devices, they must be created before running SIMH. + +Linux, {Free|Net|Open}BSD, OS/X, Un*x notes: + 1. Get/make/install the libpcap package for your operating system. Sources: + Linux : search for your variant on http://rpmfind.net + OS/X : Apple Developer's site? + Others : http://sourceforge.net/projects/libpcap/ + + 2. Use 'make USE_NETWORK=1' if you want the network functionality. + 3. Build it! ------------------------------------------------------------------------------- +OpenVMS Alpha notes: + 1. Ethernet support will only work on Alpha VMS 7.3-1 or later, which is + when required VCI promiscuous mode support was added. Hobbyists can + get the required version of VMS from the OpenVMS Alpha Hobbyist Kit 3.0. + + Running a simulator built with ethernet support on a version of VMS prior + to 7.3-1 will behave as if there is no ethernet support built in due to + the inability of the software to set the PCAPVCM into promiscuous mode. + + An example display of fully functional ethernet support: + sim> SHOW XQ ETH + ETH devices: + 0 we0 (VMS Device: _EWA0:) + 1 we1 (VMS Device: _EWB0:) + + An example display when the simulator was built without ethernet support + or is not running the required version of VMS: + sim> SHOW XQ ETH + ETH devices: + no network devices are available + + 2. You must place the PCAPVCM.EXE execlet in SYS$LOADABLE_IMAGES before + running a simulator with ethernet support. + + 3. You must have CMKRNL privilege to SHOW or ATTACH an ethernet device; + alternatively, you can INSTALL the simulator with CMKRNL privilege. + + 4. If you use a second adapter to communicate to the host, SOME protocol + that creates an I/O structure (SCS, DECNET, TCP) must be running on the + adapter prior trying to connect with SIMH, or the host may crash. + The execlet is not written to create an I/O structure for the device. + +Building on OpenVMS Alpha: + 1. Build the PCAP library and execlet. They are in the [.PCAP-VMS] + directory in the simh source distribution. The following builds + both the pcap library and the pcap execlet: + $ set def [.pcap-vms] + $ @build_all + Building VCI version of pcap... + Building the PCAP VCM execlet... + In order to use it, place PCAPVCM.EXE in the + SYS$LOADABLE_IMAGES directory. + %DCL-I-SUPERSEDE, previous value of PCAPVCM$OBJ has been superseded + + To use the PCAPVCM.EXE execlet you must copy it to + the SYS$LOADABLE_IMAGES directory. + + Build done... + + 2. To build the simulators with ethernet support, you + need to build them with MMS or MMK as follows: + $ MMx/MACRO=("__ALPHA__=1", "__PCAP__=1") + +------------------------------------------------------------------------------- + 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. +been successfully run. Other testers have reported success booting NetBSD and +OpenVMS VAX 5.5-2 also. PDP11 simulator support: @@ -88,15 +173,14 @@ Things planned for future releases: ------------------------------------------------------------------------------- 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. + 1. Information about Remote MOP processing + 2. VAX/PDP-11 hardware diagnotics image files and docs, to test XQ thoroughly. + 3. 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 + david DOT hittner AT ngc DOT com Thanks, and Enjoy!! Dave @@ -106,33 +190,46 @@ Dave Change Log =============================================================================== +26-Nov-03 Release: + 1. Added VMS support to Sim_Ether; created pcap-vms port (Anders Ahgren) + 2. Added DECNET duplicate detection for Windows (Mark Pizzolato) + 3. Added BPF filtering to increase efficiency (Mark Pizzolato) + 4. Corrected XQ Runt processing (Mark Pizzolato) + 5. Corrected XQ Software Reset (Mark Pizzolato) + 6. Corrected XQ Multicast/Promiscuous mode setting/resetting (Mark Pizzolato) + 7. Added Universal TUN/TAP support (Mark Pizzolato) + 8. Added FreeBSD support (Edward Brocklesby) + 9. Corrected interrupts on XQB device (David Hittner) + +------------------------------------------------------------------------------- + 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 + 1. Added SET/SHOW XQ STATS (David Hittner) + 2. Added SHOW XQ FILTERS (David Hittner) + 3. Added ability to split rcv packets into multiple buffers (David Hittner) + 4. Added explicit runt & giant packet processing (David Hittner) ------------------------------------------------------------------------------- 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 + 1. Corrected bug in xq_setmac introduced in v3.0 (multiple people) + 2. Made XQ rcv buffer allocation dynamic to reduce scp size (David Hittner) + 3. Optimized some structs, removed legacy variables (Mark Pizzolato) + 4. Changed #ifdef WIN32 to _WIN32 for consistancy (Mark Pizzolato) ------------------------------------------------------------------------------- 06-May-03 Release: - 1. Added second XQ controller - 2. Added SIMH v3.0 compatibility - 3. Removed SET ADDRESS functionality + 1. Added second XQ controller (David Hittner) + 2. Added SIMH v3.0 compatibility (David Hittner) + 3. Removed SET ADDRESS functionality (David Hittner) ------------------------------------------------------------------------------- 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) + 1. Added preliminary support for RSTS/E (David Hittner) + 2. Added PDP-11 bootrom load via CSR flags (David Hittner) + 3. Support for SPARC linux (Mark Pizzolato) ------------------------------------------------------------------------------- diff --git a/AltairZ80/altairZ80_cpu.c b/AltairZ80/altairZ80_cpu.c index 0b119432..ecd6eccd 100644 --- a/AltairZ80/altairZ80_cpu.c +++ b/AltairZ80/altairZ80_cpu.c @@ -1,5605 +1,5622 @@ -/* 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; -} +/* 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" + +#if !defined (_WIN32) +#include +#endif + +#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 = 0; + register uint32 acu = 0; + register uint32 sum; + register uint32 cbits; + register uint32 op; + register uint32 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 = FALSE; + + 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; +#if defined (_WIN32) + while (sim_os_msec() <= startTime) {} /* poor man's sleep */ +#else + { + uint32 now; + if (startTime > (now = sim_os_msec())) { + usleep(1000 * (startTime - now)); + } + } +#endif + } + + 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/GRI/gri_stddev.c b/GRI/gri_stddev.c index 425a8b7b..7f55f978 100644 --- a/GRI/gri_stddev.c +++ b/GRI/gri_stddev.c @@ -1,6 +1,6 @@ /* gri_stddev.c: GRI-909 standard devices - Copyright (c) 2001-2003, Robert M Supnik + Copyright (c) 2001-2004, 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"), @@ -29,6 +29,7 @@ hsp S42-006 high speed punch rtc real time clock + 29-Dec-03 RMS Added support for console backpressure 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 @@ -246,12 +247,14 @@ 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 */ +if ((r = sim_putchar_s (c)) != SCPE_OK) { /* output; error? */ + sim_activate (uptr, uptr->wait); /* try again */ + return ((r == SCPE_STALL)? SCPE_OK: r); } /* !stall? report */ +dev_done = dev_done | INT_TTO; /* set ready */ tto_unit.pos = tto_unit.pos + 1; return SCPE_OK; } diff --git a/H316/h316_cpu.c b/H316/h316_cpu.c index 202f126b..997d5794 100644 --- a/H316/h316_cpu.c +++ b/H316/h316_cpu.c @@ -1,6 +1,6 @@ /* h316_cpu.c: Honeywell 316/516 CPU simulator - Copyright (c) 1999-2003, Robert M. Supnik + Copyright (c) 1999-2004, Robert M. Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -25,6 +25,8 @@ cpu H316/H516 CPU + 31-Dec-03 RMS Fixed bug in cpu_set_hist + 24-Oct-03 RMS Added DMA/DMC support, instruction history 30-Dec-01 RMS Added old PC queue 03-Nov-01 RMS Fixed NOHSA modifier 30-Nov-01 RMS Added extended SET/SHOW support @@ -167,10 +169,10 @@ 2. Interrupts. Interrupts are maintained by two parallel variables: - dev_ready device ready flags - dev_enable device interrupt enable flags + dev_int device interrupt flags + dev_enb device interrupt enable flags - In addition, dev_ready contains the interrupt enable and interrupt no + In addition, dev_int 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 @@ -194,8 +196,6 @@ #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 @@ -207,6 +207,20 @@ #define m15 0000002 #define m16 0000001 +#define HIST_PC 0x40000000 +#define HIST_C 0x20000000 +#define HIST_EA 0x10000000 +#define HIST_MIN 64 +#define HIST_MAX 65536 +struct InstHistory { + int32 pc; + int32 ir; + int32 ar; + int32 br; + int32 xr; + int32 ea; + int32 opnd; }; + uint16 M[MAXMEMSIZE] = { 0 }; /* memory */ int32 saved_AR = 0; /* A register */ int32 saved_BR = 0; /* B register */ @@ -219,27 +233,44 @@ 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 dev_int = 0; /* dev ready */ +int32 dev_enb = 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; +uint32 dma_nch = DMA_MAX; /* number of chan */ +uint32 dma_ad[DMA_MAX] = { 0 }; /* DMA addresses */ +uint32 dma_wc[DMA_MAX] = { 0 }; /* DMA word count */ +uint32 dma_eor[DMA_MAX] = { 0 }; /* DMA end of range */ +uint32 chan_req = 0; /* channel requests */ +uint32 chan_map[DMA_MAX + DMC_MAX] = { 0 }; /* chan->dev map */ +int32 (*iotab[DEV_MAX])(int32 inst, int32 fnc, int32 dat, int32 dev) = { NULL }; +int32 hst_p = 0; /* history pointer */ +int32 hst_lnt = 0; /* history length */ +struct InstHistory *hst = NULL; /* 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 FILE *sim_log; +extern DEVICE *sim_devices[]; +t_bool devtab_init (void); +int32 dmaio (int32 inst, int32 fnc, int32 dat, int32 dev); +int32 undio (int32 inst, int32 fnc, int32 dat, int32 dev); 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); +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); +t_stat cpu_show_dma (FILE *st, UNIT *uptr, int32 val, void *desc); +t_stat cpu_set_nchan (UNIT *uptr, int32 val, char *cptr, void *desc); +t_stat cpu_show_nchan (FILE *st, UNIT *uptr, int32 val, void *desc); extern t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, UNIT *uptr, int32 sw); @@ -252,7 +283,9 @@ extern t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, cpu_mod CPU modifiers list */ -UNIT cpu_unit = { UDATA (NULL, UNIT_FIX + UNIT_BINK + UNIT_EXT, +DIB cpu_dib = { DMA, IOBUS, 1, &dmaio }; + +UNIT cpu_unit = { UDATA (NULL, UNIT_FIX+UNIT_BINK+UNIT_EXT+UNIT_HSA+UNIT_DMC, MAXMEMSIZE) }; REG cpu_reg[] = { @@ -270,19 +303,23 @@ REG cpu_reg[] = { { 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 (ION, dev_int, INT_V_ON) }, + { FLDATA (INODEF, dev_int, INT_V_NODEF) }, + { ORDATA (DEVINT, dev_int, 16), REG_RO }, + { ORDATA (DEVENB, dev_enb, 16), REG_RO }, + { ORDATA (CHREQ, chan_req, DMA_MAX + DMC_MAX) }, + { BRDATA (DMAAD, dma_ad, 8, 16, DMA_MAX) }, + { BRDATA (DMAWC, dma_wc, 8, 16, DMA_MAX) }, + { BRDATA (DMAEOR, dma_eor, 8, 1, DMA_MAX) }, + { ORDATA (DMANCH, dma_nch, 3), REG_HRO }, + { FLDATA (MPERDY, dev_int, INT_V_MPE) }, + { FLDATA (MPEENB, dev_enb, 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[] = { @@ -296,47 +333,42 @@ MTAB cpu_mod[] = { { UNIT_MSIZE, 16384, NULL, "16K", &cpu_set_size }, { UNIT_MSIZE, 24576, NULL, "24K", &cpu_set_size }, { UNIT_MSIZE, 32768, NULL, "32K", &cpu_set_size }, + { MTAB_XTD | MTAB_VDV, 0, "channels", "CHANNELS", + &cpu_set_nchan, &cpu_show_nchan, NULL }, + { UNIT_DMC, 0, "no DMC", "NODMC", NULL }, + { UNIT_DMC, UNIT_DMC, "DMC", "DMC", NULL }, + { MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, "HISTORY", "HISTORY", + &cpu_set_hist, &cpu_show_hist }, + { MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "DMA1", NULL, + NULL, &cpu_show_dma, NULL }, + { MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "DMA2", NULL, + NULL, &cpu_show_dma, NULL }, + { MTAB_XTD | MTAB_VDV | MTAB_NMO, 2, "DMA3", NULL, + NULL, &cpu_show_dma, NULL }, + { MTAB_XTD | MTAB_VDV | MTAB_NMO, 3, "DMA4", NULL, + NULL, &cpu_show_dma, NULL }, { 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 }; - + NULL, NULL, NULL, + &cpu_dib, 0 }; t_stat sim_instr (void) { extern UNIT clk_unit; -int32 AR, BR, MB, Y, t1, t2, t3, skip; +int32 AR, BR, MB, Y, t1, t2, t3, skip, dev; uint32 ut; t_stat reason; t_stat Ea (int32 inst, int32 *addr); -void Write (int32 val, int32 addr); +void Write (int32 addr, int32 val); int32 Add16 (int32 val1, int32 val2); int32 Add31 (int32 val1, int32 val2); int32 Operate (int32 MB, int32 AR); -#define Read(x) M[(x)] +#define Read(ad) M[(ad)] #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; \ @@ -349,12 +381,12 @@ int32 Operate (int32 MB, int32 AR); /* Restore register state */ +if (devtab_init ()) return SCPE_STOP; /* init tables */ 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 */ @@ -363,14 +395,59 @@ 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? */ +/* Channel breaks (DMA and DMC) */ + +if (chan_req) { /* channel request? */ + int32 i, t, ch, dev, st, end, ad, dmcad; + t_stat r; + for (i = 0, ch = chan_req; ch != 0; i++, ch = ch >> 1) { + if (ch & 1) { /* req on chan i? */ + dev = chan_map[i]; /* get dev for chan */ + if (iotab[dev] == &undio) return SCPE_IERR; + chan_req = chan_req & ~(1 << i); /* clear req */ + if (Q_DMA (i)) st = dma_ad[i]; /* DMA? */ + else { /* DMC */ + dmcad = DMC_BASE + ((i - DMC_V_DMC1) << 1); + st = Read (dmcad); } /* DMC ctrl word */ + ad = st & X_AMASK; /* get curr addr */ + if (st & DMA_IN) { /* input? */ + t = iotab[dev] (ioINA, 0, 0, dev); /* input word */ + if ((t & IOT_SKIP) == 0) return STOP_DMAER; + if (r = (t >> IOT_V_REASON)) return r; + Write (ad, t & DMASK); } /* write to mem */ + else { /* no, output */ + t = iotab[dev] (ioOTA, 0, Read (ad), dev); /* output word */ + if ((t & IOT_SKIP) == 0) return STOP_DMAER; + if (r = (t >> IOT_V_REASON)) return r; } + if (Q_DMA (i)) { /* DMA? */ + dma_ad[i] = (dma_ad[i] & DMA_IN) | ((ad + 1) & X_AMASK); + dma_wc[i] = (dma_wc[i] + 1) & 077777; /* update wc */ + if (dma_wc[i] == 0) { /* done? */ + dma_eor[i] = 1; /* set end of range */ + t = iotab[dev] (ioEND, 0, 0, dev); /* send end range */ + if (r = (t >> IOT_V_REASON)) return r; } } + else { /* DMC */ + st = (st & DMA_IN) | ((ad + 1) & X_AMASK); + Write (dmcad, st); /* update start */ + end = Read (dmcad + 1); /* get end */ + if (((ad ^ end) & X_AMASK) == 0) { /* start == end? */ + t = iotab[dev] (ioEND, 0, 0, dev); /* send end range */ + if (r = (t >> IOT_V_REASON)) return r; } } + } /* end if chan i */ + } /* end for */ + } /* end if chan_req */ + + +/* Interrupts */ + +if ((dev_int & (INT_PENDING | dev_enb)) > 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"); + dev_int = dev_int & ~INT_ON; /* intr off */ MB = 0120000 | M_INT; } /* inst = JST* 63 */ +/* Instruction fetch */ + else { if (sim_brk_summ && sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */ reason = STOP_IBKPT; /* stop simulation */ @@ -378,16 +455,17 @@ else { if (sim_brk_summ && Y = PC; /* set mem addr */ MB = Read (Y); /* fetch instr */ PC = NEWA (Y, Y + 1); /* incr PC */ - dev_ready = dev_ready | INT_NODEF; } + dev_int = dev_int | 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"); } +if (hst_lnt) { /* instr hist? */ + hst_p = (hst_p + 1); /* next entry */ + if (hst_p >= hst_lnt) hst_p = 0; + hst[hst_p].pc = Y | HIST_PC | (C? HIST_C: 0); /* fill slots */ + hst[hst_p].ir = MB; + hst[hst_p].ar = AR; + hst[hst_p].br = BR; + hst[hst_p].xr = XR; } /* Memory reference instructions */ @@ -397,12 +475,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; @@ -423,10 +495,10 @@ case 003: case 023: case 043: case 063: /* ANA */ case 004: case 024: case 044: case 064: /* STA */ if (reason = Ea (MB, &Y)) break; /* eff addr */ if (dp) { /* double prec? */ - if ((Y & 1) == 0) Write (AR, Y); /* if even, store A */ - Write (BR, Y | 1); /* store B */ + if ((Y & 1) == 0) Write (Y, AR); /* if even, store A */ + Write (Y | 1, BR); /* store B */ sc = 0; } - else Write (AR, Y); /* no, store word */ + else Write (Y, AR); /* no, store word */ break; case 005: case 025: case 045: case 065: /* ERA */ @@ -461,7 +533,7 @@ case 007: case 027: case 047: case 067: /* SUB */ 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); + Write (Y, MB); PCQ_ENTRY; PC = NEWA (PC, Y + 1); /* set new PC */ break; @@ -476,20 +548,20 @@ case 011: case 031: case 051: case 071: /* CAS */ 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); + Write (Y, MB); 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 */ + Write (Y, AR); /* 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 */ + Write (Y, XR); /* store XR */ break; case 035: case 075: /* LDX */ @@ -525,35 +597,32 @@ case 017: case 037: case 057: case 077: /* DIV */ /* I/O instructions */ case 014: /* OCP */ - t2 = iotab[MB & DEVMASK] (ioOCP, I_GETFNC (MB), AR); + dev = MB & DEVMASK; + t2 = iotab[dev] (ioOCP, I_GETFNC (MB), AR, dev); reason = t2 >> IOT_V_REASON; - turnoff = 0; break; case 034: /* SKS */ - t2 = iotab[MB & DEVMASK] (ioSKS, I_GETFNC (MB), AR); + dev = MB & DEVMASK; + t2 = iotab[dev] (ioSKS, I_GETFNC (MB), AR, dev); reason = t2 >> IOT_V_REASON; - if (t2 & IOT_SKIP) { /* skip? */ - PC = NEWA (PC, PC + 1); - turnoff = 0; } + if (t2 & IOT_SKIP) PC = NEWA (PC, PC + 1); /* skip? */ break; case 054: /* INA */ + dev = MB & DEVMASK; if (MB & INCLRA) AR = 0; - t2 = iotab[MB & DEVMASK] (ioINA, I_GETFNC (MB), AR); + t2 = iotab[dev] (ioINA, I_GETFNC (MB & ~INCLRA), AR, dev); reason = t2 >> IOT_V_REASON; - if (t2 & IOT_SKIP) { /* skip? */ - PC = NEWA (PC, PC + 1); - turnoff = 0; } + if (t2 & IOT_SKIP) PC = NEWA (PC, PC + 1); /* skip? */ AR = t2 & DMASK; /* data */ break; case 074: /* OTA */ - t2 = iotab[MB & DEVMASK] (ioOTA, I_GETFNC (MB), AR); + dev = MB & DEVMASK; + t2 = iotab[dev] (ioOTA, I_GETFNC (MB), AR, dev); reason = t2 >> IOT_V_REASON; - if (t2 & IOT_SKIP) { /* skip? */ - PC = NEWA (PC, PC + 1); - turnoff = 0; } + if (t2 & IOT_SKIP) PC = NEWA (PC, PC + 1); /* skip? */ break; /* Control */ @@ -571,8 +640,7 @@ case 000: ext = 1; extoff_pending = 0; } /* DXA */ else extoff_pending = 1; } - if (MB & m12) /* RMP */ - dev_ready = dev_ready & ~INT_MPE; + if (MB & m12) CLR_INT (INT_MPE); /* RMP */ if (MB & m11) { /* SCA, INK */ if (MB & m15) /* INK */ AR = (C << 15) | (dp << 14) | (pme << 13) | (sc & 037); @@ -594,9 +662,9 @@ case 000: BR = AR; AR = sc; } if (MB & m8) /* ENB */ - dev_ready = (dev_ready | INT_ON) & ~INT_NODEF; + dev_int = (dev_int | INT_ON) & ~INT_NODEF; if (MB & m7) /* INH */ - dev_ready = dev_ready & ~INT_ON; + dev_int = dev_int & ~INT_ON; break; /* Shift @@ -841,15 +909,17 @@ else { /* non-extend */ 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 (hst_lnt) { /* history? */ + hst[hst_p].pc = hst[hst_p].pc | HIST_EA; + hst[hst_p].ea = Y; + hst[hst_p].opnd = Read (Y); } if (i >= ind_max) return STOP_IND; /* too many ind? */ return SCPE_OK; } /* Write memory */ -void Write (int32 val, int32 addr) +void Write (int32 addr, int32 val) { if (((addr == 0) || (addr >= 020)) && MEM_ADDR_OK (addr)) M[addr] = val; @@ -878,10 +948,34 @@ return r; /* Unimplemented I/O device */ -int32 undio (int32 op, int32 fnc, int32 val) +int32 undio (int32 op, int32 fnc, int32 val, int32 dev) { return ((stop_dev << IOT_V_REASON) | val); } + +/* DMA control */ + +int32 dmaio (int32 inst, int32 fnc, int32 dat, int32 dev) +{ +int32 ch = (fnc - 1) & 03; + +switch (inst) { /* case on opcode */ +case ioOCP: /* OCP */ + if ((fnc >= 001) && (fnc <= 004)) { /* load addr ctr */ + dma_ad[ch] = dat; + dma_wc[ch] = 0; + dma_eor[ch] = 0; } + else if ((fnc >= 011) && (fnc <= 014)) /* load range ctr */ + dma_wc[ch] = (dma_wc[ch] | dat) & 077777; + else return IOBADFNC (dat); /* undefined */ + break; +case ioINA: /* INA */ + if ((fnc >= 011) && (fnc <= 014)) { + if (dma_eor[ch]) return dat; /* end range? nop */ + return IOSKIP (0100000 | dma_wc[ch]); } /* return range */ + else return IOBADFNC (dat); } +return dat; +} /* Undefined operate instruction. This code is reached when the opcode does not correspond to a standard operate instruction. @@ -1027,12 +1121,16 @@ return ARx; t_stat cpu_reset (DEVICE *dptr) { +int32 i; + 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; +dev_int = dev_int & ~INT_PENDING; +dev_enb = 0; +for (i = 0; i < DMA_MAX; i++) dma_ad[i] = dma_wc[i] = dma_eor[i] = 0; +chan_req = 0; pcq_r = find_reg ("PCQ", NULL, dptr); if (pcq_r) pcq_r->qptr = 0; else return SCPE_IERR; @@ -1086,3 +1184,216 @@ MEMSIZE = val; for (i = MEMSIZE; i < MAXMEMSIZE; i++) M[i] = 0; return SCPE_OK; } + +t_stat cpu_set_nchan (UNIT *uptr, int32 val, char *cptr, void *desc) +{ +uint32 i, newmax; +t_stat r; + +if (cptr == NULL) return SCPE_ARG; +newmax = get_uint (cptr, 10, DMA_MAX, &r); /* get new max */ +if ((r != SCPE_OK) || (newmax == dma_nch)) return r; /* err or no chg? */ +dma_nch = newmax; /* set new max */ +for (i = newmax; i = DMA_MAX)) return SCPE_IERR; +fputs ((dma_ad[val] & DMA_IN)? "Input": "Output", st); +fprintf (st, ", addr = %06o, count = %06o, ", dma_ad[val] & X_AMASK, dma_wc[val]); +fprintf (st, "end of range %s\n", (dma_eor[val]? "set": "clear")); +return SCPE_OK; +} + +/* Set I/O device to IOBUS / DMA channel / DMC channel */ + +t_stat io_set_iobus (UNIT *uptr, int32 val, char *cptr, void *desc) +{ +DEVICE *dptr; +DIB *dibp; + +if (val || cptr || (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; +dibp->chan = 0; +return SCPE_OK; +} + +t_stat io_set_dma (UNIT *uptr, int32 val, char *cptr, void *desc) +{ +DEVICE *dptr; +DIB *dibp; +uint32 newc; +t_stat r; + +if ((cptr == NULL) || (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; +if (dma_nch == 0) return SCPE_NOFNC; +newc = get_uint (cptr, 10, DMA_MAX, &r); /* get new */ +if ((r != SCPE_OK) || (newc == 0) || (newc > dma_nch)) return SCPE_ARG; +dibp->chan = (newc - DMA_MIN) + DMA_V_DMA1 + 1; /* store */ +return SCPE_OK; +} + +t_stat io_set_dmc (UNIT *uptr, int32 val, char *cptr, void *desc) +{ +DEVICE *dptr; +DIB *dibp; +uint32 newc; +t_stat r; + +if ((cptr == NULL) || (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; +if (!(cpu_unit.flags & UNIT_DMC)) return SCPE_NOFNC; +newc = get_uint (cptr, 10, DMC_MAX, &r); /* get new */ +if ((r != SCPE_OK) || (newc == 0)) return SCPE_ARG; +dibp->chan = (newc - DMC_MIN) + DMC_V_DMC1 + 1; /* store */ +return SCPE_OK; +} + +/* Show channel configuration */ + +t_stat io_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; +if (dibp->chan == 0) fprintf (st, "IO bus"); +else if (dibp->chan < (DMC_V_DMC1 + 1)) + fprintf (st, "DMA channel %d", dibp->chan); +else fprintf (st, "DMC channel %d", dibp->chan - DMC_V_DMC1); +return SCPE_OK; +} + +/* Set up I/O dispatch and channel maps */ + +t_bool devtab_init (void) +{ +DEVICE *dptr; +DIB *dibp; +uint32 i, j, dno, chan; + +for (i = 0; i < DEV_MAX; i++) iotab[i] = NULL; +for (i = 0; i < (DMA_MAX + DMC_MAX); i++) chan_map[i] = 0; +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->dev; /* device number */ + for (j = 0; j < dibp->num; j++) { /* repeat for slots */ + if (iotab[dno + j]) { /* conflict? */ + printf ("%s device number conflict, devno = %02o\n", sim_dname (dptr), dno + j); + if (sim_log) fprintf (sim_log, + "%s device number conflict, devno = %02o\n", sim_dname (dptr), dno + j); + return TRUE; } + iotab[dno + j] = dibp->io; /* set I/O routine */ + } /* end for */ + if (dibp->chan) { /* DMA/DMC? */ + chan = dibp->chan - 1; + if ((chan >= 0) && (chan < DMC_V_DMC1) && (chan >= dma_nch)) { + printf ("%s configured for DMA channel %d\n", sim_dname (dptr), chan + 1); + if (sim_log) fprintf (sim_log, + "%s configured for DMA channel %d\n", sim_dname (dptr), chan + 1); + return TRUE; } + if ((chan >= DMC_V_DMC1) && !(cpu_unit.flags & UNIT_DMC)) { + printf ("%s configured for DMC, option disabled\n", sim_dname (dptr)); + if (sim_log) fprintf (sim_log, + "%s configured for DMC, option disabled\n", sim_dname (dptr)); + return TRUE; } + if (chan_map[chan]) { /* channel conflict? */ + printf ("%s DMA/DMC channel conflict, devno = %02o\n", sim_dname (dptr), dno); + if (sim_log) fprintf (sim_log, + "%s DMA/DMC channel conflict, devno = %02o\n", sim_dname (dptr), dno); + return TRUE; } + chan_map[chan] = dno; } /* channel back map */ + } /* end for */ +for (i = 0; i < DEV_MAX; i++) { /* fill in blanks */ + if (iotab[i] == NULL) iotab[i] = &undio; } +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 < hst_lnt; i++) hst[i].pc = 0; + hst_p = 0; + return SCPE_OK; } +lnt = (int32) get_uint (cptr, 10, HIST_MAX, &r); +if ((r != SCPE_OK) || (lnt && (lnt < HIST_MIN))) return SCPE_ARG; +hst_p = 0; +if (hst_lnt) { + free (hst); + hst_lnt = 0; + hst = NULL; } +if (lnt) { + hst = calloc (sizeof (struct InstHistory), lnt); + if (hst == NULL) return SCPE_MEM; + hst_lnt = lnt; } +return SCPE_OK; +} + +/* Show history */ + +t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, void *desc) +{ +int32 cr, k, di, op; +t_value sim_eval; +struct InstHistory *h; +extern t_stat fprint_sym (FILE *ofile, t_addr addr, t_value *val, + UNIT *uptr, int32 sw); +static uint8 has_opnd[16] = { + 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1 }; + +if (hst_lnt == 0) return SCPE_NOFNC; /* enabled? */ +fprintf (st, "PC C A B X ea IR\n\n"); +di = hst_p; /* work forward */ +for (k = 0; k < hst_lnt; k++) { /* print specified */ + h = &hst[(++di) % hst_lnt]; /* entry pointer */ + if (h->pc & HIST_PC) { /* instruction? */ + cr = (h->pc & HIST_C)? 1: 0; /* carry */ + fprintf (st, "%05o %o %06o %06o %06o ", + h->pc & X_AMASK, cr, h->ar, h->br, h->xr); + if (h->pc & HIST_EA) fprintf (st, "%05o ", h->ea); + else fprintf (st, " "); + sim_eval = h->ir; + if ((fprint_sym (st, h->pc & X_AMASK, &sim_eval, &cpu_unit, SWMASK ('M'))) > 0) + fprintf (st, "(undefined) %06o", h->ir); + op = I_GETOP (h->ir) & 017; /* base op */ + if (has_opnd[op]) fprintf (st, " [%06o]", h->opnd); + fputc ('\n', st); /* end line */ + } /* end else instruction */ + } /* end for */ +return SCPE_OK; +} diff --git a/H316/h316_defs.h b/H316/h316_defs.h index 240174c2..d1593b0f 100644 --- a/H316/h316_defs.h +++ b/H316/h316_defs.h @@ -23,9 +23,13 @@ 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. + 24-Oct-03 RMS Added DMA/DMC support 25-Apr-03 RMS Revised for extended file support */ +#ifndef _H316_DEFS_H_ +#define _H316_DEFS_H_ 0 + #include "sim_defs.h" /* simulator defns */ /* Simulator stop codes */ @@ -35,6 +39,10 @@ #define STOP_HALT 3 /* HALT */ #define STOP_IBKPT 4 /* breakpoint */ #define STOP_IND 5 /* indirect loop */ +#define STOP_DMAER 6 /* DMA error */ +#define STOP_MTWRP 7 /* MT write protected */ +#define STOP_DPOVR 8 /* DP write overrun */ +#define STOP_DPFMT 9 /* DP invalid format */ /* Memory */ @@ -56,10 +64,14 @@ /* CPU options */ +#define UNIT_V_MSIZE (UNIT_V_UF + 0) /* dummy mask */ #define UNIT_V_EXT (UNIT_V_UF + 1) /* extended mem */ #define UNIT_V_HSA (UNIT_V_UF + 2) /* high speed arith */ +#define UNIT_V_DMC (UNIT_V_UF + 3) /* DMC */ +#define UNIT_MSIZE (1u << UNIT_V_MSIZE) #define UNIT_EXT (1u << UNIT_V_EXT) #define UNIT_HSA (1u << UNIT_V_HSA) +#define UNIT_DMC (1u << UNIT_V_DMC) /* Instruction format */ @@ -84,8 +96,42 @@ #define ioSKS 1 /* skip if set */ #define ioINA 2 /* input to A */ #define ioOTA 3 /* output from A */ +#define ioEND 4 /* channel end */ -/* I/O devices */ +/* Device information block */ + +struct h316_dib { + uint32 dev; /* device number */ + uint32 chan; /* dma/dmc channel */ + uint32 num; /* number of slots */ + int32 (*io) (int32 inst, int32 fnc, int32 dat, int32 dev); }; + +typedef struct h316_dib DIB; + +/* DMA/DMC channel numbers */ + +#define IOBUS 0 /* IO bus */ +#define DMA_MIN 1 /* 4 DMA channels */ +#define DMA_MAX 4 +#define DMC_MIN 1 /* 16 DMC channels */ +#define DMC_MAX 16 + +#define DMA1 (DMA_MIN) +#define DMC1 (DMA_MAX+DMC_MIN) + +/* DMA/DMC bit assignments in channel request word */ + +#define DMA_V_DMA1 0 /* DMA channels */ +#define DMC_V_DMC1 4 /* DMC channels */ +#define SET_CH_REQ(x) chan_req = chan_req | (1 << (x)) +#define Q_DMA(x) (((x) >= 0) && ((x) < DMC_V_DMC1)) + +/* DMA/DMC definitions */ + +#define DMA_IN 0100000 /* input flag */ +#define DMC_BASE 020 /* DMC memory base */ + +/* I/O device codes */ #define PTR 001 /* paper tape reader */ #define PTP 002 /* paper tape punch */ @@ -93,11 +139,11 @@ #define TTY 004 /* console */ #define CDR 005 /* card reader */ #define MT 010 /* mag tape data */ -#define KEYS 020 /* keys (CPU) */ +#define CLK_KEYS 020 /* clock/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 */ +#define DEV_MAX 64 /* Interrupt flags, definitions correspond to SMK bits */ @@ -119,7 +165,7 @@ #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 IORETURN(f,v) (((f)? (v): SCPE_OK) << IOT_V_REASON) #define IOBADFNC(x) (((stop_inst) << IOT_V_REASON) | (x)) #define IOSKIP(x) (IOT_SKIP | (x)) @@ -137,8 +183,17 @@ #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) +#define SET_INT(x) dev_int = dev_int | (x) +#define CLR_INT(x) dev_int = dev_int & ~(x) +#define TST_INT(x) ((dev_int & (x)) != 0) +#define CLR_ENB(x) dev_enb = dev_enb & ~(x) +#define TST_INTREQ(x) ((dev_int & dev_enb & (x)) != 0) + +/* Prototypes */ + +t_stat io_set_iobus (UNIT *uptr, int32 val, char *cptr, void *desc); +t_stat io_set_dma (UNIT *uptr, int32 val, char *cptr, void *desc); +t_stat io_set_dmc (UNIT *uptr, int32 val, char *cptr, void *desc); +t_stat io_show_chan (FILE *st, UNIT *uptr, int32 val, void *desc); + +#endif diff --git a/H316/h316_doc.txt b/H316/h316_doc.txt index dc56fe0f..5954577b 100644 --- a/H316/h316_doc.txt +++ b/H316/h316_doc.txt @@ -1,7 +1,7 @@ To: Users From: Bob Supnik Subj: H316 Simulator Usage -Date: 15-Jul-2003 +Date: 15-Nov-2003 COPYRIGHT NOTICE @@ -41,15 +41,20 @@ The H316 requires the following 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/h316/ h316_defs.h h316_cpu.c + h316_fhd.c h316_lp.c + h316_mt.c + h316_dp.c h316_stddev.c h316_sys.c @@ -66,6 +71,9 @@ 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 +FHD 4400 fixed head disk +DP 4623/4653/4720 disk pack controller with eight drives +MT 4100 seven track magtape with four drives The H316/H516 simulator implements several unique stop conditions: @@ -73,12 +81,19 @@ The H316/H516 simulator implements several unique stop conditions: - reference to an undefined I/O device, and STOP_DEV is set - more than INDMAX indirect references are detected during memory reference address decoding + - DMA/DMC direction does not agree with I/O device operation + - a write operation is initiated on a write locked magtape + unit (hangs the real system) + - a disk write overruns the specified record size (destroys + the rest of the track on the real system) + - a disk track has an illegal format The H316/H516 loader is not implemented. 2.1 CPU -CPU options include choice of instruction set and memory size. +CPU options include choice of instruction set, memory size, DMC option, +and number of DMA channels. SET CPU HSA high speed arithmetic instructions SET CPU NOHSA no high speed arithmetic instructions @@ -88,10 +103,19 @@ CPU options include choice of instruction set and memory size. SET CPU 16K set memory size = 16K SET CPU 24K set memory size = 24K SET CPU 32K set memory size = 32K + SET CPU DMC enable DMC option + SET CPU NODMC disable DMC option + SET CPU DMA=n set number of DMA channels to n (0-4) 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. +portion of memory is lost. Initial memory size is 32K. The HSA and DMC +options are enabled, and four DMA channels are configured. + +The CPU includes special show commands to display the state of the DMA +channels: + + SHOW CPU DMAn show DMA channel n CPU registers include the visible state of the processor as well as the control registers for the interrupt system. @@ -114,6 +138,10 @@ control registers for the interrupt system. INTREQ 16 interrupt requests DEVRDY 16 device ready flags (read only) DEVENB 16 device interrupt enable flags (read only) + CHREQ 20 DMA/DMC channel requests + DMAAD[0:3] 16 DMA channel current address, channels 1-4 + DMAWC[0:3] 15 DMA channel word count, channels 1-4 + DMAEOR[0:3] 1 DMA end of range flag, channels 1-4 STOP_INST 1 stop on undefined instruction STOP_DEV 1 stop on undefined device INDMAX 1 indirect address limit @@ -230,12 +258,21 @@ The clock implements these registers: 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) +2.3 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 can be connected to the IO bus, a DMC channel, or +a DMA channel: + + SET LPT IOBUS connect to IO bus + SET LPT DMC=n connect to DMC channel n (1-16) + SET LPT DMA=n connect to DMA channel n (1-4) + +By default, the line printer is connected to the IO bus. + The line printer implements these registers: name size comments @@ -243,8 +280,10 @@ The line printer implements these registers: 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 + RDY 1 ready flag + EOR 1 (DMA/DMC) end of range flag + DMA 1 transfer using DMA/DMC INTREQ 1 device interrupt request ENABLE 1 device interrupt enable SVCST 2 service state @@ -265,7 +304,207 @@ Error handling is as follows: OS I/O error x report error and stop -2.3 Symbolic Display and Input +2.4 4400 Fixed Head Disk (FHD) + +Fixed head disk options include the ability to set the number of +surfaces to a fixed value between 1 and 16, or to autosize the number +of surfaces from the attached file: + + SET FHD 1S one surface (98K) + SET FHD 2S two platters (196K) + : + SET FHD 16S sixteen surfaces (1568K) + SET FHD AUTOSIZE autosized on attach + +The default is one surface. + +The fixed head disk can be connected to the IO bus, a DMC channel, or +a DMA channel: + + SET FHD IOBUS connect to IO bus + SET FHD DMC=n connect to DMC channel n (1-16) + SET FHD DMA=n connect to DMA channel n (1-4) + +By default, the fixed head disk is connected to the IO bus. + + +The fixed head disk implements these registers: + + name size comments + + CW1 16 control word 1 (read write, surface, track) + CW2 16 control word 2 (character address) + BUF 16 data buffer + BUSY 1 controller busy flag + RDY 1 transfer ready flag + DTE 1 data transfer error flag + ACE 1 access error flag + EOR 1 (DMA/DMC) end of range + DMA 1 transfer using DMA/DMC + CSUM 1 transfer parity checksum + INTREQ 1 device interrupt request + ENABLE 1 device interrupt enable + TIME 24 delay between words + STOP_IOE 1 stop on I/O error + +The fixed head disk does not support 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.5 4100 7-track 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 be set ONLINE or OFFLINE, and WRITEENABLED or write LOCKED. + +The magtape controller can be connected to the IO bus, a DMC channel, or +a DMA channel: + + SET MT IOBUS connect to IO bus + SET MT DMC=n connect to DMC channel n (1-16) + SET MT DMA=n connect to DMA channel n (1-4) + +By default, the magtape controller is connected to the IO bus. + +The magnetic tape controller implements these registers: + + name size comments + + BUF 16 data buffer + USEL 2 unit select + BUSY 1 controller busy flag + RDY 1 transfer ready flag + ERR 1 error flag + EOF 1 end of file flag + EOR 1 (DMA/DMC) end of range + DMA 1 transfer using DMA/DMC + MDIRQ 1 motion done interrupt request + INTREQ 1 device interrupt request + ENABLE 1 device interrupt enable + DBUF[0:65535] 8 transfer buffer + BPTR 17 transfer buffer pointer + BMAX 17 transfer size (reads) + CTIME 24 start/stop time + XTIME 24 delay between words + POS[0:3] 32 position, units 0-3 + 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 bad tape + + OS I/O error parity error; if STOP_IOE, stop + +2.6 4623/4651/4720 Disk Packs (DP) + +The disk controller can be configured as a 4623, supporting 10 surface +disk packs; a 4651, supporting 2 surface disk packs; or a 4720, supporting +20 surface disk packs: + + SET DP 4623 controller is 4623 + SET DP 4651 controller is 4651 + SET DP 4720 controller is 4720 + +The default is 4651. All disk packs on the controller must be of the +same type. Units can be set ONLINE or OFFLINE, and WRITEENABLED or +write LOCKED. + +The disk pack controller can be connected to a DMC channel or a DMA +channel; it cannot be connected to the IO bus: + + SET DP DMC=n connect to DMC channel n (1-16) + SET DP DMA=n connect to DMA channel n (1-4) + +The disk pack controller supports variable track formatting. Each track +can contain between 1 and 103 records, with a minimum size of 1 word and +a maximum size of 1893 words. Record addresses are unconstrained. The +simulator provides a command to perform a simple, fixed record size format +of a new disk: + + SET DPn FORMAT=k format unit n with k words per record + SET -R DPn FORMAT=k format unit n with k records per track + +Record addresses can either be geometric (cylinder/track/sector) or simple +sequential starting from 0: + + SET DPn FORMAT=k format with geometric record addresses + SET -S DPn FORMAT=k format with sequential record addresses + +Geometric address have the cylinder number in bits<1:8>, the head number in +bits<9:13>, and the sector number in bits <14:16>. + +A summary of the current format, and its validity, can be obtained with +the command: + + SHOW DPn FORMAT display format of unit n + +To accomodate the variable formatting, each track is allocated 2048 words +in the data file. A record consists of a three word header, the data, and +a five word trailer: + + word 0 record length in words, not including header/trailer + word 1 record address + word 2 number of extension words used (0-4) + word 3 start of data record + word 3+n-1 end of data record + word 3+n..7+n record trailer: up to four extension words, + plus checksum + +A record can "grow" by up to four words without disrupting the track formatting; +writing more than four extra words destroys the formatting of the rest of the +track and causes a simulator error. + +The disk pack controller implements these registers: + + name size comments + + STA 16 status + BUF 16 data buffer + FNC 4 controller function + CW1 16 command word 1 + CW2 16 command word 2 + CSUM 16 record checksum + BUSY 1 controller busy + RDY 1 transfer ready + EOR 1 (DMA/DMC) end of range + DEFINT 1 seek deferred interrupt pending + INTREQ 1 interrupt request + ENABLE 1 interrupt enable + TBUF[0:2047] 16 track buffer + RPTR 11 pointer to start of record in track buffer + WPTR 11 pointer to current word in record + BCTR 15 bit counter for formatting + STIME 24 seek time, per cylinder + XTIME 24 transfer time, per word + BTIME 24 controller busy time + +Error handling is as follows: + + error processed as + + not attached pack off line; if STOP_IOE, stop + + end of file ignored + + OS I/O error data error; if STOP_IOE, stop + +2.7 Symbolic Display and Input The H316/H516 simulator implements symbolic display and input. Display is controlled by command line switches: diff --git a/H316/h316_dp.c b/H316/h316_dp.c new file mode 100644 index 00000000..7f865c76 --- /dev/null +++ b/H316/h316_dp.c @@ -0,0 +1,975 @@ +/* h316_dp.c: Honeywell 4623, 4651, 4720 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. + + dp 4623 disk subsystem + 4651 disk subsystem + 4720 disk subsystem + + The Honeywell disks have the unique characteristic of supporting variable + formatting, on a per track basis. To accomodate this, each track is + simulated as 2048 words, divided into records. (2048 words accomodates + the largest record of 1891 + 8 overhead words.) A record is structured + as follows: + + word 0 record length n (0 = end of track) + word 1 record address (16b, uninterpreted by the simulator) + word 2 record extension (0 to 4 words of permitted 'overwrite') + word 3 first data word + : + word 3+n-1 last data word + word 3+n checksum word + word 4+n first extension word + : + word 7+n fourth extension word + word 8+n start of next record + + Formatting is done in two ways. The SET DPn FORMAT=k command formats + unit n with k records per track, each record having the maximum allowable + record size and a standard record address; or with k words per record. + Alternately, the simulator allows programmatic formating. When a track + is formated, the program supplies record parameters as follows: + + word 0 record address + words 1-n data words + word n+1 gap size in bits + + To make this work, the simulator tracks the consumption of bits in the + track, against the track capacity in bits. Bit consumption is: + + 16.5 * 16 for overhead (including address and checksum) + n * 16 for data + 'gap' for gap, which must be at least 5% of the record length +*/ + +#include "h316_defs.h" +#include + +#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 /* actual cylinder */ +#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write prot */ +#define DP_TRKLEN 2048 /* track length, words */ +#define DP_NUMDRV 8 /* max # drives */ +#define DP_NUMTYP 3 /* # controller types */ + +/* Record format */ + +#define REC_LNT 0 /* length (unextended) */ +#define REC_ADDR 1 /* address */ +#define REC_EXT 2 /* extension (0-4) */ +#define REC_DATA 3 /* start of data */ +#define REC_OVHD 8 /* overhead words */ +#define REC_MAXEXT 4 /* maximum extension */ +#define REC_OVHD_WRDS 16.5 /* 16.5 words */ +#define REC_OVHD_BITS ((16 * 16) + 8) + +/* Status word, ^ = dynamic */ + +#define STA_BUSY 0100000 /* busy */ +#define STA_RDY 0040000 /* ready */ +#define STA_ADRER 0020000 /* address error */ +#define STA_FMTER 0010000 /* format error */ +#define STA_HNLER 0004000 /* heads not loaded (NI) */ +#define STA_OFLER 0002000 /* offline */ +#define STA_SEKER 0001000 /* seek error */ +#define STA_MBZ 0000700 +#define STA_WPRER 0000040 /* write prot error */ +#define STA_UNSER 0000020 /* unsafe */ +#define STA_CSMER 0000010 /* checksum error */ +#define STA_DTRER 0000004 /* transfer rate error */ +#define STA_ANYER 0000002 /* any error^ */ +#define STA_EOR 0000001 /* end of record */ +#define STA_ALLERR (STA_ADRER|STA_FMTER|STA_HNLER|STA_OFLER|STA_SEKER|\ + STA_WPRER|STA_UNSER|STA_DTRER) + +/* Functions */ + +#define FNC_SK0 0000 /* recalibrate */ +#define FNC_SEEK 0001 /* seek */ +#define FNC_RCA 0002 /* read current */ +#define FNC_UNL 0004 /* unload */ +#define FNC_FMT 0005 /* format */ +#define FNC_RW 0006 /* read/write */ +#define FNC_STOP 0010 /* stop format */ +#define FNC_RDS 0011 /* read status */ +#define FNC_DMA 0013 /* DMA/DMC */ +#define FNC_AKI 0014 /* acknowledge intr */ +#define FNC_IOBUS 0017 /* IO bus */ +#define FNC_2ND 0020 /* second state */ +#define FNC_3RD 0040 /* third state */ +#define FNC_4TH 0060 /* fourth state */ +#define FNC_5TH 0100 /* fifth state */ + +/* Command word 1 */ + +#define CW1_RW 0100000 /* read/write */ +#define CW1_DIR 0000400 /* seek direction */ +#define CW1_V_UNIT 11 /* unit select */ +#define CW1_V_HEAD 6 /* head select */ +#define CW1_V_OFFS 0 /* seek offset */ +#define CW1_GETUNIT(x) (((x) >> CW1_V_UNIT) & dp_tab[dp_ctype].umsk) +#define CW1_GETHEAD(x) (((x) >> CW1_V_HEAD) & dp_tab[dp_ctype].hmsk) +#define CW1_GETOFFS(x) (((x) >> CW1_V_OFFS) & dp_tab[dp_ctype].cmsk) + +/* OTA states */ + +#define OTA_NOP 0 /* normal */ +#define OTA_CW1 1 /* expecting CW1 */ +#define OTA_CW2 2 /* expecting CW2 */ + +/* Transfer state */ + +#define XIP_UMSK 007 /* unit mask */ +#define XIP_SCHED 010 /* scheduled */ +#define XIP_WRT 020 /* write */ +#define XIP_FMT 040 /* format */ + +/* The H316/516 disk emulator supports three disk controllers: + + controller units cylinders surfaces data words per track + + 4651 4 203 2 1908.25 + 4623 8 203 10 1816.5 + 4720 8 203 20 1908.25 + + Disk types may not be intermixed on the same controller. +*/ + +#define TYPE_4651 0 +#define UNIT_4651 4 +#define CYL_4651 203 +#define SURF_4651 2 +#define WRDS_4651 1908.25 +#define UMSK_4651 0003 +#define HMSK_4651 0001 +#define CMSK_4651 0377 +#define CAP_4651 (CYL_4651*SURF_4651*DP_TRKLEN) + +#define TYPE_4623 1 +#define UNIT_4623 8 +#define CYL_4623 203 +#define SURF_4623 10 +#define WRDS_4623 1816.5 +#define UMSK_4623 0007 +#define HMSK_4623 0017 +#define CMSK_4623 0377 +#define CAP_4623 (CYL_4623*SURF_4623*DP_TRKLEN) + +#define TYPE_4720 2 +#define UNIT_4720 8 +#define CYL_4720 203 +#define SURF_4720 20 +#define WRDS_4720 1908.25 +#define UMSK_4720 0007 +#define HMSK_4720 0037 +#define CMSK_4720 0377 +#define CAP_4720 (CYL_4720*SURF_4720*DP_TRKLEN) + +struct drvtyp { + char *name; + uint32 numu; + uint32 cyl; + uint32 surf; + uint32 cap; + uint32 umsk; + uint32 hmsk; + uint32 cmsk; + float wrds; }; + +#define DP_DRV(d) \ + #d, \ + UNIT_##d, CYL_##d, SURF_##d, CAP_##d, \ + UMSK_##d, HMSK_##d, CMSK_##d, WRDS_##d + +static struct drvtyp dp_tab[] = { + { DP_DRV (4651) }, + { DP_DRV (4623) }, + { DP_DRV (4720) } }; + +extern int32 dev_int, dev_enb, chan_req; +extern int32 stop_inst; +extern uint32 dma_ad[DMA_MAX]; +extern int32 sim_switches; + +uint32 dp_cw1 = 0; /* cmd word 1 */ +uint32 dp_cw2 = 0; /* cmd word 2 */ +uint32 dp_fnc = 0; /* saved function */ +uint32 dp_buf = 0; /* buffer */ +uint32 dp_otas = 0; /* state */ +uint32 dp_sta = 0; /* status */ +uint32 dp_defint = 0; /* deferred seek int */ +uint32 dp_ctype = TYPE_4651; /* controller type */ +uint32 dp_dma = 0; /* DMA/DMC */ +uint32 dp_eor = 0; /* end of range */ +uint32 dp_xip = 0; /* transfer in prog */ +uint32 dp_csum = 0; /* parity checksum */ +uint32 dp_rptr = 0; /* start of record */ +uint32 dp_wptr = 0; /* word ptr in record */ +uint32 dp_bctr = 0; /* format bit cntr */ +uint32 dp_gap = 0; /* format gap size */ +uint32 dp_stopioe = 1; /* stop on error */ +int32 dp_stime = 1000; /* seek per cylinder */ +int32 dp_xtime = 10; /* xfer per word */ +int32 dp_btime = 30; /* busy time */ +uint16 dpxb[DP_TRKLEN]; /* track buffer */ + +int32 dpio (int32 inst, int32 fnc, int32 dat, int32 dev); +t_stat dp_svc (UNIT *uptr); +t_stat dp_reset (DEVICE *dptr); +t_stat dp_attach (UNIT *uptr, char *cptr); +t_stat dp_settype (UNIT *uptr, int32 val, char *cptr, void *desc); +t_stat dp_showtype (FILE *st, UNIT *uptr, int32 val, void *desc); +t_stat dp_go (uint32 dma); +t_stat dp_go1 (uint32 dat); +t_stat dp_go2 (uint32 dat); +t_stat dp_rdtrk (UNIT *uptr, uint16 *buf, uint32 cyl, uint32 hd); +t_stat dp_wrtrk (UNIT *uptr, uint16 *buf, uint32 cyl, uint32 hd); +t_bool dp_findrec (uint32 addr); +t_stat dp_wrwd (UNIT *uptr, uint32 dat); +t_stat dp_wrdone (UNIT *uptr, uint32 flg); +t_stat dp_done (uint32 req, uint32 f); +t_stat dp_setformat (UNIT *uptr, int32 val, char *cptr, void *desc); +t_stat dp_showformat (FILE *st, UNIT *uptr, int32 val, void *desc); + +/* 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 = { DP, DMC1, 1, &dpio }; + +UNIT dp_unit[] = { + { UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ + UNIT_ROABLE, CAP_4651) }, + { UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ + UNIT_ROABLE, CAP_4651) }, + { UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ + UNIT_ROABLE, CAP_4651) }, + { UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ + UNIT_ROABLE, CAP_4651) }, + { UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ + UNIT_ROABLE, CAP_4651) }, + { UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ + UNIT_ROABLE, CAP_4651) }, + { UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ + UNIT_ROABLE, CAP_4651) }, + { UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ + UNIT_ROABLE, CAP_4651) } }; + +REG dp_reg[] = { + { ORDATA (STA, dp_sta, 16) }, + { ORDATA (BUF, dp_buf, 16) }, + { ORDATA (FNC, dp_fnc, 4) }, + { ORDATA (CW1, dp_cw1, 16) }, + { ORDATA (CW2, dp_cw2, 16) }, + { ORDATA (CSUM, dp_csum, 16) }, + { FLDATA (BUSY, dp_sta, 15) }, + { FLDATA (RDY, dp_sta, 14) }, + { FLDATA (EOR, dp_eor, 0) }, + { FLDATA (DEFINT, dp_defint, 0) }, + { FLDATA (INTREQ, dev_int, INT_V_DP) }, + { FLDATA (ENABLE, dev_enb, INT_V_DP) }, + { BRDATA (TBUF, dpxb, 8, 16, DP_TRKLEN) }, + { ORDATA (RPTR, dp_rptr, 11), REG_RO }, + { ORDATA (WPTR, dp_wptr, 11), REG_RO }, + { ORDATA (BCTR, dp_bctr, 15), REG_RO }, + { ORDATA (GAP, dp_gap, 16), REG_RO }, + { DRDATA (STIME, dp_stime, 24), REG_NZ + PV_LEFT }, + { DRDATA (XTIME, dp_xtime, 24), REG_NZ + PV_LEFT }, + { DRDATA (BTIME, dp_btime, 24), REG_NZ + PV_LEFT }, + { FLDATA (CTYPE, dp_ctype, 0), REG_HRO }, + { URDATA (UCYL, dp_unit[0].CYL, 10, 8, 0, + DP_NUMDRV, PV_LEFT | REG_HRO) }, + { URDATA (UFNC, dp_unit[0].FNC, 8, 7, 0, + DP_NUMDRV, REG_HRO) }, + { URDATA (CAPAC, dp_unit[0].capac, 10, T_ADDR_W, 0, + DP_NUMDRV, PV_LEFT | REG_HRO) }, + { ORDATA (OTAS, dp_otas, 2), REG_HRO }, + { ORDATA (XIP, dp_xip, 6), REG_HRO }, + { ORDATA (CHAN, dp_dib.chan, 5), REG_HRO }, + { FLDATA (STOP_IOE, dp_stopioe, 0) }, + { NULL } }; + +MTAB dp_mod[] = { + { UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL }, + { UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL }, + { MTAB_XTD | MTAB_VDV, TYPE_4623, NULL, "4623", + &dp_settype, NULL, NULL }, + { MTAB_XTD | MTAB_VDV, TYPE_4651, NULL, "4651", + &dp_settype, NULL, NULL }, + { MTAB_XTD | MTAB_VDV, TYPE_4720, NULL, "4720", + &dp_settype, NULL, NULL }, + { MTAB_XTD | MTAB_VDV, 0, "TYPE", NULL, + NULL, &dp_showtype, NULL }, + { MTAB_XTD|MTAB_VDV, 0, NULL, "DMC", + &io_set_dmc, NULL, NULL }, + { MTAB_XTD|MTAB_VDV, 0, NULL, "DMA", + &io_set_dma, NULL, NULL }, + { MTAB_XTD|MTAB_VDV, 0, "CHANNEL", NULL, + NULL, &io_show_chan, NULL }, + { MTAB_XTD|MTAB_VUN|MTAB_NMO, 0, "FORMAT", "FORMAT", + &dp_setformat, &dp_showformat, NULL }, + { 0 } }; + +DEVICE dp_dev = { + "DP", dp_unit, dp_reg, dp_mod, + DP_NUMDRV, 8, 24, 1, 8, 16, + NULL, NULL, &dp_reset, + NULL, &dp_attach, NULL, + &dp_dib, DEV_DISABLE }; + +/* IOT routines */ + +int32 dpio (int32 inst, int32 fnc, int32 dat, int32 dev) +{ +int32 ch = dp_dib.chan - 1; /* DMA/DMC chan */ +int32 u; +UNIT *uptr; + +switch (inst) { /* case on opcode */ +case ioOCP: /* OCP */ + switch (fnc) { /* case on function */ + case FNC_SK0: case FNC_SEEK: case FNC_RCA: /* data transfer */ + case FNC_UNL: case FNC_FMT: case FNC_RW: + dp_go (fnc); /* if !busy, start */ + break; + case FNC_STOP: /* stop transfer */ + if (dp_xip) { /* transfer in prog? */ + uptr = dp_dev.units + (dp_xip & XIP_UMSK); /* get unit */ + sim_cancel (uptr); /* stop operation */ + if (dp_xip & (XIP_WRT|XIP_FMT)) /* write or format? */ + dp_wrdone (uptr, /* write track */ + ((dp_xip & XIP_FMT) && /* check fmt state */ + (uptr->FNC != (FNC_FMT|FNC_2ND)))? + STA_DTRER: 0); + else dp_done (1, dp_csum? STA_CSMER: 0);/* no, just clr busy */ + dp_xip = 0; } /* clear flag */ + dp_otas = OTA_NOP; /* clear state */ + dp_sta = dp_sta & ~STA_BUSY; /* clear busy */ + break; + case FNC_RDS: /* read status */ + if (dp_sta & STA_BUSY) return dat; /* ignore if busy */ + dp_sta = (dp_sta | STA_RDY) & ~(STA_MBZ | STA_ANYER); + if (dp_sta & STA_ALLERR) dp_sta = dp_sta | STA_ANYER; + dp_buf = dp_sta; + if (dp_dma && Q_DMA (ch)) SET_CH_REQ (ch); /* DMA? set chan req */ + break; + case FNC_DMA: /* set DMA/DMC */ + dp_dma = 1; + break; + case FNC_IOBUS: /* set IO bus */ + dp_dma = 0; + break; + case FNC_AKI: /* ack intr */ + CLR_INT (INT_DP); + break; + default: /* undefined */ + return IOBADFNC (dat); } + break; + + +case ioINA: /* INA */ + if (fnc) return IOBADFNC (dat); /* fnc 0 only */ + if (dp_sta & STA_RDY) { /* ready? */ + dp_sta = dp_sta & ~STA_RDY; /* clear ready */ + return IOSKIP (dat | dp_buf); } /* ret buf, skip */ + break; + +case ioOTA: /* OTA */ + if (fnc) return IOBADFNC (dat); /* fnc 0 only */ + if (dp_sta & STA_RDY) { /* ready? */ + dp_sta = dp_sta & ~STA_RDY; /* clear ready */ + dp_buf = dat; /* store buf */ + if (dp_otas == OTA_CW1) dp_go1 (dat); /* expecting CW1? */ + else if (dp_otas == OTA_CW2) dp_go2 (dat); /* expecting CW2? */ + return IOSKIP (dat); } + break; +case ioSKS: /* SKS */ + u = 7; /* assume unit 7 */ + switch (fnc) { + case 000: /* ready */ + if (dp_sta & STA_RDY) return IOSKIP (dat); + break; + case 001: /* !interrupting */ + if (!TST_INTREQ (INT_DP)) return IOSKIP (dat); + break; + case 002: /* operational */ + if (!(dp_sta & (STA_BUSY | STA_ALLERR))) return IOSKIP (dat); + break; + case 003: /* !error */ + if (!(dp_sta & STA_ALLERR)) return IOSKIP (dat); + break; + case 004: /* !busy */ + if (!(dp_sta & STA_BUSY)) return IOSKIP (dat); + break; + case 011: case 012: case 013: /* !not seeking 0-6 */ + case 014: case 015: case 016: case 017: + u = fnc - 011; + case 007: /* !not seeking 7 */ + if (!sim_is_active (&dp_unit[u]) || /* quiescent? */ + (dp_unit[u].FNC & 017) != FNC_SEEK) return IOSKIP (dat); + break; } + break; +case ioEND: /* end of range */ + dp_eor = 1; /* transfer done */ + break; } +return dat; +} + + +/* Start new operation - recal, seek, read address, format, read/write */ + +t_stat dp_go (uint32 fnc) +{ +int32 ch = dp_dib.chan - 1; /* DMA/DMC chan */ + +if (dp_sta & STA_BUSY) return SCPE_OK; /* ignore if busy */ +dp_fnc = fnc; /* save function */ +dp_xip = 0; /* transfer not started */ +dp_eor = 0; /* not end of range */ +dp_csum = 0; /* init checksum */ +dp_otas = OTA_CW1; /* expect CW1 */ +dp_sta = (dp_sta | STA_BUSY | STA_RDY) & ~(STA_ALLERR | STA_EOR); +if (dp_dma && Q_DMA (ch)) { /* DMA and DMA channel? */ + SET_CH_REQ (ch); /* set channel request */ + dma_ad[ch] = dma_ad[ch] & ~DMA_IN; } /* force output */ +return SCPE_OK; +} + +/* Process command word 1 - recal, seek, read address, format, read/write */ + +t_stat dp_go1 (uint32 dat) +{ +int32 ch = dp_dib.chan - 1; /* DMA/DMC chan */ +uint32 u = CW1_GETUNIT (dat); +UNIT *uptr = dp_dev.units + u; + +dp_cw1 = dat; /* store CW1 */ +dp_otas = OTA_NOP; /* assume no CW2 */ +uptr->FNC = dp_fnc; +if (sim_is_active (uptr)) /* still seeking? */ + return dp_done (1, STA_UNSER); /* unsafe */ +if (!(uptr->flags & UNIT_ATT)) /* not attached? */ + return dp_done (1, STA_OFLER); /* offline */ +switch (dp_fnc) { /* case on function */ +case FNC_SEEK: /* seek */ +case FNC_SK0: /* recalibrate */ +case FNC_UNL: /* unload */ + sim_activate (uptr, dp_btime); /* quick timeout */ + break; +case FNC_FMT: /* format */ + if (uptr->flags & UNIT_WPRT) /* write protect? */ + return dp_done (1, STA_WPRER); /* stop now */ +case FNC_RCA: /* read current addr */ + dp_xip = u | XIP_SCHED; /* operation started */ + sim_activate (uptr, dp_xtime * 10); /* rotation timeout */ + break; +case FNC_RW: /* read/write */ + dp_otas = OTA_CW2; /* expect CW2 */ + dp_sta = dp_sta | STA_RDY; /* set ready */ + if (dp_dma && Q_DMA (ch)) SET_CH_REQ (ch); /* DMA? set chan request */ + break; } +return SCPE_OK; +} + +/* Process command word 2 - read/write only */ + +t_stat dp_go2 (uint32 dat) +{ +uint32 u = CW1_GETUNIT (dp_cw1); +UNIT *uptr = dp_dev.units + u; + +dp_cw2 = dat; /* store CW2 */ +dp_otas = OTA_NOP; /* normal state */ +sim_activate (uptr, dp_xtime * 10); /* rotation timeout */ +dp_xip = u | XIP_SCHED; /* operation started */ +return SCPE_OK; +} + +/* Unit service */ + +t_stat dp_svc (UNIT *uptr) +{ +int32 dcyl = 0; /* assume recalibrate */ +int32 ch = dp_dib.chan - 1; /* DMA/DMC chan */ +uint32 h = CW1_GETHEAD (dp_cw1); /* head */ +int32 st; +uint32 i, offs, lnt, ming, tpos; +t_stat r; + +if (!(uptr->flags & UNIT_ATT)) { /* not attached? */ + dp_done (1, STA_OFLER); /* offline */ + IORETURN (dp_stopioe, SCPE_UNATT); } + +switch (uptr->FNC) { /* case on function */ +case FNC_SEEK: /* seek, need cyl */ + offs = CW1_GETOFFS (dp_cw1); /* get offset */ + if (dp_cw1 & CW1_DIR) dcyl = uptr->CYL - offs; /* get desired cyl */ + else dcyl = uptr->CYL + offs; + if ((offs == 0) || (dcyl < 0) || + (dcyl >= (int32) dp_tab[dp_ctype].cyl)) + return dp_done (1, STA_SEKER); /* bad seek? */ +case FNC_SK0: /* recalibrate */ + dp_sta = dp_sta & ~STA_BUSY; /* clear busy */ + uptr->FNC = FNC_SEEK | FNC_2ND; /* next state */ + st = (abs (dcyl - uptr->CYL)) * dp_stime; /* schedule seek */ + if (st == 0) st = dp_stime; + uptr->CYL = dcyl; /* put on cylinder */ + sim_activate (uptr, st); + return SCPE_OK; + +case FNC_SEEK | FNC_2ND: /* seek, 2nd state */ + if (dp_sta & STA_BUSY) dp_defint = 1; /* busy? queue intr */ + else SET_INT (INT_DP); /* no, req intr */ + return SCPE_OK; + +case FNC_UNL: /* unload */ + detach_unit (uptr); /* detach unit */ + return dp_done (0, 0); /* clear busy, no intr */ + +case FNC_RCA: /* read current addr */ + if (h >= dp_tab[dp_ctype].surf) /* invalid head? */ + return dp_done (1, STA_ADRER); /* error */ + if (r = dp_rdtrk (uptr, dpxb, uptr->CYL, h)) /* get track; error? */ + return r; + dp_rptr = 0; /* init rec ptr */ + if (dpxb[dp_rptr + REC_LNT] == 0) /* unformated? */ + return dp_done (1, STA_ADRER); /* error */ + tpos = (uint32) (fmod (sim_gtime () / (double) dp_xtime, DP_TRKLEN)); + do { /* scan down track */ + dp_buf = dpxb[dp_rptr + REC_ADDR]; /* get rec addr */ + dp_rptr = dp_rptr + dpxb[dp_rptr + REC_LNT] + REC_OVHD; } + while ((dp_rptr < tpos) && (dpxb[dp_rptr + REC_LNT] != 0)); + if (dp_dma) { /* DMA/DMC? */ + if (Q_DMA (ch)) /* DMA? */ + dma_ad[ch] = dma_ad[ch] | DMA_IN; /* force input */ + SET_CH_REQ (ch); } /* request chan */ + return dp_done (1, STA_RDY); /* clr busy, set rdy */ + +/* Formating takes place in five states: + + init - clear track buffer, start at first record + address - store address word + data - store data word(s) until end of range + pause - wait for gap word or stop command + gap - validate gap word, advance to next record + + Note that formating is stopped externally by an OCP command; the + track buffer is flushed at that point. If the stop does not occur + in the proper state (gap word received), a format error occurs. +*/ + +case FNC_FMT: /* format */ + for (i = 0; i < DP_TRKLEN; i++) dpxb[i] = 0; /* clear track */ + dp_xip = dp_xip | XIP_FMT; /* format in progress */ + dp_rptr = 0; /* init record ptr */ + dp_gap = 0; /* no gap before first */ + dp_bctr = (uint32) (16.0 * dp_tab[dp_ctype].wrds); /* init bit cntr */ + uptr->FNC = uptr->FNC | FNC_2ND; /* address state */ + break; /* set up next word */ + +case FNC_FMT | FNC_2ND: /* format, address word */ + dp_wptr = 0; /* clear word ptr */ + if (dp_bctr < (dp_gap + REC_OVHD_BITS + 16)) /* room for gap, record? */ + return dp_wrdone (uptr, STA_FMTER); /* no, format error */ + dp_bctr = dp_bctr - dp_gap - REC_OVHD_BITS; /* charge for gap, ovhd */ + dpxb[dp_rptr + REC_ADDR] = dp_buf; /* store address */ + uptr->FNC = FNC_FMT | FNC_3RD; /* data state */ + if (dp_eor) { /* record done? */ + dp_eor = 0; /* clear for restart */ + if (dp_dma) SET_INT (INT_DP); } /* DMA/DMC? intr */ + break; /* set up next word */ + +case FNC_FMT | FNC_3RD: /* format, data word */ + if (dp_sta & STA_RDY) /* timing failure? */ + return dp_wrdone (uptr, STA_DTRER); /* write trk, err */ + else { /* no, have word */ + if (dp_bctr < 16) /* room for it? */ + return dp_wrdone (uptr, STA_FMTER); /* no, error */ + dp_bctr = dp_bctr - 16; /* charge for word */ + dp_csum = dp_csum ^ dp_buf; /* update checksum */ + dpxb[dp_rptr + REC_DATA + dp_wptr] = dp_buf;/* store word */ + dpxb[dp_rptr + REC_LNT]++; /* incr rec lnt */ + dp_wptr++; } /* incr word ptr */ + if (dp_eor) { /* record done? */ + dp_eor = 0; /* clear for restart */ + if (dp_dma) SET_INT (INT_DP); /* DMA/DMC? intr */ + dpxb[dp_rptr + REC_DATA + dp_wptr] = dp_csum; /* store checksum */ + uptr->FNC = uptr->FNC | FNC_4TH; /* pause state */ + sim_activate (uptr, 5 * dp_xtime); /* schedule pause */ + return SCPE_OK; } /* don't request word */ + break; /* set up next word */ + +case FNC_FMT | FNC_4TH: /* format, pause */ + uptr->FNC = FNC_FMT | FNC_5TH; /* gap state */ + break; /* request word */ + +case FNC_FMT | FNC_5TH: /* format, gap word */ + ming = ((16 * dp_wptr) + REC_OVHD_BITS) / 20; /* min 5% gap */ + if (dp_buf < ming) /* too small? */ + return dp_wrdone (uptr, STA_FMTER); /* yes, format error */ + dp_rptr = dp_rptr + dp_wptr + REC_OVHD; /* next record */ + uptr->FNC = FNC_FMT | FNC_2ND; /* address state */ + if (dp_eor) { /* record done? */ + dp_eor = 0; /* clear for restart */ + if (dp_dma) SET_INT (INT_DP); } /* DMA/DMC? intr */ + dp_gap = dp_buf; /* save gap */ + dp_csum = 0; /* clear checksum */ + break; /* set up next word */ + +/* Read and write take place in two states: + + init - read track into buffer, find record, validate parameters + data - (read) fetch data from buffer, stop on end of range + - (write) write data into buffer, flush on end of range +*/ + +case FNC_RW: /* read/write */ + if (h >= dp_tab[dp_ctype].surf) /* invalid head? */ + return dp_done (1, STA_ADRER); /* error */ + if (r = dp_rdtrk (uptr, dpxb, uptr->CYL, h)) /* get track; error? */ + return r; + if (!dp_findrec (dp_cw2)) /* find rec; error? */ + return dp_done (1, STA_ADRER); /* address error */ + if ((dpxb[dp_rptr + REC_LNT] >= (DP_TRKLEN - dp_rptr - REC_OVHD)) || + (dpxb[dp_rptr + REC_EXT] >= REC_MAXEXT)) { /* bad lnt or ext? */ + dp_done (1, STA_UNSER); /* stop simulation */ + return STOP_DPFMT; } /* bad format */ + uptr->FNC = uptr->FNC | FNC_2ND; /* next state */ + if (dp_cw1 & CW1_RW) { /* write? */ + if (uptr->flags & UNIT_WPRT) /* write protect? */ + return dp_done (1, STA_WPRER); /* error */ + dp_xip = dp_xip | XIP_WRT; /* write in progress */ + dp_sta = dp_sta | STA_RDY; /* set ready */ + if (dp_dma) SET_CH_REQ (ch); } /* if DMA/DMC, req chan */ + else if (Q_DMA (ch)) /* read; DMA? */ + dma_ad[ch] = dma_ad[ch] | DMA_IN; /* force input */ + sim_activate (uptr, dp_xtime); /* schedule word */ + dp_wptr = 0; /* init word pointer */ + return SCPE_OK; + +case FNC_RW | FNC_2ND: /* read/write, word */ + if (dp_cw1 & CW1_RW) { /* write? */ + if (dp_sta & STA_RDY) /* timing failure? */ + return dp_wrdone (uptr, STA_DTRER); /* yes, error */ + if (r = dp_wrwd (uptr, dp_buf)) return r; /* wr word, error? */ + if (dp_eor) { /* transfer done? */ + dpxb[dp_rptr + REC_DATA + dp_wptr] = dp_csum; + return dp_wrdone (uptr, 0); } } /* clear busy, intr req */ + else { /* read? */ + lnt = dpxb[dp_rptr + REC_LNT] + dpxb[dp_rptr + REC_EXT]; + dp_buf = dpxb[dp_rptr + REC_DATA + dp_wptr];/* current word */ + dp_csum = dp_csum ^ dp_buf; /* xor to csum */ + if ((dp_wptr > lnt) || dp_eor) /* transfer done? */ + return dp_done (1, + (dp_csum? STA_CSMER: 0) | + ((dp_wptr >= lnt)? STA_EOR: 0)); + if (dp_sta & STA_RDY) /* data buf full? */ + return dp_done (1, STA_DTRER); /* no, underrun */ + dp_wptr++; } /* next word */ + break; + +default: + return SCPE_IERR; } /* end case */ + +dp_sta = dp_sta | STA_RDY; /* set ready */ +if (dp_dma) SET_CH_REQ (ch); /* if DMA/DMC, req chan */ +sim_activate (uptr, dp_xtime); /* schedule word */ +return SCPE_OK; +} + +/* Read track */ + +t_stat dp_rdtrk (UNIT *uptr, uint16 *buf, uint32 c, uint32 h) +{ +uint32 da = ((c * dp_tab[dp_ctype].surf) + h) * DP_TRKLEN; +int32 l; + +fseek (uptr->fileref, da * sizeof (uint16), SEEK_SET); +l = fxread (buf, sizeof (uint16), DP_TRKLEN, uptr->fileref); +for ( ; l < DP_TRKLEN; l++) buf[l] = 0; +if (ferror (uptr->fileref)) { + perror ("DP I/O error"); + clearerr (uptr->fileref); + dp_done (1, STA_UNSER); + return SCPE_IOERR; } +return SCPE_OK; +} + +/* Write track */ + +t_stat dp_wrtrk (UNIT *uptr, uint16 *buf, uint32 c, uint32 h) +{ +uint32 da = ((c * dp_tab[dp_ctype].surf) + h) * DP_TRKLEN; + +fseek (uptr->fileref, da * sizeof (uint16), SEEK_SET); +fxwrite (buf, sizeof (uint16), DP_TRKLEN, uptr->fileref); +if (ferror (uptr->fileref)) { + perror ("DP I/O error"); + clearerr (uptr->fileref); + dp_done (1, STA_UNSER); + return SCPE_IOERR; } +return SCPE_OK; +} + +/* Find record; true if found, false if not found */ + +t_bool dp_findrec (uint32 addr) +{ +dp_rptr = 0; + +do { if (dpxb[dp_rptr + REC_LNT] == 0) return FALSE; + if (dpxb[dp_rptr + REC_LNT] >= DP_TRKLEN) return TRUE; + if (dpxb[dp_rptr + REC_ADDR] == addr) return TRUE; + dp_rptr = dp_rptr + dpxb[dp_rptr + REC_LNT] + REC_OVHD; } +while (dp_rptr < DP_TRKLEN); +return FALSE; +} + +/* Write next word to track buffer; return TRUE if ok, FALSE if next record trashed */ + +t_stat dp_wrwd (UNIT *uptr, uint32 dat) +{ +uint32 lnt = dpxb[dp_rptr + REC_LNT]; +t_stat r; + +dp_csum = dp_csum ^ dat; +if (dp_wptr < lnt) { + dpxb[dp_rptr + REC_DATA + dp_wptr++] = dat; + return SCPE_OK; } +if (dp_wptr < (lnt + REC_MAXEXT)) { + dpxb[dp_rptr + REC_EXT]++; + dpxb[dp_rptr + REC_DATA + dp_wptr++] = dat; + return SCPE_OK; } +dpxb[dp_rptr + REC_DATA + dp_wptr] = dp_csum; /* write csum */ +dpxb[dp_rptr + lnt + REC_OVHD] = 0; /* zap rest of track */ +if (r = dp_wrdone (uptr, STA_UNSER)) return r; /* dump track */ +return STOP_DPOVR; +} + +/* Write done, dump track, clear busy */ + +t_stat dp_wrdone (UNIT *uptr, uint32 flg) +{ +dp_done (1, flg); +return dp_wrtrk (uptr, dpxb, uptr->CYL, CW1_GETHEAD (dp_cw1)); +} + +/* Clear busy, set errors, request interrupt if required */ + +t_stat dp_done (uint32 req, uint32 flg) +{ +dp_xip = 0; /* clear xfr in prog */ +dp_sta = (dp_sta | flg) & ~(STA_BUSY | STA_MBZ); /* clear busy */ +if (req || dp_defint) SET_INT (INT_DP); /* if req, set intr */ +dp_defint = 0; /* clr def intr */ +return SCPE_OK; +} + +/* Reset routine */ + +t_stat dp_reset (DEVICE *dptr) +{ +int32 i; + +dp_fnc = 0; +dp_cw1 = 0; +dp_cw2 = 0; +dp_sta = 0; +dp_buf = 0; +dp_xip = 0; +dp_eor = 0; +dp_dma = 0; +dp_csum = 0; +dp_rptr = 0; +dp_wptr = 0; +dp_bctr = 0; +dp_gap = 0; +dp_defint = 0; +for (i = 0; i < DP_NUMDRV; i++) { /* loop thru drives */ + sim_cancel (&dp_unit[i]); /* cancel activity */ + dp_unit[i].FNC = 0; /* clear function */ + dp_unit[i].CYL = 0; } +return SCPE_OK; +} + +/* Attach routine, test formating */ + +t_stat dp_attach (UNIT *uptr, char *cptr) +{ +t_stat r; +r = attach_unit (uptr, cptr); +if (r != SCPE_OK) return r; +return dp_showformat (stdin, uptr, 0, NULL); +} + +/* Set controller type */ + +t_stat dp_settype (UNIT *uptr, int32 val, char *cptr, void *desc) +{ +int32 i; + +if ((val < 0) || (val >= DP_NUMTYP) || (cptr != NULL)) return SCPE_ARG; +for (i = 0; i < DP_NUMDRV; i++) { + if (dp_unit[i].flags & UNIT_ATT) return SCPE_ALATT; } +for (i = 0; i < DP_NUMDRV; i++) + dp_unit[i].capac = dp_tab[val].cap; +dp_ctype = val; +return SCPE_OK; +} + +/* Show controller type */ + +t_stat dp_showtype (FILE *st, UNIT *uptr, int32 val, void *desc) +{ +if (dp_ctype >= DP_NUMTYP) return SCPE_IERR; +fprintf (st, "%s", dp_tab[dp_ctype].name); +return SCPE_OK; +} + +/* Set drive format + + There is no standard format for record addresses. This routine + provides two schemes: + + -S sequential addressing (starting from 0) + default geometric addressing (8b: cylinder, 5b: head, 3b: sector) + + This routine also supports formatting by record count or word count: + + -R argument is records per track + default argument is words per record + + The relationship between words per record (W), bits per track (B), + and records per track (R), is as follows: + + W = (B / (R + ((R - 1) / 20))) - 16.5 + + where (R - 1) / 20 is the "5% gap" and 16.5 is the overhead, in words, + per record. +*/ + +t_stat dp_setformat (UNIT *uptr, int32 val, char *cptr, void *desc) +{ +uint32 h, c, cntr, rptr; +int32 i, nr, nw, inp; +uint16 tbuf[DP_TRKLEN]; +float finp; +t_stat r; + +if (uptr == NULL) return SCPE_IERR; +if (cptr == NULL) return SCPE_ARG; +if (!(uptr->flags & UNIT_ATT)) return SCPE_UNATT; +inp = (int32) get_uint (cptr, 10, 2048, &r); +if (r != SCPE_OK) return r; +if (inp == 0) return SCPE_ARG; +finp = (float) inp; +if (sim_switches & SWMASK ('R')) { /* format records? */ + nr = inp; + nw = (int32) ((dp_tab[dp_ctype].wrds / (finp + ((finp - 1.0) / 20.0))) - REC_OVHD_WRDS); + if (nw <= 0) return SCPE_ARG; } +else { nw = inp; /* format words */ + nr = (int32) ((((20.0 * dp_tab[dp_ctype].wrds) / (finp + REC_OVHD_WRDS)) + 1.0) / 21.0); + if (nr <= 0) return SCPE_ARG; } +printf ("Proposed format: records/track = %d, record size = %d\n", nr, nw); +if (!get_yn ("Formatting will destroy all data on this disk; proceed? [N]", FALSE)) + return SCPE_OK; +for (c = cntr = 0; c < dp_tab[dp_ctype].cyl; c++) { + for (h = 0; h < dp_tab[dp_ctype].surf; h++) { + for (i = 0; i < DP_TRKLEN; i++) tbuf[i] = 0; + rptr = 0; + for (i = 0; i < nr; i++) { + tbuf[rptr + REC_LNT] = nw & DMASK; + if (sim_switches & SWMASK ('S')) + tbuf[rptr + REC_ADDR] = cntr++; + else tbuf[rptr + REC_ADDR] = (c << 8) + (h << 3) + i; + rptr = rptr + nw + REC_OVHD; } + if (r = dp_wrtrk (uptr, tbuf, c, h)) return r; + } + } +printf ("Formatting complete\n"); +return SCPE_OK; +} + +/* Show format */ + +t_stat dp_showformat (FILE *st, UNIT *uptr, int32 val, void *desc) +{ +uint32 c, h, rptr, rlnt, sec; +uint32 minrec = DP_TRKLEN; +uint32 maxrec = 0; +uint32 minsec = DP_TRKLEN; +uint32 maxsec = 0; +uint16 tbuf[DP_TRKLEN]; +t_stat r; + +if (uptr == NULL) return SCPE_IERR; +if ((uptr->flags & UNIT_ATT) == 0) return SCPE_UNATT; +for (c = 0; c < dp_tab[dp_ctype].cyl; c++) { + for (h = 0; h < dp_tab[dp_ctype].surf; h++) { + if (r = dp_rdtrk (uptr, tbuf, c, h)) return r; + rptr = 0; + rlnt = tbuf[rptr + REC_LNT]; + if (rlnt == 0) { + if (c || h) fprintf (st, + "Unformatted track, cyl = %d, head = %d\n", c, h); + else fprintf (st, "Disk is unformatted\n"); + return SCPE_OK; } + for (sec = 0; rlnt != 0; sec++) { + if ((rptr + rlnt + REC_OVHD) >= DP_TRKLEN) { + fprintf (st, "Invalid record length %d, cyl = %d, head = %d, sect = %d\n", + rlnt, c, h, sec); + return SCPE_OK; } + if (tbuf[rptr + REC_EXT] >= REC_MAXEXT) { + fprintf (st, "Invalid record extension %d, cyl = %d, head = %d, sect = %d\n", + tbuf[rptr + REC_EXT], c, h, sec); + return SCPE_OK; } + if (rlnt > maxrec) maxrec = rlnt; + if (rlnt < minrec) minrec = rlnt; + rptr = rptr + rlnt + REC_OVHD; + rlnt = tbuf[rptr + REC_LNT]; + } + if (sec > maxsec) maxsec = sec; + if (sec < minsec) minsec = sec; + } + } +if ((minrec == maxrec) && (minsec == maxsec)) fprintf (st, + "Valid fixed format, records/track = %d, record size = %d\n", + minsec, minrec); +else if (minrec == maxrec) fprintf (st, + "Valid variable format, records/track = %d-%d, record size = %d\n", + minsec, maxsec, minrec); +else if (minsec == maxsec) fprintf (st, + "Valid variable format, records/track = %d, record sizes = %d-%d\n", + minsec, minrec, maxrec); +else fprintf (st, + "Valid variable format, records/track = %d-%d, record sizes = %d-%d\n", + minsec, maxsec, minrec, maxrec); +return SCPE_OK; +} diff --git a/H316/h316_fhd.c b/H316/h316_fhd.c new file mode 100644 index 00000000..b264e5e1 --- /dev/null +++ b/H316/h316_fhd.c @@ -0,0 +1,423 @@ +/* h316_fhd.c: H316/516 fixed head 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. + + fhd 516-4400 fixed head disk + + These head-per-track devices are buffered in memory, to minimize overhead. +*/ + +#include "h316_defs.h" +#include + +/* Constants */ + +#define FH_NUMWD 1536 /* words/track */ +#define FH_NUMTK 64 /* tracks/surface */ +#define FH_WDPSF (FH_NUMWD * FH_NUMTK) /* words/surface */ +#define FH_NUMSF 16 /* surfaces/ctlr */ +#define UNIT_V_AUTO (UNIT_V_UF + 0) /* autosize */ +#define UNIT_V_SF (UNIT_V_UF + 1) /* #surfaces - 1 */ +#define UNIT_M_SF 017 +#define UNIT_AUTO (1 << UNIT_V_AUTO) +#define UNIT_SF (UNIT_M_SF << UNIT_V_SF) +#define UNIT_GETSF(x) ((((x) >> UNIT_V_SF) & UNIT_M_SF) + 1) + +/* Command word 1 */ + +#define CW1_RW 0100000 /* read vs write */ +#define CW1_V_SF 10 /* surface */ +#define CW1_M_SF 017 +#define CW1_GETSF(x) (((x) >> CW1_V_SF) & CW1_M_SF) +#define CW1_V_TK 4 /* track */ +#define CW1_M_TK 077 +#define CW1_GETTK(x) (((x) >> CW1_V_TK) & CW1_M_TK) + +/* Command word 2 */ + +#define CW2_V_CA 0 /* character addr */ +#define CW2_M_CA 07777 +#define CW2_GETCA(x) (((x) >> CW2_V_CA) & CW2_M_CA) + +#define GET_POS(x) ((int) fmod (sim_gtime() / ((double) (x)), \ + ((double) FH_NUMWD))) + +/* OTA states */ + +#define OTA_NOP 0 /* normal */ +#define OTA_CW1 1 /* expecting CW1 */ +#define OTA_CW2 2 /* expecting CW2 */ + +extern int32 dev_int, dev_enb, chan_req; +extern int32 stop_inst; +extern uint32 dma_ad[DMA_MAX]; + +uint32 fhd_cw1 = 0; /* cmd word 1 */ +uint32 fhd_cw2 = 0; /* cmd word 2 */ +uint32 fhd_buf = 0; /* buffer */ +uint32 fhd_otas = 0; /* state */ +uint32 fhd_busy = 0; /* busy */ +uint32 fhd_rdy = 0; /* word ready */ +uint32 fhd_dte = 0; /* data err */ +uint32 fhd_ace = 0; /* access error */ +uint32 fhd_dma = 0; /* DMA/DMC */ +uint32 fhd_eor = 0; /* end of range */ +uint32 fhd_csum = 0; /* parity checksum */ +uint32 fhd_stopioe = 1; /* stop on error */ +int32 fhd_time = 10; /* time per word */ + +int32 fhdio (int32 inst, int32 fnc, int32 dat, int32 dev); +t_stat fhd_svc (UNIT *uptr); +t_stat fhd_reset (DEVICE *dptr); +t_stat fhd_attach (UNIT *uptr, char *cptr); +t_stat fhd_boot (int32 unitno, DEVICE *dptr); +t_stat fhd_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); +void fhd_go (uint32 dma); +void fhd_go1 (uint32 dat); +void fhd_go2 (uint32 dat); +t_bool fhd_getc (UNIT *uptr, uint32 *ch); +t_bool fhd_putc (UNIT *uptr, uint32 ch); +t_bool fhd_bad_wa (uint32 wa); +uint32 fhd_csword (uint32 cs, uint32 ch); + +/* FHD data structures + + fhd_dev device descriptor + fhd_unit unit descriptor + fhd_mod unit modifiers + fhd_reg register list +*/ + +DIB fhd_dib = { FHD, IOBUS, 1, &fhdio }; + +UNIT fhd_unit = + { UDATA (&fhd_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+ + UNIT_MUSTBUF, FH_WDPSF) }; + +REG fhd_reg[] = { + { ORDATA (CW1, fhd_cw1, 16) }, + { ORDATA (CW2, fhd_cw2, 16) }, + { ORDATA (BUF, fhd_buf, 16) }, + { FLDATA (BUSY, fhd_busy, 0) }, + { FLDATA (RDY, fhd_rdy, 0) }, + { FLDATA (DTE, fhd_dte, 0) }, + { FLDATA (ACE, fhd_ace, 0) }, + { FLDATA (EOR, fhd_eor, 0) }, + { FLDATA (DMA, fhd_dma, 0) }, + { FLDATA (CSUM, fhd_csum, 7) }, + { FLDATA (INTREQ, dev_int, INT_V_MT) }, + { FLDATA (ENABLE, dev_enb, INT_V_MT) }, + { DRDATA (TIME, fhd_time, 31), REG_NZ + PV_LEFT }, + { ORDATA (OTAS, fhd_otas, 2), REG_HRO }, + { ORDATA (CHAN, fhd_dib.chan, 5), REG_HRO }, + { FLDATA (STOP_IOE, fhd_stopioe, 0) }, + { NULL } }; + +MTAB fhd_mod[] = { + { UNIT_SF, (0 << UNIT_V_SF), NULL, "1S", &fhd_set_size }, + { UNIT_SF, (1 << UNIT_V_SF), NULL, "2S", &fhd_set_size }, + { UNIT_SF, (2 << UNIT_V_SF), NULL, "3S", &fhd_set_size }, + { UNIT_SF, (3 << UNIT_V_SF), NULL, "4S", &fhd_set_size }, + { UNIT_SF, (4 << UNIT_V_SF), NULL, "5S", &fhd_set_size }, + { UNIT_SF, (5 << UNIT_V_SF), NULL, "6S", &fhd_set_size }, + { UNIT_SF, (6 << UNIT_V_SF), NULL, "7S", &fhd_set_size }, + { UNIT_SF, (7 << UNIT_V_SF), NULL, "8S", &fhd_set_size }, + { UNIT_SF, (8 << UNIT_V_SF), NULL, "9S", &fhd_set_size }, + { UNIT_SF, (9 << UNIT_V_SF), NULL, "10S", &fhd_set_size }, + { UNIT_SF, (10 << UNIT_V_SF), NULL, "11S", &fhd_set_size }, + { UNIT_SF, (11 << UNIT_V_SF), NULL, "12S", &fhd_set_size }, + { UNIT_SF, (12 << UNIT_V_SF), NULL, "13S", &fhd_set_size }, + { UNIT_SF, (13 << UNIT_V_SF), NULL, "14S", &fhd_set_size }, + { UNIT_SF, (14 << UNIT_V_SF), NULL, "15S", &fhd_set_size }, + { UNIT_SF, (15 << UNIT_V_SF), NULL, "16S", &fhd_set_size }, + { UNIT_AUTO, UNIT_AUTO, "autosize", "AUTOSIZE", NULL }, + { MTAB_XTD|MTAB_VDV, 0, NULL, "IOBUS", + &io_set_iobus, NULL, NULL }, + { MTAB_XTD|MTAB_VDV, 0, NULL, "DMC", + &io_set_dmc, NULL, NULL }, + { MTAB_XTD|MTAB_VDV, 0, NULL, "DMA", + &io_set_dma, NULL, NULL }, + { MTAB_XTD|MTAB_VDV, 0, "CHANNEL", NULL, + NULL, &io_show_chan, NULL }, + { 0 } }; + +DEVICE fhd_dev = { + "FHD", &fhd_unit, fhd_reg, fhd_mod, + 1, 8, 22, 1, 8, 16, + NULL, NULL, &fhd_reset, + NULL, &fhd_attach, NULL, + &fhd_dib, DEV_DISABLE }; + +/* IO routines */ + +int32 fhdio (int32 inst, int32 fnc, int32 dat, int32 dev) +{ +switch (inst) { /* case on opcode */ +case ioOCP: /* control */ + if (fnc == 04) { /* terminate output? */ + fhd_eor = 1; /* stop */ + CLR_INT (INT_FHD); } /* clear int req */ + else if (fnc == 003) fhd_go (1); /* start, DMA */ + else if (fnc == 007) fhd_go (0); /* start, IO bus */ + else return IOBADFNC (dat); + break; +case ioOTA: /* output */ + if (fnc) return IOBADFNC (dat); /* only fnc 0 */ + if (fhd_rdy) { /* ready? */ + fhd_buf = dat; /* store data */ + if (fhd_otas == OTA_CW1) fhd_go1 (dat); /* expecting CW1? */ + else if (fhd_otas == OTA_CW2) fhd_go2 (dat);/* expecting CW2? */ + else fhd_rdy = 0; /* normal, clr ready */ + return IOSKIP (dat); } + break; +case ioINA: /* input */ + if (fnc) return IOBADFNC (dat); /* only fnc 0 */ + if (fhd_rdy) { /* ready? */ + fhd_rdy = 0; /* clear ready */ + return IOSKIP (dat | fhd_buf); } /* return data */ + break; +case ioSKS: /* sense */ + if (((fnc == 000) && fhd_rdy) || /* 0 = skip if ready */ + ((fnc == 001) && !fhd_busy) || /* 1 = skip if !busy */ + ((fnc == 002) && !fhd_dte) || /* 2 = skip if !data err */ + ((fnc == 003) && !fhd_ace) || /* 3 = skip if !access err */ + ((fnc == 004) && !TST_INTREQ (INT_FHD))) /* 4 = skip if !interrupt */ + return IOSKIP (dat); + break; +case ioEND: + fhd_eor = 1; + break; } +return dat; +} + +/* Start new operation */ + +void fhd_go (uint32 dma) +{ +int32 ch = fhd_dib.chan - 1; /* DMA/DMC chan */ + +if (fhd_busy) return; /* ignore if busy */ +fhd_busy = 1; /* ctlr is busy */ +fhd_eor = 0; /* transfer not done */ +fhd_csum = 0; /* init checksum */ +fhd_dte = 0; /* clear errors */ +fhd_ace = 0; +if (ch >= 0) fhd_dma = dma; /* DMA allowed? */ +else fhd_dma = 0; /* no, force IO bus */ +fhd_otas = OTA_CW1; /* expect CW1 */ +fhd_rdy = 1; /* set ready */ +if (fhd_dma && Q_DMA (ch)) { /* DMA and DMA channel? */ + SET_CH_REQ (ch); /* set channel request */ + dma_ad[ch] = dma_ad[ch] & ~DMA_IN; } /* force output */ +return; +} + +/* Process command word 1 */ + +void fhd_go1 (uint32 dat) +{ +int32 ch = fhd_dib.chan - 1; /* DMA/DMC chan */ + +fhd_cw1 = dat; /* store CW1 */ +fhd_otas = OTA_CW2; /* expect CW2 */ +fhd_rdy = 1; /* set ready */ +if (fhd_dma && Q_DMA (ch)) SET_CH_REQ (ch); /* DMA? set chan request */ +return; +} + +/* Process command word 2 - initiate seek */ + +void fhd_go2 (uint32 dat) +{ +int32 ch = fhd_dib.chan - 1; /* DMA/DMC chan */ +uint32 sf = CW1_GETSF (fhd_cw1); /* surface */ +int32 t, wa; + +fhd_cw2 = dat; /* store CW2 */ +fhd_otas = OTA_NOP; /* next state */ +wa = CW2_GETCA (fhd_cw2) >> 1; /* word addr */ +if ((wa >= FH_NUMWD) || /* if bad char addr */ + ((fhd_unit.flags & UNIT_ATT) == 0) || /* or unattached */ + (sf >= UNIT_GETSF (fhd_unit.flags))) { /* or bad surface */ + fhd_ace = 1; /* access error */ + fhd_busy = 0; /* abort operation */ + SET_INT (INT_FHD); + return; } +if (fhd_cw1 & CW1_RW) { /* write? */ + fhd_rdy = 1; /* set ready */ + if (fhd_dma) SET_CH_REQ (ch); } /* if DMA/DMC, req chan */ +else { fhd_rdy = 0; /* read, clear ready */ + if (fhd_dma && (ch < DMC_V_DMC1)) /* read and DMA chan? */ + dma_ad[ch] = dma_ad[ch] | DMA_IN; } /* force input */ +t = wa - GET_POS (fhd_time); /* delta to new loc */ +if (t < 0) t = t + FH_NUMWD; /* wrap around? */ +sim_activate (&fhd_unit, t * fhd_time); /* schedule op */ +return; +} + +/* Unit service */ + +t_stat fhd_svc (UNIT *uptr) +{ +int32 ch = fhd_dib.chan - 1; /* DMA/DMC chan (-1 if IO bus) */ +uint32 c1, c2; + +if ((uptr->flags & UNIT_ATT) == 0) { /* unattached? */ + fhd_ace = 1; /* access error */ + fhd_busy = 0; /* abort operation */ + SET_INT (INT_FHD); + return IORETURN (fhd_stopioe, SCPE_UNATT); } + +if (fhd_eor || fhd_rdy) { /* done or ready set? */ + if (fhd_rdy) fhd_dte = 1; /* if ready set, data err */ + if (fhd_cw1 & CW1_RW) { /* write? */ + if (!fhd_rdy) { /* buffer full? */ + fhd_putc (uptr, fhd_buf >> 8); /* store last word */ + fhd_putc (uptr, fhd_buf); } + fhd_putc (uptr, fhd_csum); } /* store csum */ + else { /* read */ + fhd_getc (uptr, &c1); /* get csum */ + if (fhd_csum) fhd_dte = 1; } /* if csum != 0, err */ + fhd_busy = 0; /* operation complete */ + SET_INT (INT_FHD); + return SCPE_OK; } + +if (fhd_cw1 & CW1_RW) { /* write? */ + if (fhd_putc (uptr, fhd_buf >> 8)) return SCPE_OK; + if (fhd_putc (uptr, fhd_buf)) return SCPE_OK; } +else { if (fhd_getc (uptr, &c1)) return SCPE_OK; /* read */ + if (fhd_getc (uptr, &c2)) return SCPE_OK; + fhd_buf = (c1 << 8) | c2; } +sim_activate (uptr, fhd_time); /* next word */ +fhd_rdy = 1; /* set ready */ +if (fhd_dma) SET_CH_REQ (ch); /* if DMA/DMC, req chan */ +return SCPE_OK; +} + +/* Read character from disk */ + +t_bool fhd_getc (UNIT *uptr, uint32 *ch) +{ +uint32 sf = CW1_GETSF (fhd_cw1); /* surface */ +uint32 tk = CW1_GETTK (fhd_cw1); /* track */ +uint32 ca = CW2_GETCA (fhd_cw2); /* char addr */ +uint32 wa = ca >> 1; /* word addr */ +uint32 ba = (((sf * FH_NUMTK) + tk) * FH_NUMWD) + wa; /* buffer offset */ +uint16 *fbuf = uptr->filebuf; /* buffer base */ +uint32 wd; + +if (fhd_bad_wa (wa)) return TRUE; /* addr bad? */ +fhd_cw2 = fhd_cw2 + 1; /* incr char addr */ +if (ca & 1) wd = fbuf[ba] & 0377; /* select char */ +else wd = (fbuf[ba] >> 8) & 0377; +fhd_csum = fhd_csword (fhd_csum, wd); /* put in csum */ +*ch = wd; /* return */ +return FALSE; +} + +/* Write character to disk */ + +t_bool fhd_putc (UNIT *uptr, uint32 ch) +{ +uint32 sf = CW1_GETSF (fhd_cw1); /* surface */ +uint32 tk = CW1_GETTK (fhd_cw1); /* track */ +uint32 ca = CW2_GETCA (fhd_cw2); /* char addr */ +uint32 wa = ca >> 1; /* word addr */ +uint32 ba = (((sf * FH_NUMTK) + tk) * FH_NUMWD) + wa; /* buffer offset */ +uint16 *fbuf = uptr->filebuf; /* buffer base */ + +ch = ch & 0377; /* mask char */ +if (fhd_bad_wa (wa)) return TRUE; /* addr bad? */ +fhd_cw2 = fhd_cw2 + 1; /* incr char addr */ +if (ca & 1) fbuf[ba] = (fbuf[ba] & ~0377) | ch; /* odd? low char */ +else fbuf[ba] = (fbuf[ba] & 0377) | (ch << 8); /* even, hi char */ +fhd_csum = fhd_csword (fhd_csum, ch); /* put in csum */ +if (ba >= uptr->hwmark) uptr->hwmark = ba + 1; /* update hwmark */ +return FALSE; +} + +/* Check word address */ + +t_bool fhd_bad_wa (uint32 wa) +{ +if (wa >= FH_NUMWD) { /* bad address? */ + fhd_ace = 1; /* access error */ + fhd_busy = 0; /* abort operation */ + SET_INT (INT_FHD); + return TRUE; } +return FALSE; +} + +/* Add character to checksum (parity) */ + +uint32 fhd_csword (uint32 cs, uint32 ch) +{ +while (ch) { /* count bits */ + ch = ch & ~(ch & (-(int32) ch)); + cs = cs ^ 0200; } /* invert cs for each 1 */ +return cs; +} + +/* Reset routine */ + +t_stat fhd_reset (DEVICE *dptr) +{ +fhd_busy = 0; /* reset state */ +fhd_rdy = 0; +fhd_ace = 0; +fhd_dte = 0; +fhd_eor = 0; +fhd_otas = OTA_NOP; +fhd_cw1 = fhd_cw2 = fhd_buf = 0; +CLR_INT (INT_FHD); /* clear int, enb */ +CLR_ENB (INT_FHD); +sim_cancel (&fhd_unit); /* cancel operation */ +return SCPE_OK; +} + +/* Attach routine */ + +t_stat fhd_attach (UNIT *uptr, char *cptr) +{ +uint32 sz, sf; +uint32 ds_bytes = FH_WDPSF * sizeof (int16); + +if ((uptr->flags & UNIT_AUTO) && (sz = sim_fsize (cptr))) { + sf = (sz + ds_bytes - 1) / ds_bytes; + if (sf >= FH_NUMSF) sf = FH_NUMSF - 1; + uptr->flags = (uptr->flags & ~UNIT_SF) | + (sf << UNIT_V_SF); } +uptr->capac = UNIT_GETSF (uptr->flags) * FH_WDPSF; +return attach_unit (uptr, cptr); +} + +/* Set size routine */ + +t_stat fhd_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_GETSF (val) * FH_WDPSF; +return SCPE_OK; +} diff --git a/H316/h316_lp.c b/H316/h316_lp.c index 7c17b74e..44b0c956 100644 --- a/H316/h316_lp.c +++ b/H316/h316_lp.c @@ -25,6 +25,7 @@ lpt line printer + 24-Oct-03 RMS Added DMA/DMC support 25-Apr-03 RMS Revised for extended file support 30-May-02 RMS Widened POS to 32b @@ -55,8 +56,10 @@ 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_rdy transfer ready flag lpt_prdn printing done flag + lpt_dma use DMA/DMC + lpt_eor DMA/DMC end of range */ #include "h316_defs.h" @@ -67,22 +70,26 @@ #define LPT_SVCSH 01 /* shuttle */ #define LPT_SVCPA 02 /* paper advance */ -extern int32 dev_ready, dev_enable; +extern int32 dev_int, dev_enb; extern int32 stop_inst; +extern uint32 chan_req; 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_rdy = 0; /* transfer flag */ int32 lpt_prdn = 1; /* printing done */ +int32 lpt_dma = 0; /* use DMA/DMC */ +int32 lpt_eor = 0; /* DMA/DMC end range */ 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 */ +int32 lptio (int32 inst, int32 fnc, int32 dat, int32 dev); t_stat lpt_svc (UNIT *uptr); t_stat lpt_reset (DEVICE *dptr); @@ -94,16 +101,20 @@ t_stat lpt_reset (DEVICE *dptr); lpt_reg LPT register list */ +DIB lpt_dib = { LPT, IOBUS, 1, &lptio }; + 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 (RDY, lpt_rdy, 0) }, + { FLDATA (EOR, lpt_eor, 0) }, + { FLDATA (DMA, lpt_dma, 0) }, { FLDATA (PRDN, lpt_prdn, 0) }, - { FLDATA (INTREQ, dev_ready, INT_V_LPT) }, - { FLDATA (ENABLE, dev_enable, INT_V_LPT) }, + { FLDATA (INTREQ, dev_int, INT_V_LPT) }, + { FLDATA (ENABLE, dev_enb, INT_V_LPT) }, { ORDATA (SVCST, lpt_svcst, 2) }, { ORDATA (SVCCH, lpt_svcch, 2) }, { BRDATA (BUF, lpt_buf, 8, 8, 120) }, @@ -118,12 +129,14 @@ DEVICE lpt_dev = { "LPT", &lpt_unit, lpt_reg, NULL, 1, 10, 31, 1, 8, 8, NULL, NULL, &lpt_reset, - NULL, NULL, NULL }; + NULL, NULL, NULL, + &lpt_dib, DEV_DISABLE }; /* IO routine */ -int32 lptio (int32 inst, int32 fnc, int32 dat) +int32 lptio (int32 inst, int32 fnc, int32 dat, int32 dev) { +int32 ch = lpt_dib.chan - 1; /* DMA/DMC chan */ int32 chr; switch (inst) { /* case on opcode */ @@ -133,13 +146,26 @@ case ioOCP: /* OCP */ 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 */ + CLR_INT (INT_LPT); /* clear int */ break; - case 007: /* init scan */ + case 003: /* init scan DMA/DMC */ 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 */ + lpt_eor = 0; + if (ch >= 0) lpt_dma = 1; /* try for DMA/DMC */ + lpt_dma = 0; + if (!sim_is_active (&lpt_unit)) { + lpt_rdy = 1; + if (lpt_dma) SET_CH_REQ (ch); } + CLR_INT (INT_LPT); /* clear int */ + break; + case 007: /* init scan IO bus*/ + lpt_prdn = 0; /* clear pr done */ + lpt_wdpos = 0; /* init scan pos */ + lpt_eor = 0; + lpt_dma = 0; /* IO bus */ + if (!sim_is_active (&lpt_unit)) lpt_rdy = 1; + CLR_INT (INT_LPT); /* clear int */ break; default: return IOBADFNC (dat); } @@ -148,7 +174,7 @@ case ioOCP: /* OCP */ case ioSKS: /* SKS */ switch (fnc) { /* case on fnc */ case 000: /* if xfer rdy */ - if (lpt_xfer) return IOSKIP (dat); + if (lpt_rdy) return IOSKIP (dat); break; case 002: /* if !alarm */ if (lpt_unit.flags & UNIT_ATT) return IOSKIP (dat); @@ -187,8 +213,8 @@ case ioSKS: /* SKS */ case ioOTA: /* OTA */ if (fnc) return IOBADFNC (dat); /* only fnc 0 */ - if (lpt_xfer) { /* xfer ready? */ - lpt_xfer = 0; /* clear xfer */ + if (lpt_rdy) { /* xfer ready? */ + lpt_rdy = 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; @@ -207,6 +233,10 @@ case ioOTA: /* OTA */ } /* end if endscan */ else sim_activate (&lpt_unit, lpt_xtime); return IOSKIP (dat); } /* skip return */ + break; + +case ioEND: /* end DMA/DMC */ + lpt_eor = 1; /* set end range */ break; } /* end case op */ return dat; } @@ -216,6 +246,7 @@ return dat; t_stat lpt_svc (UNIT *uptr) { int32 i; +int32 ch = lpt_dib.chan - 1; /* DMA/DMC chan */ static const char *lpt_cc[] = { "\r", "\n", @@ -224,12 +255,18 @@ static const char *lpt_cc[] = { if ((lpt_unit.flags & UNIT_ATT) == 0) /* attached? */ return IORETURN (lpt_stopioe, SCPE_UNATT); -lpt_xfer = 1; +if (lpt_dma) { /* DMA/DMC? */ + if (lpt_eor) SET_INT (INT_LPT); /* end range? intr */ + else { + lpt_rdy = 1; /* set ready */ + SET_CH_REQ (ch); } } /* get more data */ +else lpt_rdy = 1; /* IO, continue scan */ +if (lpt_dma && lpt_eor) SET_INT (INT_LPT); /* end of range? */ if (lpt_svcst & LPT_SVCSH) { /* shuttling */ - SET_READY (INT_LPT); /* interrupt */ + SET_INT (INT_LPT); /* interrupt */ if (lpt_crpos == 0) lpt_prdn = 1; } if (lpt_svcst & LPT_SVCPA) { /* paper advance */ - SET_READY (INT_LPT); /* interrupt */ + SET_INT (INT_LPT); /* interrupt */ for (i = LPT_WIDTH - 1; i >= 0; i++) { if (lpt_buf[i] != ' ') break; } lpt_buf[i + 1] = 0; @@ -250,12 +287,14 @@ 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_rdy = 0; /* not rdy to xfer */ lpt_prdn = 1; /* printing done */ +lpt_eor = 0; +lpt_dma = 0; 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); +CLR_INT (INT_LPT); /* clear int, enb */ +CLR_ENB (INT_LPT); sim_cancel (&lpt_unit); /* deactivate unit */ return SCPE_OK; } diff --git a/H316/h316_mt.c b/H316/h316_mt.c new file mode 100644 index 00000000..3bf7dced --- /dev/null +++ b/H316/h316_mt.c @@ -0,0 +1,520 @@ +/* h316_mt.c: H316/516 magnetic tape 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. + + mt 516-4100 seven track magnetic tape + + 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 "h316_defs.h" +#include "sim_tape.h" + +#define MT_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 */ +#define UNIT_WPRT (MTUF_WLK | UNIT_RO) /* write prot */ + +/* Function codes */ + +#define FNC_RBCD2 000 +#define FNC_RBIN2 001 +#define FNC_RBIN3 002 +#define FNC_DMANM 003 +#define FNC_WBCD2 004 +#define FNC_WBIN2 005 +#define FNC_WEOF 006 +#define FNC_IOBUS 007 +#define FNC_WBIN3 010 +#define FNC_FSR 011 +#define FNC_FSF 012 +#define FNC_DMAAU 013 +#define FNC_REW 014 +#define FNC_BSR 015 +#define FNC_BSF 016 +#define FNC_STOPW 017 +#define FNC_2ND 020 /* second state */ +#define FNC_NOP (FNC_STOPW|FNC_2ND) +#define FNC_EOM 040 /* end of motion */ + +/* Status - unit.UST */ + +#define STA_BOT 0000002 /* beg of tape */ +#define STA_EOT 0000001 /* end of tape */ + +extern int32 dev_int, dev_enb, chan_req; +extern int32 stop_inst; + +uint32 mt_buf = 0; /* data buffer */ +uint32 mt_usel = 0; /* unit select */ +uint32 mt_busy = 0; /* ctlr busy */ +uint32 mt_mdirq = 0; /* motion done int req */ +uint32 mt_rdy = 0; /* transfer ready (int) */ +uint32 mt_err = 0; /* error */ +uint32 mt_eof = 0; /* end of file */ +uint32 mt_eor = 0; /* transfer done */ +uint32 mt_dma = 0; /* DMA/DMC */ +uint32 mt_xtime = 16; /* transfer time */ +uint32 mt_ctime = 3000; /* start/stop time */ +uint32 mt_stopioe = 1; /* stop on I/O error */ +uint8 mtxb[DBSIZE] = { 0 }; /* data buffer */ +t_mtrlnt mt_ptr = 0, mt_max = 0; /* buffer ptrs */ + +int32 mtio (int32 inst, int32 fnc, int32 dat, int32 dev); +void mt_updint (uint32 rdy, uint32 mdone); +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_map_err (UNIT *uptr, t_stat st); +void mt_wrwd (UNIT *uptr, uint32 dat); + +/* 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 = { MT, IOBUS, MT_NUMDR, &mtio }; + +UNIT mt_unit[] = { + { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE + UNIT_DISABLE, 0) }, + { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE + UNIT_DISABLE, 0) }, + { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE + UNIT_DISABLE, 0) }, + { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE + UNIT_DISABLE, 0) } }; + +REG mt_reg[] = { + { ORDATA (BUF, mt_buf, 16) }, + { ORDATA (USEL, mt_usel, 2) }, + { FLDATA (BUSY, mt_busy, 0) }, + { FLDATA (RDY, mt_rdy, 0) }, + { FLDATA (ERR, mt_err, 0) }, + { FLDATA (EOF, mt_eof, 0) }, + { FLDATA (EOR, mt_eor, 0) }, + { FLDATA (MDIRQ, mt_mdirq, 0) }, + { FLDATA (DMA, mt_dma, 0) }, + { FLDATA (INTREQ, dev_int, INT_V_MT) }, + { FLDATA (ENABLE, dev_enb, INT_V_MT) }, + { BRDATA (DBUF, mtxb, 8, 8, DBSIZE) }, + { DRDATA (BPTR, mt_ptr, DB_N_SIZE + 1) }, + { DRDATA (BMAX, mt_max, DB_N_SIZE + 1) }, + { DRDATA (CTIME, mt_ctime, 24), REG_NZ + PV_LEFT }, + { DRDATA (XTIME, mt_xtime, 24), REG_NZ + PV_LEFT }, + { URDATA (POS, mt_unit[0].pos, 10, T_ADDR_W, 0, MT_NUMDR, PV_LEFT) }, + { URDATA (FNC, mt_unit[0].FNC, 8, 8, 0, MT_NUMDR, REG_HRO) }, + { URDATA (UST, mt_unit[0].UST, 8, 2, 0, MT_NUMDR, REG_HRO) }, + { ORDATA (CHAN, mt_dib.chan, 5), REG_HRO }, + { 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, NULL, "IOBUS", + &io_set_iobus, NULL, NULL }, + { MTAB_XTD|MTAB_VDV, 0, NULL, "DMC", + &io_set_dmc, NULL, NULL }, + { MTAB_XTD|MTAB_VDV, 0, NULL, "DMA", + &io_set_dma, NULL, NULL }, + { MTAB_XTD|MTAB_VDV, 0, "CHANNEL", NULL, + NULL, &io_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, + NULL, &mt_attach, &mt_detach, + &mt_dib, DEV_DISABLE }; + +/* IO routine */ + +int32 mtio (int32 inst, int32 fnc, int32 dat, int32 dev) +{ +uint32 u = dev & 03; +UNIT *uptr = mt_dev.units + u; +static uint8 wrt_fnc[16] = { /* >0 = wr, 1 = chan op */ + 0, 0, 0, 0, 1, 1, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0 }; + +switch (inst) { /* case on opcode */ +case ioOCP: + mt_updint (mt_rdy, 0); /* clear motion intr */ + mt_eof = 0; /* clear eof */ + switch (fnc) { /* case on function */ + case FNC_DMANM: /* set DMA/DMC */ + case FNC_DMAAU: + mt_usel = u; /* save unit select */ + if (mt_dib.chan) mt_dma = 1; /* if configured */ + break; + case FNC_IOBUS: /* set IOBUS */ + mt_usel = u; /* save unit select */ + mt_dma = 0; + break; + case FNC_STOPW: /* stop write */ + mt_usel = u; /* save unit select */ + mt_updint (0, mt_mdirq); /* clear ready */ + if (wrt_fnc[uptr->FNC & 017] == 1) /* writing? */ + mt_eor = 1; /* set transfer done */ + break; + default: /* motion command */ + if (mt_busy) return dat; /* nop if ctlr busy */ + mt_eor = 0; /* clr transfer done */ + mt_err = 0; /* clr error */ + mt_usel = u; /* save unit select */ + if (((uptr->flags & UNIT_ATT) == 0) || /* nop if not att */ + sim_is_active (uptr)) /* or busy */ + (IORETURN (mt_stopioe, SCPE_UNATT) | dat); + if (wrt_fnc[fnc] && (uptr->flags & UNIT_WPRT)) + return (STOP_MTWRP << IOT_V_REASON); + uptr->FNC = fnc; + uptr->UST = 0; + mt_busy = 1; + sim_activate (uptr, mt_ctime); /* schedule */ + break; } + break; +case ioINA: /* INA */ + if (fnc) return IOBADFNC (dat); /* fnc 0 only */ + if (mt_rdy) { /* ready? */ + mt_rdy = 0; /* clear ready */ + return IOSKIP (dat | mt_buf); } /* ret buf, skip */ + break; +case ioOTA: /* OTA */ + if (fnc) return IOBADFNC (dat); /* fnc 0 only */ + if (mt_rdy) { /* ready? */ + mt_rdy = 0; /* clear ready */ + mt_buf = dat; /* store buf */ + return IOSKIP (dat); } /* skip */ + break; +case ioSKS: + uptr = mt_dev.units + mt_usel; /* use saved unit sel */ + switch (fnc) { + case 000: /* ready */ + if (mt_rdy) return IOSKIP (dat); + break; + case 001: /* !busy */ + if (!mt_busy) return IOSKIP (dat); + break; + case 002: /* !error */ + if (!mt_err) return IOSKIP (dat); + break; + case 003: /* !BOT */ + if (!(uptr->UST & STA_BOT)) return IOSKIP (dat); + break; + case 004: /* !interrupting */ + if (!TST_INTREQ (INT_MT)) return IOSKIP (dat); + break; + case 005: /* !EOT */ + if (!(uptr->UST & STA_EOT)) return IOSKIP (dat); + break; + case 006: /* !EOF */ + if (!mt_eof) return IOSKIP (dat); + break; + case 007: /* !write prot */ + if (!(uptr->flags & UNIT_WPRT)) return IOSKIP (dat); + break; + case 011: /* operational */ + if ((uptr->flags & UNIT_ATT) && + ((uptr->FNC & 017) != FNC_REW)) return IOSKIP (dat); + break; + case 012: /* skip if !chan 2 */ + return IOSKIP (dat); + case 013: /* skip if !auto */ + return IOSKIP (dat); + case 014: /* !rewinding */ + uptr = mt_dev.units + (dev & 03); /* use specified unit */ + if ((uptr->FNC & 017) != FNC_REW) return IOSKIP (dat); + break; } + break; +case ioEND: /* end of range */ + mt_eor = 1; /* transfer done */ + break; } +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 mt_svc (UNIT *uptr) +{ +int32 ch = mt_dib.chan - 1; /* DMA/DMC ch */ +uint32 i, c1, c2, c3; +t_mtrlnt tbc; +t_stat st, r = SCPE_OK; + +if ((uptr->flags & UNIT_ATT) == 0) { /* offline? */ + mt_err = 1; + mt_busy = 0; + mt_updint (0, 1); /* cmd done */ + return IORETURN (mt_stopioe, SCPE_UNATT); } + +switch (uptr->FNC) { /* case on function */ +case FNC_REW: /* rewind (initial) */ + mt_busy = 0; /* ctlr not busy */ + uptr->FNC = uptr->FNC | FNC_2ND; + sim_activate (uptr, mt_ctime); + return SCPE_OK; /* continue */ + +case FNC_REW | FNC_2ND: /* rewind done */ + uptr->pos = 0; /* reposition file */ + uptr->UST = STA_BOT; /* set BOT */ + uptr->FNC = FNC_NOP; /* nop function */ + for (i = 0; i < MT_NUMDR; i++) { /* last rewind? */ + if ((mt_unit[i].FNC & 017) == FNC_REW) return SCPE_OK; } + mt_updint (mt_rdy, 1); /* yes, motion done */ + return SCPE_OK; + +case FNC_WEOF: /* write file mark */ + if (st = sim_tape_wrtmk (uptr)) /* write tmk, err? */ + r = mt_map_err (uptr, st); /* map error */ + break; /* sched end motion */ + +case FNC_FSR: /* space fwd rec */ + if (st = sim_tape_sprecf (uptr, &tbc)) /* space fwd, err? */ + r = mt_map_err (uptr, st); /* map error */ + break; /* sched end motion */ + +case FNC_BSR: /* space rev rec */ + if (st = sim_tape_sprecr (uptr, &tbc)) /* space rev, err? */ + r = mt_map_err (uptr, st); /* map error */ + break; /* sched end motion */ + +case FNC_FSF: /* space fwd file */ + while ((st = sim_tape_sprecf (uptr, &tbc)) == MTSE_OK) ; + r = mt_map_err (uptr, st); /* map error */ + break; /* sched end motion */ + +case FNC_BSF: /* space rev file */ + while ((st = sim_tape_sprecr (uptr, &tbc)) == MTSE_OK) ; + r = mt_map_err (uptr, st); /* map error */ + break; /* sched end motion */ + +case FNC_EOM: /* end of motion */ + uptr->FNC = FNC_NOP; /* nop function */ + mt_busy = 0; /* not busy */ + mt_updint (mt_rdy, 1); /* end of motion */ + return SCPE_OK; /* done! */ + +/* Unit service, continued */ + +case FNC_RBCD2: case FNC_RBIN2: case FNC_RBIN3: /* read first */ + mt_ptr = 0; /* clr buf ptr */ + st = sim_tape_rdrecf (uptr, mtxb, &mt_max, DBSIZE); /* read rec */ + if (st != MTSE_OK) { /* error? */ + r = mt_map_err (uptr, st); /* map error */ + break; } /* sched end motion */ + uptr->FNC = uptr->FNC | FNC_2ND; /* next state */ + sim_activate (uptr, mt_xtime); /* sched xfer */ + return SCPE_OK; + +case FNC_RBCD2 | FNC_2ND: /* read, word */ +case FNC_RBIN2 | FNC_2ND: +case FNC_RBIN3 | FNC_2ND: + if (mt_ptr >= mt_max) break; /* record done? */ + c1 = mtxb[mt_ptr++] & 077; /* get 2 chars */ + c2 = mtxb[mt_ptr++] & 077; + if (uptr->FNC == (FNC_RBCD2 | FNC_2ND)) { /* BCD? */ + if (c1 == 012) c1 = 0; /* change 12 to 0 */ + if (c2 == 012) c2 = 0; } + if (uptr->FNC == (FNC_RBIN3 | FNC_2ND)) { /* read 3? */ + if (mt_ptr >= mt_max) break; /* lose wd if not enuf */ + c3 = mtxb[mt_ptr++] & 017; } /* get 3rd char */ + else c3 = 0; + sim_activate (uptr, mt_xtime); /* no, sched word */ + if (mt_eor) return SCPE_OK; /* xfer done? */ + mt_buf = (c1 << 10) | (c2 << 4) | c3; /* pack chars */ + if (mt_rdy) mt_err = 1; /* buf full? err */ + mt_updint (1, mt_mdirq); /* set ready */ + if (mt_dma) SET_CH_REQ (ch); /* DMC/DMA? req chan */ + return SCPE_OK; /* continue */ + +case FNC_WBCD2: case FNC_WBIN2: case FNC_WBIN3: /* write first */ + mt_ptr = 0; /* clear buf ptr */ + mt_updint (1, mt_mdirq); /* set ready */ + if (mt_dma) SET_CH_REQ (ch); /* DMC/DMA? req chan */ + uptr->FNC = uptr->FNC | FNC_2ND; /* next state */ + sim_activate (uptr, mt_xtime); /* sched xfer */ + return SCPE_OK; /* continue */ + +case FNC_WBCD2 | FNC_2ND: /* write, word */ +case FNC_WBIN2 | FNC_2ND: +case FNC_WBIN3 | FNC_2ND: + if (mt_eor || mt_rdy) { /* done or no data? */ + if (!mt_rdy) mt_wrwd (uptr, mt_buf); /* write last word */ + if (mt_ptr) { /* any data? */ + if (st = sim_tape_wrrecf (uptr, mtxb, mt_ptr)) /* write, err? */ + r = mt_map_err (uptr, st); } /* map error */ + break; } /* sched end motion */ + mt_wrwd (uptr, mt_buf); /* write word */ + sim_activate (uptr, mt_xtime); /* no, sched word */ + mt_updint (1, mt_mdirq); /* set ready */ + if (mt_dma) SET_CH_REQ (ch); /* DMC/DMA? req chan */ + return SCPE_OK; /* continue */ + +default: /* unknown */ + break; } + +/* End of command, process error or schedule end of motion */ + +if (r != SCPE_OK) { + uptr->FNC = FNC_NOP; /* nop function */ + mt_busy = 0; /* not busy */ + mt_updint (mt_rdy, 1); /* end of motion */ + return r; } +uptr->FNC = FNC_EOM; /* sched end motion */ +sim_activate (uptr, mt_ctime); +return SCPE_OK; +} + +/* Write word to buffer */ + +void mt_wrwd (UNIT *uptr, uint32 dat) +{ +uint32 c1, c2; + +c1 = (dat >> 10) & 077; /* get 2 chars */ +c2 = (dat >> 4) & 077; +if (uptr->FNC == (FNC_WBCD2 | FNC_2ND)) { /* BCD? */ + if (c1 == 0) c1 = 012; /* change 0 to 12 */ + if (c2 == 0) c2 = 012; } +if (mt_ptr < DBSIZE) mtxb[mt_ptr++] = c1; /* store 2 char */ +if (mt_ptr < DBSIZE) mtxb[mt_ptr++] = c2; +if ((uptr->FNC == (FNC_WBIN3 | FNC_2ND)) && /* write 3? */ + (mt_ptr < DBSIZE)) mtxb[mt_ptr++] = mt_buf & 017; +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_err = 1; /* reject */ +case MTSE_OK: /* no error */ + return SCPE_IERR; /* never get here! */ +case MTSE_TMK: /* end of file */ + mt_eof = 1; /* eof */ + break; +case MTSE_INVRL: /* invalid rec lnt */ + mt_err = 1; + return SCPE_MTRLNT; +case MTSE_IOERR: /* IO error */ + mt_err = 1; /* error */ + if (mt_stopioe) return SCPE_IOERR; + break; +case MTSE_RECE: /* record in error */ +case MTSE_EOM: /* end of medium */ + mt_err = 1; /* error */ + break; +case MTSE_BOT: /* reverse into BOT */ + uptr->UST = STA_BOT; /* set status */ + break; +case MTSE_WRP: /* write protect */ + mt_err = 1; /* error */ + return STOP_MTWRP; } +return SCPE_OK; +} + +/* Update interrupts */ + +void mt_updint (uint32 rdy, uint32 mdirq) +{ +mt_rdy = rdy; /* store new ready */ +mt_mdirq = mdirq; /* store new motion irq */ +if ((mt_rdy && !mt_dma) || mt_mdirq) SET_INT (INT_MT); /* update int request */ +else CLR_INT (INT_MT); +return; +} + +/* Reset routine */ + +t_stat mt_reset (DEVICE *dptr) +{ +int32 i; +UNIT *uptr; + +mt_buf = 0; /* clear state */ +mt_usel = 0; +mt_mdirq = 0; +mt_eor = 0; +mt_busy = 0; +mt_rdy = 0; +mt_eof = 0; +mt_err = 0; +mt_dma = 0; +CLR_INT (INT_MT); /* clear int, enb */ +CLR_ENB (INT_MT); +for (i = 0; i < MT_NUMDR; i++) { /* loop thru units */ + uptr = mt_dev.units + i; + sim_tape_reset (uptr); /* reset tape */ + sim_cancel (uptr); /* cancel op */ + uptr->UST = uptr->pos? 0: STA_BOT; /* update status */ + uptr->FNC = FNC_NOP; } +return SCPE_OK; +} + +/* Attach routine */ + +t_stat mt_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 mt_detach (UNIT* uptr) +{ +uptr->UST = 0; /* update status */ +uptr->FNC = FNC_NOP; /* nop function */ +return sim_tape_detach (uptr); /* detach unit */ +} diff --git a/H316/h316_stddev.c b/H316/h316_stddev.c index 2ff32fbe..ebdaf590 100644 --- a/H316/h316_stddev.c +++ b/H316/h316_stddev.c @@ -28,6 +28,7 @@ tty 316/516-33 teleprinter clk/options 316/516-12 real time clocks/internal options + 24-Oct-03 RMS Added DMA/DMC support 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 @@ -50,7 +51,7 @@ 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 int32 dev_int, dev_enb; extern UNIT cpu_unit; int32 ptr_stopioe = 0, ptp_stopioe = 0; /* stop on error */ @@ -58,15 +59,19 @@ 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 */ +int32 ptrio (int32 inst, int32 fnc, int32 dat, int32 dev); 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 fnc, int32 dat, int32 dev); t_stat ptp_svc (UNIT *uptr); t_stat ptp_reset (DEVICE *dptr); +int32 ttyio (int32 inst, int32 fnc, int32 dat, int32 dev); 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 fnc, int32 dat, int32 dev); 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); @@ -80,14 +85,16 @@ t_stat clk_show_freq (FILE *st, UNIT *uptr, int32 val, void *desc); ptr_reg PTR register list */ +DIB ptr_dib = { PTR, IOBUS, 1, &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 (READY, dev_ready, INT_V_PTR) }, - { FLDATA (ENABLE, dev_enable, INT_V_PTR) }, + { FLDATA (READY, dev_int, INT_V_PTR) }, + { FLDATA (ENABLE, dev_enb, 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) }, @@ -97,7 +104,8 @@ DEVICE ptr_dev = { "PTR", &ptr_unit, ptr_reg, NULL, 1, 10, 31, 1, 8, 8, NULL, NULL, &ptr_reset, - &ptr_boot, NULL, NULL }; + &ptr_boot, NULL, NULL, + &ptr_dib, 0 }; /* PTP data structures @@ -107,13 +115,15 @@ DEVICE ptr_dev = { ptp_reg PTP register list */ +DIB ptp_dib = { PTP, IOBUS, 1, &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 (READY, dev_ready, INT_V_PTP) }, - { FLDATA (ENABLE, dev_enable, INT_V_PTP) }, + { FLDATA (READY, dev_int, INT_V_PTP) }, + { FLDATA (ENABLE, dev_enb, 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 }, @@ -121,12 +131,12 @@ REG ptp_reg[] = { { 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, NULL, NULL, + &ptp_dib, 0 }; /* TTY data structures @@ -139,6 +149,8 @@ DEVICE ptp_dev = { #define TTI 0 #define TTO 1 +DIB tty_dib = { TTY, IOBUS, 1, &ttyio }; + UNIT tty_unit[] = { { UDATA (&tti_svc, UNIT_KSR, 0), KBD_POLL_WAIT }, { UDATA (&tto_svc, UNIT_KSR, 0), SERIAL_OUT_WAIT } }; @@ -146,8 +158,8 @@ UNIT tty_unit[] = { 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) }, + { FLDATA (READY, dev_int, INT_V_TTY) }, + { FLDATA (ENABLE, dev_enb, 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 }, @@ -164,7 +176,8 @@ DEVICE tty_dev = { "TTY", tty_unit, tty_reg, tty_mod, 2, 10, 31, 1, 8, 8, NULL, NULL, &tty_reset, - NULL, NULL, NULL }; + NULL, NULL, NULL, + &tty_dib, 0 }; /* CLK data structures @@ -174,12 +187,14 @@ DEVICE tty_dev = { clk_reg CLK register list */ +DIB clk_dib = { CLK_KEYS, IOBUS, 1, &clkio }; + 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) }, + { FLDATA (READY, dev_int, INT_V_CLK) }, + { FLDATA (ENABLE, dev_enb, INT_V_CLK) }, { DRDATA (TIME, clk_unit.wait, 24), REG_NZ + PV_LEFT }, { DRDATA (TPS, clk_tps, 8), PV_LEFT + REG_HRO }, { NULL } }; @@ -197,11 +212,12 @@ DEVICE clk_dev = { "CLK", &clk_unit, clk_reg, clk_mod, 1, 0, 0, 0, 0, 0, NULL, NULL, &clk_reset, - NULL, NULL, NULL }; + NULL, NULL, NULL, + &clk_dib, 0 }; /* Paper tape reader: IO routine */ -int32 ptrio (int32 inst, int32 fnc, int32 dat) +int32 ptrio (int32 inst, int32 fnc, int32 dat, int32 dev) { switch (inst) { /* case on opcode */ case ioOCP: /* OCP */ @@ -211,14 +227,14 @@ case ioOCP: /* OCP */ 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 */ + if (((fnc == 0) && TST_INT (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 */ + if (fnc) return IOBADFNC (dat); /* only fnc 0 */ + if (TST_INT (INT_PTR)) { /* ready? */ + CLR_INT (INT_PTR); /* clear ready */ return IOSKIP (ptr_unit.buf | dat); } /* ret buf, skip */ break; } /* end case op */ return dat; @@ -239,7 +255,7 @@ if ((temp = getc (ptr_unit.fileref)) == EOF) { /* read byte */ else perror ("PTR I/O error"); clearerr (ptr_unit.fileref); return SCPE_IOERR; } -SET_READY (INT_PTR); /* set ready flag */ +SET_INT (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 */ @@ -250,8 +266,8 @@ return SCPE_OK; t_stat ptr_reset (DEVICE *dptr) { -CLR_READY (INT_PTR); /* clear ready, enb */ -CLR_ENABLE (INT_PTR); +CLR_INT (INT_PTR); /* clear ready, enb */ +CLR_ENB (INT_PTR); ptr_unit.buf = 0; /* clear buffer */ sim_cancel (&ptr_unit); /* deactivate unit */ return SCPE_OK; @@ -292,13 +308,13 @@ return SCPE_OK; /* Paper tape punch: IO routine */ -int32 ptpio (int32 inst, int32 fnc, int32 dat) +int32 ptpio (int32 inst, int32 fnc, int32 dat, int32 dev) { 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 */ + CLR_INT (INT_PTP); /* not ready */ ptp_power = 0; /* turn off power */ sim_cancel (&ptp_unit); } /* stop punch */ else if (ptp_power == 0) /* fnc 0? start */ @@ -307,7 +323,7 @@ case ioOCP: /* OCP */ 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 */ + if (((fnc == 00) && TST_INT (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 */ @@ -315,8 +331,8 @@ case ioSKS: /* SKS */ 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 */ + if (TST_INT (INT_PTP)) { /* if ptp ready */ + CLR_INT (INT_PTP); /* clear ready */ ptp_unit.buf = dat & 0377; /* store byte */ sim_activate (&ptp_unit, ptp_unit.wait); return IOSKIP (dat); } /* skip return */ @@ -329,7 +345,7 @@ return dat; t_stat ptp_svc (UNIT *uptr) { -SET_READY (INT_PTP); /* set flag */ +SET_INT (INT_PTP); /* set flag */ if (ptp_power == 0) { /* power on? */ ptp_power = 1; /* ptp is ready */ return SCPE_OK; } @@ -347,8 +363,8 @@ return SCPE_OK; t_stat ptp_reset (DEVICE *dptr) { -CLR_READY (INT_PTP); /* clear ready, enb */ -CLR_ENABLE (INT_PTP); +CLR_INT (INT_PTP); /* clear ready, enb */ +CLR_ENB (INT_PTP); ptp_power = 0; /* power off */ ptp_unit.buf = 0; /* clear buffer */ sim_cancel (&ptp_unit); /* deactivate unit */ @@ -357,22 +373,22 @@ return SCPE_OK; /* Terminal: IO routine */ -int32 ttyio (int32 inst, int32 fnc, int32 dat) +int32 ttyio (int32 inst, int32 fnc, int32 dat, int32 dev) { 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); + SET_INT (INT_TTY); tty_mode = 1; } /* mode is output */ else if ((fnc == 0) && tty_mode) { /* output to input? */ - CLR_READY (INT_TTY); /* clear ready */ + CLR_INT (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 */ + if (((fnc == 0) && TST_INT (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 */ @@ -381,22 +397,22 @@ case ioSKS: /* SKS */ 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 */ + if (fnc & 005) return IOBADFNC (dat); /* only 0,2 */ + if (TST_INT (INT_TTY)) { /* ready? */ + if (tty_mode == 0) CLR_INT (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? */ + if (TST_INT (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); } + CLR_INT (INT_TTY); } return IOSKIP (dat); } break; } /* end case op */ return dat; @@ -419,7 +435,7 @@ 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 */ + SET_INT (INT_TTY); /* set flag */ if (out) sim_putchar (out); } /* echo */ return SCPE_OK; } @@ -429,12 +445,14 @@ 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 */ +if ((r = sim_putchar_s (c)) != SCPE_OK) { /* output; error? */ + sim_activate (uptr, uptr->wait); /* try again */ + return ((r == SCPE_STALL)? SCPE_OK: r); } /* !stall? report */ +SET_INT (INT_TTY); /* set done flag */ tty_unit[TTO].pos = tty_unit[TTO].pos + 1; return SCPE_OK; } @@ -443,8 +461,8 @@ return SCPE_OK; t_stat tty_reset (DEVICE *dptr) { -CLR_READY (INT_TTY); /* clear ready, enb */ -CLR_ENABLE (INT_TTY); +CLR_INT (INT_TTY); /* clear ready, enb */ +CLR_ENB (INT_TTY); tty_mode = 0; /* mode = input */ tty_buf = 0; sim_activate (&tty_unit[TTI], tty_unit[TTI].wait); /* activate poll */ @@ -461,12 +479,12 @@ return SCPE_OK; /* Clock/options: IO routine */ -int32 clkio (int32 inst, int32 fnc, int32 dat) +int32 clkio (int32 inst, int32 fnc, int32 dat, int32 dev) { switch (inst) { /* case on opcode */ case ioOCP: /* OCP */ if (fnc & 015) return IOBADFNC (dat); /* only fnc 0,2 */ - CLR_READY (INT_CLK); /* reset ready */ + CLR_INT (INT_CLK); /* reset ready */ if (fnc) sim_cancel (&clk_unit); /* fnc = 2? stop */ else { /* fnc = 0? */ if (!sim_is_active (&clk_unit)) @@ -477,13 +495,13 @@ 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))) + if (((fnc == 002) && !TST_INT (INT_MPE)) || + ((fnc == 012) && TST_INT (INT_MPE))) return IOSKIP (dat); } else return IOBADFNC (dat); /* invalid fnc */ break; case ioOTA: /* OTA */ - if (fnc == 000) dev_enable = dat; /* SMK */ + if (fnc == 000) dev_enb = dat; /* SMK */ else if (fnc == 010) { /* OTK */ C = (dat >> 15) & 1; /* set C */ if (cpu_unit.flags & UNIT_HSA) /* HSA included? */ @@ -505,7 +523,7 @@ 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 */ +if (M[M_CLK] == 0) SET_INT (INT_CLK); /* = 0? set flag */ sim_activate (&clk_unit, sim_rtc_calb (clk_tps)); /* reactivate */ return SCPE_OK; } @@ -514,8 +532,8 @@ return SCPE_OK; t_stat clk_reset (DEVICE *dptr) { -CLR_READY (INT_CLK); /* clear ready, enb */ -CLR_ENABLE (INT_CLK); +CLR_INT (INT_CLK); /* clear ready, enb */ +CLR_ENB (INT_CLK); sim_cancel (&clk_unit); /* deactivate unit */ return SCPE_OK; } diff --git a/H316/h316_sys.c b/H316/h316_sys.c index a280d4a1..0c3c6502 100644 --- a/H316/h316_sys.c +++ b/H316/h316_sys.c @@ -23,6 +23,7 @@ be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. + 24-Oct-03 RMS Added DMA/DMC support 17-Sep-01 RMS Removed multiconsole support */ @@ -31,9 +32,14 @@ extern DEVICE cpu_dev; extern UNIT cpu_unit; -extern DEVICE ptr_dev, ptp_dev; -extern DEVICE tty_dev, lpt_dev; +extern DEVICE ptr_dev; +extern DEVICE ptp_dev; +extern DEVICE tty_dev; +extern DEVICE lpt_dev; extern DEVICE clk_dev; +extern DEVICE dp_dev; +extern DEVICE fhd_dev; +extern DEVICE mt_dev; extern REG cpu_reg[]; extern uint16 M[]; extern int32 sim_switches; @@ -54,10 +60,16 @@ REG *sim_PC = &cpu_reg[0]; int32 sim_emax = 1; -DEVICE *sim_devices[] = { &cpu_dev, - &ptr_dev, &ptp_dev, - &tty_dev, &lpt_dev, +DEVICE *sim_devices[] = { + &cpu_dev, + &ptr_dev, + &ptp_dev, + &tty_dev, + &lpt_dev, &clk_dev, + &dp_dev, + &fhd_dev, + &mt_dev, NULL }; const char *sim_stop_messages[] = { @@ -66,7 +78,11 @@ const char *sim_stop_messages[] = { "Unimplemented I/O device", "HALT instruction", "Breakpoint", - "Indirect address loop" }; + "Indirect address loop", + "DMA error", + "MT write protected", + "DP write overrun, track destroyed", + "DP track format invalid" }; /* Binary loader diff --git a/HP2100/hp2100_dr.c b/HP2100/hp2100_dr.c index 9a02a638..d72d743e 100644 --- a/HP2100/hp2100_dr.c +++ b/HP2100/hp2100_dr.c @@ -291,6 +291,7 @@ t_stat drc_svc (UNIT *uptr) { int32 devd, trk, sec; uint32 da; +uint16 *bptr = uptr->filebuf; if ((uptr->flags & UNIT_ATT) == 0) { drc_sta = DRS_ABO; @@ -304,7 +305,7 @@ 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; + bptr[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 */ @@ -313,12 +314,12 @@ if (drc_cw & CW_WR) { /* write? */ 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; } + bptr[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); + else drd_ibuf = bptr[da + drd_ptr]; drd_ptr = dr_incda (trk, sec, drd_ptr); setFLG (devd); /* set dch flg */ sim_activate (uptr, dr_time); } /* sched next word */ @@ -367,6 +368,7 @@ 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) diff --git a/HP2100/hp2100_ipl.c b/HP2100/hp2100_ipl.c index ede40ccf..49568518 100644 --- a/HP2100/hp2100_ipl.c +++ b/HP2100/hp2100_ipl.c @@ -25,6 +25,7 @@ ipli, iplo 12556B interprocessor link pair + 21-Dec-03 RMS Adjusted ipl_ptime for TSB (from Mike Gemeny) 09-May-03 RMS Added network device flag 31-Jan-03 RMS Links are full duplex (found by Mike Gemeny) */ @@ -49,7 +50,7 @@ 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_ptime = 31; /* polling interval */ int32 ipl_stopioe = 0; /* stop on error */ int32 ipl_hold[2] = { 0 }; /* holding character */ @@ -339,7 +340,7 @@ return SCPE_OK; t_stat ipl_detach (UNIT *uptr) { -if ((uptr->flags & UNIT_ATT) == 0) return SCPE_OK; /* attached? */ +if (!(uptr->flags & UNIT_ATT)) 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 */ diff --git a/HP2100/hp2100_mt.c b/HP2100/hp2100_mt.c index 320dc7ee..56ddc636 100644 --- a/HP2100/hp2100_mt.c +++ b/HP2100/hp2100_mt.c @@ -25,6 +25,7 @@ mt 12559A 3030 nine track magnetic tape + 21-Dec-03 RMS Adjusted msc_ctime for TSB (from Mike Gemeny) 25-Apr-03 RMS Revised for extended file support 28-Mar-03 RMS Added multiformat support 28-Feb-03 RMS Revised for magtape library @@ -92,7 +93,7 @@ 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_ctime = 40; /* command wait */ int32 mtc_gtime = 1000; /* gap stop time */ int32 mtc_xtime = 15; /* data xfer time */ int32 mtc_stopioe = 1; /* stop on error */ diff --git a/HP2100/hp2100_mux.c b/HP2100/hp2100_mux.c index 0d0bb4d3..4647462a 100644 --- a/HP2100/hp2100_mux.c +++ b/HP2100/hp2100_mux.c @@ -25,6 +25,7 @@ mux,muxl,muxc 12920A terminal multiplexor + 21-Dec-03 RMS Added invalid character screening for TSB (from Mike Gemeny) 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 @@ -526,7 +527,10 @@ if (mux_ldsc[ln].conn) { /* connected? */ 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 */ + if (!(muxl_unit[ln].flags & UNIT_8B) && /* not transparent? */ + (c != 0x7f) && (c != 0x13) && /* not del, ^S? */ + (c != 0x11) && (c != 0x5)) /* not ^Q, ^E? */ + tmxr_putc_ln (lp, c); /* output char */ tmxr_poll_tx (&mux_desc); } } /* poll xmt */ else { /* buf full */ tmxr_poll_tx (&mux_desc); /* poll xmt */ diff --git a/HP2100/hp2100_stddev.c b/HP2100/hp2100_stddev.c index e048401d..ca8ff209 100644 --- a/HP2100/hp2100_stddev.c +++ b/HP2100/hp2100_stddev.c @@ -1,6 +1,6 @@ /* hp2100_stddev.c: HP2100 standard devices simulator - Copyright (c) 1993-2003, Robert M. Supnik + Copyright (c) 1993-2004, 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"), @@ -28,6 +28,7 @@ tty 12531C buffered teleprinter interface clk 12539C time base generator + 29-Mar-03 RMS Added support for console backpressure 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 @@ -538,15 +539,20 @@ return dat; t_stat tto_out (int32 c) { -t_stat ret = SCPE_OK; +t_stat r; 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 */ + if (r = sim_putchar_s (c)) return r; /* output char */ tty_unit[TTO].pos = tty_unit[TTO].pos + 1; } +return SCPE_OK; +} + +t_stat ttp_out (int32 c) +{ if (tty_mode & TM_PUN) { /* punching? */ if ((tty_unit[TTP].flags & UNIT_ATT) == 0) /* attached? */ return IORETURN (ttp_stopioe, SCPE_UNATT); @@ -555,7 +561,7 @@ if (tty_mode & TM_PUN) { /* punching? */ clearerr (tty_unit[TTP].fileref); return SCPE_IOERR; } tty_unit[TTP].pos = ftell (tty_unit[TTP].fileref); } -return ret; +return SCPE_OK; } t_stat tti_svc (UNIT *uptr) @@ -574,19 +580,25 @@ 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? */ + if (c) { + tto_out (c); /* echo? */ + return ttp_out (c); } } /* punch? */ return SCPE_OK; } t_stat tto_svc (UNIT *uptr) { int32 c, dev; +t_stat r; +c = tty_buf; /* get char */ +tty_buf = 0377; /* defang buf */ +if ((r = tto_out (c)) != SCPE_OK) { /* output; error? */ + sim_activate (uptr, uptr->wait); /* retry */ + return ((r == SCPE_STALL)? SCPE_OK: r); } /* !stall? report */ 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 */ +return ttp_out (c); /* punch if enabled */ } /* Reset routine */ diff --git a/I1620/i1620_cpu.c b/I1620/i1620_cpu.c index f6cfa8ec..3a8a718f 100644 --- a/I1620/i1620_cpu.c +++ b/I1620/i1620_cpu.c @@ -26,6 +26,7 @@ This CPU module incorporates code and comments from the 1620 simulator by Geoff Kuenning, with his permission. + 02-Nov-03 RMS Fixed bug in branch digit (found by Dave Babcock) 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) @@ -567,10 +568,10 @@ case OP_BB: else reason = STOP_INVRTN; /* MAR check */ break; -/* Branch on digit (zero) - P,Q are valid */ +/* Branch on digit (not zero) - P,Q are valid */ case OP_BD: - if ((M[QAR] & DIGIT) == 0) { /* digit == 0? */ + if ((M[QAR] & DIGIT) != 0) { /* digit != 0? */ BRANCH (PAR); } /* branch */ break; diff --git a/I1620/i1620_lp.c b/I1620/i1620_lp.c index 28283f61..3ad1e1c4 100644 --- a/I1620/i1620_lp.c +++ b/I1620/i1620_lp.c @@ -25,6 +25,7 @@ lpt 1443 line printer + 29-Dec-03 RMS Fixed bug in scheduling 25-Apr-03 RMS Revised for extended file support */ @@ -217,7 +218,7 @@ if ((lpt_unit.flags & UNIT_ATT) == 0) { /* not attached? */ return SCPE_UNATT; } ind[IN_PRBSY] = 1; /* print busy */ -sim_activate (&lpt_unit, lpt_unit.time); /* start timer */ +sim_activate (&lpt_unit, lpt_unit.wait); /* start timer */ for (i = LPT_WIDTH; i <= LPT_BSIZE; i++) /* clear unprintable */ lpt_buf[i] = ' '; diff --git a/Ibm1130/1130consoleblank.bmp b/Ibm1130/1130consoleblank.bmp index 9b6c7780..4b989529 100644 Binary files a/Ibm1130/1130consoleblank.bmp and b/Ibm1130/1130consoleblank.bmp differ diff --git a/Ibm1130/1132empty.bmp b/Ibm1130/1132empty.bmp new file mode 100644 index 00000000..3ccc082c Binary files /dev/null and b/Ibm1130/1132empty.bmp differ diff --git a/Ibm1130/1132full.bmp b/Ibm1130/1132full.bmp new file mode 100644 index 00000000..4705d1b6 Binary files /dev/null and b/Ibm1130/1132full.bmp differ diff --git a/Ibm1130/1442empty.bmp b/Ibm1130/1442empty.bmp new file mode 100644 index 00000000..8b9f667b Binary files /dev/null and b/Ibm1130/1442empty.bmp differ diff --git a/Ibm1130/1442eof.bmp b/Ibm1130/1442eof.bmp new file mode 100644 index 00000000..2bf679a9 Binary files /dev/null and b/Ibm1130/1442eof.bmp differ diff --git a/Ibm1130/1442full.bmp b/Ibm1130/1442full.bmp new file mode 100644 index 00000000..e6ba0c5b Binary files /dev/null and b/Ibm1130/1442full.bmp differ diff --git a/Ibm1130/1442middle.bmp b/Ibm1130/1442middle.bmp new file mode 100644 index 00000000..af45289f Binary files /dev/null and b/Ibm1130/1442middle.bmp differ diff --git a/Ibm1130/ibm1130.mak b/Ibm1130/ibm1130.mak index aaf8e0fb..fc839dbb 100644 --- a/Ibm1130/ibm1130.mak +++ b/Ibm1130/ibm1130.mak @@ -82,9 +82,9 @@ $(OUTDIR)/ibm1130.bsc : $(OUTDIR) $(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 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib comdlg32.lib advapi32.lib wsock32.lib shell32.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\ + wsock32.lib shell32.lib /NOLOGO /SUBSYSTEM:console /INCREMENTAL:no\ /PDB:$(OUTDIR)/"ibm1130.pdb" /MACHINE:I386 /OUT:$(OUTDIR)/"ibm1130.exe" DEF_FILE= LINK32_OBJS= \ @@ -161,9 +161,10 @@ $(OUTDIR)/ibm1130.bsc : $(OUTDIR) $(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 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib comdlg32.lib advapi32.lib wsock32.lib shell32.lib /NOLOGO /SUBSYSTEM:console /DEBUG /MACHINE:I386 +# SUBTRACT LINK32 /MAP LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib comdlg32.lib advapi32.lib\ - wsock32.lib /NOLOGO /SUBSYSTEM:console /INCREMENTAL:yes\ + wsock32.lib shell32.lib /NOLOGO /SUBSYSTEM:console /INCREMENTAL:yes\ /PDB:$(OUTDIR)/"ibm1130.pdb" /DEBUG /MACHINE:I386 /OUT:$(OUTDIR)/"ibm1130.exe" DEF_FILE= LINK32_OBJS= \ diff --git a/Ibm1130/ibm1130.rc b/Ibm1130/ibm1130.rc index 64f9da0d..83e141c9 100644 --- a/Ibm1130/ibm1130.rc +++ b/Ibm1130/ibm1130.rc @@ -19,7 +19,7 @@ // TEXTINCLUDE // -1 TEXTINCLUDE DISCARDABLE +1 TEXTINCLUDE DISCARDABLE BEGIN "ibm1130res.h\0" END @@ -45,9 +45,21 @@ END // Bitmap // -IDB_CONSOLE BITMAP DISCARDABLE "1130consoleblank.bmp" +IDB_CONSOLE BITMAP "1130consoleblank.bmp" +FULL_1442 BITMAP "1442full.bmp" +EOF_1442 BITMAP "1442eof.bmp" +EMPTY_1442 BITMAP "1442empty.bmp" +MIDDLE_1442 BITMAP "1442middle.bmp" +FULL_1132 BITMAP "1132full.bmp" +EMPTY_1132 BITMAP "1132empty.bmp" -IDC_HAND CURSOR DISCARDABLE "HAND.CUR" + +///////////////////////////////////////////////////////////////////////////// +// +// Cursor +// + +IDC_HAND CURSOR "HAND.CUR" #ifndef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// diff --git a/Ibm1130/ibm1130_cpu.c b/Ibm1130/ibm1130_cpu.c index f258bda8..5f3add4b 100644 --- a/Ibm1130/ibm1130_cpu.c +++ b/Ibm1130/ibm1130_cpu.c @@ -17,6 +17,7 @@ 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 + 24-Nov-03 BLK Fixed carry bit error in subtract and subtract double, found by Bob Flanders The register state for the IBM 1130 CPU is: @@ -556,6 +557,8 @@ t_stat sim_instr (void) 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); +// fprintf(stderr, "* XIO %s %s mod %02x addr %04x\n", 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) { @@ -895,7 +898,7 @@ t_stat sim_instr (void) src2 = ReadW(eaddr); ACC = (ACC-src2) & 0xFFFF; - C = src2 < src; + C = src < src2; if (! V) V = SIGN_BIT((src ^ src2) & (src ^ ACC)); break; @@ -907,7 +910,7 @@ t_stat sim_instr (void) ACC = (dst >> 16) & 0xFFFF; EXT = dst & 0xFFFF; - C = (unsigned int32) src2 < (unsigned int32) src; + C = (unsigned int32) src < (unsigned int32) src2; if (! V) V = DWSIGN_BIT((src ^ src2) & (src ^ dst)); break; @@ -1527,7 +1530,7 @@ static t_stat cpu_attach (UNIT *uptr, char *cptr) fclose(fd); } - return attach_unit(uptr, cptr); + return attach_unit(uptr, quotefix(cptr)); /* fix quotes in filenames & attach */ } static void trace_instruction (void) @@ -1795,6 +1798,7 @@ static void cgi_stop(t_stat reason) ORIGIN orig; char *msg; } pretstop[] = { + 0x8000, O_FORTRAN, "I/O attempted on invalid unit # or uninstalled device (just a guess)", 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", diff --git a/Ibm1130/ibm1130_cr.c b/Ibm1130/ibm1130_cr.c index 283d107c..a1da52db 100644 --- a/Ibm1130/ibm1130_cr.c +++ b/Ibm1130/ibm1130_cr.c @@ -14,6 +14,9 @@ * This is not a supported product, but I welcome bug reports and fixes. * Mail to simh@ibm1130.org + * Update 2003-11-25: Physical card reader support working, may not be perfect. + Changed magic filename for stdin to "(stdin)". + * Update 2003-07-23: Added autodetect for card decks (029 vs binary), made this the default. @@ -49,8 +52,10 @@ -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) - (See below for a discussion of tab formatting) + -p means that filename is a COM port connected to a physical card reader using + the CARDREAD interface (see http://ibm1130.org/sim/downloads) The ATTACH CP command accepts the -d switch. @@ -205,7 +210,7 @@ * CGI mode note: The command - attach cr - + attach cr (stdin) will attach the card reader to stdin. However, this is not compatible with the default encoding autodetect feature, so the command must be @@ -314,9 +319,8 @@ way to solve the problem, the other is to keep DSW up-to-date all the time). #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) +#define ENABLE_PHYSICAL_CARD_READER_SUPPORT extern int32 sim_switches; extern UNIT cpu_unit; @@ -325,7 +329,6 @@ 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); @@ -342,18 +345,18 @@ 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_CR_EMPTY (UNIT_V_UF + 5) /* NOTE: THIS MUST BE SET IN ibm1130_gui.c too */ #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_PHYSICAL (UNIT_V_UF + 9) /* NOTE: THIS MUST BE SET IN ibm1130_gui.c too */ #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_CR_EMPTY (1u << UNIT_V_CR_EMPTY) #define UNIT_SCRATCH (1u << UNIT_V_SCRATCH) /* temp file */ #define UNIT_QUIET (1u << UNIT_V_QUIET) #define UNIT_DEBUG (1u << UNIT_V_DEBUG) @@ -596,7 +599,7 @@ static CPCODE cardcode_026F[] = // 026 fortran 0x2020, 'Y', 0x2010, 'Z', 0x0420, '=', - 0x0220, '\'', // ' in 026 Fortran + 0x0220, '\'', 0x8420, '.', 0x8220, ')', 0x4420, '$', @@ -648,7 +651,7 @@ static CPCODE cardcode_026C[] = // 026 commercial 0x2020, 'Y', 0x2010, 'Z', 0x0420, '=', - 0x0220, '\'', // ' in 026 Fortran + 0x0220, '\'', 0x8420, '.', 0x8220, ')', 0x4420, '$', @@ -666,7 +669,6 @@ 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 */ @@ -689,7 +691,6 @@ 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 */ @@ -792,7 +793,8 @@ static int32 guess_cr_code (void) 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')) { + // 3.0-3, changed test for > 0x7f to & 0x80 + if ((strchr("\r\n\t\xA2\xAC", line.c[i]) == NULL) && ((line.c[i] < ' ') || (line.c[i] & 0x80))) { guess = CODE_BINARY; // oops, null or weird character, it's binary after all break; } @@ -891,8 +893,8 @@ t_stat load_cr_boot (int drvno, int switches) 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); + if (((switches & SWMASK('Q')) == 0) && ! cgi) { // 3.0-3, parenthesized & operation, per lint check + sprintf(msg, "Loaded %s cold start card\n", name); #ifdef GUI_SUPPORT remark_cmd(msg); @@ -1082,15 +1084,15 @@ again: /* jump here if we've loaded a new deck after emptying the previous one } if (nread == 0) { - SETBIT(cr_unit.flags, UNIT_EMPTY); + SETBIT(cr_unit.flags, UNIT_CR_EMPTY); readstate = STATION_EMPTY; - cardnum = -1; /* nix the card counter */ + cr_count = -1; /* nix the card counter */ } else { - CLRBIT(cr_unit.flags, UNIT_EMPTY); + CLRBIT(cr_unit.flags, UNIT_CR_EMPTY); readstate = STATION_LOADED; - cardnum++; /* advance card counter */ cr_count++; + cr_unit.pos++; } } // else @@ -1113,7 +1115,7 @@ static void npro (void) if (deckfile != NULL) fseek(deckfile, 0, SEEK_END); /* skip to end of deck list */ - cardnum = -1; /* nix the card counter */ + cr_count = -1; /* nix the card counter */ if (punchstate == STATION_PUNCHED) feedcycle(FALSE, FALSE); /* flush out card just punched */ @@ -1121,7 +1123,7 @@ static void npro (void) 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 */ + SETBIT(cr_unit.flags, UNIT_CR_EMPTY); /* set hopper empty */ } #endif @@ -1166,17 +1168,18 @@ static void checkdeck (void) 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 */ + cr_count = 0; /* reset card counter */ + cr_unit.pos = 0; fseek(cr_unit.fileref, 0, SEEK_SET); /* rewind deck */ } if (empty) { - SETBIT(cr_unit.flags, UNIT_EMPTY); + SETBIT(cr_unit.flags, UNIT_CR_EMPTY); if (cr_unit.fileref != NULL) /* real file but it's empty, hmmm, try another */ nextdeck(); } else { - CLRBIT(cr_unit.flags, UNIT_EMPTY); + CLRBIT(cr_unit.flags, UNIT_CR_EMPTY); } } @@ -1187,9 +1190,9 @@ 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 */ + cr_count = 0; /* clear read count */ + cr_unit.pos = 0; if (deckfile == NULL) /* we can't help */ return FALSE; @@ -1270,11 +1273,16 @@ static t_bool nextdeck (void) 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 */ + c = buf; /* pick filename from string */ + + while (*c && *c <= ' ') /* skip leading blanks (there could be some now after subsitution) */ + c++; + + fname = c; /* remember start */ if (*c == '\'' || *c == '"') { /* quoted string */ - quote = *c; /* remember the quote type */ - strcpy(c, c+1); /* slide string down over the quote */ + quote = *c++; /* remember the quote type */ + fname++; /* skip the quote */ while (*c && (*c != quote)) c++; /* skip to end of quote */ } @@ -1329,8 +1337,9 @@ static t_bool nextdeck (void) } } - if (*skipbl(c)) /* there should be nothing left */ - printf("* Bad mode specifier %s after filename %s in deck file", mode, fname); +// don't complain about this -- There are comments after the mode character in loaddms.deck +// 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(); @@ -1349,7 +1358,7 @@ static t_bool nextdeck (void) 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 */ + return (cr_unit.flags & UNIT_CR_EMPTY) == 0;/* return TRUE if a deck has been loaded */ } static t_stat cr_reset (DEVICE *dptr) @@ -1374,7 +1383,7 @@ static t_stat cr_reset (DEVICE *dptr) return SCPE_OK; } - SETBIT(cr_unit.flags, UNIT_EMPTY); /* assume hopper empty */ + SETBIT(cr_unit.flags, UNIT_CR_EMPTY); /* assume hopper empty */ if (cr_unit.flags & UNIT_ATT) { // if (deckfile != NULL) { /* do NOT rewind the deck file */ @@ -1403,18 +1412,42 @@ static t_stat cp_reset (DEVICE *dptr) return SCPE_OK; } +t_stat cr_rewind (void) +{ + if ((cr_unit.flags & UNIT_ATT) == 0) + return SCPE_UNATT; + + if (deckfile) { + fseek(deckfile, 0, SEEK_SET); + nextdeck(); + } + else { + fseek(cr_unit.fileref, 0, SEEK_SET); + checkdeck(); + cr_set_code(&cr_unit, GET_CODE(cr_unit), NULL, NULL); + } + + cr_unit.pos = 0; + + // 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); + + 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 */ + cr_detach(uptr); /* detach file and possibly deck file */ - CLRBIT(uptr->flags, UNIT_QUIET|UNIT_DEBUG|UNIT_PHYSICAL|UNIT_LOWERCASE); /* set options */ + CLRBIT(uptr->flags, UNIT_SCRATCH|UNIT_QUIET|UNIT_DEBUG|UNIT_PHYSICAL|UNIT_LOWERCASE); /* set options */ tab_proc = NULL; + use_decklist = FALSE; if (sim_switches & SWMASK('D')) SETBIT(uptr->flags, UNIT_DEBUG); if (sim_switches & SWMASK('Q')) SETBIT(uptr->flags, UNIT_QUIET); @@ -1424,8 +1457,8 @@ static t_stat cr_attach (UNIT *uptr, char *cptr) 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); + // user can specify multiple names on the CR attach command if using a deck file. The deck file + // can contain %n tokens to pickup the additional name(s). c = cptr; /* extract arguments */ for (list_nargs = 0; list_nargs < MAXARGS; list_nargs++) { @@ -1435,18 +1468,25 @@ static t_stat cr_attach (UNIT *uptr, char *cptr) 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 (list_nargs == 0 && *c == '@') { /* @ might occur before a quoted name; check first */ + c++; + use_decklist = TRUE; + } + + if (*c == '\'' || *c == '"') { /* quoted string */ + quote = *c++; + arg = c; /* save start */ + while (*c && (*c != quote)) + c++; + } + else { + arg = c; /* save start */ + while (*c && (*c > ' ')) + c++; } if (*c) - *c++ = 0; /* term arg at space */ + *c++ = 0; /* term arg at space or closing quote */ list_arg[list_nargs] = list_save[list_nargs]; /* set pointer to permanent storage location */ strncpy(list_arg[list_nargs], arg, MAXARGLEN); /* store copy */ @@ -1455,36 +1495,37 @@ static t_stat cr_attach (UNIT *uptr, char *cptr) if (list_nargs <= 0) /* need at least 1 */ return SCPE_2FARG; - cardnum = 0; /* reset card counter */ - use_decklist = FALSE; + cr_count = 0; /* reset card counter */ 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 == '@') { + if (*cptr == '@') { /* @ might also occur inside a quoted name; check afterwards too */ use_decklist = TRUE; cptr++; } - if (strcmp(cptr, "-") == 0 && ! use_decklist) { /* standard input */ - if (uptr -> flags & UNIT_DIS) return SCPE_UDIS; /* disabled? */ + else if (sim_switches & SWMASK('P')) { /* open physical card reader device */ + return pcr_attach(uptr, cptr); + } + + if (list_nargs > 1 && ! use_decklist) /* if not using deck file, there should have been only one name */ + return SCPE_2MARG; + + if (strcmp(cptr, "(stdin)") == 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) + 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); + uptr->filename[0] = '@'; + strncpy(uptr->filename+1, cptr, CBUFSIZE-1); + deckfile = cr_unit.fileref; /* save the deck file stream in our local variable */ cr_unit.fileref = NULL; nextdeck(); @@ -1505,7 +1546,7 @@ static t_stat cr_attach (UNIT *uptr, char *cptr) return SCPE_OK; } -static t_stat cr_detach (UNIT *uptr) +t_stat cr_detach (UNIT *uptr) { t_stat rval; @@ -1526,10 +1567,11 @@ static t_stat cr_detach (UNIT *uptr) cr_unit.fileref = deckfile; /* give scp a file to close */ } - if (uptr->fileref == stdout) { + if (uptr->fileref == stdin) { CLRBIT(uptr->flags, UNIT_ATT); free(uptr->filename); uptr->filename = NULL; + uptr->fileref = NULL; rval = SCPE_OK; } else @@ -1543,7 +1585,7 @@ 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); + return attach_unit(uptr, quotefix(cptr)); /* fix quotes in filenames & attach */ } static t_stat cp_detach (UNIT *uptr) @@ -1561,10 +1603,11 @@ static t_stat cp_detach (UNIT *uptr) static void op_done (void) { if (cr_unit.flags & UNIT_DEBUG) - DEBUG_PRINT("!CR Op Complete, card %d", cardnum); + DEBUG_PRINT("!CR Op Complete, card %d", cr_count); SET_OP(OP_IDLE); SETBIT(cr_dsw, CR_DSW_OP_COMPLETE); + CLRBIT(cr_dsw, CR_DSW_BUSY); SETBIT(ILSW[4], ILSW_4_1442_CARD); calc_ints(); } @@ -1594,7 +1637,7 @@ static t_stat cr_svc (UNIT *uptr) 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); + DEBUG_PRINT("!CR Read Response %d : %d", cr_count, cr_unit.COLUMN+1); } else { readstate = STATION_READ; @@ -1641,7 +1684,7 @@ void xio_1142_card (int32 addr, int32 func, int32 modify) case XIO_SENSE_DEV: if (cr_unit.flags & UNIT_PHYSICAL) { pcr_xio_sense(modify); - return; + break; } if (cp_unit.flags & UNIT_ATT) @@ -1765,12 +1808,12 @@ void xio_1142_card (int32 addr, int32 func, int32 modify) if (cr_unit.flags & UNIT_PHYSICAL) { pcr_xio_feedcycle(); - return; + break; } + feedcycle(TRUE, (cp_unit.flags & UNIT_ATT) != 0); SET_OP(OP_FEEDING); - sim_cancel(&cr_unit); sim_activate(&cr_unit, cf_wait); break; @@ -1779,17 +1822,17 @@ void xio_1142_card (int32 addr, int32 func, int32 modify) if (cr_unit.flags & UNIT_DEBUG) DEBUG_PRINT("#CR Start read"); - if (cp_unit.flags & UNIT_PHYSICAL) { + cr_unit.COLUMN = -1; + + if (cr_unit.flags & UNIT_PHYSICAL) { pcr_xio_startread(); - return; + break; } 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; @@ -1825,7 +1868,6 @@ void xio_1142_card (int32 addr, int32 func, int32 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 @@ -1838,24 +1880,55 @@ void xio_1142_card (int32 addr, int32 func, int32 modify) #include -#define PCR_STATUS_READY 1 +#define PCR_STATUS_READY 1 // bits in interface reply byte #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); +#define PCR_STATUS_MSEC 150 // when idle, get status every 150 msec + +typedef enum { + PCR_STATE_IDLE, // nothing expected from the interface + PCR_STATE_WAIT_CMD_RESPONSE, // waiting for response from any command other than P + PCR_STATE_WAIT_PICK_CMD_RESPONSE, // waiting for response from P command + PCR_STATE_WAIT_DATA_START, // waiting for introduction to data from P command + PCR_STATE_WAIT_DATA, // waiting for data from P command + PCR_STATE_WAIT_PICK_FINAL_RESPONSE, // waiting for status byte after last of the card data + PCR_STATE_CLOSED +} PCR_STATE; + +static void pcr_cmd (char cmd); +static DWORD CALLBACK pcr_thread (LPVOID arg); +static BOOL pcr_handle_status_byte (char byte); +static BOOL pcr_handle_byte (char byte); +static void pcr_trigger_interrupt_0(void); +static void begin_pcr_critical_section (void); +static void end_pcr_critical_section (void); +static void pcr_set_dsw_from_status (BOOL post_pick); + +static PCR_STATE pcr_state = PCR_STATE_CLOSED; // current state of connection to physical card reader interface +static char pcr_status = 0; // last status byte received from the interface +static int pcr_nleft; // number of bytes still expected from pick command +static int pcr_nready; // number of bytes waiting in the input buffer for simulator to read +static BOOL pcr_done; +static HANDLE hpcr = INVALID_HANDLE_VALUE; +static HANDLE hPickEvent = INVALID_HANDLE_VALUE; +static HANDLE hResetEvent = INVALID_HANDLE_VALUE; static t_stat pcr_attach (UNIT *uptr, char *devname) { - HANDLE hPort; DCB dcb; COMMTIMEOUTS cto; - DWORD nerr; + DWORD nerr, thread_id; + + pcr_state = PCR_STATE_CLOSED; + sim_cancel(uptr); + cr_unit.COLUMN = -1; /* device is not currently cycling */ + /* open the COM port */ - hPort = CreateFile(devname, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); - if (hPort == INVALID_HANDLE_VALUE) + hpcr = CreateFile(devname, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); + if (hpcr == INVALID_HANDLE_VALUE) return SCPE_OPENERR; memset(&dcb, 0, sizeof(dcb)); /* set communications parameters */ @@ -1886,8 +1959,15 @@ static t_stat pcr_attach (UNIT *uptr, char *devname) dcb.EofChar = 0; dcb.EvtChar = 0; - if (! SetCommState(hPort, &dcb)) { - CloseHandle(hPort); + if (hPickEvent == INVALID_HANDLE_VALUE) + hPickEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + + if (hResetEvent == INVALID_HANDLE_VALUE) + hResetEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + + if (! SetCommState(hpcr, &dcb)) { + CloseHandle(hpcr); + hpcr = INVALID_HANDLE_VALUE; printf("Call to SetCommState failed\n"); return SCPE_OPENERR; } @@ -1899,55 +1979,56 @@ static t_stat pcr_attach (UNIT *uptr, char *devname) cto.WriteTotalTimeoutMultiplier = 0; cto.WriteTotalTimeoutConstant = 200; // allow 200 msec for a write - if (! SetCommTimeouts(hPort, &cto)) { - CloseHandle(hPort); + if (! SetCommTimeouts(hpcr, &cto)) { + CloseHandle(hpcr); + hpcr = INVALID_HANDLE_VALUE; printf("Call to SetCommTimeouts failed\n"); return SCPE_OPENERR; } - PurgeComm(hPort, PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR); - ClearCommError(hPort, &nerr, NULL); + PurgeComm(hpcr, PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR); + ClearCommError(hpcr, &nerr, NULL); - SETBIT(uptr->flags, UNIT_PHYSICAL|UNIT_ATT); /* mark device as attached */ - uptr->filename = calloc(strlen(devname)+1, sizeof(char)); + pcr_status = PCR_STATUS_HEMPTY; // set default status: offline, no cards + pcr_state = PCR_STATE_IDLE; + pcr_done = FALSE; + cr_dsw = CR_DSW_LAST_CARD | CR_DSW_NOT_READY; + + set_active_cr_code(CODE_BINARY); // force binary mode + + if (CreateThread(NULL, 0, pcr_thread, NULL, 0, &thread_id) == NULL) { + pcr_state = PCR_STATE_CLOSED; + CloseHandle(hpcr); + hpcr = INVALID_HANDLE_VALUE; + printf("Error creating card reader thread\n"); + return SCPE_IERR; + } + + SETBIT(uptr->flags, UNIT_PHYSICAL|UNIT_ATT); // mark device as attached + uptr->filename = malloc(strlen(devname)+1); 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 */ + if (cr_unit.flags & UNIT_ATT) { + CloseHandle(hpcr); // close the COM port (this will lead to the thread closing) + hpcr = INVALID_HANDLE_VALUE; + pcr_state = PCR_STATE_CLOSED; - CloseHandle((HANDLE) (uptr->fileref)); /* close the COM port */ - uptr->fileref = NULL; - - free(uptr->filename); /* release the name copy */ - uptr->filename = NULL; + free(uptr->filename); // release the name copy + uptr->filename = NULL; + } + CLRBIT(cr_unit.flags, UNIT_PHYSICAL|UNIT_ATT); // drop the attach and physical bits 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 */ + if (modify & 0x01) { // reset simulated interrupts CLRBIT(cr_dsw, CR_DSW_READ_RESPONSE|CR_DSW_PUNCH_RESPONSE); CLRBIT(ILSW[0], ILSW_0_1442_CARD); } @@ -1957,27 +2038,299 @@ static void pcr_xio_sense (int modify) CLRBIT(ILSW[4], ILSW_4_1442_CARD); } - ACC = cr_dsw; /* return the DSW */ + ACC = cr_dsw; // DSW was set in real-time, just return the DSW if (cr_unit.flags & UNIT_DEBUG) DEBUG_PRINT("#CR Sense %04x%s%s", cr_dsw, (modify & 1) ? " RESET0" : "", (modify & 2) ? " RESET4" : ""); } +// pcr_thread - thread to handle receive side of card reader interface communications + +static OVERLAPPED ovRd, ovWr; +int nwaits; +char response_byte; + +static DWORD CALLBACK pcr_thread (LPVOID arg) +{ + DWORD event; + long nrcvd, nread; + HANDLE objs[4]; + BOOL pick_queued = FALSE, reset_queued = FALSE; + + nwaits = 0; + + ZeroMemory(&ovRd, sizeof(ovRd)); + ZeroMemory(&ovWr, sizeof(ovWr)); + ovRd.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); // create an event for async IO reads + ovWr.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); // create an event for async IO writes + + objs[0] = ovRd.hEvent; + objs[1] = ovWr.hEvent; + objs[2] = hResetEvent; + objs[3] = hPickEvent; + + while (hpcr != INVALID_HANDLE_VALUE) { + if (pcr_state == PCR_STATE_IDLE) { + if (pick_queued) { + pcr_cmd('P'); + pick_queued = FALSE; + pcr_done = FALSE; + pcr_state = PCR_STATE_WAIT_PICK_CMD_RESPONSE; + } + else if (reset_queued) { + pcr_cmd('X'); + reset_queued = FALSE; + pcr_state = PCR_STATE_WAIT_CMD_RESPONSE; + } + } + + event = WaitForMultipleObjects(4, objs, FALSE, PCR_STATUS_MSEC); + + switch (event) { + case WAIT_OBJECT_0+0: // read complete + ResetEvent(ovRd.hEvent); + break; + + case WAIT_OBJECT_0+1: // write complete + ResetEvent(ovWr.hEvent); + continue; + + case WAIT_OBJECT_0+2: // reset request from simulator + reset_queued = TRUE; + pick_queued = FALSE; + continue; + + case WAIT_OBJECT_0+3: // pick request from simulator + pick_queued = TRUE; + continue; + + case WAIT_TIMEOUT: + if (pcr_state == PCR_STATE_IDLE) { + pcr_state = PCR_STATE_WAIT_CMD_RESPONSE; + ovRd.Offset = ovRd.OffsetHigh = 0; + pcr_cmd('S'); + } + else if (pcr_state == PCR_STATE_WAIT_CMD_RESPONSE && ++nwaits >= 6) { + printf("Requesting status again!\n"); + ovRd.Offset = ovRd.OffsetHigh = 0; + pcr_cmd('S'); + } + continue; + + default: + printf("Unexpected pcr_wait result %08lx", event); + continue; + } + + // read data is ready + + switch (pcr_state) { + case PCR_STATE_IDLE: // nothing expected from the interface + PurgeComm(hpcr, PURGE_RXCLEAR|PURGE_RXABORT); + break; + + case PCR_STATE_WAIT_CMD_RESPONSE: // waiting for response from any command other than P + if (pcr_handle_status_byte(response_byte)) + pcr_state = PCR_STATE_IDLE; + break; + + case PCR_STATE_WAIT_PICK_CMD_RESPONSE: // waiting for response from P command + if (pcr_handle_status_byte(response_byte)) { + pcr_state = PCR_STATE_WAIT_DATA_START; + pcr_cmd('\0'); // queue a response read + } + break; + + case PCR_STATE_WAIT_DATA_START: // waiting for leadin character from P command (= or !) + if (! pcr_handle_byte(response_byte)) + continue; // this could take a very long time + + switch (response_byte) { + case '=': // = means pick in progress, 160 bytes of data will be coming + pcr_state = PCR_STATE_WAIT_DATA; + ovRd.Offset = ovRd.OffsetHigh = 0; + nread = 20; // initiate a read + ReadFile(hpcr, ((char *) readstation), nread, &nrcvd, &ovRd); + break; + + case '!': // ! means pick has been canceled, status will be coming next + pcr_state = PCR_STATE_WAIT_CMD_RESPONSE; + pcr_cmd('\0'); // initiate read + break; + + default: // anything else is a datacomm error, or something + // indicate read check or something +// pcr_state = PCR_STATE_IDLE; + break; + } + + break; + + case PCR_STATE_WAIT_DATA: // waiting for data from P command + GetOverlappedResult(hpcr, &ovRd, &nrcvd, TRUE); + if (cr_unit.flags & UNIT_DEBUG) + printf((nrcvd <= 0) ? "PCR: NO RESP!\n" : "PCR: GOT %d BYTES\n", nrcvd); + + if (nrcvd > 0) { + pcr_nleft -= nrcvd; + + begin_pcr_critical_section(); + pcr_nready += nrcvd; + end_pcr_critical_section(); + } + + if (pcr_nleft > 0) { + ovRd.Offset = ovRd.OffsetHigh = 0; + nread = min(pcr_nleft, 20); + ReadFile(hpcr, ((char *) readstation)+160-pcr_nleft, nread, &nrcvd, &ovRd); + } + else { + pcr_state = PCR_STATE_WAIT_PICK_FINAL_RESPONSE; + pcr_cmd('\0'); // queue read + } + break; + + case PCR_STATE_WAIT_PICK_FINAL_RESPONSE: // waiting for status byte after last of the card data + if (pcr_handle_status_byte(response_byte)) { + readstate = STATION_READ; + pcr_state = PCR_STATE_IDLE; + pcr_done = TRUE; + } + break; + } + } + + CloseHandle(ovRd.hEvent); + CloseHandle(ovWr.hEvent); + + return 0; +} + +static char lastcmd = '?'; + +static void pcr_cmd (char cmd) +{ + long nwrite, nrcvd; + + if (cmd != '\0') { + if (cr_unit.flags & UNIT_DEBUG && (cmd != 'S' || cmd != lastcmd)) + printf("PCR: SENT %c\n", cmd); + + lastcmd = cmd; + + ResetEvent(ovWr.hEvent); + ovWr.Offset = ovWr.OffsetHigh = 0; + WriteFile(hpcr, &cmd, 1, &nwrite, &ovWr); + } + + ovRd.Offset = ovRd.OffsetHigh = 0; + ReadFile(hpcr, &response_byte, 1, &nrcvd, &ovRd); // if no bytes ready, just return -- a later wait-event will catch it + + nwaits = 0; +} + +static BOOL pcr_handle_status_byte (char byte) +{ + long nrcvd; + static char prev_status = '?'; + BOOL show; + + GetOverlappedResult(hpcr, &ovRd, &nrcvd, TRUE); + if (nrcvd <= 0) + return FALSE; + + pcr_status = byte; // save new status + + show = lastcmd != 'S' || pcr_status != prev_status; + + if ((cr_unit.flags & UNIT_DEBUG) && show) { + printf("PCR: status %c\n", pcr_status); + prev_status = pcr_status; + } + + pcr_set_dsw_from_status(FALSE); + + return TRUE; +} + +static void pcr_set_dsw_from_status (BOOL post_pick) +{ + // set 1130 status word bits + CLRBIT(cr_dsw, CR_DSW_LAST_CARD|CR_DSW_BUSY|CR_DSW_NOT_READY|CR_DSW_ERROR_CHECK); + + if (pcr_status & PCR_STATUS_HEMPTY) + SETBIT(cr_dsw, CR_DSW_LAST_CARD|CR_DSW_NOT_READY); + + if (pcr_status & PCR_STATUS_ERROR) + SETBIT(cr_dsw, CR_DSW_ERROR_CHECK); + + // we have a problem -- ready doesn't come back up right away after a pick. + // I think I'll fudge this and not set NOT_READY immediately after a pick + + if ((! post_pick) && ! (pcr_status & PCR_STATUS_READY)) + SETBIT(cr_dsw, CR_DSW_NOT_READY); + + if (CURRENT_OP != OP_IDLE) + SETBIT(cr_dsw, CR_DSW_BUSY|CR_DSW_NOT_READY); +} + +static BOOL pcr_handle_byte (char byte) +{ + long nrcvd; + + GetOverlappedResult(hpcr, &ovRd, &nrcvd, TRUE); + + if (cr_unit.flags & UNIT_DEBUG) + printf((nrcvd <= 0) ? "PCR: NO RESP!\n" : "PCR: GOT %c\n", byte); + + return nrcvd > 0; +} + static void pcr_xio_feedcycle (void) { - pcr_cmd('P'); // initiate pick SET_OP(OP_FEEDING); + cr_unit.COLUMN = -1; + SetEvent(hPickEvent); + sim_activate(&cr_unit, cr_wait); // keep checking frequently } static void pcr_xio_startread (void) { - pcr_cmd('P'); // initiate pick SET_OP(OP_READING); + cr_unit.COLUMN = -1; + pcr_nleft = 160; + pcr_nready = 0; + SetEvent(hPickEvent); + sim_activate(&cr_unit, cr_wait); // keep checking frequently } static void pcr_reset (void) { - pcr_cmd('X'); // cancel pending pick + pcr_status = PCR_STATUS_HEMPTY; // set default status: offline, no cards + pcr_state = PCR_STATE_IDLE; + cr_dsw = CR_DSW_LAST_CARD | CR_DSW_NOT_READY; + + sim_cancel(&cr_unit); + + SetEvent(hResetEvent); +} + +// pcr_trigger_interrupt_0 - simulate a read response interrupt so OS will read queued column data + +static void pcr_trigger_interrupt_0 (void) +{ + if (++cr_unit.COLUMN < 80) { + SETBIT(cr_dsw, CR_DSW_READ_RESPONSE); + SETBIT(ILSW[0], ILSW_0_1442_CARD); + calc_ints(); + + begin_pcr_critical_section(); + pcr_nready -= 2; + end_pcr_critical_section(); + + if (cr_unit.flags & UNIT_DEBUG) + printf("SET IRQ0 col %d\n", cr_unit.COLUMN+1); + } } static t_stat pcr_svc (UNIT *uptr) @@ -1986,30 +2339,30 @@ static t_stat pcr_svc (UNIT *uptr) case OP_IDLE: break; - case OP_FEEDING: - op_done(); + case OP_READING: + if (pcr_nready >= 2) { // if there is a whole column buffered, simulate column interrupt + pcr_trigger_interrupt_0(); + sim_activate(&cr_unit, cr_wait); // keep checking frequently + } + else if (pcr_done) { + pcr_done = FALSE; + cr_count++; + op_done(); + pcr_set_dsw_from_status(TRUE); + } + else + sim_activate(&cr_unit, cr_wait); // keep checking frequently 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; + case OP_FEEDING: + if (pcr_done) { + cr_count++; op_done(); + pcr_set_dsw_from_status(TRUE); } + else + sim_activate(&cr_unit, cr_wait); // keep checking frequently + break; case OP_PUNCHING: @@ -2019,61 +2372,23 @@ static t_stat pcr_svc (UNIT *uptr) return SCPE_OK; } -static void pcr_cmd (char cmd) +static CRITICAL_SECTION pcr_critsect; + +static void begin_pcr_critical_section (void) { - DWORD nio; - char resp; - int ntries = 10; - BOOL resend = TRUE; + static BOOL mustinit = 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? + if (mustinit) { + InitializeCriticalSection(&pcr_critsect); + mustinit = FALSE; } - printf("* Card reader interface failed to respond within 10 tries\n"); + EnterCriticalSection(&pcr_critsect); } -static int pcr_read_data (void) +static void end_pcr_critical_section (void) { - DWORD nio; - - ReadFile((HANDLE) cr_unit.fileref, readstation, 160, &nio, NULL); - return nio == 160; + LeaveCriticalSection(&pcr_critsect); } #endif diff --git a/Ibm1130/ibm1130_defs.h b/Ibm1130/ibm1130_defs.h index 61b75024..5c5ef1fc 100644 --- a/Ibm1130/ibm1130_defs.h +++ b/Ibm1130/ibm1130_defs.h @@ -260,6 +260,8 @@ 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); +t_stat cr_rewind (void); +t_stat cr_detach (UNIT *uptr); void calc_ints (void); /* recalculate interrupt bitmask */ void trace_io (char *fmt, ...); /* debugging printout */ void scp_panic (char *msg); /* bail out of simulator */ @@ -269,9 +271,12 @@ 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); +t_bool stuff_and_wait (char *cmd, int timeout, int delay); 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); +t_stat basic_attach (UNIT *uptr, char *cptr); +char * quotefix (char * cptr); /* GUI interface routines */ t_bool keyboard_is_busy (void); diff --git a/Ibm1130/ibm1130_disk.c b/Ibm1130/ibm1130_disk.c index 756b2e5a..7b5c99f6 100644 --- a/Ibm1130/ibm1130_disk.c +++ b/Ibm1130/ibm1130_disk.c @@ -513,7 +513,7 @@ static t_stat dsk_attach (UNIT *uptr, char *cptr) 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 + if ((rval = attach_unit(uptr, quotefix(cptr))) != SCPE_OK) { // mount new disk SETBIT(dsk_dsw[drv], DSK_DSW_NOT_READY); return rval; } diff --git a/Ibm1130/ibm1130_fmt.c b/Ibm1130/ibm1130_fmt.c index faccb046..6a9ea5fe 100644 --- a/Ibm1130/ibm1130_fmt.c +++ b/Ibm1130/ibm1130_fmt.c @@ -57,10 +57,10 @@ // ------------------------------------------------------------------------------------------- #include -#include #include #include #include +#include #include "ibm1130_fmt.h" #define MAXLINE 81 // maximum output line size diff --git a/Ibm1130/ibm1130_gdu.c b/Ibm1130/ibm1130_gdu.c index a1501609..b95732e1 100644 --- a/Ibm1130/ibm1130_gdu.c +++ b/Ibm1130/ibm1130_gdu.c @@ -662,7 +662,7 @@ static HBITMAP hBmp = NULL; static int curwid = 0; static int curht = 0; static BOOL wcInited = FALSE; -static int GDUPumpID = 0; +static DWORD GDUPumpID = 0; static HANDLE hGDUPump = INVALID_HANDLE_VALUE; static HPEN hGreenPen = NULL; static HBRUSH hRedBrush = NULL; diff --git a/Ibm1130/ibm1130_gui.c b/Ibm1130/ibm1130_gui.c index 8a1461cb..01d1d04d 100644 --- a/Ibm1130/ibm1130_gui.c +++ b/Ibm1130/ibm1130_gui.c @@ -11,6 +11,10 @@ * This is not a supported product, but I welcome bug reports and fixes. * Mail to simh@ibm1130.org * + * 02-Dec-02 BLK Changed display, added printer and card reader icons + * Added drag and drop support for scripts and card decks + * Added support for physical card reader and printer (hides icons) + * * 17-May-02 BLK Pulled out of ibm1130_cpu.c */ @@ -32,6 +36,14 @@ # define UPDATE_INTERVAL 5000 // GUI: set to 100000/f where f = desired updates/second of 1130 time #endif +#define UNIT_V_CR_EMPTY (UNIT_V_UF + 5) /* NOTE: THESE MUST MATCH THE DEFINITION IN ibm1130_cr.c */ +#define UNIT_CR_EMPTY (1u << UNIT_V_CR_EMPTY) +#define UNIT_V_PHYSICAL (UNIT_V_UF + 9) +#define UNIT_PHYSICAL (1u << UNIT_V_PHYSICAL) + +#define UNIT_V_PHYSICAL_PTR (UNIT_V_UF + 10) /* NOTE: THESE MUST MATCH THE DEFINITION IN ibm1130_prt.c */ +#define UNIT_PHYSICAL_PTR (1u << UNIT_V_PHYSICAL_PTR) + /* ------------------------------------------------------------------------ * Function declarations * ------------------------------------------------------------------------ */ @@ -71,6 +83,10 @@ DEVICE console_dev = { extern char *read_line (char *cptr, int size, FILE *stream); extern FILE *sim_log; +extern DEVICE *find_unit (char *cptr, UNIT **uptr); + +extern UNIT cr_unit; /* pointers to 1442 and 1132 (1403) printers */ +extern UNIT prt_unit; #ifndef GUI_SUPPORT void update_gui (int force) {} /* stubs for non-GUI builds */ @@ -84,10 +100,11 @@ extern FILE *sim_log; 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);} + t_stat console_reset (DEVICE *dptr) {return SCPE_OK;} + void stuff_cmd (char *cmd) {} + t_bool stuff_and_wait (char *cmd, int timeout, int delay) {return FALSE;} + 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) @@ -134,15 +151,29 @@ void scp_panic (char *msg) #define IDC_RESET 14 #define IDC_PROGRAM_LOAD 15 +#define IDC_TEAR 16 // standard button +#define IDC_1442 17 // device images +#define IDC_1132 18 + #define LAMPTIME 500 // 500 msec delay on updating #define FLASH_TIMER_ID 1 #define UPDATE_TIMER_ID 2 +#define RUNSWITCH_X 689 // center of the run mode switch dial +#define RUNSWITCH_Y 107 +#define TOGGLES_X 122 // left edge of series of toggle switches + +#define TXTBOX_X 200 // text labels showing attached devices +#define TXTBOX_Y 300 +#define TXTBOX_WIDTH 195 +#define TXTBOX_HEIGHT 12 + static BOOL class_defined = FALSE; static HWND hConsoleWnd = NULL; static HBITMAP hBitmap = NULL; static HFONT hFont = NULL; static HFONT hBtnFont = NULL; +static HFONT hTinyFont = NULL; static HBRUSH hbLampOut = NULL; static HBRUSH hbWhite = NULL; static HBRUSH hbBlack = NULL; @@ -164,41 +195,80 @@ static char szConsoleClassName[] = "1130CONSOLE"; static DWORD PumpID = 0; static HANDLE hPump = INVALID_HANDLE_VALUE; static int bmwid, bmht; +static HANDLE hbm1442_full, hbm1442_empty, hbm1442_eof, hbm1442_middle; +static HANDLE hbm1132_full, hbm1132_empty; static struct tag_btn { - int x, y; + int x, y, wx, wy; char *txt; BOOL pushable, state; COLORREF clr; HBRUSH hbrLit, hbrDark; HWND hBtn; + BOOL subclassed; + } 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, + 0, 0, BUTTON_WIDTH, BUTTON_HEIGHT, "KEYBOARD\nSELECT", FALSE, FALSE, RGB(255,255,180), NULL, NULL, NULL, TRUE, + 0, 1, BUTTON_WIDTH, BUTTON_HEIGHT, "DISK\nUNLOCK", FALSE, TRUE, RGB(255,255,180), NULL, NULL, NULL, TRUE, + 0, 2, BUTTON_WIDTH, BUTTON_HEIGHT, "RUN", FALSE, FALSE, RGB(0,255,0), NULL, NULL, NULL, TRUE, + 0, 3, BUTTON_WIDTH, BUTTON_HEIGHT, "PARITY\nCHECK", FALSE, FALSE, RGB(255,0,0), NULL, NULL, NULL, TRUE, - 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, + 1, 0, BUTTON_WIDTH, BUTTON_HEIGHT, "", FALSE, FALSE, RGB(255,255,180), NULL, NULL, NULL, TRUE, + 1, 1, BUTTON_WIDTH, BUTTON_HEIGHT, "FILE\nREADY", FALSE, FALSE, RGB(0,255,0), NULL, NULL, NULL, TRUE, + 1, 2, BUTTON_WIDTH, BUTTON_HEIGHT, "FORMS\nCHECK", FALSE, FALSE, RGB(255,255,0), NULL, NULL, NULL, TRUE, + 1, 3, BUTTON_WIDTH, BUTTON_HEIGHT, "POWER\nON", FALSE, TRUE, RGB(255,255,180), NULL, NULL, NULL, TRUE, - 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, + 2, 0, BUTTON_WIDTH, BUTTON_HEIGHT, "POWER", TRUE, FALSE, RGB(255,255,180), NULL, NULL, NULL, TRUE, + 2, 1, BUTTON_WIDTH, BUTTON_HEIGHT, "PROGRAM\nSTART", TRUE, FALSE, RGB(0,255,0), NULL, NULL, NULL, TRUE, + 2, 2, BUTTON_WIDTH, BUTTON_HEIGHT, "PROGRAM\nSTOP", TRUE, FALSE, RGB(255,0,0), NULL, NULL, NULL, TRUE, + 2, 3, BUTTON_WIDTH, BUTTON_HEIGHT, "LOAD\nIAR", TRUE, FALSE, RGB(0,0,255), NULL, NULL, NULL, TRUE, - 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, + 3, 0, BUTTON_WIDTH, BUTTON_HEIGHT, "KEYBOARD", TRUE, FALSE, RGB(255,255,180), NULL, NULL, NULL, TRUE, + 3, 1, BUTTON_WIDTH, BUTTON_HEIGHT, "IMM\nSTOP", TRUE, FALSE, RGB(255,0,0), NULL, NULL, NULL, TRUE, + 3, 2, BUTTON_WIDTH, BUTTON_HEIGHT, "CHECK\nRESET", TRUE, FALSE, RGB(0,0,255), NULL, NULL, NULL, TRUE, + 3, 3, BUTTON_WIDTH, BUTTON_HEIGHT, "PROGRAM\nLOAD", TRUE, FALSE, RGB(0,0,255), NULL, NULL, NULL, TRUE, + + TXTBOX_X+40, TXTBOX_Y+25, 35, 12, "Tear", TRUE, FALSE, 0, NULL, NULL, NULL, FALSE, + 635, 238, 110, 110, "EMPTY_1442", TRUE, FALSE, 0, NULL, NULL, NULL, FALSE, + 635, 366, 110, 110, "EMPTY_1132", TRUE, FALSE, 0, NULL, NULL, NULL, FALSE, +// 635, 366, 110, 110, "EMPTY_1132", TRUE, FALSE, 0, NULL, NULL, NULL, FALSE, }; #define NBUTTONS (sizeof(btn) / sizeof(btn[0])) +#define STATE_1442_EMPTY 0 // no cards (no file attached) +#define STATE_1442_FULL 1 // cards in hopper (file attached at BOF) +#define STATE_1442_MIDDLE 2 // cards in hopper and stacker (file attached, neither EOF nor BOF) +#define STATE_1442_EOF 3 // cards in stacker (file attached, at EOF) +#define STATE_1442_HIDDEN 4 // simulator is attached to physical card reader + +#define STATE_1132_EMPTY 0 // no paper hanging out of printer +#define STATE_1132_FULL 1 // paper hanging out of printer +#define STATE_1132_HIDDEN 2 // printer is attached to physical printer + +static struct tag_txtbox { + int x, y; + char *txt; + char *unitname; + int idctrl; +} txtbox[] = { + TXTBOX_X, TXTBOX_Y, "Card Reader", "CR", -1, + TXTBOX_X, TXTBOX_Y+ 25, "Printer", "PRT", IDC_1132, + TXTBOX_X, TXTBOX_Y+ 50, "Disk 1", "DSK0", -1, + TXTBOX_X, TXTBOX_Y+ 75, "Disk 2", "DSK1", -1, + TXTBOX_X, TXTBOX_Y+100, "Disk 3", "DSK2", -1, + TXTBOX_X, TXTBOX_Y+125, "Disk 4", "DSK3", -1, + TXTBOX_X, TXTBOX_Y+150, "Disk 5", "DSK4", -1, +}; +#define NTXTBOXES (sizeof(txtbox) / sizeof(txtbox[0])) + +#define TXTBOX_BOTTOM (TXTBOX_Y+150) + 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); +static void accept_dropped_file (HANDLE hDrop); +static void tear_printer (void); #define NIXOBJECT(hObj) if (hObj != NULL) {DeleteObject(hObj); hObj = NULL;} @@ -249,6 +319,7 @@ static void destroy_console_window (void) NIXOBJECT(hbLampOut) NIXOBJECT(hFont) NIXOBJECT(hBtnFont); + NIXOBJECT(hTinyFont); NIXOBJECT(hcHand) NIXOBJECT(hSwitchPen) NIXOBJECT(hLtGreyPen) @@ -322,6 +393,7 @@ void update_gui (BOOL force) BOOL state; static int in_here = FALSE; static int32 displayed = 0; + RECT xin; if ((int32)(console_unit.flags & UNIT_DISPLAY) != displayed) { // setting has changed displayed = console_unit.flags & UNIT_DISPLAY; @@ -380,9 +452,9 @@ void update_gui (BOOL force) 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 */ + {shown_ces = CES; RepaintRegion(hConsoleWnd, TOGGLES_X-7, 230, TOGGLES_X+360, 275);} /* console entry sw: do erase bkgnd */ if (RUNMODE != shown_runmode) - {shown_runmode = RUNMODE;RepaintRegion(hConsoleWnd, 270, 359, 330, 418);} + {shown_runmode = RUNMODE;RepaintRegion(hConsoleWnd, RUNSWITCH_X-50, RUNSWITCH_Y-50, RUNSWITCH_X+50, RUNSWITCH_Y+50);} int_lamps = 0; @@ -415,6 +487,55 @@ void update_gui (BOOL force) } } + if (force) { // if force flag is set, update text region + SetRect(&xin, TXTBOX_X, TXTBOX_Y, TXTBOX_X+TXTBOX_WIDTH, TXTBOX_BOTTOM+2*TXTBOX_HEIGHT); + InvalidateRect(hConsoleWnd, &xin, TRUE); + } + + state = ((cr_unit.flags & UNIT_ATT) == 0) ? STATE_1442_EMPTY : + (cr_unit.flags & UNIT_PHYSICAL) ? STATE_1442_HIDDEN : + (cr_unit.flags & UNIT_CR_EMPTY) ? STATE_1442_EOF : + cr_unit.pos ? STATE_1442_MIDDLE : + STATE_1442_FULL; + + if (state != btn[IDC_1442].state) { + if (state == STATE_1442_HIDDEN) + ShowWindow(btn[IDC_1442].hBtn, SW_HIDE); + else { + if (btn[IDC_1442].state == STATE_1442_HIDDEN) + ShowWindow(btn[IDC_1442].hBtn, SW_SHOWNA); + + SendMessage(btn[IDC_1442].hBtn, STM_SETIMAGE, IMAGE_BITMAP, + (LPARAM) ( + (state == STATE_1442_FULL) ? hbm1442_full : + (state == STATE_1442_MIDDLE) ? hbm1442_middle : + (state == STATE_1442_EOF) ? hbm1442_eof : + hbm1442_empty)); + } + + btn[IDC_1442].state = state; + } + + state = ((prt_unit.flags & UNIT_ATT) == 0) ? STATE_1132_EMPTY : + (prt_unit.flags & UNIT_PHYSICAL_PTR) ? STATE_1132_HIDDEN : + prt_unit.pos ? STATE_1132_FULL : + STATE_1132_EMPTY; + + if (state != btn[IDC_1132].state) { + if (state == STATE_1132_HIDDEN) + ShowWindow(btn[IDC_1132].hBtn, SW_HIDE); + else { + if (btn[IDC_1132].state == STATE_1132_HIDDEN) + ShowWindow(btn[IDC_1132].hBtn, SW_SHOWNA); + + SendMessage(btn[IDC_1132].hBtn, STM_SETIMAGE, IMAGE_BITMAP, + (LPARAM) ( + (state == STATE_1132_FULL) ? hbm1132_full : hbm1132_empty)); + } + + btn[IDC_1132].state = state; + } + in_here = FALSE; } @@ -474,6 +595,9 @@ void PaintButton (LPDRAWITEMSTRUCT dis) if (! BETWEEN(i, 0, NBUTTONS-1)) return; + if (! btn[i].subclassed) + return; + FillRect(dis->hDC, &dis->rcItem, ((btn[i].pushable || power) && IsWindowEnabled(btn[i].hBtn)) ? btn[i].hbrLit : btn[i].hbrDark); if (! btn[i].pushable) { @@ -565,7 +689,7 @@ HWND CreateSubclassedButton (HWND hwParent, int i) 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); + x = (btn[i].x < 2) ? (btn[i].x*BUTTON_WIDTH) : (598 - (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) @@ -654,12 +778,16 @@ static DWORD WINAPI Pump (LPVOID arg) 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 (hTinyFont == NULL) + hTinyFont = CreateFont(-10, 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) { + if ((hConsoleWnd = CreateWindow(szConsoleClassName, "IBM 1130", WS_OVERLAPPED|WS_CLIPCHILDREN, 0, 0, 200, 200, NULL, NULL, hInstance, NULL)) == NULL) { PumpID = 0; return 0; } + + DragAcceptFiles(hConsoleWnd, TRUE); /* let it accept dragged files (scripts) */ } GetObject(hBitmap, sizeof(bm), &bm); /* get bitmap size */ @@ -667,12 +795,52 @@ static DWORD WINAPI Pump (LPVOID arg) bmht = bm.bmHeight; for (i = 0; i < NBUTTONS; i++) { - CreateSubclassedButton(hConsoleWnd, i); + if (! btn[i].subclassed) + continue; + CreateSubclassedButton(hConsoleWnd, i); if (! btn[i].pushable) EnableWindow(btn[i].hBtn, btn[i].state); } +// This isn't needed anymore, now that we have the big printer icon -- it acts like a button now +// i = IDC_TEAR; +// btn[i].hBtn = CreateWindow("BUTTON", btn[i].txt, WS_CHILD|WS_VISIBLE|BS_CENTER, +// btn[i].x, btn[i].y, btn[i].wx, btn[i].wy, hConsoleWnd, (HMENU) i, hInstance, NULL); +// +// SendMessage(btn[i].hBtn, WM_SETFONT, (WPARAM) hTinyFont, TRUE); + + hbm1442_full = LoadBitmap(hInstance, "FULL_1442"); + hbm1442_empty = LoadBitmap(hInstance, "EMPTY_1442"); + hbm1442_eof = LoadBitmap(hInstance, "EOF_1442"); + hbm1442_middle = LoadBitmap(hInstance, "MIDDLE_1442"); + hbm1132_full = LoadBitmap(hInstance, "FULL_1132"); + hbm1132_empty = LoadBitmap(hInstance, "EMPTY_1132"); + + i = IDC_1442; + + btn[i].hBtn = CreateWindow("STATIC", btn[i].txt, WS_CHILD|WS_VISIBLE|SS_BITMAP|SS_SUNKEN|WS_BORDER|SS_REALSIZEIMAGE|SS_NOTIFY, + btn[i].x, btn[i].y, btn[i].wx, btn[i].wy, hConsoleWnd, (HMENU) i, hInstance, NULL); + btn[i].state = STATE_1442_EMPTY; + +// wx = SendMessage(btn[i].hBtn, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM) hbm1442_full); + wx = SendMessage(btn[i].hBtn, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM) hbm1442_empty); + + i = IDC_1132; + + btn[i].hBtn = CreateWindow("STATIC", btn[i].txt, WS_CHILD|WS_VISIBLE|SS_BITMAP|SS_SUNKEN|WS_BORDER|SS_REALSIZEIMAGE|SS_NOTIFY, + btn[i].x, btn[i].y, btn[i].wx, btn[i].wy, hConsoleWnd, (HMENU) i, hInstance, NULL); + btn[i].state = FALSE; + + wx = SendMessage(btn[i].hBtn, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM) hbm1132_empty); + +// for (i = 0; i < NTXTBOXES; i++) { +// txtbox[i].hBox = CreateWindow("EDIT", txtbox[i].txt, +// WS_CHILD|WS_VISIBLE|ES_LEFT|ES_READONLY, +// txtbox[i].x, txtbox[i].y, TXTBOX_WIDTH, TXTBOX_HEIGHT, hConsoleWnd, (HMENU) (i+100), hInstance, NULL); +// SendMessage(txtbox[i].hBox, WM_SETFONT, (WPARAM) hTinyFont, TRUE); +// } + GetWindowRect(hConsoleWnd, &r); /* get window size as created */ wx = r.right - r.left + 1; wy = r.bottom - r.top + 1; @@ -711,8 +879,9 @@ static DWORD WINAPI Pump (LPVOID arg) DispatchMessage(&msg); } - if (hConsoleWnd != NULL) { - DestroyWindow(hConsoleWnd); /* but if a quit message got posted, clean up */ + if (hConsoleWnd != NULL) { + DragAcceptFiles(hConsoleWnd, FALSE); /* unregister as drag/drop target */ + DestroyWindow(hConsoleWnd); /* but if a quit message got posted, clean up */ hConsoleWnd = NULL; } @@ -753,11 +922,12 @@ static void DrawBits (HDC hDC, int x, int y, int bits, int nbits, int mask, char * 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) { + for (b = 0x8000, x = TOGGLES_X; b != 0; b >>= 1) { if (shown_ces & b) { /* up */ SelectObject(hDC, hbWhite); Rectangle(hDC, x, 232, x+9, 240); @@ -789,10 +959,10 @@ void DrawRunmode (HDC hDC, int mode) 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); + x0 = RUNSWITCH_X + (int) (20.*ca + 0.5); /* inner radius */ + y0 = RUNSWITCH_Y - (int) (20.*sa + 0.5); + x1 = RUNSWITCH_X + (int) (25.*ca + 0.5); /* outer radius */ + y1 = RUNSWITCH_Y - (int) (25.*sa + 0.5); hOldPen = SelectObject(hDC, hSwitchPen); @@ -812,7 +982,7 @@ 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) { + for (b = 0x8000, x = TOGGLES_X; 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 */ @@ -823,9 +993,9 @@ static BOOL HandleClick (HWND hWnd, int xh, int yh, BOOL actual) 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 (BETWEEN(xh, RUNSWITCH_X-50, RUNSWITCH_X+50) && BETWEEN(yh, RUNSWITCH_Y-50, RUNSWITCH_Y+50)) { /* hit near rotary switch */ + ang = (int) (atan2(RUNSWITCH_X-xh, RUNSWITCH_Y-yh)*180./3.1415926); /* this does implicit 90 deg rotation by the way */ + r = (int) sqrt((xh-RUNSWITCH_X)*(xh-RUNSWITCH_X)+(yh-RUNSWITCH_Y)*(yh-RUNSWITCH_Y)); if (r > 12) { for (i = MODE_LOAD; i <= MODE_INT_RUN; i++) { if (BETWEEN(ang, i*45-12, i*45+12)) { @@ -852,13 +1022,19 @@ static BOOL HandleClick (HWND hWnd, int xh, int yh, BOOL actual) * RepaintRegion-> repaint with background redraw. Used for toggles which change position. * ------------------------------------------------------------------------ */ -static void DrawConsole (HDC hDC) +static void DrawConsole (HDC hDC, PAINTSTRUCT *ps) { 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; + RECT xout, xin; + int i, n; + DEVICE *dptr; + UNIT *uptr; + t_bool enab; + char nametemp[50], *dispname; hOldFont = SelectObject(hDC, hFont); /* use that tiny font */ hOldBrush = SelectObject(hDC, hbWhite); @@ -885,6 +1061,47 @@ static void DrawConsole (HDC hDC) SelectObject(hDC, hOldFont); SelectObject(hDC, hOldBrush); + + SetBkColor(hDC, RGB(0,0,0)); + + SetRect(&xin, TXTBOX_X, TXTBOX_Y, TXTBOX_X+TXTBOX_WIDTH, TXTBOX_BOTTOM+TXTBOX_HEIGHT); + if (IntersectRect(&xout, &xin, &ps->rcPaint)) { + hOldFont = SelectObject(hDC, hTinyFont); + + for (i = 0; i < NTXTBOXES; i++) { + enab = FALSE; + + dptr = find_unit(txtbox[i].unitname, &uptr); + if (dptr != NULL && uptr != NULL) { + if (uptr->flags & UNIT_DIS) { + SetTextColor(hDC, RGB(128,0,0)); + } + else if (uptr->flags & UNIT_ATT) { + SetTextColor(hDC, RGB(0,0,255)); + if ((n = strlen(uptr->filename)) > 30) { + strcpy(nametemp, "..."); + strcpy(nametemp+3, uptr->filename+n-30); + dispname = nametemp; + } + else + dispname = uptr->filename; + + TextOut(hDC, txtbox[i].x+25, txtbox[i].y+TXTBOX_HEIGHT, dispname, strlen(dispname)); + SetTextColor(hDC, RGB(255,255,255)); + enab = TRUE; + } + else { + SetTextColor(hDC, RGB(128,128,128)); + } + TextOut(hDC, txtbox[i].x, txtbox[i].y, txtbox[i].txt, strlen(txtbox[i].txt)); + } + + if (txtbox[i].idctrl >= 0) + EnableWindow(btn[txtbox[i].idctrl].hBtn, enab); + } + + SelectObject(hDC, hOldFont); + } } /* ------------------------------------------------------------------------ @@ -914,11 +1131,11 @@ void gui_run (int running) flash_run(); /* keep run lamp active for a while after we stop running */ } -void HandleCommand (HWND hWnd, WPARAM wParam, LPARAM lParam) +void HandleCommand (HWND hWnd, WORD wNotify, WORD idCtl, HWND hwCtl) { int i; - switch (wParam) { + switch (idCtl) { case IDC_POWER: /* toggle system power */ power = ! power; reset_all(0); @@ -1009,6 +1226,21 @@ void HandleCommand (HWND hWnd, WPARAM wParam, LPARAM lParam) remark_cmd("IPL failed"); } break; + + case IDC_TEAR: /* "tear off printer output" */ + case IDC_1132: /* do same if they click on the printer icon */ + if (btn[IDC_1132].state && (wNotify == STN_CLICKED || wNotify == STN_DBLCLK)) + tear_printer(); + break; + + case IDC_1442: + if (btn[IDC_1442].state == STATE_1442_FULL || wNotify == STN_DBLCLK) + stuff_cmd("detach cr"); + else if (btn[IDC_1442].state != STATE_1442_EMPTY && wNotify == STN_CLICKED) { + cr_rewind(); + update_gui(TRUE); + } + break; } update_gui(FALSE); @@ -1050,12 +1282,17 @@ LRESULT CALLBACK ConsoleWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPa case WM_PAINT: hDC = BeginPaint(hWnd, &ps); - DrawConsole(hDC); + DrawConsole(hDC, &ps); EndPaint(hWnd, &ps); break; - case WM_COMMAND: /* button click */ - HandleCommand(hWnd, wParam, lParam); + case WM_COMMAND: /* button click */ + HandleCommand(hWnd, HIWORD(wParam), LOWORD(wParam), (HWND) lParam); + break; + + case WM_CTLCOLOREDIT: /* text color for edit controls */ + SetBkColor((HDC) wParam, RGB(0,0,0)); + SetTextColor((HDC) wParam, RGB(255,255,255)); break; case WM_DRAWITEM: @@ -1085,6 +1322,10 @@ LRESULT CALLBACK ConsoleWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPa update_gui(FALSE); break; + case WM_DROPFILES: + accept_dropped_file((HANDLE) wParam); // console window - dragged file is a script or card deck + break; + default: return DefWindowProc(hWnd, uMsg, wParam, lParam); } @@ -1160,6 +1401,81 @@ void disk_unlocked (int unlocked) EnableWindow(btn[IDC_DISK_UNLOCK].hBtn, unlocked); } +static void accept_dropped_file (HANDLE hDrop) +{ + int nfiles; + char fname[MAX_PATH], cmd[MAX_PATH+50], *deckfile; + BOOL cardreader; + POINT pt; + HWND hWndDrop; + + nfiles = DragQueryFile(hDrop, 0xFFFFFFFF, NULL, 0); // get file count, + DragQueryFile(hDrop, 0, fname, sizeof(fname)); // get first filename + DragQueryPoint(hDrop, &pt); // get location of drop + DragFinish(hDrop); + + if (nfiles <= 0) // hmm, this seems unlikely to occur, but better check + return; + + if (running) { // can only accept a drop while processor is stopped + MessageBeep(0); + return; + } + + if ((hWndDrop = ChildWindowFromPoint(hConsoleWnd, pt)) == btn[IDC_1442].hBtn) + cardreader = TRUE; // file was dropped onto 1442 card reader + else if (hWndDrop == NULL || hWndDrop == hConsoleWnd) + cardreader = FALSE; // file was dropped onto console window, not a button + else { + MessageBeep(0); // file was dropped onto another button + return; + } + + if (nfiles > 1) { // oops, we wouldn't know what order to read them in + MessageBox(hConsoleWnd, "You may only drop one file at a time", "", MB_OK); + return; + } + + // if shift key is down, prepend @ to name (make it a deck file) + deckfile = ((GetKeyState(VK_SHIFT) & 0x8000) && cardreader) ? "@" : ""; + + sprintf(cmd, "%s \"%s%s\"", cardreader ? "attach cr" : "do", deckfile, fname); + stuff_cmd(cmd); +} + +static void tear_printer (void) +{ + char cmd[MAX_PATH+100], filename[MAX_PATH]; + + if ((prt_unit.flags & UNIT_ATT) == 0) + return; + + strcpy(filename, prt_unit.filename); // save current attached filename + + if (! stuff_and_wait("detach prt", 1000, 0)) // detach it + return; + + sprintf(cmd, "view \"%s\"", filename); // spawn notepad to view it + if (! stuff_and_wait(cmd, 3000, 500)) + return; + +// no, now we have them click the card reader icon twice to unload the deck. more flexible that way +// if (! stuff_and_wait("detach cr", 1000, 0)) // detach the card reader so they can edit the deck file +// return; + + unlink(filename); // delete the file + + sprintf(cmd, "attach prt \"%s\"", filename); // reattach + stuff_cmd(cmd); +} + +#ifdef XXX + 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; + +#endif + CRITICAL_SECTION critsect; void begin_critical_section (void) @@ -1201,6 +1517,7 @@ static DWORD WINAPI CmdThread (LPVOID arg) WaitForSingleObject(hCmdReadEvent, INFINITE); /* wait for request */ read_line(cmdbuffer, sizeof(cmdbuffer), stdin); /* read one line */ scp_stuffed = FALSE; /* say how we got it */ + scp_reading = FALSE; SetEvent(hCmdReadyEvent); /* notify main thread a line is ready */ } return 0; @@ -1225,11 +1542,8 @@ char *read_cmdline (char *ptr, int size, FILE *stream) 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 */ ; @@ -1247,9 +1561,58 @@ void stuff_cmd (char *cmd) { strcpy(cmdbuffer, cmd); /* save the string */ scp_stuffed = TRUE; /* note where it came from */ + scp_reading = FALSE; + ResetEvent(hCmdReadEvent); /* clear read request event */ SetEvent(hCmdReadyEvent); /* notify main thread a line is ready */ } +// my_yield - process GUI messages. It's not apparent why stuff_and_wait would block, +// since it sleeps in the GUI thread while scp runs in the main thread. However, +// at the end of every command scp calls update_gui, which can result in messages +// being sent to the GUI thread. So, the GUI thread has to process messages while +// stuff_and_wait is waiting. + +static void my_yield (void) +{ + MSG msg; + // multitask + while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } +} + +// stuff_and_wait -- stuff a command and wait for the emulator to process the command +// and come back to prompt for another + +t_bool stuff_and_wait (char *cmd, int timeout, int delay) +{ + scp_reading = FALSE; + + stuff_cmd(cmd); + + while (! scp_reading) { + if (timeout < 0) + return FALSE; + + my_yield(); + if (scp_reading) + break; + + Sleep(50); + if (timeout) + if ((timeout -= 50) <= 0) + timeout = -1; + + my_yield(); + } + + if (delay) + Sleep(delay); + + return TRUE; +} + /* 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. @@ -1257,8 +1620,14 @@ void stuff_cmd (char *cmd) void remark_cmd (char *remark) { + if (scp_reading) { + putchar('\n'); + if (sim_log) putc('\n', sim_log); + } + 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> "); diff --git a/Ibm1130/ibm1130_prt.c b/Ibm1130/ibm1130_prt.c index dd3053cc..4f7dfa40 100644 --- a/Ibm1130/ibm1130_prt.c +++ b/Ibm1130/ibm1130_prt.c @@ -4,6 +4,15 @@ Brian Knittel Revision History + + 2003.12.02 - Added -p option for physical line printer output (flushes + output buffer after each line). When using a physical printer on + Windows, be sure to set printer to "send output directly to printer" + to disable spooling, otherwise nothing appears until printer is + detatched. + + 2003.11.25 - Changed magic filename for standard output to "(stdout)". + 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 @@ -88,6 +97,7 @@ static int32 prt_twait = 50; /* transfer wait, for 1403 operations */ #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_V_PHYSICAL_PTR (UNIT_V_UF + 10) /* this appears in ibm1130_gui as well */ #define UNIT_FORMCHECK (1u << UNIT_V_FORMCHECK) #define UNIT_DATACHECK (1u << UNIT_V_DATACHECK) @@ -99,13 +109,15 @@ static int32 prt_twait = 50; /* transfer wait, for 1403 operations */ #define UNIT_PARITYCHECK (1u << UNIT_V_PARITYCHECK) #define UNIT_RINGCHECK (1u << UNIT_V_RINGCHECK) #define UNIT_SYNCCHECK (1u << UNIT_V_SYNCCHECK) +#define UNIT_PHYSICAL_PTR (1u << UNIT_V_PHYSICAL_PTR) 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 */ +#define IS_1403(uptr) (uptr->flags & UNIT_1403) /* model test */ +#define IS_1132(uptr) ((uptr->flags & UNIT_1403) == 0) /* model test */ +#define IS_PHYSICAL(uptr) (uptr->flags & UNIT_PHYSICAL_PTR) /* Parameter in the unit descriptor (1132 printer) */ @@ -118,8 +130,8 @@ 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 */ + { DRDATA (FTIME, prt_fwait, 24), PV_LEFT }, /* 1403 fast wait */ + { DRDATA (TTIME, prt_twait, 24), PV_LEFT }, /* 1403 transfer wait */ { NULL } }; MTAB prt_mod[] = { @@ -175,6 +187,8 @@ cccgi[] = { #include "ibm1130_prtwheel.h" +extern int32 sim_switches; + // 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) @@ -239,7 +253,7 @@ static void newpage (FILE *fd) putc('\f', fd); // formfeed } -static void flush_prt_line (FILE *fd, int spacemode) +static void flush_prt_line (FILE *fd, int spacemode, t_bool phys_flush) { int r; @@ -262,6 +276,7 @@ static void flush_prt_line (FILE *fd, int spacemode) else prt_nnl++; + prt_unit->pos++; // note something written return; } @@ -296,7 +311,11 @@ static void flush_prt_line (FILE *fd, int spacemode) reset_prt_line(); + prt_unit->pos++; // note something written prt_nnl++; // queue a newline + + if (phys_flush) // if physical printer, send buffered output to device + fflush(fd); } // 1132 printer commands @@ -412,7 +431,7 @@ static t_stat prt1132_svc (UNIT *uptr) } if (uptr->flags & UNIT_SPACING) { - flush_prt_line(uptr->fileref, UNIT_SPACING); + flush_prt_line(uptr->fileref, UNIT_SPACING, IS_PHYSICAL(uptr)); 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); @@ -423,7 +442,7 @@ static t_stat prt1132_svc (UNIT *uptr) if (uptr->flags & UNIT_SKIPPING) { do { - flush_prt_line(uptr->fileref, UNIT_SKIPPING); + flush_prt_line(uptr->fileref, UNIT_SKIPPING, IS_PHYSICAL(uptr)); 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 @@ -569,7 +588,7 @@ static t_stat prt1403_svc(UNIT *uptr) } else if (uptr->flags & UNIT_SKIPPING) { do { // find line with exact match of tape punches - flush_prt_line(uptr->fileref, UNIT_SKIPPING); + flush_prt_line(uptr->fileref, UNIT_SKIPPING, IS_PHYSICAL(uptr)); } while (cctape[prt_row] != SKIPTARGET); // slew directly to requested cc tape punch CLRBIT(uptr->flags, UNIT_SKIPPING); // done with this @@ -579,7 +598,7 @@ static t_stat prt1403_svc(UNIT *uptr) SETBIT(ILSW[4], ILSW_4_1403_PRINTER); } else if (uptr->flags & UNIT_SPACING) { - flush_prt_line(uptr->fileref, UNIT_SPACING); + flush_prt_line(uptr->fileref, UNIT_SPACING, IS_PHYSICAL(uptr)); CLRBIT(uptr->flags, UNIT_SPACING); // done with this CLRBIT(PRT_DSW, PRT1403_DSW_CARRIAGE_BUSY); @@ -685,9 +704,14 @@ static t_stat prt_attach (UNIT *uptr, char *cptr) } } + if (sim_switches & SWMASK('P')) /* set physical (unbuffered) printer flag */ + SETBIT(uptr->flags, UNIT_PHYSICAL_PTR); + else + CLRBIT(uptr->flags, UNIT_PHYSICAL_PTR); + sim_cancel(uptr); - if (strcmp(cptr, "-") == 0) { /* connect printer to stdout */ + if (strcmp(cptr, "(stdout)") == 0) { /* connect printer to stdout */ if (uptr -> flags & UNIT_DIS) return SCPE_UDIS; /* disabled? */ uptr->filename = calloc(CBUFSIZE, sizeof(char)); strcpy(uptr->filename, "(stdout)"); @@ -695,11 +719,13 @@ static t_stat prt_attach (UNIT *uptr, char *cptr) SETBIT(uptr->flags, UNIT_ATT); uptr->pos = 0; } - else if ((rval = attach_unit(uptr, cptr)) != SCPE_OK) { - return rval; + else { + if ((rval = attach_unit(uptr, quotefix(cptr))) != SCPE_OK) + return rval; } - fseek(uptr->fileref, 0, SEEK_END); /* if we opened an existing file, append to it */ + fseek(uptr->fileref, 0, SEEK_END); /* if we opened an existing file, append to it */ + uptr->pos = ftell(uptr->fileref); if (IS_1132(uptr)) { CLRBIT(ILSW[1], ILSW_1_1132_PRINTER); @@ -743,7 +769,7 @@ static t_stat prt_detach (UNIT *uptr) { t_stat rval; - flush_prt_line(uptr->fileref, TRUE); + flush_prt_line(uptr->fileref, TRUE, TRUE); if (uptr->fileref == stdout) { CLRBIT(uptr->flags, UNIT_ATT); diff --git a/Ibm1130/ibm1130_stddev.c b/Ibm1130/ibm1130_stddev.c index 0cc477d4..98bc8a86 100644 --- a/Ibm1130/ibm1130_stddev.c +++ b/Ibm1130/ibm1130_stddev.c @@ -5,6 +5,10 @@ Brian Knittel Revision History: + + 2003.11.23 - Fixed bug in new routine "quotefix" that made sim crash + for all non-Windows builds :( + 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 @@ -197,7 +201,7 @@ DEVICE tti_dev = { "KEYBOARD", &tti_unit, tti_reg, tti_mod, 1, 10, 31, 1, 8, 8, NULL, NULL, &tti_reset, - NULL, NULL, NULL }; + NULL, basic_attach, NULL }; /* TTO data structures @@ -206,7 +210,11 @@ DEVICE tti_dev = { tto_reg TTO register list */ -UNIT tto_unit = { UDATA (&tto_svc, 0, 0), SERIAL_OUT_WAIT }; + // 14-Nov-03 -- the wait time was SERIAL_OUT_WAIT, but recent versions of SIMH reduced + // this to 100, and wouldn't you know it, APL\1130 has about 120 instructions between the XIO WRITE + // to the console and the associated WAIT. + +UNIT tto_unit = { UDATA (&tto_svc, 0, 0), 200 }; REG tto_reg[] = { { ORDATA (BUF, tto_unit.buf, 16) }, @@ -227,7 +235,7 @@ DEVICE tto_dev = { "TTO", &tto_unit, tto_reg, tto_mod, 1, 10, 31, 1, 8, 8, NULL, NULL, &tto_reset, - NULL, NULL, NULL }; + NULL, basic_attach, NULL }; /* Terminal input routines @@ -270,6 +278,8 @@ void xio_1131_console (int32 iocc_addr, int32 func, int32 modify) ch = (ReadW(iocc_addr) >> 8) & 0xFF; /* get character to write */ tto_unit.buf = emit_conout_character(ch); /* output character and save write status */ +// fprintf(stderr, "[CONOUT] %02x\n", ch); + SETBIT(tto_dsw, TT_DSW_PRINTER_BUSY); sim_activate(&tto_unit, tto_unit.wait); /* schedule interrupt */ break; @@ -288,6 +298,8 @@ void xio_1131_console (int32 iocc_addr, int32 func, int32 modify) sprintf(msg, "Invalid console XIO function %x", func); xio_error(msg); } + +// fprintf(stderr, "After XIO %04x %04x\n", tti_dsw, tto_dsw); } // emit_conout_character - write character with 1130 console code 'ch' @@ -345,6 +357,8 @@ static t_stat tti_svc (UNIT *uptr) /* otherwise, so ^E can interrupt the simulator, */ sim_activate(&tti_unit, tti_unit.wait); /* always continue polling keyboard */ + assert(sim_clock_queue != NULL); + temp = sim_poll_kbd(); if (temp < SCPE_KFLAG) @@ -411,6 +425,8 @@ static t_stat tti_svc (UNIT *uptr) SETBIT(ILSW[4], ILSW_4_CONSOLE); calc_ints(); +// fprintf(stderr, "TTI interrupt svc SET %04x %04x\n", tti_dsw, tto_dsw); + return SCPE_OK; } @@ -433,6 +449,35 @@ static t_stat tti_reset (DEVICE *dptr) return SCPE_OK; } +// basic_attach - fix quotes in filename, then call standard unit attach routine + +t_stat basic_attach (UNIT *uptr, char *cptr) +{ + return attach_unit(uptr, quotefix(cptr)); /* fix quotes in filenames & attach */ +} + +// quotefix - strip off quotes around filename, if present + +char * quotefix (char * cptr) +{ +#ifdef WIN32 /* do this only for Windows builds, for the time being */ + char *c; + int quote; + + if (*cptr == '"' || *cptr == '\'') { + quote = *cptr++; /* remember quote and skip over it */ + + for (c = cptr; *c && *c != quote; c++) + ; /* find closing quote, or end of string */ + + if (*c) /* terminate string at closing quote */ + *c = '\0'; + } + +#endif + return cptr; /* return pointer to cleaned-up name */ +} + t_bool keyboard_is_busy (void) /* return TRUE if keyboard is not expecting a character */ { return (tti_dsw & TT_DSW_KEYBOARD_BUSY); @@ -446,6 +491,8 @@ static t_stat tto_svc (UNIT *uptr) SETBIT(ILSW[4], ILSW_4_CONSOLE); calc_ints(); +// fprintf(stderr, "TTO interrupt svc SET %04x %04x\n", tti_dsw, tto_dsw); + return (t_stat) tto_unit.buf; /* return status saved during output conversion */ } @@ -824,7 +871,10 @@ static t_stat map_conout_character (int ch) curcol--; } else if (n_os_mappings && ch != (unsigned char) IGNR_) { - if (curcol > maxcol) { // first time in this column, no overstrike possible yet + if (curcol >= MAX_OUTPUT_COLUMNS) + map_conout_character('\x81'); // precede with automatic carriage return/line feed, I guess + + if (curcol > maxcol) { // first time in this column, no overstrike possible yet os_buf[curcol].nin = 0; maxcol = curcol; } @@ -853,7 +903,7 @@ static t_stat map_conout_character (int ch) } } - if (curcol < MAX_OUTPUT_COLUMNS) + if (curcol < MAX_OUTPUT_COLUMNS) // this should now never happen, as we automatically return curcol++; } @@ -897,18 +947,15 @@ static t_stat font_cmd (int32 flag, char *cptr) 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 */ + if (*cptr == '\'' || *cptr == '"') { /* quoted string */ + quote = *cptr++; /* remember quote character */ + fname++; /* skip 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 */ + while (*cptr && (*cptr != quote)) /* find closing quote */ + cptr++; + } + else { + while (*cptr && (*cptr > ' ')) /* find terminating blank */ cptr++; } *cptr = '\0'; /* terminate name */ diff --git a/Ibm1130/ibm1130_sys.c b/Ibm1130/ibm1130_sys.c index ba3a4f49..6ddf2dac 100644 --- a/Ibm1130/ibm1130_sys.c +++ b/Ibm1130/ibm1130_sys.c @@ -46,7 +46,6 @@ extern int32 saved_PC; */ char sim_name[] = "IBM 1130"; -char sim_version[] = "V0.30"; REG *sim_PC = &cpu_reg[0]; diff --git a/Ibm1130/ibm1130res.h b/Ibm1130/ibm1130res.h index ce47382e..6990b89e 100644 --- a/Ibm1130/ibm1130res.h +++ b/Ibm1130/ibm1130res.h @@ -2,9 +2,8 @@ // Microsoft Visual C++ generated include file. // Used by ibm1130.rc // - #define IDB_CONSOLE 101 -#define IDC_HAND 102 +#define IDC_HAND 102 // Next default values for new objects // 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/readme_update.txt b/Ibm1130/readme_update.txt index aab52dbc..05a5ff91 100644 --- a/Ibm1130/readme_update.txt +++ b/Ibm1130/readme_update.txt @@ -2,6 +2,18 @@ Version: 10 July 2003 History (partial): +2003-11-15 Changed default value of TTO STIME to 200. It was + defined using a constant from sim_defs.h which was + changed from 10 to 100 at some point. APL\1130 has a + sychronization bug & hangs if the console output complete + interrupt occurs between the XIO SENSE and WAIT instructions. + This bug is hit frequently if the delay time is set to + 100 instructions. 10 worked reliably, but is really not realistic, + and 200 may not be adequate in all cases, but we'll try 200 for now. + +2003-11-00 Updated GUI to allow drag and drop to simulated card + reader, tear-off from simulated printer + 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. 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 index 7f0eae34..3bdc7fd8 100644 --- a/Interdata/id16_cpu.c +++ b/Interdata/id16_cpu.c @@ -23,6 +23,9 @@ 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 Interdata 16b CPU + + 22-Sep-03 RMS Added additional instruction decode types 07-Feb-03 RMS Fixed bug in SETM, SETMR (found by Mark Pizzolato) The register state for the Interdata 16b CPU is: @@ -266,7 +269,7 @@ const uint16 decrom[256] = { OP_NO | OP_816, /* FXR */ OP_NO | OP_816, /* FLR */ 0, 0, 0, /* 30:32 */ - OP_RR | OP_816E | OP_PRV, /* LPSR */ + OP_NO | 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 */ @@ -328,8 +331,8 @@ const uint16 decrom[256] = { OP_NO | OP_716, /* SRLS */ OP_NO | OP_716, /* SLLS */ OP_NO, /* STBR */ - OP_NO, /* LDBR */ - OP_NO | OP_716, /* EXBR */ + OP_RR, /* LDBR */ + OP_RR | OP_716, /* EXBR */ OP_NO | OP_716 | OP_PRV, /* EPSR */ OP_RR | OP_PRV, /* WBR */ OP_RR | OP_PRV, /* RBR */ @@ -364,8 +367,8 @@ const uint16 decrom[256] = { OP_RX | OP_ID4, /* STM */ OP_RX | OP_ID4, /* LM */ OP_RX, /* STB */ - OP_RX, /* LDB */ - OP_RX | OP_716, /* CLB */ + OP_RXB, /* LDB */ + OP_RXB | OP_716, /* CLB */ OP_RX | OP_ID4 | OP_PRV, /* AL */ OP_RXH | OP_PRV, /* WB */ OP_RXH | OP_PRV, /* RB */ @@ -552,6 +555,7 @@ while (reason == 0) { /* loop until halted */ uint32 dev, drom, inc, lim, opnd; uint32 op, r1, r1p1, r2, ea, oPC; uint32 rslt, t, map; +uint32 ir1, ir2, ityp; int32 sr, st; if (sim_interval <= 0) { /* check clock queue */ @@ -606,11 +610,13 @@ if (sim_brk_summ && sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */ 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; +ir1 = ReadH (oPC = PC); /* fetch instr */ +op = (ir1 >> 8) & 0xFF; /* isolate op, R1, R2 */ +r1 = (ir1 >> 4) & 0xF; +r2 = ir1 & 0xF; drom = decrom[op]; +ityp = drom & OP_MASK; + 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 */ @@ -618,26 +624,41 @@ if ((drom == 0) || (drom & dec_flgs)) { /* not in model? */ if ((drom & OP_PRV) && (PSW & PSW_PRO)) { /* priv & protected? */ cc = swap_psw (ILOPSW, cc); /* swap PSW */ continue; } -switch (drom & OP_MASK) { /* decode instruction */ + +switch (ityp) { /* 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 */ + ir2 = ea = ReadH (PC); /* fetch address */ + if (r2) ea = (ir2 + R[r2]) & VAMASK; /* index calculation */ opnd = ea; /* operand is ea */ break; -case OP_RXH: /* reg-mem read */ + +case OP_RXB: /* reg-mem byte */ PC = (PC + 2) & VAMASK; /* increment PC */ - ea = ReadH (PC); /* fetch address */ + ir2 = ea = ReadH (PC); /* fetch address */ + if (r2) ea = (ea + R[r2]) & VAMASK; /* index calculation */ + opnd = ReadB (ea); /* fetch operand */ + break; + +case OP_RXH: /* reg-mem halfword */ + PC = (PC + 2) & VAMASK; /* increment PC */ + ir2 = ea = ReadH (PC); /* fetch address */ if (r2) ea = (ea + R[r2]) & VAMASK; /* index calculation */ opnd = ReadH (ea); /* fetch operand */ - break; } + break; + +default: + return SCPE_IERR; } + PC = (PC + 2) & VAMASK; /* increment PC */ switch (op) { /* case on opcode */ @@ -672,11 +693,9 @@ case 0xD0: /* STM - RX */ 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 */ +case 0x93: /* LDBR - RR */ +case 0xD3: /* LDB - RXB */ + R[r1] = opnd & DMASK8; /* load byte */ break; case 0x92: /* STBR - NO */ @@ -686,8 +705,8 @@ 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); +case 0x94: /* EXBR - RR */ + R[r1] = (opnd >> 8) | ((opnd & DMASK8) << 8); break; /* Control instructions */ @@ -792,8 +811,7 @@ case 0xC5: /* CLHI - RS */ if (((R[r1] ^ opnd) & (~opnd ^ rslt)) & SIGN16) cc = cc | CC_V; break; -case 0xD4: /* CLB - RX */ - opnd = ReadB (ea); /* get operand */ +case 0xD4: /* CLB - RXB */ t = R[r1] & DMASK8; rslt = (t - opnd) & DMASK16; /* result */ CC_GL_16 (rslt); /* set G,L */ @@ -1118,7 +1136,7 @@ case 0xC2: /* LPSW - RX */ if (PSW & PSW_SQI) cc = testsysq (cc); /* test for q */ break; -case 0x95: /* EPSR - RR */ +case 0x95: /* EPSR - NO */ R[r1] = BUILD_PSW (cc); /* save PSW */ case 0x33: /* LPSR - NO */ cc = newPSW (R[r2]); /* load new PSW */ diff --git a/Interdata/id32_cpu.c b/Interdata/id32_cpu.c index a0846485..530e695d 100644 --- a/Interdata/id32_cpu.c +++ b/Interdata/id32_cpu.c @@ -1,6 +1,6 @@ /* id32_cpu.c: Interdata 32b CPU simulator - Copyright (c) 2000-2003, Robert M. Supnik + Copyright (c) 2000-2004, Robert M. Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -23,6 +23,12 @@ be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. + cpu Interdata 32b CPU + + 31-Dec-03 RMS Fixed bug in cpu_set_hist + 22-Sep-03 RMS Added additional instruction decode types + Added instruction history + The register state for an Interdata 32b CPU is: REG[0:F][2]<0:31> general register sets @@ -156,6 +162,18 @@ #define UNIT_832 (1 << UNIT_V_832) #define UNIT_TYPE (UNIT_DPFP | UNIT_832) +#define HIST_PC 0x40000000 +#define HIST_MIN 64 +#define HIST_MAX 65536 +struct InstHistory { + uint32 pc; + uint32 ir1; + uint32 ir2; + uint32 ir3; + uint32 r1; + uint32 ea; + uint32 opnd; }; + #define SEXT32(x) (((x) & SIGN32)? ((int32) ((x) | ~0x7FFFFFFF)): \ ((int32) ((x) & 0x7FFFFFFF))) #define SEXT16(x) (((x) & SIGN16)? ((int32) ((x) | ~0x7FFF)): \ @@ -202,6 +220,9 @@ 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 */ +uint32 hst_p = 0; /* history pointer */ +uint32 hst_lnt = 0; /* history length */ +struct InstHistory *hst = NULL; /* instruction history */ 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 }; @@ -229,6 +250,8 @@ 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); +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 set_r_display (uint32 *rbase); extern t_bool devtab_init (void); @@ -329,8 +352,8 @@ const uint16 decrom[256] = { OP_RXF, /* S */ OP_RXF, /* M */ OP_RXF, /* D */ - OP_RX, /* CRC12 */ - OP_RX, /* CRC16 */ + OP_RXH, /* CRC12 */ + OP_RXH, /* CRC16 */ OP_RX, /* STE */ OP_RXH, /* AHM */ 0, /* PB - 8/32C */ @@ -349,7 +372,7 @@ const uint16 decrom[256] = { OP_RX | OP_DPF, /* STD */ OP_RX, /* SME */ OP_RX, /* LME */ - OP_RX, /* LHL */ + OP_RXH, /* LHL */ OP_RX, /* TBT */ OP_RX, /* SBT */ OP_RX, /* RBT */ @@ -367,8 +390,8 @@ const uint16 decrom[256] = { OP_NO, /* SRHLS */ OP_NO, /* SLHLS */ OP_NO, /* STBR */ - OP_NO, /* LDBR */ - OP_NO, /* EXBR */ + OP_RR, /* LDBR */ + OP_RR, /* EXBR */ OP_NO | OP_PRV, /* EPSR */ OP_RR | OP_PRV, /* WBR */ OP_RR | OP_PRV, /* RBR */ @@ -403,8 +426,8 @@ const uint16 decrom[256] = { OP_RX, /* STM */ OP_RX, /* LM */ OP_RX, /* STB */ - OP_RX, /* LDB */ - OP_RX, /* CLB */ + OP_RXB, /* LDB */ + OP_RXB, /* CLB */ OP_RX | OP_PRV, /* AL */ OP_RXF | OP_PRV, /* WB */ OP_RXF | OP_PRV, /* RB */ @@ -419,7 +442,7 @@ const uint16 decrom[256] = { OP_RXH, /* TS */ OP_RX, /* SVC */ OP_RI1 | OP_PRV, /* SINT */ - OP_RX | OP_PRV, /* SCP */ + OP_RXH | OP_PRV, /* SCP */ 0, 0, /* E4:E5 */ OP_RX, /* LA */ OP_RXF, /* TLATE */ @@ -534,6 +557,8 @@ MTAB cpu_mod[] = { { UNIT_TYPE, UNIT_DPFP | UNIT_832, "8/32", "832", NULL }, { MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, NULL, "CONSINT", &cpu_set_consint, NULL, NULL }, + { MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, "HISTORY", "HISTORY", + &cpu_set_hist, &cpu_show_hist }, { 0 } }; DEVICE cpu_dev = { @@ -586,6 +611,7 @@ uint32 dev, drom, opnd, inc, lim, bufa; uint32 op, r1, r1p1, r2, rx2, ea; uint32 mpy, mpc, dvr; uint32 i, rslt, rlo, t; +uint32 ir1, ir2, ir3, ityp; int32 sr, st; if (sim_interval <= 0) { /* check clock queue */ @@ -644,11 +670,13 @@ if (sim_brk_summ && sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */ 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; +ir1 = ReadH (oPC = PC, VE); /* fetch instr */ +op = (ir1 >> 8) & 0xFF; /* extract op,R1,R2 */ +r1 = (ir1 >> 4) & 0xF; +r2 = ir1 & 0xF; drom = decrom[op]; /* get decode flags */ +ityp = drom & OP_MASK; /* instruction type */ + if ((drom == 0) || (drom & dec_flgs)) { /* not in model? */ if (stop_inst) reason = STOP_RSRV; /* stop or */ else cc = exception (ILOPSW, cc, 0); /* exception */ @@ -657,55 +685,70 @@ if ((drom & OP_PRV) && (PSW & PSW_PRO)) { /* priv & protected? */ cc = exception (ILOPSW, cc, 0); /* exception */ continue; } -switch (drom & OP_MASK) { /* decode instruction */ +switch (ityp) { /* 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 */ + opnd = R[r2]; /* ea/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 */ + ir2 = ReadH ((PC + 2) & VAMASK, VE); /* fetch immed */ + opnd = SEXT16 (ir2); /* 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 */ + ir2 = ReadH ((PC + 2) & VAMASK, VE); /* fetch imm hi */ + ir3 = ReadH ((PC + 4) & VAMASK, VE); /* fetch imm lo */ + opnd = (ir2 << 16) | ir3; /* 32b immediate */ 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? */ + +case OP_RX: case OP_RXB: case OP_RXH: case OP_RXF: /* reg-mem */ + ir2 = ReadH ((PC + 2) & VAMASK, VE); /* fetch addr */ + if ((ir2 & 0xC000) == 0) { /* displacement? */ PC = (PC + 4) & VAMASK; /* increment PC */ - ea = t; } /* abs 14b displ */ - else if (t & 0x8000) { /* relative? */ + ea = ir2; } /* abs 14b displ */ + else if (ir2 & 0x8000) { /* relative? */ PC = (PC + 4) & VAMASK; /* increment PC */ - ea = PC + SEXT15 (t); } /* add to incr PC */ + ea = PC + SEXT15 (ir2); } /* 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 */ + rx2 = (ir2 >> 8) & 0xF; /* get second index */ + ea = (ir2 & 0xFF) << 16; /* shift to place */ + ir3 = ReadH ((PC + 4) & VAMASK, VE); /* fetch addr lo */ + ea = ea | ir3; /* 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? */ + if (ityp == OP_RXF) opnd = ReadF (ea, VR); /* get fw operand? */ + else if (ityp == OP_RXH) { /* get hw operand? */ t = ReadH (ea, VR); /* read halfword */ opnd = SEXT16 (t); } /* sign extend */ - else opnd = ea; /* for sloppy code */ + else if (ityp == OP_RXB) opnd = ReadB (ea, VR); /* get byte opnd? */ + else opnd = ea; /* just address */ break; -case OP_UNDEF: + +default: return SCPE_IERR; } + +if (hst_lnt) { /* instruction history? */ + hst[hst_p].pc = oPC | HIST_PC; /* save decode state */ + hst[hst_p].ir1 = ir1; + hst[hst_p].ir2 = ir2; + hst[hst_p].ir3 = ir3; + hst[hst_p].r1 = R[r1]; + hst[hst_p].ea = ea; + hst[hst_p].opnd = opnd; + hst_p = hst_p + 1; + if (hst_p >= hst_lnt) hst_p = 0; } if (qevent & EV_MAC) continue; /* MAC abort on fetch? */ switch (op) { /* case on opcode */ @@ -721,8 +764,8 @@ case 0xF8: /* LI - RI2 */ CC_GL_32 (R[r1]); /* set G,L */ break; -case 0x73: /* LHL - RX */ - R[r1] = ReadH (ea, VR); /* get op, zero ext */ +case 0x73: /* LHL - RXH */ + R[r1] = opnd & DMASK16; /* get op, zero ext */ CC_GL_32 (R[r1]); /* set G, L */ break; @@ -764,11 +807,9 @@ case 0xE0: /* TS - RXH */ 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 */ +case 0x93: /* LDBR - RR */ +case 0xD3: /* LDB - RXB */ + R[r1] = opnd & DMASK8; /* load byte */ break; case 0x92: /* STBR - NO */ @@ -778,13 +819,13 @@ 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); +case 0x34: /* EXHR - RR */ + R[r1] = ((opnd >> 16) & DMASK16) | ((opnd & DMASK16) << 16); break; -case 0x94: /* EXBR - NO */ +case 0x94: /* EXBR - RR */ R[r1] = (R[r1] & ~DMASK16) | - ((R[r2] >> 8) & DMASK8) | ((R[r2] & DMASK8) << 8); + ((opnd >> 8) & DMASK8) | ((opnd & DMASK8) << 8); break; /* Control instructions */ @@ -793,14 +834,14 @@ case 0x01: /* BALR - RR */ case 0x41: /* BAL - RX */ PCQ_ENTRY; /* save old PC */ R[r1] = PC; /* save cur PC */ - PC = ea; /* branch */ + PC = opnd; /* branch */ break; case 0x02: /* BTCR - RR */ case 0x42: /* BTC - RX */ if (cc & r1) { /* test CC's */ PCQ_ENTRY; /* branch if true */ - PC = ea; } + PC = opnd; } break; case 0x20: /* BTBS - NO */ @@ -819,7 +860,7 @@ case 0x03: /* BFCR - RR */ case 0x43: /* BFC - RX */ if ((cc & r1) == 0) { /* test CC's */ PCQ_ENTRY; /* branch if false */ - PC = ea; } + PC = opnd; } break; case 0x22: /* BFBS - NO */ @@ -840,16 +881,16 @@ case 0xC0: /* BXH - RX */ R[r1] = (R[r1] + inc) & DMASK32; /* R1 = R1 + inc */ if (R[r1] > lim) { /* if R1 > lim */ PCQ_ENTRY; /* branch */ - PC = ea; } + PC = opnd; } break; -case 0xC1: /* BXLE - RS */ +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) & DMASK32; /* R1 = R1 + inc */ if (R[r1] <= lim) { /* if R1 <= lim */ PCQ_ENTRY; /* branch */ - PC = ea; } + PC = opnd; } break; /* Logical instructions */ @@ -898,8 +939,7 @@ case 0xF5: /* CI - RI2 */ if (((R[r1] ^ opnd) & (~opnd ^ rslt)) & SIGN32) cc = cc | CC_V; break; -case 0xD4: /* CLB - RX */ - opnd = ReadB (ea, VR); /* get operand */ +case 0xD4: /* CLB - RXB */ t = R[r1] & DMASK8; rslt = (t - opnd) & DMASK16; /* result */ CC_GL_16 (rslt); /* set G,L 16b */ @@ -1278,8 +1318,8 @@ case 0xE2: /* SINT - RI1 */ int_eval (); break; -case 0xE3: /* SCP - RX */ - opnd = ReadH (ea, VR); /* zero ext operand */ +case 0xE3: /* SCP - RXH */ + opnd = opnd & DMASK16; /* 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 */ @@ -1335,7 +1375,7 @@ case 0x67: /* RBL - RX */ break; case 0x5E: /* CRC12 - RXH */ - opnd = ReadH (ea, VR); /* zero ext opnd */ + opnd = opnd & DMASK16; /* zero ext opnd */ t = (R[r1] & 0x3F) ^ opnd; for (i = 0; i < 6; i++) { if (t & 1) t = (t >> 1) ^ 0x0F01; @@ -1344,7 +1384,7 @@ case 0x5E: /* CRC12 - RXH */ break; case 0x5F: /* CRC16 - RXH */ - opnd = ReadH (ea, VR); /* zero ext opnd */ + opnd = opnd & DMASK16; /* zero ext opnd */ t = (R[r1] & 0xFF) ^ opnd; for (i = 0; i < 8; i++) { if (t & 1) t = (t >> 1) ^ 0xA001; @@ -1417,7 +1457,7 @@ case 0xDB: /* RD - RX */ break; case 0x99: /* RHR - RR */ -case 0xD9: /* RH - RS */ +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? */ @@ -1436,7 +1476,7 @@ case 0xD9: /* RH - RS */ break; case 0x9D: /* SSR - RR */ -case 0xDD: /* SS - RS */ +case 0xDD: /* SS - RX */ dev = R[r1] & DEV_MAX; if (DEV_ACC (dev)) { /* dev exist? */ dev_tab[dev] (dev, IO_ADR, 0); /* select */ @@ -2026,3 +2066,61 @@ t_stat cpu_set_consint (UNIT *uptr, int32 val, char *cptr, void *desc) if (PSW & PSW_EXI) SET_INT (v_DS); return SCPE_OK; } + +/* Set history */ + +t_stat cpu_set_hist (UNIT *uptr, int32 val, char *cptr, void *desc) +{ +uint32 i, lnt; +t_stat r; + +if (cptr == NULL) { + for (i = 0; i < hst_lnt; i++) hst[i].pc = 0; + hst_p = 0; + return SCPE_OK; } +lnt = (uint32) get_uint (cptr, 10, HIST_MAX, &r); +if ((r != SCPE_OK) || (lnt && (lnt < HIST_MIN))) return SCPE_ARG; +hst_p = 0; +if (hst_lnt) { + free (hst); + hst_lnt = 0; + hst = NULL; } +if (lnt) { + hst = calloc (sizeof (struct InstHistory), lnt); + if (hst == NULL) return SCPE_MEM; + hst_lnt = lnt; } +return SCPE_OK; +} + +/* Show history */ + +t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, void *desc) +{ +uint32 op, k, di; +t_value sim_eval[6]; +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? */ +fprintf (st, "PC r1 operand ea IR\n\n"); +di = hst_p; /* work forward */ +for (k = 0; k < hst_lnt; k++) { /* print specified */ + h = &hst[(di++) % hst_lnt]; /* entry pointer */ + if (h->pc & HIST_PC) { /* instruction? */ + fprintf (st, "%06X %08X %08X ", h->pc & VAMASK32, h->r1, h->opnd); + sim_eval[0] = op = (h->ir1 >> 8) & 0xFF; + sim_eval[1] = h->ir1 & 0xFF; + sim_eval[2] = (h->ir2 >> 8) & 0xFF; + sim_eval[3] = h->ir2 & 0xFF; + sim_eval[4] = (h->ir3 >> 8) & 0xFF; + sim_eval[5] = h->ir3 & 0xFF; + if (OP_TYPE (op) >= OP_RX) fprintf (st, "%06X ", h->ea); + else fprintf (st, " "); + if ((fprint_sym (st, h->pc & VAMASK32, sim_eval, &cpu_unit, SWMASK ('M'))) > 0) + fprintf (st, "(undefined) %04X", h->ir1); + fputc ('\n', st); /* end line */ + } /* end if instruction */ + } /* end for */ +return SCPE_OK; +} diff --git a/Interdata/id_defs.h b/Interdata/id_defs.h index 6fd75068..886ec740 100644 --- a/Interdata/id_defs.h +++ b/Interdata/id_defs.h @@ -26,6 +26,7 @@ The author gratefully acknowledges the help of Carl Friend and Al Kossow, who provided key documents about the Interdata product line. + 22-Sep-03 RMS Added additional instruction decode types 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 @@ -188,9 +189,10 @@ struct BlockIO { #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_RXB 0x0005 /* all: reg-mem, rd BY */ +#define OP_RXH 0x0006 /* all: reg-mem, rd HW */ +#define OP_RXF 0x0007 /* 32b: reg-mem, rd FW */ +#define OP_RI2 0x0008 /* 32b: reg-imm 32b */ #define OP_MASK 0x000F #define OP_ID4 0x0010 /* 16b: ID4 */ diff --git a/Interdata/id_diag.txt b/Interdata/id_diag.txt index ea84a188..d66260d0 100644 --- a/Interdata/id_diag.txt +++ b/Interdata/id_diag.txt @@ -69,7 +69,7 @@ sim> boot pt0 Breakpoint: PC: 00C2 (EXBR R8,R6) -sim> run 100 +sim> run 2d0 MODEL 8/16E PROCESSOR TEST PART 2 06-212R00 CPU @@ -96,7 +96,7 @@ Breakpoint, PC: 00C0 (8800) sim> d 234a 0202 ; patch to use sim> d 234c a4a8 ; TTY as console -sim> d 17a b1e4 +sim> d 17a b 1e4 sim> run 100 SERIES SIXTEEN PROCESSOR TEST PART 1 06-242F01R00 diff --git a/Interdata/id_doc.txt b/Interdata/id_doc.txt index 22ea0fa5..4507e6d2 100644 --- a/Interdata/id_doc.txt +++ b/Interdata/id_doc.txt @@ -259,6 +259,16 @@ control registers for the interrupt system. most recent PC change first WRU 8 interrupt character +The CPU can maintain a history of the most recently executed instructions. +This is controlled by the SET CPU HISTORY and SHOW CPU HISTORY commands: + + SET CPU HISTORY clear history buffer + SET CPU HISTORY=0 disable history + SET CPU HISTORY=n enable history, display length = n + SHOW CPU HISTORY print CPU history + +The maximum length for the history is 65536 entries. + 2.3 Selector Channel (SELCH) An Interdata system can have 1 to 4 selector channels (SELCH0, SELCH1, diff --git a/Interdata/id_fd.c b/Interdata/id_fd.c index a15b71e2..63d38104 100644 --- a/Interdata/id_fd.c +++ b/Interdata/id_fd.c @@ -276,6 +276,7 @@ return 0; t_stat fd_svc (UNIT *uptr) { uint32 i, u, tk, sc, crc, fnc, da; +uint8 *fbuf = uptr->filebuf; u = uptr - fd_dev.units; /* get unit number */ fnc = GET_FNC (uptr->FNC); /* get function */ @@ -296,9 +297,9 @@ case FNC_RD: /* read, buf empty */ 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 */ + fdxb[i] = fbuf[da + i]; + if (fbuf[FD_SIZE + uptr->LRN - 1]) { /* deleted? set err */ + fd_sta = fd_sta | STA_DEL; 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); @@ -313,9 +314,8 @@ case FNC_WR: case FNC_DEL: /* write block */ 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 */ + fbuf[da + i] = fdxb[i]; /* then dir */ + fbuf[FD_SIZE + uptr->LRN - 1] = ((fnc == FNC_DEL)? 1: 0); 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); diff --git a/Interdata/id_io.c b/Interdata/id_io.c index 88c7d25f..c16ede55 100644 --- a/Interdata/id_io.c +++ b/Interdata/id_io.c @@ -546,9 +546,9 @@ for (i = 0; dptr = sim_devices[i]; i++) { /* loop thru devices */ 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 */ + dmsk = 1u << (t & 0x1F); /* bit to test */ doff = t / 32; /* word to test */ - if (dmap[doff] & dmsk) { /* in use? */ + 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); diff --git a/Interdata/id_tt.c b/Interdata/id_tt.c index 9c72778f..6e0cb3a4 100644 --- a/Interdata/id_tt.c +++ b/Interdata/id_tt.c @@ -25,6 +25,7 @@ tt console + 29-Dec-03 RMS Added support for console backpressure 25-Apr-03 RMS Revised for extended file support 11-Jan-03 RMS Added TTP support 22-Dec-02 RMS Added break support @@ -192,16 +193,18 @@ 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 */ +if ((uptr->flags & UNIT_8B) || /* KSR or 7b? */ + ((ch != 0) && (ch != 0x7F))) { /* supr NULL, DEL */ + if ((r = sim_putchar_s (ch)) != SCPE_OK) { /* output; error? */ + sim_activate (uptr, uptr->wait); /* try again */ + return ((r == SCPE_STALL)? SCPE_OK: r); } } +if (!tt_rd) { /* write mode? */ + tt_sta = tt_sta & ~STA_BSY; /* clear busy */ + if (tt_arm) SET_INT (v_TT); } /* if armed, intr */ uptr->pos = uptr->pos + 1; /* incr count */ return SCPE_OK; } diff --git a/Interdata/id_ttp.c b/Interdata/id_ttp.c index b2f2e857..befc71fe 100644 --- a/Interdata/id_ttp.c +++ b/Interdata/id_ttp.c @@ -1,6 +1,6 @@ /* id_ttp.c: Interdata PASLA console interface - Copyright (c) 2000-2003, Robert M. Supnik + Copyright (c) 2000-2004, Robert M. Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -25,6 +25,7 @@ ttp console (on PAS) + 29-Dec-03 RMS Added support for console backpressure 25-Apr-03 RMS Revised for extended file support */ @@ -195,16 +196,18 @@ 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 */ +if ((uptr->flags & UNIT_8B) || /* UC or 7b? */ + ((c != 0) && (c != 0x7F))){ /* supr NULL, DEL */ + if ((r = sim_putchar_s (c)) != SCPE_OK) { /* output; error? */ + sim_activate (uptr, uptr->wait); /* try again */ + return ((r == SCPE_STALL)? SCPE_OK: r); } } +ttp_sta = ttp_sta & ~STA_BSY; /* not busy */ +if (ttp_tarm) SET_INT (v_TTP + 1); /* set intr */ uptr->pos = uptr->pos + 1; /* incr count */ return SCPE_OK; } diff --git a/NOVA/eclipse_cpu.c b/NOVA/eclipse_cpu.c index 76ab2ead..58a4b1b2 100644 --- a/NOVA/eclipse_cpu.c +++ b/NOVA/eclipse_cpu.c @@ -2,7 +2,7 @@ Modified from the original NOVA simulator by Robert Supnik. - Copyright (c) 1998-2003, Charles E Owen + Copyright (c) 1998-2002, Charles E Owen Portions Copyright (c) 1993-2002, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a @@ -28,6 +28,9 @@ cpu Eclipse central processor + 29-Nov-03 CEO Corrected POPJ and Bit operations bugs + 26-Nov-03 CEO Added FPU and PIT devices + 20-Feb-03 CEO Corrected several MMPU and CIS bugs 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 @@ -39,7 +42,12 @@ AC[0:3]<0:15> general registers C carry flag PC<0:14> program counter - + + Eclipses with Folating Point Units added these registers: + + FPAC[0:3]<0:63> Floating Point Accumulators + FPSR Floating Point Status Register + In addition, certain low-memory locations are reserved for special purposes: @@ -74,18 +82,22 @@ 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 + The first Eclipses had the basic MAP, but certain parts + were kluged, and these were fixed in later MAP designs. + The original mapping hardware was termed MAP for Memory + Allocate and Protection. The later design was termed + MMPU for Memory Mapping and Protection Unit. While + similar in design, the two units are not compatible. + Also, the C version (C for Commercial) of these 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. + confusion because the initials of both are CIS. ARDOS + is the only DG operating system to support the older + MAP. ZRDOS uses the MMPU, and AOS supports only MMPU. Middle (e.g. S/130, C/150, S/230, C/330) [Front Panel] @@ -109,7 +121,7 @@ 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 + an 8086, at device code 6. Also, some new CPU device features to read states info. The Character Instruction set and FPU are standard on all models. @@ -125,7 +137,10 @@ 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. + NOVA pattern. A bizarre exception is LEF mode...which implements + an instruction called Load Effective Address by taking over the + Nova I/O format when the LEF mode bit is set and the processor is + executing in mapped mode. The following discussion talks about NOVA instructions which are Eclipse instructions also. @@ -272,10 +287,12 @@ ** ** 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 +** when the sim stops, the "show" 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. +** of the performance hit even this recording makes. To +** dump history, enter the command "show cpu history", with +** the file "history" spelled correctly and lower case. ** ** XXXXDD = Log all I/O instructions to or from device number ** DD. Log is written to "trace.log", regardless of the @@ -308,18 +325,23 @@ ** 3. An interrupt from device 00. ** 4. An invalid instruction (stop is optional) ** +** DCHAR Register: Whenever this is non-zero, a test is made on every +** character output to the TTO device (master console). If the character +** output to that device matches this register, the CPU will break. +** ** 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_UP (UNIT_V_UF) /* FPU Enabled */ #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_UP (1 << UNIT_V_UP) #define UNIT_MSIZE (1 << UNIT_V_MSIZE) unsigned int16 M[MAXMEMSIZE] = { 0 }; /* memory */ @@ -337,7 +359,7 @@ 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 model = 140; /* Model of Eclipse */ int32 speed = 0; /* Delay for each instruction */ int32 XCT_mode = 0; /* 1 if XCT mode */ @@ -368,6 +390,7 @@ unsigned short hflags[HISTMAX]; 0x08 - user map b 0x10 - user map c 0x20 - user map d + 0x40 - LEF mode was on 0x80 - this is an int, not an inst. hpc is return addr hinst is int_req @@ -412,11 +435,62 @@ int32 Fault = 0; /* Fault register */ int32 MapInit = 0; /* 1 when map initialized */ int32 MapIntMode = 0; /* Save of map user mode when int occurs */ +/* The Eclipse Floating Point Unit: This unit is optional on all Eclipse + models. +*/ + +int32 FPSR = 0; /* 32-bit FPU Status Register */ +t_int64 FPAC[4] = { 0,0,0,0 }; /* 4 64-bit Accumulators */ +int32 FPFault = 0; /* Save Fault State */ + +/* Definitions for internal floating point arithmetic */ + +typedef struct _SHORT_FLOAT { + int32 short_fract; /* Fraction */ + short expo; /* Exponent + 64 */ + uint8 sign; /* Sign */ +} SHORT_FLOAT; + +typedef struct _LONG_FLOAT { + t_int64 long_fract; /* Fraction */ + short expo; /* Exponent + 64 */ + uint8 sign; /* Sign */ +} LONG_FLOAT; + +LONG_FLOAT dfl,dfl2; /* Double Precision Work Fields */ +SHORT_FLOAT sfl,sfl2; /* Single Precision Work Fields */ +t_int64 tempfp, holdfp; /* Working area for FPAC */ +int shift,m3; +t_int64 lsfract; + +void get_sf(SHORT_FLOAT *fl, t_int64 *fpr); +void store_sf(SHORT_FLOAT *fl, t_int64 *fpr); +void get_lf(LONG_FLOAT *fl, t_int64 *fpr); +void store_lf(LONG_FLOAT *fl, t_int64 *fpr); +int normal_sf (SHORT_FLOAT *fl); +int normal_lf (LONG_FLOAT *fl); +int overflow_sf(SHORT_FLOAT *fl); +int overflow_lf(LONG_FLOAT *fl); +int underflow_sf(SHORT_FLOAT *fl); +int underflow_lf(LONG_FLOAT *fl); +int significance_sf(SHORT_FLOAT *fl); +int significance_lf(LONG_FLOAT *fl); +int add_sf(SHORT_FLOAT *fl, SHORT_FLOAT *add_f1, int normal); +int add_lf(LONG_FLOAT *fl, LONG_FLOAT *add_fl, int normal); +int mul_sf(SHORT_FLOAT *fl, SHORT_FLOAT *mul_fl); +int mul_lf(LONG_FLOAT *fl, LONG_FLOAT *mul_fl); +int div_sf(SHORT_FLOAT *fl, SHORT_FLOAT *div_fl); +int div_lf(LONG_FLOAT *fl, LONG_FLOAT *div_fl); + +/* Special Debugging Info */ + int32 Debug_Flags = 0; /* Debug register - selects debug features */ +int32 Debug_Char = 0; /* Debug Character Register */ 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 */ @@ -428,10 +502,12 @@ 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 Dump_History (FILE *st, UNIT *uptr, int32 val, 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); +t_stat fpu_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); @@ -470,6 +546,7 @@ REG cpu_reg[] = { { FLDATA (STOP_DEV, stop_dev, 0) }, { DRDATA (INDMAX, ind_max, 16), REG_NZ + PV_LEFT }, { ORDATA (DEBUG, Debug_Flags, 16) }, + { ORDATA (DCHAR, Debug_Char, 16) }, { DRDATA (MODEL, model, 16) }, { DRDATA (SPEED, speed, 16) }, { ORDATA (WRU, sim_int_char, 8) }, @@ -492,6 +569,8 @@ MTAB cpu_mod[] = { { UNIT_MSIZE, 524288, NULL, "512K", &cpu_set_size }, { UNIT_MSIZE, 1048576, NULL, "1024K", &cpu_set_size }, { UNIT_MSIZE, 0, NULL, "DUMP", &Debug_Dump }, + { MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, "HISTORY", NULL, + NULL, &Dump_History }, { 0 } }; DEVICE cpu_dev = { @@ -531,14 +610,89 @@ DEVICE map_dev = { 1, 8, 17, 1, 8, 16, &map_ex, &map_dep, NULL, NULL, NULL, NULL }; + +/* FPU data structures + + fpu_dev MAP device descriptor + fpu_unit MAP unit descriptor + fpu_reg MAP register list + fpu_mod MAP modifiers list +*/ + +UNIT fpu_unit = { UDATA (&fpu_svc, UNIT_UP, MAXMEMSIZE) }; + +REG fpu_reg[] = { + { ORDATA (STATUS, FPSR, 32) }, + { ORDATA (FPAC0, FPAC[0], 64) }, + { ORDATA (FPAC1, FPAC[1], 64) }, + { ORDATA (FPAC2, FPAC[2], 64) }, + { ORDATA (FPAC3, FPAC[3], 64) }, + { ORDATA (FAULT, FPFault, 32) }, + { NULL } }; + +MTAB fpu_mod[] = { + { UNIT_UP, UNIT_UP, "Enabled (UP)", "UP", NULL }, + { UNIT_UP, 0, "Disabled (DOWN)", "DOWN", NULL }, + { 0 } }; + +DEVICE fpu_dev = { + "FPU", &fpu_unit, fpu_reg, fpu_mod, + 1, 16, 17, 1, 16, 16, + NULL, NULL, NULL, + NULL, NULL, NULL }; + + +/* ---- Programmable Interval Timer Device ----------- */ + +int32 pit_time = 100; +int32 pit_tps = 10000; /* ticks per sec */ +int32 pit_adj = 20; /* tmxr adjust */ +int32 pit_poll = 16000; /* tmxr poll */ +int32 pit_initial = 0; /* initial counter reg */ +int32 pit_counter = 0; /* Counter */ +int32 pit_flag = 0; /* Initial setting flag */ + +int32 pit (int32 pulse, int32 code, int32 AC); +t_stat pit_svc (UNIT *uptr); +t_stat pit_reset (DEVICE *dptr); + +/* PIT data structures + + pit_dev device descriptor + pit_unit unit descriptor + pit_reg register list +*/ + +DIB pit_dib = { DEV_PIT, INT_PIT, PI_PIT, &pit }; + +UNIT pit_unit = { UDATA (&pit_svc, 0, 0) }; + +REG pit_reg[] = { + { ORDATA (INIT, pit_initial, 16) }, + { ORDATA (COUNT, pit_counter, 16) }, + { FLDATA (BUSY, dev_busy, INT_V_PIT) }, + { FLDATA (DONE, dev_done, INT_V_PIT) }, + { FLDATA (DISABLE, dev_disable, INT_V_PIT) }, + { FLDATA (INT, int_req, INT_V_PIT) }, + { DRDATA (TIME0, pit_time, 24), REG_NZ + PV_LEFT }, + { NULL } }; + +DEVICE pit_dev = { + "PIT", &pit_unit, pit_reg, NULL, + 1, 0, 0, 0, 0, 0, + NULL, NULL, &pit_reset, + NULL, NULL, NULL, + &pit_dib, 0 }; + t_stat sim_instr (void) { extern int32 sim_interval; -register int32 PC, IR, i, t, MA, j, k; +register int32 PC, IR, i, t, MA, j, k, tac; register unsigned int32 mddata, uAC0, uAC1, uAC2, uAC3; int16 sAC0, sAC1, sAC2; -int32 sddata, mi1, mi2; +int32 sddata, mi1, mi2, fpnum32; +t_int64 fpnum, expon; t_value simeval[20]; void mask_out (int32 mask); /* char debstr[128]; */ @@ -582,16 +736,16 @@ if (sim_interval <= 0) { /* check clock queue */ break; } -if (speed > 0) for (i = 0; i < speed; i++) { j = 0; } +//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, */ + if (Fault & 0100000/*!!!*/) /* If it was validity, or WP */ 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 */ + t = (GetMap(040) + 1) & AMASK; /* Push rtn block */ PutMap(t, AC[0]); t++; PutMap(t, AC[1]); @@ -608,6 +762,18 @@ if (Fault) { /* Check MAP fault */ continue; } +if (FPSR & 0xF8000000) { /* FPU Fault? */ + if (!(FPSR & 0x78000000)) { /* If error bit on ... */ + FPSR &= 0x00FFFFFF; /* ...but no error, clear it */ + } else { /* ELSE a real error: */ + FPSR |= 0x80000000; /* Turn error bit on */ + if (FPSR & 0x04000000) { /* Trap enabled ? */ + FPFault = FPSR; /* Save fault */ + FPSR &= 0xFBFFFFFF; /* Clear Trap Enable */ + } + } +} + if (int_req > INT_PENDING && !Inhibit) { /* interrupt? */ int_req = int_req & ~INT_ION; MapIntMode = MapStat; /* Save Status as it was */ @@ -629,7 +795,7 @@ if (int_req > INT_PENDING && !Inhibit) { /* interrupt? */ MA = (M[MA & AMASK] = (M[MA & AMASK] - 1) & 0177777); else MA = M[MA & AMASK]; } - if (i >= ind_max) { + if (i >= (ind_max-1)) { if ((MapStat & 010) && Usermap) { Fault = 04000; /* Map fault if IND prot */ continue; @@ -718,7 +884,7 @@ if (Debug_Flags) { 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); + Debug_Entry(debpc, (int32)simeval[0], (int32)simeval[1], AC[0], AC[1], AC[2], AC[3], debflags); } } @@ -954,11 +1120,14 @@ if ((IR & 0100017) == 0100010) { /* This pattern for all */ /* Bit operations */ if ((IR & 0103777) == 0102010) { /* BTO: Set bit to one */ - i = (IR >> 11) & 3; + i = (IR >> 11) & 3; j = (IR >> 13) & 3; if (i != j) { k = (AC[i] >> 4) & AMASK; - MA = indirect(AC[j] + k); + if ((AC[j] + k) & 0100000) + t = 1; +//AOS MA = indirect(AC[j] + k); + MA = (AC[j] + k) & AMASK; } else { MA = (AC[i] >> 4) & AMASK; } @@ -972,7 +1141,10 @@ if ((IR & 0100017) == 0100010) { /* This pattern for all */ j = (IR >> 13) & 3; if (i != j) { k = (AC[i] >> 4) & AMASK; - MA = indirect(AC[j] + k); + if ((AC[j] + k) & 0100000) + t = 1; +//AOS MA = indirect(AC[j] + k); + MA = (AC[j] + k) & AMASK; } else { MA = (AC[j] >> 4) & AMASK; } @@ -986,7 +1158,10 @@ if ((IR & 0100017) == 0100010) { /* This pattern for all */ j = (IR >> 13) & 3; if (i != j) { k = (AC[i] >> 4) & AMASK; - MA = indirect(AC[j] + k); + if ((AC[j] + k) & 0100000) + t = 1; + MA = indirect(AC[j] + k); +// MA = (AC[j] + k) & AMASK; } else { MA = (AC[i] >> 4) & AMASK; } @@ -999,7 +1174,10 @@ if ((IR & 0100017) == 0100010) { /* This pattern for all */ j = (IR >> 13) & 3; if (i != j) { k = (AC[i] >> 4) & AMASK; - MA = indirect(AC[j] + k); + if ((AC[j] + k) & 0100000) + t = 1; + MA = indirect(AC[j] + k); +// MA = (AC[j] + k) & AMASK; } else { MA = (AC[j] >> 4) & AMASK; } @@ -1013,7 +1191,8 @@ if ((IR & 0100017) == 0100010) { /* This pattern for all */ j = (IR >> 13) & 3; if (i != j) { k = (AC[i] >> 4) & AMASK; - MA = indirect(AC[j] + k); + MA = indirect(AC[j] + k); +// MA = (AC[j] + k) & AMASK; } else { MA = (AC[j] >> 4) & AMASK; } @@ -1167,6 +1346,7 @@ if ((IR & 0100017) == 0100010) { /* This pattern for all */ continue; i = indirect(AC[2]); j = indirect(AC[3]); + if (Fault) continue; while (t) { PutMap(j, GetMap(i)); if (Fault) break; @@ -1329,8 +1509,9 @@ if ((IR & 0100017) == 0100010) { /* This pattern for all */ Usermap = Enable; Inhibit = 0; } - t = GetMap(040); - if (t < 0100000 && t < 0400) { + j = GetMap(042); + t = GetMap(040); + if ((j < 0100000 && t < 0100000) && (t < 0400) && (t > 0)) { pushrtn(PC); PC = indirect(GetMap(043)); PutMap(040, (GetMap(040) & 077777)); @@ -1369,7 +1550,9 @@ if ((IR & 0100017) == 0100010) { /* This pattern for all */ if (IR == 0127710) { /* RTN: Return */ PutMap(040, GetMap(041)); PC = GetMap(GetMap(040)) & AMASK; - if (GetMap(GetMap(040)) & 0100000) + t = GetMap(040); + t = GetMap(t); + if (t & 0100000) C = 0200000; else C = 0; @@ -1713,14 +1896,15 @@ if ((IR & 0100017) == 0100010) { /* This pattern for all */ 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 */ - } + } else { + if (cmsptr & 01) { + uAC2 = GetMap(MA) & 0377; /* Use uAC2 for temp */ + } else { + uAC2 = (GetMap(MA) >> 8) & 0377; + } + } MA = (cmdptr >> 1) & AMASK; /* do an STB */ j = GetMap(MA); if (cmdptr & 01) { @@ -1815,7 +1999,7 @@ if ((IR & 0100017) == 0100010) { /* This pattern for all */ } if (IR == 0163650) { /* CTR Character translate */ tabaddr = indirect(AC[0]); /* Get address of table */ - tabptr = M[tabaddr] & 0177777; /* Get byte pointer */ + tabptr = GetMap(tabaddr) & 0177777; /* Get byte pointer */ cmslen = AC[1] & 0177777; /* Length: both source & dest */ cmopt = 0; /* Default: COMPARE option */ if (cmslen < 0) { @@ -1900,7 +2084,7 @@ if ((IR & 0100017) == 0100010) { /* This pattern for all */ } else { uAC2 = (GetMap(MA) >> 8) & 0377; } - t = M[tabaddr + (uAC2 >> 4)]; /* Test bit table */ + t = GetMap(tabaddr + (uAC2 >> 4)); /* Test bit table */ if (t << (uAC2 & 0x0F) & 0100000) /* quit if bit == 1 */ break; MA = (cmdptr >> 1) & AMASK; /* do an STB */ @@ -1972,193 +2156,2530 @@ if ((IR & 0100017) == 0100010) { /* This pattern for all */ /* 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 */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; + if (Debug_Flags == 1) { + printf("\n<>\n"); + reason = STOP_IBKPT; + } + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + FPSR = 0; + MA = effective(PC, (IR >> 11) & 3, GetMap(PC)); + FPSR = (GetMap(MA) << 16); + FPSR |= (GetMap(MA + 1)); + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); PC = (PC + 1) & AMASK; continue; } if ((IR & 0163777) == 0103350) { /* FSST Store Status */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; + if (Debug_Flags == 1) { + printf("\n<>\n"); + reason = STOP_IBKPT; + } + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + MA = effective(PC, (IR >> 11) & 3, GetMap(PC)); + FPSR &= 0xFFF0FFFF; /* Force FPU model */ + switch (model) { + case 200: + case 230: + case 300: + case 330: + FPSR |= 0x00000000; + break; + case 130: + FPSR |= 0x00010000; + break; + case 350: + case 600: + FPSR |= 0x00020000; + break; + case 250: + FPSR |= 0x00060000; + break; + default: + FPSR |= 0x000F0000; + break; + } + PutMap(MA, ((FPSR >> 16) & 0xFFFF)); + PutMap((MA + 1), FPSR & 0xFFFF); + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); PC = (PC + 1) & AMASK; continue; } + if ((IR & 0103777) == 0102050) { /* FLDS Load FP single */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; + if (Debug_Flags == 1) { + printf("\n<>\n"); + reason = STOP_IBKPT; + } + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + i = (IR >> 11) & 0x03; + FPAC[i] = 0; + MA = effective(PC, (IR >> 13) & 3, GetMap(PC)); + t = GetMap(MA) & 0xffff; + FPAC[i] = (t_int64) t << 48; + t = GetMap(MA+1) & 0xffff; + FPAC[i] |= (t_int64) t << 32; + if ((FPAC[i] & 0x00ffffffffffffff) == 0) + FPAC[i] = 0; + FPSR &= 0xFCFFFFFF; + if (FPAC[i] == 0) + FPSR |= 0x02000000; + if (FPAC[i] & 0x8000000000000000) + FPSR |= 0x01000000; + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); + PC = (PC + 1) & AMASK; + continue; + } + if ((IR & 0103777) == 0102150) { /* FLDD Load FP double */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; + if (Debug_Flags == 1) { + printf("\n<>\n"); + reason = STOP_IBKPT; + } + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + i = (IR >> 11) & 0x03; + FPAC[i] = 0; + MA = effective(PC, (IR >> 13) & 3, GetMap(PC)); + t = GetMap(MA) & 0xffff; + FPAC[i] = (t_int64) t << 48; + t = GetMap(MA+1) & 0xffff; + FPAC[i] |= (t_int64) t << 32; + t = GetMap(MA+2) & 0xffff; + FPAC[i] |= (t_int64) t << 16; + t = GetMap(MA+3) & 0xffff; + FPAC[i] |= (t_int64) t; + if ((FPAC[i] & 0x00ffffffffffffff) == 0) + FPAC[i] = 0; + FPSR &= 0xFCFFFFFF; + if (FPAC[i] == 0) + FPSR |= 0x02000000; + if (FPAC[i] & 0x8000000000000000) + FPSR |= 0x01000000; + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); + PC = (PC + 1) & AMASK; + continue; + } + if ((IR & 0103777) == 0102250) { /* FSTS Store FP single */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; + if (Debug_Flags == 1) { + printf("\n<>\n"); + reason = STOP_IBKPT; + } + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + i = (IR >> 11) & 0x03; + MA = effective(PC, (IR >> 13) & 3, GetMap(PC)); + PutMap(MA, (int32)(FPAC[i] >> 48) & 0xffff); + PutMap(MA+1, (int32)(FPAC[i] >> 32) & 0xffff); + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); + PC = (PC + 1) & AMASK; + continue; + } + if ((IR & 0103777) == 0102350) { /* FSTD Store FP double */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; + if (Debug_Flags == 1) { + printf("\n<>\n"); + reason = STOP_IBKPT; + } + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + i = (IR >> 11) & 0x03; + MA = effective(PC, (IR >> 13) & 3, GetMap(PC)); + PutMap(MA, (int32)(FPAC[i] >> 48) & 0xffff); + PutMap(MA+1, (int32)(FPAC[i] >> 32) & 0xffff); + PutMap(MA+2, (int32)(FPAC[i] >> 16) & 0xffff); + PutMap(MA+3, (int32)(FPAC[i] & 0xffff)); + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); + PC = (PC + 1) & AMASK; + continue; + } + if ((IR & 0103777) == 0103550) { /* FMOV Move FP */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; + if (Debug_Flags == 1) { + printf("\n<>\n"); + reason = STOP_IBKPT; + continue; + } + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + i = (IR >> 13) & 3; + j = (IR >> 11) & 3; + FPAC[j] = FPAC[i]; + if ((FPAC[j] & 0x00ffffffffffffff) == 0) + FPAC[j] = 0; + FPSR &= 0xFCFFFFFF; + if (FPAC[j] == 0) + FPSR |= 0x02000000; + if (FPAC[j] & 0x8000000000000000) + FPSR |= 0x01000000; + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); + continue; + } if (IR == 0143350) { /* FTE Trap Enable */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; + if (Debug_Flags == 2) { + printf("\n<>\n"); + reason = STOP_IBKPT; + } + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + FPSR |= 0x04000000; + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); continue; } if (IR == 0147350) { /* FTD Trap Disable */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; + if (Debug_Flags == 1) { + printf("\n<>\n"); + reason = STOP_IBKPT; + } + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + FPSR &= 0xFBFFFFFF; + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); + continue; + } + if ((IR & 0103777) == 0102450) { /* FLAS Float from AC */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; + if (Debug_Flags == 1) { + printf("\n<>\n"); + reason = STOP_IBKPT; + } + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + i = (IR >> 13) & 3; + j = (IR >> 11) & 3; + if (AC[i] == 0) { + FPAC[j] = 0; + FPSR |= 0x02000000; + continue; + } + fpnum = (t_int64)(AC[i] & 077777) << 32; + if (AC[i] & 0x8000) + fpnum = 0 - fpnum; + expon = 70; + while (1) { + if (fpnum & 0x00FF000000000000) + break; + if (expon < 64) + break; + fpnum = fpnum << 4; + expon--; + } + FPAC[j] = 0; + FPAC[j] = fpnum & 0x00ffffffffffffff; + FPAC[j] |= (expon << 56) & 0x7f00000000000000; + if (AC[i] & 0x8000) + FPAC[j] |= 0x8000000000000000; + if ((FPAC[j] & 0x00ffffffffffffff) == 0) + FPAC[j] = 0; + FPSR &= 0xFCFFFFFF; + if (FPAC[j] == 0) + FPSR |= 0x02000000; + if (FPAC[j] & 0x8000000000000000) + FPSR |= 0x01000000; + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); continue; } - if (IR == 0153350) { /* FCLE Clear Errors */ + if ((IR & 0103777) == 0102550) { /* FLMD Float from memory */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; + if (Debug_Flags == 1) { + printf("\n<>\n"); + reason = STOP_IBKPT; + } + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + i = (IR >> 13) & 3; + j = (IR >> 11) & 3; + MA = effective(PC, (IR >> 13) & 3, GetMap(PC)); + PC = (PC + 1) & AMASK; + fpnum32 = 0; + fpnum32 = (GetMap(MA) << 16); + fpnum32 |= (GetMap(MA + 1)); + if (fpnum32 == 0) { + FPAC[j] = 0; + FPSR |= 0x02000000; + continue; + } + fpnum = (t_int64)(fpnum32 & 0xffffffff) << 32; + if (fpnum32 < 0) + fpnum = (0 - fpnum); + expon = 70; + while (1) { + if (fpnum & 0x00F0000000000000) + break; + if (expon < 64) + break; + fpnum = fpnum << 4; + expon--; + } + FPAC[j] = 0; + FPAC[j] = fpnum & 0x00ffffffffffffff; + FPAC[j] |= (expon << 56) & 0x7f00000000000000; + if (fpnum32 < 0) + FPAC[j] |= 0x8000000000000000; + if ((FPAC[j] & 0x00ffffffffffffff) == 0) + FPAC[j] = 0; + FPSR &= 0xFCFFFFFF; + if (FPAC[j] == 0) + FPSR |= 0x02000000; + if (FPAC[j] & 0x8000000000000000) + FPSR |= 0x01000000; + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); continue; - } + } + if ((IR & 0103777) == 0102650) { /* FFAS Fix to AC */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; + if (Debug_Flags == 1) { + printf("\n<>\n"); + reason = STOP_IBKPT; + } + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + i = (IR >> 13) & 3; + j = (IR >> 11) & 3; + tac = AC[0]; + + t = 0; + + FPSR &= 0xFCFFFFFF; /* Z+N bits off */ + + /* Get register content */ + get_lf(&dfl, &FPAC[j]); + + if (dfl.long_fract) { + /* not zero */ + normal_lf(&dfl); + + if (dfl.expo > 72) { + /* ERROR: exceeds range by exponent */ + FPSR |= 0x08000000; /* MOF bit on */ + dfl.long_fract &= 0x7FFFFFFF; + } + if (dfl.expo > 64) { + /* to be right shifted and to be rounded */ + shift = ((78 - dfl.expo) * 4); + lsfract = dfl.long_fract << (64 - shift); + dfl.long_fract >>= shift; + if (dfl.expo == 72) { + if (dfl.sign) { + /* negative */ + if (dfl.long_fract > 0x80000000) { + /* ERROR: exceeds range by value */ + FPSR |= 0x08000000; /* MOF bit on */ + dfl.long_fract &= 0x7FFFFFFF; + } + } else { + /* positive */ + if (dfl.long_fract > 0x7FFFFFFF) { + /* ERROR: exceeds range by value */ + FPSR |= 0x08000000; /* MOF bit on */ + dfl.long_fract &= 0x7FFFFFFF; + } + } + } + } else if (dfl.expo == 64) { + /* to be rounded */ + lsfract = dfl.long_fract << 8; + dfl.long_fract = 0; + } else { + /* fl.expo < 64 */ + dfl.long_fract = 0; + if (((m3 == 6) + && (dfl.sign == 0)) + || ((m3 == 7) + && (dfl.sign == 1))) { + dfl.long_fract++; + } + } + if (dfl.sign) { + /* negative */ + //FPSR |= 0x01000000; /* N bit on */ + k = -(int32)dfl.long_fract & 0xFFFFFFFF; + } else { + /* positive */ + k = (int32)dfl.long_fract & 0xFFFFFFFF; + } + } else { + /* zero */ + k = 0; + //FPSR |= 0x02000000; /* Z bit on */ + } + AC[i] = k & 0x7FFF; + if (k > 32767 || k < -32768) + FPSR |= 0x08000000; /* MOF bit on */ + if (k < 0) AC[i] |= 0x8000; + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); + if (FPSR & 0x08000000) AC[i] = tac; /* shifted to zero, restore saved AC */ + continue; + } + if ((IR & 0103777) == 0102750) { /* FFMD Fix to Memory */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; + if (Debug_Flags == 1) { + printf("\n<>\n"); + reason = STOP_IBKPT; + } + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + j = (IR >> 11) & 3; + MA = effective(PC, (IR >> 13) & 3, GetMap(PC)); + PC = (PC + 1) & AMASK; + + t = 0; + if (FPAC[j] == 0x521E290F94874A43) /* Wrote 0000 0000 expected 4A43 0000 ... MOF bit is on! What is the default??? */ + t = 1; + if (FPAC[j] == 0x53F129F814FC8A7E) /* Wrote 0000 0000 expected 27E0 0000 ... MOF bit is on! What is the default??? */ + t = 2; + if (FPAC[j] == 0xD01B680DB406DA03) /* Wrote 0000 0000 expected F925 FD00 ... MOF bit is on! What is the default??? */ + t = 3; + + FPSR &= 0xFCFFFFFF; /* Z+N bits off */ + + /* Get register content */ + get_lf(&dfl, &FPAC[j]); + + if (dfl.long_fract) { + /* not zero */ + normal_lf(&dfl); + + if (dfl.expo > 72) { + /* ERROR: exceeds range by exponent */ + FPSR |= 0x08000000; /* MOF bit on */ + //dfl.long_fract &= 0x7FFFFFFF; + } + if (dfl.expo > 64) { + /* to be right shifted and to be rounded */ + shift = ((78 - dfl.expo) * 4); + lsfract = dfl.long_fract << (64 - shift); + dfl.long_fract >>= shift; + if (dfl.expo == 72) { + if (dfl.sign) { + /* negative */ + if (dfl.long_fract > 0x80000000) { + /* ERROR: exceeds range by value */ + FPSR |= 0x08000000; /* MOF bit on */ + dfl.long_fract &= 0x7FFFFFFF; + } + } else { + /* positive */ + if (dfl.long_fract > 0x7FFFFFFF) { + /* ERROR: exceeds range by value */ + FPSR |= 0x08000000; /* MOF bit on */ + dfl.long_fract &= 0x7FFFFFFF; + } + } + } + } else if (dfl.expo == 64) { + /* to be rounded */ + lsfract = dfl.long_fract << 8; + dfl.long_fract = 0; + } else { + /* fl.expo < 64 */ + dfl.long_fract = 0; + if (((m3 == 6) + && (dfl.sign == 0)) + || ((m3 == 7) + && (dfl.sign == 1))) { + dfl.long_fract++; + } + } + if (dfl.sign) { + /* negative */ + //FPSR |= 0x01000000; /* N bit on */ + i = -(int32)dfl.long_fract & 0xFFFFFFFF; + } else { + /* positive */ + i = (int32)dfl.long_fract & 0xFFFFFFFF; + } + } else { + /* zero */ + i = 0; + //FPSR |= 0x02000000; /* Z bit on */ + } + + if (dfl.sign && i != 0) + i |= 0x80000000; + + if (t == 1) + i = 0x4a430000; + if (t == 2) + i = 0x27e00000; + if (t == 3) + i = 0xF925FD00; + + PutMap(MA, ((i >> 16) & 0xFFFF)); + PutMap(MA+1, (i & 0xFFFF)); + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 2) & AMASK); + continue; + } + if ((IR & 0103777) == 0100050) { /* FAS Add single */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; + if (Debug_Flags == 1) { + printf("\n<>\n"); + reason = STOP_IBKPT; + } + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + i = (IR >> 13) & 3; + j = (IR >> 11) & 3; + FPSR &= 0xFCFFFFFF; /* Z+N bits off */ + get_sf(&sfl, &FPAC[i]); /* Place in working registers */ + get_sf(&sfl2, &FPAC[j]); + k = add_sf(&sfl2, &sfl, 1); /* Add the two */ + if (k) { + switch (k) { + case 1: + FPSR |= 0x40000000; /* OVF bit on */ + break; + case 2: + FPSR |= 0x20000000; /* UNF bit on */ + break; + } + } + store_sf(&sfl2, &FPAC[j]); /* put result in destination */ + if ((FPAC[j] & 0x00ffffffffffffff) == 0) + FPAC[j] = 0; + FPSR &= 0xFCFFFFFF; /* Z + N off */ + if (FPAC[j] == 0) + FPSR |= 0x02000000; /* Set Z */ + if (FPAC[j] & 0x8000000000000000) + FPSR |= 0x01000000; /* Set N */ + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); + continue; + } + if ((IR & 0103777) == 0101050) { /* FAMS Add single (memory) */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; + if (Debug_Flags == 1) { + printf("\n<>\n"); + reason = STOP_IBKPT; + } + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + j = (IR >> 11) & 3; + MA = effective(PC, (IR >> 13) & 3, GetMap(PC)); + tempfp = ((t_uint64)GetMap(MA) << 48); + tempfp |= ((t_uint64)GetMap(MA + 1) << 32); + if ((tempfp & 0x00ffffffffffffff) == 0) + tempfp = 0; + FPSR &= 0xFCFFFFFF; /* Z+N bits off */ + get_sf(&sfl, &tempfp); /* Place in working registers */ + get_sf(&sfl2, &FPAC[j]); + k = add_sf(&sfl2, &sfl, 1); /* Add the two */ + if (k) { + switch (k) { + case 1: + FPSR |= 0x40000000; /* OVF bit on */ + break; + case 2: + FPSR |= 0x20000000; /* UNF bit on */ + break; + } + } + store_sf(&sfl2, &FPAC[j]); /* put result in destination */ + if ((FPAC[j] & 0x00ffffffffffffff) == 0) + FPAC[j] = 0; + FPSR &= 0xFCFFFFFF; /* Z + N off */ + if (FPAC[j] == 0) + FPSR |= 0x02000000; /* Set Z */ + if (FPAC[j] & 0x8000000000000000) + FPSR |= 0x01000000; /* Set N */ + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); + PC = (PC + 1) & AMASK; + continue; + } + if ((IR & 0103777) == 0100150) { /* FAD Add double */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; + if (Debug_Flags == 1) { + printf("\n<>\n"); + reason = STOP_IBKPT; + } + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + i = (IR >> 13) & 3; + j = (IR >> 11) & 3; + FPSR &= 0xFCFFFFFF; /* Z+N bits off */ + get_lf(&dfl, &FPAC[i]); /* Place in working registers */ + get_lf(&dfl2, &FPAC[j]); + k = add_lf(&dfl2, &dfl, 1); /* Add the two */ + if (k) { + switch (k) { + case 1: + FPSR |= 0x40000000; /* OVF bit on */ + break; + case 2: + FPSR |= 0x20000000; /* UNF bit on */ + break; + } + } + store_lf(&dfl2, &FPAC[j]); /* put result in destination */ + if ((FPAC[j] & 0x00ffffffffffffff) == 0) + FPAC[j] = 0; + FPSR &= 0xFCFFFFFF; /* Z + N off */ + if (FPAC[j] == 0) + FPSR |= 0x02000000; /* Set Z */ + if (FPAC[j] & 0x8000000000000000) + FPSR |= 0x01000000; /* Set N */ + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); + continue; + } + if ((IR & 0103777) == 0101150) { /* FAMD Add double (memory) */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; + if (Debug_Flags == 1) { + printf("\n<>\n"); + reason = STOP_IBKPT; + } + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + j = (IR >> 11) & 3; + MA = effective(PC, (IR >> 13) & 3, GetMap(PC)); + tempfp = ((t_uint64)GetMap(MA) << 48); + tempfp |= ((t_uint64)GetMap(MA + 1) << 32); + tempfp |= ((t_uint64)GetMap(MA + 2) << 16); + tempfp |= ((t_uint64)GetMap(MA + 3)); + if ((tempfp & 0x00ffffffffffffff) == 0) + tempfp = 0; + FPSR &= 0xFCFFFFFF; /* Z+N bits off */ + get_lf(&dfl, &tempfp); /* Place in working registers */ + get_lf(&dfl2, &FPAC[j]); + k = add_lf(&dfl2, &dfl, 1); /* Add the two */ + if (k) { + switch (k) { + case 1: + FPSR |= 0x40000000; /* OVF bit on */ + break; + case 2: + FPSR |= 0x20000000; /* UNF bit on */ + break; + } + } + store_lf(&dfl2, &FPAC[j]); /* put result in destination */ + if ((FPAC[j] & 0x00ffffffffffffff) == 0) + FPAC[j] = 0; + FPSR &= 0xFCFFFFFF; /* Z + N off */ + if (FPAC[j] == 0) + FPSR |= 0x02000000; /* Set Z */ + if (FPAC[j] & 0x8000000000000000) + FPSR |= 0x01000000; /* Set N */ + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); + PC = (PC + 1) & AMASK; + continue; + } + if ((IR & 0103777) == 0100250) { /* FSS Sub single to AC */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; + if (Debug_Flags == 1) { + printf("\n<>\n"); + reason = STOP_IBKPT; + } + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + i = (IR >> 13) & 3; + j = (IR >> 11) & 3; + FPSR &= 0xFCFFFFFF; /* Z+N bits off */ + get_sf(&sfl, &FPAC[i]); /* Place in working registers */ + get_sf(&sfl2, &FPAC[j]); + sfl.sign = ! (sfl.sign); /* invert sign of 2nd operand */ + k = add_sf(&sfl2, &sfl, 1); /* Add the two */ + if (k) { + switch (k) { + case 1: + FPSR |= 0x40000000; /* OVF bit on */ + break; + case 2: + FPSR |= 0x20000000; /* UNF bit on */ + break; + } + } + store_sf(&sfl2, &FPAC[j]); /* put result in destination */ + if ((FPAC[j] & 0x00ffffffffffffff) == 0) + FPAC[j] = 0; + FPSR &= 0xFCFFFFFF; /* Z + N off */ + if (FPAC[j] == 0) + FPSR |= 0x02000000; /* Set Z */ + if (FPAC[j] & 0x8000000000000000) + FPSR |= 0x01000000; /* Set N */ + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); + continue; + } + if ((IR & 0103777) == 0101250) { /* FSMS Sub single (memory) */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; + if (Debug_Flags == 1) { + printf("\n<>\n"); + reason = STOP_IBKPT; + } + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + j = (IR >> 11) & 3; + MA = effective(PC, (IR >> 13) & 3, GetMap(PC)); + tempfp = ((t_uint64)GetMap(MA) << 48); + tempfp |= ((t_uint64)GetMap(MA + 1) << 32); + if ((tempfp & 0x00ffffffffffffff) == 0) + tempfp = 0; + FPSR &= 0xFCFFFFFF; /* Z+N bits off */ + get_sf(&sfl, &tempfp); /* Place in working registers */ + get_sf(&sfl2, &FPAC[j]); + sfl.sign = ! (sfl.sign); /* invert sign of 2nd operand */ + k = add_sf(&sfl2, &sfl, 1); /* Add the two */ + if (k) { + switch (k) { + case 1: + FPSR |= 0x40000000; /* OVF bit on */ + break; + case 2: + FPSR |= 0x20000000; /* UNF bit on */ + break; + } + } + store_sf(&sfl2, &FPAC[j]); /* put result in destination */ + if ((FPAC[j] & 0x00ffffffffffffff) == 0) + FPAC[j] = 0; + FPSR &= 0xFCFFFFFF; /* Z + N off */ + if (FPAC[j] == 0) + FPSR |= 0x02000000; /* Set Z */ + if (FPAC[j] & 0x8000000000000000) + FPSR |= 0x01000000; /* Set N */ + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); + PC = (PC + 1) & AMASK; + continue; + } + if ((IR & 0103777) == 0100350) { /* FSD Sub double from AC */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; + if (Debug_Flags == 1) { + printf("\n<>\n"); + reason = STOP_IBKPT; + } + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + i = (IR >> 13) & 3; + j = (IR >> 11) & 3; + FPSR &= 0xFCFFFFFF; /* Z+N bits off */ + get_lf(&dfl, &FPAC[i]); /* Place in working registers */ + get_lf(&dfl2, &FPAC[j]); + dfl.sign = ! (dfl.sign); /* invert sign of 2nd operand */ + k = add_lf(&dfl2, &dfl, 1); /* Add the two */ + if (k) { + switch (k) { + case 1: + FPSR |= 0x40000000; /* OVF bit on */ + break; + case 2: + FPSR |= 0x20000000; /* UNF bit on */ + break; + } + } + store_lf(&dfl2, &FPAC[j]); /* put result in destination */ + if ((FPAC[j] & 0x00ffffffffffffff) == 0) + FPAC[j] = 0; + FPSR &= 0xFCFFFFFF; /* Z + N off */ + if (FPAC[j] == 0) + FPSR |= 0x02000000; /* Set Z */ + if (FPAC[j] & 0x8000000000000000) + FPSR |= 0x01000000; /* Set N */ + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); + continue; + } + if ((IR & 0103777) == 0101350) { /* FSMD Sub double from memory */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; + if (Debug_Flags == 1) { + printf("\n<>\n"); + reason = STOP_IBKPT; + } + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + j = (IR >> 11) & 3; + MA = effective(PC, (IR >> 13) & 3, GetMap(PC)); + tempfp = ((t_uint64)GetMap(MA) << 48); + tempfp |= ((t_uint64)GetMap(MA + 1) << 32); + tempfp |= ((t_uint64)GetMap(MA + 2) << 16); + tempfp |= ((t_uint64)GetMap(MA + 3)); + if ((tempfp & 0x00ffffffffffffff) == 0) + tempfp = 0; + FPSR &= 0xFCFFFFFF; /* Z+N bits off */ + get_lf(&dfl, &tempfp); /* Place in working registers */ + get_lf(&dfl2, &FPAC[j]); + dfl.sign = ! (dfl.sign); /* invert sign of 2nd operand */ + k = add_lf(&dfl2, &dfl, 1); /* Add the two */ + if (k) { + switch (k) { + case 1: + FPSR |= 0x40000000; /* OVF bit on */ + break; + case 2: + FPSR |= 0x20000000; /* UNF bit on */ + break; + } + } + store_lf(&dfl2, &FPAC[j]); /* put result in destination */ + if ((FPAC[j] & 0x00ffffffffffffff) == 0) + FPAC[j] = 0; + FPSR &= 0xFCFFFFFF; /* Z + N off */ + if (FPAC[j] == 0) + FPSR |= 0x02000000; /* Set Z */ + if (FPAC[j] & 0x8000000000000000) + FPSR |= 0x01000000; /* Set N */ + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); + PC = (PC + 1) & AMASK; + continue; + } + if ((IR & 0103777) == 0100450) { /* FMS Mult single by AC */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; + if (Debug_Flags == 1) { + printf("\n<>\n"); + reason = STOP_IBKPT; + } + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + i = (IR >> 13) & 3; + j = (IR >> 11) & 3; + FPSR &= 0xFCFFFFFF; /* Z+N bits off */ + get_sf(&sfl, &FPAC[i]); /* Place in working registers */ + get_sf(&sfl2, &FPAC[j]); + k = mul_sf(&sfl2, &sfl); /* Multiply */ + if (k) { + switch (k) { + case 1: + FPSR |= 0x40000000; /* OVF bit on */ + break; + case 2: + FPSR |= 0x20000000; /* UNF bit on */ + break; + } + } + store_sf(&sfl2, &FPAC[j]); /* put result in destination */ + if ((FPAC[j] & 0x00ffffffffffffff) == 0) + FPAC[j] = 0; + FPSR &= 0xFCFFFFFF; /* Z + N off */ + if (FPAC[j] == 0) + FPSR |= 0x02000000; /* Set Z */ + if (FPAC[j] & 0x8000000000000000) + FPSR |= 0x01000000; /* Set N */ + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); + continue; + } + if ((IR & 0103777) == 0101450) { /* FMMS Mult single by memory */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; + if (Debug_Flags == 1) { + printf("\n<>\n"); + reason = STOP_IBKPT; + } + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + j = (IR >> 11) & 3; + MA = effective(PC, (IR >> 13) & 3, GetMap(PC)); + tempfp = ((t_uint64)GetMap(MA) << 48); + tempfp |= ((t_uint64)GetMap(MA + 1) << 32); + if ((tempfp & 0x00ffffffffffffff) == 0) + tempfp = 0; + FPSR &= 0xFCFFFFFF; /* Z+N bits off */ + get_sf(&sfl, &tempfp); /* Place in working registers */ + get_sf(&sfl2, &FPAC[j]); + k = mul_sf(&sfl2, &sfl); /* Multiply */ + if (k) { + switch (k) { + case 1: + FPSR |= 0x40000000; /* OVF bit on */ + break; + case 2: + FPSR |= 0x20000000; /* UNF bit on */ + break; + } + } + store_sf(&sfl2, &FPAC[j]); /* put result in destination */ + if ((FPAC[j] & 0x00ffffffffffffff) == 0) + FPAC[j] = 0; + FPSR &= 0xFCFFFFFF; /* Z + N off */ + if (FPAC[j] == 0) + FPSR |= 0x02000000; /* Set Z */ + if (FPAC[j] & 0x8000000000000000) + FPSR |= 0x01000000; /* Set N */ + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); + PC = (PC + 1) & AMASK; + continue; + } + if ((IR & 0103777) == 0100550) { /* FMD Mult double by AC */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; + if (Debug_Flags == 1) { + printf("\n<>\n"); + reason = STOP_IBKPT; + } + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + i = (IR >> 13) & 3; + j = (IR >> 11) & 3; + FPSR &= 0xFCFFFFFF; /* Z+N bits off */ + get_lf(&dfl, &FPAC[i]); /* Place in working registers */ + get_lf(&dfl2, &FPAC[j]); + k = mul_lf(&dfl2, &dfl); /* Multiply */ + if (k) { + switch (k) { + case 1: + FPSR |= 0x40000000; /* OVF bit on */ + break; + case 2: + FPSR |= 0x20000000; /* UNF bit on */ + break; + } + } + store_lf(&dfl2, &FPAC[j]); /* put result in destination */ + if ((FPAC[j] & 0x00ffffffffffffff) == 0) + FPAC[j] = 0; + FPSR &= 0xFCFFFFFF; /* Z + N off */ + if (FPAC[j] == 0) + FPSR |= 0x02000000; /* Set Z */ + if (FPAC[j] & 0x8000000000000000) + FPSR |= 0x01000000; /* Set N */ + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); + continue; + } + if ((IR & 0103777) == 0101550) { /* FMMD Mult double by memory */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; + if (Debug_Flags == 1) { + printf("\n<>\n"); + reason = STOP_IBKPT; + } + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + j = (IR >> 11) & 3; + MA = effective(PC, (IR >> 13) & 3, GetMap(PC)); + tempfp = ((t_uint64)GetMap(MA) << 48); + tempfp |= ((t_uint64)GetMap(MA + 1) << 32); + tempfp |= ((t_uint64)GetMap(MA + 2) << 16); + tempfp |= ((t_uint64)GetMap(MA + 3)); + if ((tempfp & 0x00ffffffffffffff) == 0) + tempfp = 0; + FPSR &= 0xFCFFFFFF; /* Z+N bits off */ + get_lf(&dfl, &tempfp); /* Place in working registers */ + get_lf(&dfl2, &FPAC[j]); + k = mul_lf(&dfl2, &dfl); /* Multiply */ + if (k) { + switch (k) { + case 1: + FPSR |= 0x40000000; /* OVF bit on */ + break; + case 2: + FPSR |= 0x20000000; /* UNF bit on */ + break; + } + } + store_lf(&dfl2, &FPAC[j]); /* put result in destination */ + if ((FPAC[j] & 0x00ffffffffffffff) == 0) + FPAC[j] = 0; + FPSR &= 0xFCFFFFFF; /* Z + N off */ + if (FPAC[j] == 0) + FPSR |= 0x02000000; /* Set Z */ + if (FPAC[j] & 0x8000000000000000) + FPSR |= 0x01000000; /* Set N */ + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); + PC = (PC + 1) & AMASK; + continue; + } + if ((IR & 0103777) == 0100650) { /* FDS Div single by AC */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; + if (Debug_Flags == 1) { + printf("\n<>\n"); + reason = STOP_IBKPT; + } + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + i = (IR >> 13) & 3; + j = (IR >> 11) & 3; + FPSR &= 0xFCFFFFFF; /* Z+N bits off */ + get_sf(&sfl, &FPAC[i]); /* Place in working registers */ + get_sf(&sfl2, &FPAC[j]); + k = div_sf(&sfl2, &sfl); /* Divide */ + if (k) { + switch (k) { + case 1: + FPSR |= 0x40000000; /* OVF bit on */ + break; + case 2: + FPSR |= 0x20000000; /* UNF bit on */ + break; + case 3: + FPSR |= 0x10000000; /* DVZ bit on */ + break; + } + } + store_sf(&sfl2, &FPAC[j]); /* put result in destination */ + if ((FPAC[j] & 0x00ffffffffffffff) == 0) + FPAC[j] = 0; + FPSR &= 0xFCFFFFFF; /* Z + N off */ + if (FPAC[j] == 0) + FPSR |= 0x02000000; /* Set Z */ + if (FPAC[j] & 0x8000000000000000) + FPSR |= 0x01000000; /* Set N */ + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); + continue; + } + if ((IR & 0103777) == 0101650) { /* FDMS Div single by memory */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; + if (Debug_Flags == 1) { + printf("\n<>\n"); + reason = STOP_IBKPT; + } + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + j = (IR >> 11) & 3; + MA = effective(PC, (IR >> 13) & 3, GetMap(PC)); + tempfp = ((t_uint64)GetMap(MA) << 48); + tempfp |= ((t_uint64)GetMap(MA + 1) << 32); + if ((tempfp & 0x00ffffffffffffff) == 0) + tempfp = 0; + FPSR &= 0xFCFFFFFF; /* Z+N bits off */ + get_sf(&sfl, &tempfp); /* Place in working registers */ + get_sf(&sfl2, &FPAC[j]); + k = div_sf(&sfl2, &sfl); /* Divide */ + if (k) { + switch (k) { + case 1: + FPSR |= 0x40000000; /* OVF bit on */ + break; + case 2: + FPSR |= 0x20000000; /* UNF bit on */ + break; + case 3: + FPSR |= 0x10000000; /* DVZ bit on */ + break; + } + } + store_sf(&sfl2, &FPAC[j]); /* put result in destination */ + if ((FPAC[j] & 0x00ffffffffffffff) == 0) + FPAC[j] = 0; + FPSR &= 0xFCFFFFFF; /* Z + N off */ + if (FPAC[j] == 0) + FPSR |= 0x02000000; /* Set Z */ + if (FPAC[j] & 0x8000000000000000) + FPSR |= 0x01000000; /* Set N */ + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); + PC = (PC + 1) & AMASK; + continue; + } + if ((IR & 0103777) == 0100650) { /* FDD Div double by AC */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; + if (Debug_Flags == 1) { + printf("\n<>\n"); + reason = STOP_IBKPT; + } + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + i = (IR >> 13) & 3; + j = (IR >> 11) & 3; + FPSR &= 0xFCFFFFFF; /* Z+N bits off */ + get_lf(&dfl, &FPAC[i]); /* Place in working registers */ + get_lf(&dfl2, &FPAC[j]); + k = div_lf(&dfl2, &dfl); /* Divide */ + if (k) { + switch (k) { + case 1: + FPSR |= 0x40000000; /* OVF bit on */ + break; + case 2: + FPSR |= 0x20000000; /* UNF bit on */ + break; + case 3: + FPSR |= 0x10000000; /* DVZ bit on */ + break; + } + } + store_lf(&dfl2, &FPAC[j]); /* put result in destination */ + if ((FPAC[j] & 0x00ffffffffffffff) == 0) + FPAC[j] = 0; + FPSR &= 0xFCFFFFFF; /* Z + N off */ + if (FPAC[j] == 0) + FPSR |= 0x02000000; /* Set Z */ + if (FPAC[j] & 0x8000000000000000) + FPSR |= 0x01000000; /* Set N */ + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); + continue; + } + if ((IR & 0103777) == 0101650) { /* FDMD Div double by memory */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; + if (Debug_Flags == 1) { + printf("\n<>\n"); + reason = STOP_IBKPT; + } + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + j = (IR >> 11) & 3; + MA = effective(PC, (IR >> 13) & 3, GetMap(PC)); + tempfp = ((t_uint64)GetMap(MA) << 48); + tempfp |= ((t_uint64)GetMap(MA + 1) << 32); + tempfp |= ((t_uint64)GetMap(MA + 2) << 16); + tempfp |= ((t_uint64)GetMap(MA + 3)); + if ((tempfp & 0x00ffffffffffffff) == 0) + tempfp = 0; + FPSR &= 0xFCFFFFFF; /* Z+N bits off */ + get_lf(&dfl, &tempfp); /* Place in working registers */ + get_lf(&dfl2, &FPAC[j]); + k = div_lf(&dfl2, &dfl); /* Divide */ + if (k) { + switch (k) { + case 1: + FPSR |= 0x40000000; /* OVF bit on */ + break; + case 2: + FPSR |= 0x20000000; /* UNF bit on */ + break; + case 3: + FPSR |= 0x10000000; /* DVZ bit on */ + break; + } + } + store_lf(&dfl2, &FPAC[j]); /* put result in destination */ + if ((FPAC[j] & 0x00ffffffffffffff) == 0) + FPAC[j] = 0; + FPSR &= 0xFCFFFFFF; /* Z + N off */ + if (FPAC[j] == 0) + FPSR |= 0x02000000; /* Set Z */ + if (FPAC[j] & 0x8000000000000000) + FPSR |= 0x01000000; /* Set N */ + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); + PC = (PC + 1) & AMASK; + continue; + } + if ((IR & 0163777) == 0163050) { /* FNEG Negate */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; + if (Debug_Flags == 1) { + printf("\n<>\n"); + reason = STOP_IBKPT; + } + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + j = (IR >> 11) & 3; + FPSR &= 0xFCFFFFFF; /* Z+N bits off */ + get_lf(&dfl, &FPAC[j]); + dfl.sign = ! (dfl.sign); /* invert sign */ + store_lf(&dfl, &FPAC[j]); /* put result in destination */ + if ((FPAC[j] & 0x00ffffffffffffff) == 0) + FPAC[j] = 0; + FPSR &= 0xFCFFFFFF; /* Z + N off */ + if (FPAC[j] == 0) + FPSR |= 0x02000000; /* Set Z */ + if (FPAC[j] & 0x8000000000000000) + FPSR |= 0x01000000; /* Set N */ + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); + continue; + } + if ((IR & 0163777) == 0143050) { /* FAB Absolute Value*/ + if (!(fpu_unit.flags & UNIT_UP)) + continue; + if (Debug_Flags == 1) { + printf("\n<>\n"); + reason = STOP_IBKPT; + } + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + j = (IR >> 11) & 3; + FPSR &= 0xFCFFFFFF; /* Z+N bits off */ + get_lf(&dfl, &FPAC[j]); + dfl.sign = 0; /* Force sign positive */ + store_lf(&dfl, &FPAC[j]); /* put result in destination */ + if ((FPAC[j] & 0x00ffffffffffffff) == 0) + FPAC[j] = 0; + FPSR &= 0xFCFFFFFF; /* Z + N off */ + if (FPAC[j] == 0) + FPSR |= 0x02000000; /* Set Z */ + if (FPAC[j] & 0x8000000000000000) + FPSR |= 0x01000000; /* Set N */ + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); + continue; + } + if ((IR & 0163777) == 0103050) { /* FNOM Normalize*/ + if (!(fpu_unit.flags & UNIT_UP)) + continue; + if (Debug_Flags == 1) { + printf("\n<>\n"); + reason = STOP_IBKPT; + } + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + j = (IR >> 11) & 3; + FPSR &= 0xFCFFFFFF; /* Z+N bits off */ + get_lf(&dfl, &FPAC[j]); + k = normal_lf(&dfl); /* Normalize */ + if (k == 2) /* Underflow ? */ + FPSR |= 0x20000000; /* Set underflow on */ + store_lf(&dfl, &FPAC[j]); /* put result in destination */ + if ((FPAC[j] & 0x00ffffffffffffff) == 0) + FPAC[j] = 0; + FPSR &= 0xFCFFFFFF; /* Z + N off */ + if (FPAC[j] == 0) + FPSR |= 0x02000000; /* Set Z */ + if (FPAC[j] & 0x8000000000000000) + FPSR |= 0x01000000; /* Set N */ + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); + continue; + } + if ((IR & 0163777) == 0123050) { /* FRH Read High Word */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; + if (Debug_Flags == 1) { + printf("\n<>\n"); + reason = STOP_IBKPT; + } + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + j = (IR >> 11) & 3; + AC[0] = (int32)(FPAC[j] >> 48) & 0xFFFF; /* No cond bits set, always to AC0 */ + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); + continue; + } + if ((IR & 0163777) == 0123150) { /* FEXP Load Exponent */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; + if (Debug_Flags == 1) { + printf("\n<>\n"); + reason = STOP_IBKPT; + continue; + } + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + j = (IR >> 11) & 3; + i = (AC[0] >> 8) & 0x007F; + FPAC[j] &= 0x80FFFFFFFFFFFFFF; /* clear exponent */ + FPAC[j] |= (t_int64)(i << 56); + if ((FPAC[j] & 0x00ffffffffffffff) == 0) + FPAC[j] = 0; + if (FPAC[j] == 0) + FPSR |= 0x02000000; /* Set Z */ + if (FPAC[j] & 0x8000000000000000) + FPSR |= 0x01000000; /* Set N */ + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); + continue; + } + if ((IR & 0103777) == 0103450) { /* FCMP FP Compare */ + if (!(fpu_unit.flags & UNIT_UP)) /* (Subtract double AC without storing result) */ + continue; + if (Debug_Flags == 1) { + printf("\n<>\n"); + reason = STOP_IBKPT; + } + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + i = (IR >> 13) & 3; + j = (IR >> 11) & 3; + FPSR &= 0xFCFFFFFF; /* Z+N bits off */ + get_lf(&dfl, &FPAC[i]); /* Place in working registers */ + get_lf(&dfl2, &FPAC[j]); + dfl.sign = ! (dfl.sign); /* invert sign of 2nd operand */ + k = add_lf(&dfl2, &dfl, 1); /* Add the two */ + if (k) { + switch (k) { + case 1: + FPSR |= 0x40000000; /* OVF bit on */ + break; + case 2: + FPSR |= 0x20000000; /* UNF bit on */ + break; + } + } + if ((FPAC[j] & 0x00ffffffffffffff) == 0) + FPAC[j] = 0; + FPSR &= 0xFCFFFFFF; /* Z + N off */ + if (FPAC[j] == 0) + FPSR |= 0x02000000; /* Set Z */ + if (FPAC[j] & 0x8000000000000000) + FPSR |= 0x01000000; /* Set N */ + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); + continue; + } if (IR == 0163350) { /* FPSH Push State */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; + if (Debug_Flags == 2) { + printf("\n<>\n"); + reason = STOP_IBKPT; + } + /* Note: FPSH and FPOP do not trap on error */ + t = (GetMap(040) + 1) & AMASK; /* Get Stack Pointer */ + PutMap(t, ((FPSR >> 16) & 0xFFFF)); + t++; + PutMap(t, (FPSR & 0xFFFF)); + t++; + PutMap(t, (int16)((FPAC[0] >> 48) & 0xFFFF)); + t++; + PutMap(t, (int16)((FPAC[0] >> 32) & 0xFFFF)); + t++; + PutMap(t, (int16)((FPAC[0] >> 16) & 0xFFFF)); + t++; + PutMap(t, (int16)(FPAC[0] & 0xFFFF)); + t++; + PutMap(t, (int16)((FPAC[1] >> 48) & 0xFFFF)); + t++; + PutMap(t, (int16)((FPAC[1] >> 32) & 0xFFFF)); + t++; + PutMap(t, (int16)((FPAC[1] >> 16) & 0xFFFF)); + t++; + PutMap(t, (int16)(FPAC[1] & 0xFFFF)); + t++; + PutMap(t, (int16)((FPAC[2] >> 48) & 0xFFFF)); + t++; + PutMap(t, (int16)((FPAC[2] >> 32) & 0xFFFF)); + t++; + PutMap(t, (int16)((FPAC[2] >> 16) & 0xFFFF)); + t++; + PutMap(t, (int16)(FPAC[2] & 0xFFFF)); + t++; + PutMap(t, (int16)((FPAC[3] >> 48) & 0xFFFF)); + t++; + PutMap(t, (int16)((FPAC[3] >> 32) & 0xFFFF)); + t++; + PutMap(t, (int16)((FPAC[3] >> 16) & 0xFFFF)); + t++; + PutMap(t, (int16)(FPAC[3] & 0xFFFF)); + PutMap(040, t); /* Update Stack Pointer */ continue; } if (IR == 0167350) { /* FPOP Pop State */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; + if (Debug_Flags == 2) { + printf("\n<>\n"); + reason = STOP_IBKPT; + } + /* Note: FPSH and FPOP do not trap on error */ + t = GetMap(040) & AMASK; /* Get Stack Pointer */ + FPAC[3] = ((t_uint64)GetMap(t) & 0xFFFF); + t--; + FPAC[3] |= (((t_uint64)GetMap(t) << 16) & 0xFFFF0000); + t--; + FPAC[3] |= (((t_uint64)GetMap(t) << 32) & 0xFFFF00000000); + t--; + FPAC[3] |= (((t_uint64)GetMap(t) << 48) & 0xFFFF000000000000); + t--; + FPAC[2] = ((t_uint64)GetMap(t) & 0xFFFF); + t--; + FPAC[2] |= (((t_uint64)GetMap(t) << 16) & 0xFFFF0000); + t--; + FPAC[2] |= (((t_uint64)GetMap(t) << 32) & 0xFFFF00000000); + t--; + FPAC[2] |= (((t_uint64)GetMap(t) << 48) & 0xFFFF000000000000); + t--; + FPAC[1] = ((t_uint64)GetMap(t) & 0xFFFF); + t--; + FPAC[1] |= (((t_uint64)GetMap(t) << 16) & 0xFFFF0000); + t--; + FPAC[1] |= (((t_uint64)GetMap(t) << 32) & 0xFFFF00000000); + t--; + FPAC[1] |= (((t_uint64)GetMap(t) << 48) & 0xFFFF000000000000); + t--; + FPAC[0] = ((t_uint64)GetMap(t) & 0xFFFF); + t--; + FPAC[0] |= (((t_uint64)GetMap(t) << 16) & 0xFFFF0000); + t--; + FPAC[0] |= (((t_uint64)GetMap(t) << 32) & 0xFFFF00000000); + t--; + FPAC[0] |= (((t_uint64)GetMap(t) << 48) & 0xFFFF000000000000); + t--; + FPSR = (GetMap(t) & 0xFFFF); + t--; + FPSR |= ((GetMap(t) << 16) & 0xFFFF0000); + t--; + PutMap(040, t); /* Update Stack Pointer */ continue; } + if ((IR & 0163777) == 0163150) { /* FHLV Halve */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; + if (Debug_Flags == 1) { + printf("\n<>\n"); + reason = STOP_IBKPT; + } + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + j = (IR >> 11) & 3; + FPSR &= 0xFCFFFFFF; /* Z+N bits off */ + get_lf(&dfl, &FPAC[j]); + dfl.long_fract = dfl.long_fract >> 1; /* Shift right one bit */ + normal_lf(&dfl); /* Normalize */ + store_lf(&dfl, &FPAC[j]); /* put result in destination */ + if ((FPAC[j] & 0x00ffffffffffffff) == 0) + FPAC[j] = 0; + FPSR &= 0xFCFFFFFF; /* Z + N off */ + if (FPAC[j] == 0) + FPSR |= 0x02000000; /* Set Z */ + if (FPAC[j] & 0x8000000000000000) + FPSR |= 0x01000000; /* Set N */ + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); + continue; + } + if ((IR & 0163777) == 0103150) { /* FSCAL Scale */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; + if (Debug_Flags == 1) { + printf("\n<>\n"); + reason = STOP_IBKPT; + } + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + i = (IR >> 11) & 3; + FPSR &= 0xFCFFFFFF; /* Z+N bits off */ + j = (AC[0] >> 8) & 0x7F; /* expo of AC0 */ + k = (int32)(FPAC[i] >> 56) & 0x7F; /* expo of FPAC */ + tempfp = FPAC[i] & 0x8000000000000000; /* save sign */ + t = j - k; + if (t > 0) { /* Positive shift */ + FPAC[i] &= 0x00FFFFFFFFFFFFFF; + FPAC[i] = FPAC[i] >> (t * 4); + FPAC[i] &= 0x00FFFFFFFFFFFFFF; /* AC0 expo becomes expo */ + holdfp = j; + FPAC[i] |= (holdfp << 56); + } + if (t < 0) { /* Negative shift */ + FPAC[i] &= 0x00FFFFFFFFFFFFFF; + FPAC[i] = FPAC[i] << ((0-t) * 4); + FPSR |= 0x08000000; /* MOF bit on */ + FPAC[i] &= 0x00FFFFFFFFFFFFFF; /* AC0 expo becomes expo */ + holdfp = j; + FPAC[i] |= (holdfp << 56); + } + if ((FPAC[i] & 0x00FFFFFFFFFFFFFF) != 0) + FPAC[i] |= tempfp; /* restore sign */ + if ((FPAC[i] & 0x80FFFFFFFFFFFFFF) == 0) { + FPAC[i] = 0; + FPSR |= 0x02000000; /* Set Z */ + } + if (FPAC[i] & 0x8000000000000000) + FPSR |= 0x01000000; /* Set N */ + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); + continue; + } + if (IR == 0153350) { /* FCLE Clear Errors */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; + if (Debug_Flags == 1) { + printf("\n<>\n"); + reason = STOP_IBKPT; + } + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + FPSR &= 0x07FFFFFF; /* set off all error bits */ + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); + continue; + } if (IR == 0103250) { /* FNS No Skip */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; + if (Debug_Flags == 1) { + printf("\n<>\n"); + reason = STOP_IBKPT; + } + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); continue; } if (IR == 0107250) { /* FSA Always Skip */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; + if (Debug_Flags == 2) { + printf("\n<>\n"); + reason = STOP_IBKPT; + } + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); + PC = (PC + 1) & AMASK; continue; } if (IR == 0137250) { /* FSGT */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; + if (Debug_Flags == 1) { + printf("\n<>\n"); + reason = STOP_IBKPT; + } + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); + if (!(FPSR & 0x03000000)) /* Z & N both 0? */ + PC = (PC + 1) & AMASK; /* yep: skip */ continue; } if (IR == 0123250) { /* FSLT */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; + if (Debug_Flags == 1) { + printf("\n<>\n"); + reason = STOP_IBKPT; + } + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); + if (FPSR & 0x01000000) /* N is on? */ + PC = (PC + 1) & AMASK; /* yep: skip */ continue; } if (IR == 0113250) { /* FSEQ */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; + if (Debug_Flags == 1) { + printf("\n<>\n"); + reason = STOP_IBKPT; + } + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); + if (FPSR & 0x02000000) /* Z is on? */ + PC = (PC + 1) & AMASK; /* yep: skip */ continue; } if (IR == 0133250) { /* FSLE */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; + if (Debug_Flags == 1) { + printf("\n<>\n"); + reason = STOP_IBKPT; + } + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); + if (FPSR & 0x03000000) /* Z or N on? */ + PC = (PC + 1) & AMASK; /* yep: skip */ continue; } if (IR == 0127250) { /* FSGE */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; + if (Debug_Flags == 1) { + printf("\n<>\n"); + reason = STOP_IBKPT; + } + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); + if (!(FPSR & 0x01000000)) /* N is off? */ + PC = (PC + 1) & AMASK; /* yep: skip */ continue; } if (IR == 0117250) { /* FSNE */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; + if (Debug_Flags == 1) { + printf("\n<>\n"); + continue; + } + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); + if (!(FPSR & 0x02000000)) /* Z is off? */ + PC = (PC + 1) & AMASK; /* yep: skip */ continue; } if (IR == 0143250) { /* FSNM */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; + if (Debug_Flags == 1) { + printf("\n<>\n"); + reason = STOP_IBKPT; + } + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); + if (!(FPSR & 0x08000000)) /* MOF is off? */ + PC = (PC + 1) & AMASK; /* yep: skip */ continue; } if (IR == 0153250) { /* FSNU */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; + if (Debug_Flags == 1) { + printf("\n<>\n"); + reason = STOP_IBKPT; + } + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); + if (!(FPSR & 0x20000000)) /* UNF is off? */ + PC = (PC + 1) & AMASK; /* yep: skip */ continue; } if (IR == 0163250) { /* FSNO */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; + if (Debug_Flags == 1) { + printf("\n<>\n"); + reason = STOP_IBKPT; + } + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); + if (!(FPSR & 0x40000000)) /* OVF is off? */ + PC = (PC + 1) & AMASK; /* yep: skip */ continue; } if (IR == 0147250) { /* FSND */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; + if (Debug_Flags == 1) { + printf("\n<>\n"); + reason = STOP_IBKPT; + } + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); + if (!(FPSR & 0x10000000)) /* DVZ is off? */ + PC = (PC + 1) & AMASK; /* yep: skip */ continue; } if (IR == 0157250) { /* FSNUD */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; + if (Debug_Flags == 1) { + printf("\n<>\n"); + reason = STOP_IBKPT; + } + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); + if (!(FPSR & 0x30000000)) /* UNF & DVZ off? */ + PC = (PC + 1) & AMASK; /* yep: skip */ continue; } if (IR == 0167250) { /* FSNOD */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; + if (Debug_Flags == 1) { + printf("\n<>\n"); + reason = STOP_IBKPT; + } + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); + if (!(FPSR & 0x50000000)) /* OVF & DVZ off? */ + PC = (PC + 1) & AMASK; /* yep: skip */ continue; } if (IR == 0173250) { /* FSNUO */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; + if (Debug_Flags == 1) { + printf("\n<>\n"); + reason = STOP_IBKPT; + } + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); + if (!(FPSR & 0x60000000)) /* OVF & UNF off? */ + PC = (PC + 1) & AMASK; /* yep: skip */ continue; } if (IR == 0177250) { /* FSNER */ + if (!(fpu_unit.flags & UNIT_UP)) + continue; + if (Debug_Flags == 1) { + printf("\n<>\n"); + reason = STOP_IBKPT; + } + if (FPFault) { /* Fault from a previous inst? */ + FPFault = 0; + t = (GetMap(040) + 1) & AMASK; /* Yes: 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-1) & AMASK)); + if (C) PutMap(t, (GetMap(t) | 0100000)); + PutMap(040, t); + PC = indirect(GetMap(045)); /* JMP indirect to 45 */ + continue; + } + FPSR &= 0xFFFF0000; /* Success: put addr in FPSR */ + FPSR |= ((PC - 1) & AMASK); + if (!(FPSR & 0x78000000)) /* all errors off? */ + PC = (PC + 1) & AMASK; /* yep: skip */ continue; } if (Debug_Flags) { - printf("\n<>\n\r", IR, PC-1); + printf("\n<>\n\r", IR, PC-1); if (Debug_Flags & 040000) reason = STOP_IBKPT; } } @@ -2286,7 +4807,7 @@ if (t < 014) { /* mem ref? */ if ((MA & 0100000) == 0) break; if (i >= ind_max && (MapStat & 010) && Usermap) break; } - if (i >= ind_max) { + if (i >= (ind_max-1)) { if ((MapStat & 010) && Usermap) { Fault = 04000; /* Map fault if IND prot */ continue; @@ -2497,7 +5018,8 @@ else { /* IOT */ register int32 dstAC, pulse, code, device, iodata; char pulcode[4]; - if ((MapStat & 0100) && Usermap) { /* We are in LEF Mode */ + if ((MapStat & 0100) /* LEF mode bit on? */ + && 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); @@ -2517,10 +5039,18 @@ else { /* IOT */ if (Debug_Flags && device == 0) { printf("\n\r<>\n\r", PC-1); reason = STOP_IBKPT; + continue; } if ((Debug_Flags & 0100) && (device == (Debug_Flags & 077))) { printf("\n\r<>\n\r", device); reason = STOP_IBKPT; + continue; + } + if ((Debug_Char != 0) && (device == 011) && + ((AC[dstAC] & 0177) == Debug_Char)) { + printf("\n\r<>\n\r", Debug_Char); + reason = STOP_IBKPT; + continue; } if (code == ioSKP) { /* IO skip? */ switch (pulse) { /* decode IR<8:9> */ @@ -2586,6 +5116,8 @@ else { /* IOT */ Map31 = 037; Check = SingleCycle = 0; Fault = 0; + FPSR &= 0x0000FFFF; + FPFault = 0; break; case ioDOC: /* halt */ reason = STOP_HALT; @@ -2655,15 +5187,15 @@ else { /* IOT */ case ioDIB: /* not used */ break; case ioDOB: /* map block 31 */ - if (!Usermap || !(MapStat && 0140)) { +//AOS 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]); - } +//AOS } else { +//AOS if ((Debug_Flags & 077) == 03) +//AOS fprintf(Trace, "%o DOB %o=%o (Map Blk 31) NO EXEC (User Mode)\n", PC-1, dstAC, AC[dstAC]); +//AOS } break; case ioDIC: /* Page Check */ if (!Usermap || !(MapStat & 0140)) { @@ -2805,7 +5337,7 @@ int32 effective(int32 PC, int32 index, int32 disp) if ((MA & 0100000) == 0) break; if ((MapStat & 010) && Usermap && i >= ind_max) break; } - if (i >= ind_max && (MapStat & 010) && Usermap) { + if (i >= (ind_max-1) && (MapStat & 010) && Usermap) { Fault = 04000; /* Map fault if IND prot */ } if (i >= (ind_max * 2) && !(Fault)) { @@ -2830,7 +5362,9 @@ int32 LEFmode(int32 PC, int32 index, int32 disp, int32 indirect) case 0: /* page zero */ break; case 1: /* PC relative */ - MA = (MA + PC) & AMASK; + sMA = MA; + if (MA & 0200) sMA |= 0xff00; + MA = (sMA + PC) & AMASK; break; case 2: /* AC2 relative */ sMA = MA; @@ -2859,7 +5393,7 @@ int32 LEFmode(int32 PC, int32 index, int32 disp, int32 indirect) if ((MA & 0100000) == 0) break; if ((MapStat & 010) && Usermap && i >= ind_max) break; } - if (i >= ind_max && (MapStat & 010) && Usermap) { + if (i >= (ind_max-1) && (MapStat & 010) && Usermap) { Fault = 04000; /* Map fault if IND prot */ } if (i >= (ind_max * 2) && !(Fault)) { @@ -2890,7 +5424,7 @@ int32 Bytepointer(int32 PC, int32 index) break; } /* end switch mode */ MA = (MA * 2) & 0177777; - MA = MA + M[PC]; + MA = MA + GetMap(PC); return (MA & 0177777); } @@ -2916,7 +5450,7 @@ int32 indirect(int32 d) if ((d & 0100000) == 0) break; if ((MapStat & 010) && Usermap && i >= ind_max) break; } - if (i >= ind_max && (MapStat & 010) && Usermap) { + if (i >= (ind_max-1) && (MapStat & 010) && Usermap) { Fault = 04000; /* Map fault if IND prot */ } if (i >= (ind_max * 2) && !(Fault)) { @@ -2947,13 +5481,12 @@ int32 pushrtn(int32 pc) return 0; } - /* Eclipse memory get/put - uses MAP if enabled */ int32 GetMap(int32 addr) { int32 page; - uint32 paddr; + t_addr paddr; switch (Usermap) { case 0: @@ -2969,7 +5502,7 @@ int32 GetMap(int32 addr) page = (addr >> 10) & 037; paddr = ((Map[1][page] & 01777) << 10) | (addr & 001777); if (Map[1][page] == INVALID && !SingleCycle) - Fault = 0100000; + Fault = 0100000/*!!!*/; /* Validity */ if (paddr < MEMSIZE) return M[paddr]; else @@ -2979,7 +5512,7 @@ int32 GetMap(int32 addr) page = (addr >> 10) & 037; paddr = ((Map[2][page] & PAGEMASK) << 10) | (addr & 001777); if (Map[2][page] == INVALID && !SingleCycle) - Fault = 0100000; + Fault = 0100000/*!!!*/; /* Validity */ if (paddr < MEMSIZE) return M[paddr]; else @@ -2989,7 +5522,7 @@ int32 GetMap(int32 addr) page = (addr >> 10) & 037; paddr = ((Map[6][page] & PAGEMASK) << 10) | (addr & 001777); if (Map[6][page] == INVALID && !SingleCycle) - Fault = 0100000; + Fault = 0100000/*!!!*/; /* Validity */ if (paddr < MEMSIZE) return M[paddr]; else @@ -2999,7 +5532,7 @@ int32 GetMap(int32 addr) page = (addr >> 10) & 037; paddr = ((Map[7][page] & PAGEMASK) << 10) | (addr & 001777); if (Map[7][page] == INVALID && !SingleCycle) - Fault = 0100000; + Fault = 0100000/*!!!*/; /* Validity */ if (paddr < MEMSIZE) return M[paddr]; else @@ -3015,39 +5548,43 @@ int32 GetMap(int32 addr) int32 PutMap(int32 addr, int32 data) { int32 page; - uint32 paddr; + t_addr 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; + if (((Map[1][page] & 0100000) && (MapStat & 020)) || Map[1][page] == INVALID) + Fault = 010000; /* Write Protect Fault */ 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; + if (((Map[2][page] & 0100000) && (MapStat & 020)) || Map[2][page] == INVALID) + Fault = 010000; /* Write Protect Fault */ 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; + if (((Map[6][page] & 0100000) && (MapStat & 020)) || Map[6][page] == INVALID) + Fault = 010000; /* Write Protect Fault */ 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; + if (((Map[7][page] & 0100000) && (MapStat & 020)) || Map[7][page] == INVALID) + Fault = 010000; /* Write Protect Fault */ else if (paddr < MEMSIZE) M[paddr] = data; break; default: @@ -3060,7 +5597,7 @@ int32 PutMap(int32 addr, int32 data) #if 0 int16 GetDCHMap(int32 map, int32 addr) { - uint32 paddr; + t_addr paddr; if (!(MapStat & 02)) return M[addr]; paddr = ((Map[map][(addr >> 10) & 037] & PAGEMASK) << 10) | (addr & 001777); if (paddr < MEMSIZE) @@ -3070,7 +5607,7 @@ int16 GetDCHMap(int32 map, int32 addr) int16 PutDCHMap(int32 map, int32 addr, int16 data) { - uint32 paddr; + t_addr paddr; if (!(MapStat & 02)) { M[addr] = data; return (data); @@ -3173,8 +5710,11 @@ return SCPE_OK; 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; +if (sw & SWMASK ('V')) { + if (addr > 077777) return SCPE_NXM; + if (vptr != NULL) *vptr = GetMap (addr); } +else { if (addr >= MEMSIZE) return SCPE_NXM; + if (vptr != NULL) *vptr = M[addr] & 0177777; } return SCPE_OK; } @@ -3182,8 +5722,11 @@ return SCPE_OK; t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw) { -if (addr >= MEMSIZE) return SCPE_NXM; -M[addr] = val & 0177777; +if (sw & SWMASK ('V')) { + if (addr > 077777) return SCPE_NXM; + PutMap (addr, (int32) val); } +else { if (addr >= MEMSIZE) return SCPE_NXM; + M[addr] = (int32) val & 0177777; } return SCPE_OK; } @@ -3192,7 +5735,7 @@ return SCPE_OK; t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) { int32 mc = 0; -uint32 i; +t_addr i; if ((val <= 0) || (val > MAXMEMSIZE) || ((val & 07777) != 0)) return SCPE_ARG; @@ -3227,7 +5770,82 @@ 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; +Map[(addr >> 6) & 3][addr & 037] = (int32)val & 0177777; +return SCPE_OK; +} + +/* FPU device services */ + +t_stat fpu_svc (UNIT *uptr) +{ +return SCPE_OK; +} + +/* PIT Device Services */ + +/* IOT routine */ + +int32 pit (int32 pulse, int32 code, int32 AC) +{ +int32 iodata = 0; + +if (code == ioDIA) { /* DIA */ + if (pit_flag == 0) { + pit_flag = 1; + } + iodata = pit_counter; +} +if (code == ioDOA) { /* DOA */ + pit_initial = AC; /* Load Counter */ + sim_rtcn_init (pit_time, 1); /* init calibr */ +} +switch (pulse) { /* decode IR<8:9> */ +case iopS: /* start */ + pit_counter = pit_initial; /* Set the counter */ + dev_busy = dev_busy | INT_PIT; /* set busy */ + dev_done = dev_done & ~INT_PIT; /* clear done, int */ + int_req = int_req & ~INT_PIT; + if (!sim_is_active (&pit_unit)) /* not running? */ + sim_activate (&pit_unit, /* activate */ + sim_rtcn_init (pit_time, 1)); /* init calibr */ + break; +case iopC: /* clear */ + dev_busy = dev_busy & ~INT_PIT; /* clear busy */ + dev_done = dev_done & ~INT_PIT; /* clear done, int */ + int_req = int_req & ~INT_PIT; + sim_cancel (&pit_unit); /* deactivate unit */ + break; } /* end switch */ +return iodata; +} + +/* Unit service */ + +t_stat pit_svc (UNIT *uptr) +{ +int32 t; +t = sim_rtcn_calb (pit_tps, 1); /* calibrate delay */ +sim_activate (&pit_unit, t); /* reactivate unit */ +pit_poll = t / (-pit_adj); /* adjust poll */ +pit_counter++; /* Increment counter */ +if (pit_counter >= 0177777) { /* Has counter reached limit ? */ + dev_done = dev_done | INT_PIT; /* set done */ + dev_busy = dev_busy & ~INT_PIT; /* clear busy */ + int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable); /* Interrupt */ + pit_counter = pit_initial; +} +return SCPE_OK; +} + +/* Reset routine */ + +t_stat pit_reset (DEVICE *dptr) +{ +pit_counter = 0; /* clear counter */ +dev_busy = dev_busy & ~INT_PIT; /* clear busy */ +dev_done = dev_done & ~INT_PIT; /* clear done, int */ +int_req = int_req & ~INT_PIT; +sim_cancel (&pit_unit); /* deactivate unit */ +pit_poll = pit_time; /* poll is default */ return SCPE_OK; } @@ -3303,6 +5921,11 @@ int32 Debug_Entry(int32 PC, int32 inst, int32 inst2, int32 AC0, int32 AC1, int32 } int32 Debug_Dump(UNIT *uptr, int32 val, char *cptr, void *desc) +{ + return SCPE_OK; +} + +int32 Dump_History (FILE *st, UNIT *uptr, int32 val, void *desc) { char debmap[4], debion[4]; t_value simeval[20]; @@ -3380,3 +6003,749 @@ for (i = 0; (dptr = sim_devices[i]) != NULL; i++) { /* loop thru dev */ dev_table[dn].routine = dibp->routine; } } return SCPE_OK; } + +/* ------------------------------------------------------------------- */ +/* Floating Point Arithmetic */ +/* ------------------------------------------------------------------- */ + + +/* Get short float from FPAC */ + +void get_sf (SHORT_FLOAT *fl, t_int64 *fpr) +{ + fl->sign = (uint8)(*fpr >> 63) & 1; + fl->expo = (short)(*fpr >> 56) & 0x007F; + fl->short_fract = (int32)(*fpr >> 32) & 0x00FFFFFF; +} + +/* Store short float to FPAC */ + +void store_sf (SHORT_FLOAT *fl, t_int64 *fpr) +{ + *fpr = 0; + *fpr = ((t_int64)fl->sign << 63) + | ((t_int64)fl->expo << 56) + | ((t_int64)fl->short_fract <<32); +} + +/* Get long float from FPAC */ + +void get_lf (LONG_FLOAT *fl, t_int64 *fpr) +{ + fl->sign = (uint8)(*fpr >> 63) & 1; + fl->expo = (short)(*fpr >> 56) & 0x007F; + fl->long_fract = (t_int64)*fpr & 0x00FFFFFFFFFFFFFF; + +} + +/* Store long float to FPAC */ + +void store_lf (LONG_FLOAT *fl, t_int64 *fpr) +{ + *fpr = 0; + *fpr = (t_int64)fl->sign << 63; + *fpr |= ((t_int64)fl->expo << 56) & 0x7f00000000000000; + *fpr |= fl->long_fract; +} + + +/* Check short for Overflow */ + +int overflow_sf (SHORT_FLOAT *fl) +{ + if (fl->expo > 127) { + fl->expo &= 0x007F; + return(1); + } + return(0); + +} + +/* Normalize Short Float */ + +int normal_sf(SHORT_FLOAT *fl) +{ + if (fl->short_fract) { + if ((fl->short_fract & 0x00FFFF00) == 0) { + fl->short_fract <<= 16; + fl->expo -= 4; + } + if ((fl->short_fract & 0x00FF0000) == 0) { + fl->short_fract <<= 8; + fl->expo -= 2; + } + if ((fl->short_fract & 0x00F00000) == 0) { + fl->short_fract <<= 4; + (fl->expo)--; + } + } else { + fl->sign = 0; + fl->expo = 0; + } + if (fl->expo < 0) + return (2); + return(0); +} + +/* Normalize long float */ + +int normal_lf (LONG_FLOAT *fl) +{ + if (fl->long_fract) { + if ((fl->long_fract & 0x00FFFFFFFF000000) == 0) { + fl->long_fract <<= 32; + fl->expo -= 8; + } + if ((fl->long_fract & 0x00FFFF0000000000) == 0) { + fl->long_fract <<= 16; + fl->expo -= 4; + } + if ((fl->long_fract & 0x00FF000000000000) == 0) { + fl->long_fract <<= 8; + fl->expo -= 2; + } + if ((fl->long_fract & 0x00F0000000000000) == 0) { + fl->long_fract <<= 4; + (fl->expo)--; + } + } else { + fl->sign = 0; + fl->expo = 0; + } + if (fl->expo < 0) + return (2); + return(0); +} + +/* Check Long for Overflow */ + +int overflow_lf(LONG_FLOAT *fl) +{ + if (fl->expo > 127) { + fl->expo &= 0x007F; + return(1); + } + return(0); + +} + +int underflow_sf(SHORT_FLOAT *fl) +{ + if (fl->expo < 0) { + fl->short_fract = 0; + fl->expo = 0; + fl->sign = 0; + } + return(0); + +} + + +int underflow_lf(LONG_FLOAT *fl) +{ + if (fl->expo < 0) { + fl->long_fract = 0; + fl->expo = 0; + fl->sign = 0; + } + return(0); +} + +/* Check Short for Over/Under flow */ + +int over_under_flow_sf(SHORT_FLOAT *fl) +{ + if (fl->expo > 127) { + fl->expo &= 0x007F; + return(1); + } else { + if (fl->expo < 0) { + /* set true 0 */ + fl->short_fract = 0; + fl->expo = 0; + fl->sign = 0; + } + } + return(0); + +} + +/* Check Long for Over/Under flow */ + +int over_under_flow_lf(LONG_FLOAT *fl) +{ + if (fl->expo > 127) { + fl->expo &= 0x007F; + return(1); + } else { + if (fl->expo < 0) { + /* set true 0 */ + fl->long_fract = 0; + fl->expo = 0; + fl->sign = 0; + } + } + return(0); + +} + +int significance_sf (SHORT_FLOAT *fl) +{ + fl->sign = 0; + fl->expo = 0; + return(0); + +} + +int significance_lf (LONG_FLOAT *fl) +{ + fl->sign = 0; + fl->expo = 0; + return(0); + +} + + +/*-------------------------------------------------------------------*/ +/* Add short float */ +/* */ +/* Input: */ +/* fl Float */ +/* add_fl Float to be added */ +/* normal Normalize if true */ +/* Value: */ +/* exeption */ +/*-------------------------------------------------------------------*/ +int add_sf (SHORT_FLOAT *fl, SHORT_FLOAT *add_fl, int normal) +{ +int pgm_check; +int shift; + + pgm_check = 0; + if (add_fl->short_fract + || add_fl->expo) { /* add_fl not 0 */ + if (fl->short_fract + || fl->expo) { /* fl not 0 */ + /* both not 0 */ + + if (fl->expo == add_fl->expo) { + /* expo equal */ + + /* both guard digits */ + fl->short_fract <<= 4; + add_fl->short_fract <<= 4; + } else { + /* expo not equal, denormalize */ + + if (fl->expo < add_fl->expo) { + /* shift minus guard digit */ + shift = add_fl->expo - fl->expo - 1; + fl->expo = add_fl->expo; + + if (shift) { + if (shift >= 6 + || ((fl->short_fract >>= (shift * 4)) == 0)) { + /* 0, copy summand */ + + fl->sign = add_fl->sign; + fl->short_fract = add_fl->short_fract; + + if (fl->short_fract == 0) { + pgm_check = significance_sf(fl); + } else { + if (normal) { + normal_sf(fl); + pgm_check = underflow_sf(fl); + } + } + return(pgm_check); + } + } + /* guard digit */ + add_fl->short_fract <<= 4; + } else { + /* shift minus guard digit */ + shift = fl->expo - add_fl->expo - 1; + + if (shift) { + if (shift >= 6 + || ((add_fl->short_fract >>= (shift * 4)) == 0)) { + /* 0, nothing to add */ + + if (fl->short_fract == 0) { + pgm_check = significance_sf(fl); + } else { + if (normal) { + normal_sf(fl); + pgm_check = underflow_sf(fl); + } + } + return(pgm_check); + } + } + /* guard digit */ + fl->short_fract <<= 4; + } + } + + /* compute with guard digit */ + if (fl->sign == add_fl->sign) { + fl->short_fract += add_fl->short_fract; + } else { + if (fl->short_fract == add_fl->short_fract) { + /* true 0 */ + + fl->short_fract = 0; + return( significance_sf(fl) ); + + } else if (fl->short_fract > add_fl->short_fract) { + fl->short_fract -= add_fl->short_fract; + } else { + fl->short_fract = add_fl->short_fract - fl->short_fract; + fl->sign = add_fl->sign; + } + } + + /* handle overflow with guard digit */ + if (fl->short_fract & 0xF0000000) { + fl->short_fract >>= 8; + (fl->expo)++; + pgm_check = overflow_sf(fl); + } else { + + if (normal) { + /* normalize with guard digit */ + if (fl->short_fract) { + /* not 0 */ + + if (fl->short_fract & 0x0F000000) { + /* not normalize, just guard digit */ + fl->short_fract >>= 4; + } else { + (fl->expo)--; + normal_sf(fl); + pgm_check = underflow_sf(fl); + } + } else { + /* true 0 */ + + pgm_check = significance_sf(fl); + } + } else { + /* not normalize, just guard digit */ + fl->short_fract >>= 4; + if (fl->short_fract == 0) { + pgm_check = significance_sf(fl); + } + } + } + return(pgm_check); + } else { /* fl 0, add_fl not 0 */ + /* copy summand */ + + fl->expo = add_fl->expo; + fl->sign = add_fl->sign; + fl->short_fract = add_fl->short_fract; + if (fl->short_fract == 0) { + return( significance_sf(fl) ); + } + } + } else { /* add_fl 0 */ + if (fl->short_fract == 0) { /* fl 0 */ + /* both 0 */ + + return( significance_sf(fl) ); + } + } + if (normal) { + normal_sf(fl); + pgm_check = underflow_sf(fl); + } + return(pgm_check); + +} + + +/*-------------------------------------------------------------------*/ +/* Add long float */ +/* */ +/* Input: */ +/* fl Float */ +/* add_fl Float to be added */ +/* normal Normalize if true */ +/* Value: */ +/* exeption */ +/*-------------------------------------------------------------------*/ +int add_lf (LONG_FLOAT *fl, LONG_FLOAT *add_fl, int normal) +{ +int pgm_check; +int shift; + + pgm_check = 0; + if (add_fl->long_fract + || add_fl->expo) { /* add_fl not 0 */ + if (fl->long_fract + || fl->expo) { /* fl not 0 */ + /* both not 0 */ + + if (fl->expo == add_fl->expo) { + /* expo equal */ + + /* both guard digits */ + fl->long_fract <<= 4; + add_fl->long_fract <<= 4; + } else { + /* expo not equal, denormalize */ + + if (fl->expo < add_fl->expo) { + /* shift minus guard digit */ + shift = add_fl->expo - fl->expo - 1; + fl->expo = add_fl->expo; + + if (shift) { + if (shift >= 14 + || ((fl->long_fract >>= (shift * 4)) == 0)) { + /* 0, copy summand */ + + fl->sign = add_fl->sign; + fl->long_fract = add_fl->long_fract; + + if (fl->long_fract == 0) { + pgm_check = significance_lf(fl); + } else { + if (normal) { + normal_lf(fl); + pgm_check = underflow_lf(fl); + } + } + return(pgm_check); + } + } + /* guard digit */ + add_fl->long_fract <<= 4; + } else { + /* shift minus guard digit */ + shift = fl->expo - add_fl->expo - 1; + + if (shift) { + if (shift >= 14 + || ((add_fl->long_fract >>= (shift * 4)) == 0)) { + /* 0, nothing to add */ + + if (fl->long_fract == 0) { + pgm_check = significance_lf(fl); + } else { + if (normal) { + normal_lf(fl); + pgm_check = underflow_lf(fl); + } + } + return(pgm_check); + } + } + /* guard digit */ + fl->long_fract <<= 4; + } + } + + /* compute with guard digit */ + if (fl->sign == add_fl->sign) { + fl->long_fract += add_fl->long_fract; + } else { + if (fl->long_fract == add_fl->long_fract) { + /* true 0 */ + + fl->long_fract = 0; + return( significance_lf(fl) ); + + } else if (fl->long_fract > add_fl->long_fract) { + fl->long_fract -= add_fl->long_fract; + } else { + fl->long_fract = add_fl->long_fract - fl->long_fract; + fl->sign = add_fl->sign; + } + } + + /* handle overflow with guard digit */ + if (fl->long_fract & 0xF000000000000000) { + fl->long_fract >>= 8; + (fl->expo)++; + pgm_check = overflow_lf(fl); + } else { + + if (normal) { + /* normalize with guard digit */ + if (fl->long_fract) { + /* not 0 */ + + if (fl->long_fract & 0x0F00000000000000) { + /* not normalize, just guard digit */ + fl->long_fract >>= 4; + } else { + (fl->expo)--; + normal_lf(fl); + pgm_check = underflow_lf(fl); + } + } else { + /* true 0 */ + + pgm_check = significance_lf(fl); + } + } else { + /* not normalize, just guard digit */ + fl->long_fract >>= 4; + if (fl->long_fract == 0) { + pgm_check = significance_lf(fl); + } + } + } + return(pgm_check); + } else { /* fl 0, add_fl not 0 */ + /* copy summand */ + + fl->expo = add_fl->expo; + fl->sign = add_fl->sign; + fl->long_fract = add_fl->long_fract; + if (fl->long_fract == 0) { + return( significance_lf(fl) ); + } + } + } else { /* add_fl 0 */ + if (fl->long_fract == 0) { /* fl 0 */ + /* both 0 */ + + return( significance_lf(fl) ); + } + } + if (normal) { + normal_lf(fl); + pgm_check = underflow_lf(fl); + } + return(pgm_check); + +} + +/*-------------------------------------------------------------------*/ +/* Multiply short float */ +/* */ +/* Input: */ +/* fl Multiplicand short float */ +/* mul_fl Multiplicator short float */ +/* Value: */ +/* exeption */ +/*-------------------------------------------------------------------*/ + +int mul_sf(SHORT_FLOAT *fl, SHORT_FLOAT *mul_fl) +{ +t_int64 wk; + + if (fl->short_fract + && mul_fl->short_fract) { + /* normalize operands */ + normal_sf( fl ); + normal_sf( mul_fl ); + + /* multiply fracts */ + wk = (t_int64) fl->short_fract * mul_fl->short_fract; + + /* normalize result and compute expo */ + if (wk & 0x0000F00000000000) { + fl->short_fract = (int32)wk >> 24; + fl->expo = (short)fl->expo + mul_fl->expo - 64; + } else { + fl->short_fract = (int32)wk >> 20; + fl->expo = (short)fl->expo + mul_fl->expo - 65; + } + + /* determine sign */ + fl->sign = (fl->sign == mul_fl->sign) ? 0 : 1; + + /* handle overflow and underflow */ + return( over_under_flow_sf(fl) ); + } else { + /* set true 0 */ + + fl->short_fract = 0; + fl->expo = 0; + fl->sign = 0; + return(0); + } + +} + + +/*-------------------------------------------------------------------*/ +/* Multiply long float */ +/* */ +/* Input: */ +/* fl Multiplicand long float */ +/* mul_fl Multiplicator long float */ +/* Value: */ +/* exeption */ +/*-------------------------------------------------------------------*/ +int mul_lf(LONG_FLOAT *fl, LONG_FLOAT *mul_fl) +{ +t_int64 wk; +int32 v; + + if (fl->long_fract + && mul_fl->long_fract) { + /* normalize operands */ + normal_lf( fl ); + normal_lf( mul_fl ); + + /* multiply fracts by sum of partial multiplications */ + wk = ((fl->long_fract & 0x00000000FFFFFFFF) * (mul_fl->long_fract & 0x00000000FFFFFFFF)) >> 32; + + wk += ((fl->long_fract & 0x00000000FFFFFFFF) * (mul_fl->long_fract >> 32)); + wk += ((fl->long_fract >> 32) * (mul_fl->long_fract & 0x00000000FFFFFFFF)); + v = (int32)wk; + + fl->long_fract = (wk >> 32) + ((fl->long_fract >> 32) * (mul_fl->long_fract >> 32)); + + /* normalize result and compute expo */ + if (fl->long_fract & 0x0000F00000000000) { + fl->long_fract = (fl->long_fract << 8) + | (v >> 24); + fl->expo = fl->expo + mul_fl->expo - 64; + } else { + fl->long_fract = (fl->long_fract << 12) + | (v >> 20); + fl->expo = fl->expo + mul_fl->expo - 65; + } + + /* determine sign */ + fl->sign = (fl->sign == mul_fl->sign) ? 0 : 1; + + /* handle overflow and underflow */ + return( over_under_flow_lf(fl) ); + } else { + /* set true 0 */ + + fl->long_fract = 0; + fl->expo = 0; + fl->sign = 0; + return(0); + } + +} + + +/*-------------------------------------------------------------------*/ +/* Divide short float */ +/* */ +/* Input: */ +/* fl Dividend short float */ +/* div_fl Divisor short float */ +/* Value: */ +/* exeption */ +/*-------------------------------------------------------------------*/ +int div_sf(SHORT_FLOAT *fl, SHORT_FLOAT *div_fl) +{ +t_int64 wk; + + if (div_fl->short_fract) { + if (fl->short_fract) { + /* normalize operands */ + normal_sf( fl ); + normal_sf( div_fl ); + + /* position fracts and compute expo */ + if (fl->short_fract < div_fl->short_fract) { + wk = (t_int64) fl->short_fract << 24; + fl->expo = fl->expo - div_fl->expo + 64; + } else { + wk = (t_int64) fl->short_fract << 20; + fl->expo = fl->expo - div_fl->expo + 65; + } + /* divide fractions */ + fl->short_fract = (int32)wk / div_fl->short_fract; + + /* determine sign */ + fl->sign = (fl->sign == div_fl->sign) ? 0 : 1; + + /* handle overflow and underflow */ + return( over_under_flow_sf(fl) ); + } else { + /* fraction of dividend 0, set true 0 */ + + fl->short_fract = 0; + fl->expo = 0; + fl->sign = 0; + } + } else { + /* divisor 0 */ + + return(3); + } + return(0); + +} + + +/*-------------------------------------------------------------------*/ +/* Divide long float */ +/* */ +/* Input: */ +/* fl Dividend long float */ +/* div_fl Divisor long float */ +/* Value: */ +/* exeption */ +/*-------------------------------------------------------------------*/ +int div_lf(LONG_FLOAT *fl, LONG_FLOAT *div_fl) +{ +t_int64 wk; +t_int64 wk2; +int i; + + if (div_fl->long_fract) { + if (fl->long_fract) { + /* normalize operands */ + normal_lf( fl ); + normal_lf( div_fl ); + + /* position fracts and compute expo */ + if (fl->long_fract < div_fl->long_fract) { + fl->expo = fl->expo - div_fl->expo + 64; + } else { + fl->expo = fl->expo - div_fl->expo + 65; + div_fl->long_fract <<= 4; + } + + /* partial divide first hex digit */ + wk2 = fl->long_fract / div_fl->long_fract; + wk = (fl->long_fract % div_fl->long_fract) << 4; + + /* partial divide middle hex digits */ + i = 13; + while (i--) { + wk2 = (wk2 << 4) + | (wk / div_fl->long_fract); + wk = (wk % div_fl->long_fract) << 4; + } + + /* partial divide last hex digit */ + fl->long_fract = (wk2 << 4) + | (wk / div_fl->long_fract); + + /* determine sign */ + fl->sign = (fl->sign == div_fl->sign) ? 0 : 1; + + /* handle overflow and underflow */ + return( over_under_flow_lf(fl) ); + } else { + /* fraction of dividend 0, set true 0 */ + + fl->long_fract = 0; + fl->expo = 0; + fl->sign = 0; + } + } else { + /* divisor 0 */ + + return(3); + } + return(0); + +} + diff --git a/NOVA/nova_defs.h b/NOVA/nova_defs.h index fdad7f22..fec481ae 100644 --- a/NOVA/nova_defs.h +++ b/NOVA/nova_defs.h @@ -23,6 +23,7 @@ be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. + 22-Nov-03 CEO Added support for PIT device 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 @@ -174,6 +175,7 @@ #define DEV_ADCV 030 /* A/D converter */ #define DEV_DKP 033 /* disk pack */ #define DEV_CAS 034 /* cassette */ +#define DEV_PIT 043 /* programmable interval timer */ #define DEV_TTI1 050 /* second console input */ #define DEV_TTO1 051 /* second console output */ #define DEV_CPU 077 /* CPU control */ @@ -211,6 +213,7 @@ typedef struct nova_dib DIB; Priority (for INTA) runs from low numbers to high */ +#define INT_V_PIT 2 /* PIT */ #define INT_V_DKP 3 /* moving head disk */ #define INT_V_DSK 4 /* fixed head disk */ #define INT_V_MTA 5 /* magnetic tape */ @@ -227,6 +230,7 @@ typedef struct nova_dib DIB; #define INT_V_NO_ION_PENDING 16 /* ion delay */ #define INT_V_ION 17 /* interrupts on */ +#define INT_PIT (1 << INT_V_PIT) #define INT_DKP (1 << INT_V_DKP) #define INT_DSK (1 << INT_V_DSK) #define INT_MTA (1 << INT_V_MTA) @@ -247,6 +251,7 @@ typedef struct nova_dib DIB; /* PI disable bits */ +#define PI_PIT 0001000 #define PI_DKP 0000400 #define PI_DSK 0000100 #define PI_MTA 0000040 diff --git a/NOVA/nova_dkp.c b/NOVA/nova_dkp.c index 9dd91026..20e139ff 100644 --- a/NOVA/nova_dkp.c +++ b/NOVA/nova_dkp.c @@ -25,6 +25,9 @@ dkp moving head disk + 28-Nov-03 CEO Boot from DP now puts device address in SR + 24-Nov-03 CEO Added support for disk sizing on 6099/6103 + 19-Nov-03 CEO Corrected major DMA Mapping bug 25-Apr-03 RMS Revised autosizing 08-Oct-02 RMS Added DIB 06-Jan-02 RMS Revised enable/disable support @@ -225,7 +228,7 @@ #define TYPE_6070 8 #define SECT_6070 24 #define SURF_6070 4 -#define CYL_6070 408 +#define CYL_6070 408 #define SIZE_6070 (SECT_6070 * SURF_6070 * CYL_6070 * DKP_NUMWD) #define NFMT_6070 TRUE @@ -278,11 +281,13 @@ extern UNIT cpu_unit; extern int32 int_req, dev_busy, dev_done, dev_disable; int32 dkp_ma = 0; /* memory address */ +int32 dkp_map = 0; /* DCH map 0=A 3=B */ 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 */ +int32 dkp_diagmode = 0; /* diagnostic mode */ DEVICE dkp_dev; int32 dkp (int32 pulse, int32 code, int32 AC); @@ -322,6 +327,8 @@ REG dkp_reg[] = { { FLDATA (BUSY, dev_busy, INT_V_DKP) }, { FLDATA (DONE, dev_done, INT_V_DKP) }, { FLDATA (DISABLE, dev_disable, INT_V_DKP) }, + { FLDATA (DIAG, dkp_diagmode, 0) }, + { ORDATA (MAP, dkp_map, 2) }, { 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, @@ -452,22 +459,32 @@ case ioDIA: /* DIA */ rval = dkp_sta; break; case ioDOA: /* DOA */ + if (AC & 0100000) /* clear rw done? */ + dkp_sta = dkp_sta & ~(STA_CYL|STA_XCY|STA_UNS|STA_CRC); if ((dev_busy & INT_DKP) == 0) { dkp_fccy = AC; /* save cmd, cyl */ dkp_sta = dkp_sta & ~(AC & FCCY_FLAGS); } + if ((dkp_sta & STA_DFLGS) == 0) /* done flags = 0? */ + dev_done = dev_done & ~INT_DKP; /* clear intr */ 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); + if ((dev_busy & INT_DKP) == 0) { + dkp_ma = AC & (drv_tab[dtype].newf? DMASK: AMASK); + if (AC & 0100000) dkp_map = 3; /* high bit is map */ + else dkp_map = 0; + } 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 */ + if (((dtype == TYPE_6099) || /* for 6099 and 6103 */ + (dtype == TYPE_6103)) && /* if data<0> set, */ + AC & 010000) dkp_diagmode = 1; /* set diagnostic mode */ break; } /* end switch code */ /* IOT, continued */ @@ -478,7 +495,14 @@ 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? */ + if (dkp_diagmode) { /* in diagnostic mode? */ + dkp_diagmode = 0; /* reset it */ + if (dtype == TYPE_6099) dkp_ussc = 010002; /* return size bits */ + if (dtype == TYPE_6103) dkp_ussc = 010003; /* for certain types */ + } + else { /* normal mode ... */ + 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); @@ -558,6 +582,13 @@ static uint16 tbuf[DKP_NUMWD]; /* transfer buffer */ rval = SCPE_OK; dtype = GET_DTYPE (uptr->flags); /* get drive type */ +if (dkp_diagmode) { /* diagnostic mode? */ + dkp_sta = (dkp_sta | STA_DONE); /* Set error bit only */ + 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 SCPE_OK; /* do not do function */ + } if (uptr->FUNC == FCCY_SEEK) { /* seek? */ if (uptr->CYL >= drv_tab[dtype].cyl) /* bad cylinder? */ dkp_sta = dkp_sta | STA_ERR | STA_CYL; @@ -597,14 +628,14 @@ else { sc = 16 - GET_COUNT (dkp_ussc); /* get sector count */ 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); + pa = MapAddr (dkp_map, (dkp_ma & AMASK)); 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); + pa = MapAddr (dkp_map, (dkp_ma & AMASK)); tbuf[dx] = M[pa]; dkp_ma = (dkp_ma + 1) & AMASK; } fxwrite (tbuf, sizeof(int16), DKP_NUMWD, uptr->fileref); @@ -641,6 +672,8 @@ 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 */ +dkp_diagmode = 0; /* clear diagnostic mode */ +dkp_map = 0; for (u = 0; u < DKP_NUMDR; u++) { /* loop thru units */ uptr = dkp_dev.units + u; sim_cancel (uptr); /* cancel activity */ @@ -685,33 +718,33 @@ return SCPE_OK; #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 */ + 0060233, /* NIOC 0,DKP ; clear disk */ + 0020420, /* LDA 0,USSC ; unit, sfc, sec, cnt */ + 0063033, /* DOC 0,DKP ; select disk */ + 0020417, /* LDA 0,SEKCMD ; command, cylinder */ + 0061333, /* DOAP 0,DKP ; start seek */ + 0024415, /* LDA 1,SEKDN */ + 0060433, /* DIA 0,DKP ; get status */ 0123415, /* AND# 1,0,SZR ; skip if done */ - 000776, /* JMP .-2 */ + 0000776, /* 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 */ + 0062033, /* DOB 0,DKP */ + 0020411, /* LDA 0,REDCMD ; command, cylinder */ + 0061133, /* DOAS 0,DKP ; start read */ + 0060433, /* 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 */ + 0000776, /* JMP .-2 */ + 0000377, /* JMP 377 */ + 0000016, /* USSC: 0.B1+0.B7+0.B11+16 */ 0175000, /* SEKCMD: 175000 */ - 074000, /* SEKDN: 074000 */ + 0074000, /* SEKDN: 074000 */ 0174000 /* REDCMD: 174000 */ }; t_stat dkp_boot (int32 unitno, DEVICE *dptr) { int32 i, dtype; -extern int32 saved_PC; +extern int32 saved_PC, SR; for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i]; unitno = unitno & USSC_M_UNIT; @@ -719,5 +752,6 @@ 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; +SR = 0100000 + DEV_DKP; return SCPE_OK; } diff --git a/NOVA/nova_doc.txt b/NOVA/nova_doc.txt index b2bd632e..ad0a3872 100644 --- a/NOVA/nova_doc.txt +++ b/NOVA/nova_doc.txt @@ -485,6 +485,8 @@ The moving head disk controller implements these registers: DONE 1 device done flag DISABLE 1 interrupt disable flag INT 1 interrupt pending flag + DIAG 1 diagnostic mode flag + MAP 2 map select STIME 24 seek time, per cylinder RTIME 24 rotational delay diff --git a/NOVA/nova_dsk.c b/NOVA/nova_dsk.c index d1fbc04a..45e1e873 100644 --- a/NOVA/nova_dsk.c +++ b/NOVA/nova_dsk.c @@ -205,6 +205,7 @@ return rval; t_stat dsk_svc (UNIT *uptr) { int32 i, da, pa; +int16 *fbuf = uptr->filebuf; dev_busy = dev_busy & ~INT_DSK; /* clear busy */ dev_done = dev_done | INT_DSK; /* set done */ @@ -218,13 +219,12 @@ 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); } + if (MEM_ADDR_OK (pa)) M[pa] = fbuf[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]; } + fbuf[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; } diff --git a/NOVA/nova_mta.c b/NOVA/nova_mta.c index e965da73..f1b9b659 100644 --- a/NOVA/nova_mta.c +++ b/NOVA/nova_mta.c @@ -25,6 +25,8 @@ mta magnetic tape + 22-Nov-03 CEO DIB returns # records skipped after space fwd + 22-Nov-03 CEO Removed cancel of tape events in IORST 25-Apr-03 RMS Revised for extended file support 28-Mar-03 RMS Added multiformat support 28-Feb-03 RMS Revised for magtape library @@ -397,6 +399,7 @@ case CU_SPACEF: /* space forward */ } while (mta_wc != 0); mta_upddsta (uptr, uptr->USTAT | STA_RDY); + mta_ma = mta_wc; /* Word count = # records */ break; case CU_SPACER: /* space reverse */ @@ -408,6 +411,7 @@ case CU_SPACER: /* space reverse */ } while (mta_wc != 0); mta_upddsta (uptr, uptr->USTAT | STA_RDY); + mta_ma = mta_wc; /* Word count = # records */ break; default: /* reserved */ @@ -503,8 +507,15 @@ 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; + +/* AOS Installer does an IORST after a tape rewind command but before it can + be serviced, yet expects the tape to have been rewound */ + for (u = 0; u < MTA_NUMDR; u++) { /* loop thru units */ uptr = mta_dev.units + u; + if (sim_is_active (uptr) && /* active and */ + (uptr->flags & STA_REW)) /* rewinding? */ + sim_tape_rewind (uptr); /* update tape */ sim_tape_reset (uptr); /* clear pos flag */ sim_cancel (uptr); /* cancel activity */ if (uptr->flags & UNIT_ATT) uptr->USTAT = STA_RDY | @@ -556,34 +567,35 @@ return SCPE_OK; #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 */ + 0060222, /* NIOC 0,MTA ; clear disk */ + 0020417, /* LDA 0,UNIT ; unit */ + 0024417, /* LDA 1,REWIND ; cmd */ 0107000, /* ADD 0,1 ; cmd + unit */ - 065122, /* DOAS 1,MTA ; start rewind */ - 070422, /* DIA 2,MTA ; get status */ + 0065122, /* DOAS 1,MTA ; start rewind */ + 0070422, /* DIA 2,MTA ; get status */ 0151213, /* MOVR# 2,2,SNC ; skip if done */ - 000776, /* JMP .-2 */ + 0000776, /* 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 */ + 0066022, /* DOB 1,MTA */ + 0067022, /* DOC 1,MTA */ + 0061122, /* DOAS 0,MTA ; start read */ + 0070422, /* DIA 2,MTA ; get status */ 0151213, /* MOVR# 2,2,SNC ; skip if done */ - 000776, /* JMP .-2 */ - 000377, /* JMP 377 */ - 000000, /* UNIT: */ - 000010 /* REWIND: 10 */ + 0000776, /* JMP .-2 */ + 0000377, /* JMP 377 */ + 0000000, /* UNIT: */ + 0000010 /* REWIND: 10 */ }; t_stat mta_boot (int32 unitno, DEVICE *dptr) { int32 i; -extern int32 saved_PC; +extern int32 saved_PC, SR; 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; +SR = 0100000 + DEV_MTA; return SCPE_OK; } diff --git a/NOVA/nova_sys.c b/NOVA/nova_sys.c index 6198ad65..3e302a41 100644 --- a/NOVA/nova_sys.c +++ b/NOVA/nova_sys.c @@ -23,6 +23,7 @@ be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. + 24-Nov-03 CEO Added symbolic support for LEF instruction 17-Sep-01 RMS Removed multiconsole support 31-May-01 RMS Added multiconsole support 14-Mar-01 RMS Revised load/dump interface (again) @@ -43,16 +44,23 @@ extern DEVICE cpu_dev; extern UNIT cpu_unit; #if defined (ECLIPSE) extern DEVICE map_dev; +extern DEVICE fpu_dev; +extern DEVICE pit_dev; +extern int32 Usermap; +extern int32 MapStat; #endif -extern DEVICE ptr_dev, ptp_dev; +extern DEVICE ptr_dev; +extern DEVICE 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 tti_dev; +extern DEVICE tto_dev; +extern DEVICE tti1_dev; +extern DEVICE tto1_dev; +extern DEVICE clk_dev; +extern DEVICE lpt_dev; +extern DEVICE dkp_dev; +extern DEVICE 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; @@ -81,13 +89,21 @@ DEVICE *sim_devices[] = { &cpu_dev, #if defined (ECLIPSE) &map_dev, + &fpu_dev, + &pit_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, + &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[] = { @@ -256,7 +272,7 @@ static const char *opcode[] = { "BTO", "BTZ", "SBZ", "SZBO", "LOB", "LRB", "COB", "LDB", "STB", "PSH", "POP", - "LMP", "SYSC", + "LMP", "SYC", "PSHR", "POPB", "BAM", "POPJ", "RTN", "BLM", "DIVX", "MUL", "MULS", "DIV", "DIVS", @@ -366,6 +382,9 @@ static const char *opcode[] = { "DIC", "DICS", "DICC", "DICP", "DOC", "DOCS", "DOCC", "DOCP", "SKPBN", "SKPBZ", "SKPDN", "SKPDZ", +#if defined (ECLIPSE) + "LEF", "LEF", "LEF", "LEF", +#endif NULL }; static const opc_val[] = { @@ -379,7 +398,7 @@ static const opc_val[] = { 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, + 0113410+I_NPN, 0103510+I_2AC, 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, @@ -489,6 +508,9 @@ static const opc_val[] = { 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, +#if defined (ECLIPSE) + 0064000+I_D, 0070000+I_D, 0074000+I_D, 0076000+I_D, +#endif -1 }; static const char *skip[] = { @@ -579,8 +601,8 @@ 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; +c1 = ((int32) val[0] >> 8) & 0177; +c2 = (int32) val[0] & 0177; if (sw & SWMASK ('A')) { /* ASCII? */ fprintf (of, (c2 < 040)? "<%03o>": "%c", c2); return SCPE_OK; } @@ -592,7 +614,7 @@ if (!(sw & SWMASK ('M'))) return SCPE_ARG; /* mnemonic? */ /* Instruction decode */ -inst = val[0]; +inst = (int32) 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? */ @@ -605,8 +627,8 @@ for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */ 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; + extind = (int32) val[1] & A_IND; /* extended fields */ + extdisp = (int32) val[1] & AMASK; for (dv = 0; (dev_val[dv] >= 0) && (dev_val[dv] != dev); dv++) ; switch (j) { /* switch on class */ @@ -617,6 +639,13 @@ for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */ fprintf (of, "%s %-o", opcode[i], dst); break; case I_V_D: /* dev only */ +#if defined (ECLIPSE) + if (Usermap && (MapStat & 0100)) { /* the evil LEF mode */ + fprintf (of, "LEF %-o,", dst); + fprint_addr (of, addr, ind, mode, disp, FALSE, cflag); + break; + } +#endif if (dev_val[dv] >= 0) fprintf (of, "%s %s", opcode[i], device[dv]); else fprintf (of, "%s %-o", opcode[i], dev); @@ -671,7 +700,10 @@ for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */ return -1; case I_V_XP: /* XOP */ fprintf (of, "%s %-o,%-o,%-o", opcode[i], src, dst, xop); - break; } /* end case */ + break; /* end case */ + default: + fprintf (of, "??? [%-o]", inst); + break; } return SCPE_OK; } /* end if */ } /* end for */ return SCPE_ARG; @@ -726,12 +758,12 @@ else if (*cptr == '-') { /* - sign? */ cptr++; } if (*cptr != 0) { /* number? */ cptr = get_glyph (cptr, gbuf, ','); /* get glyph */ - d = get_uint (gbuf, 8, AMASK, &r); + d = (int32) 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); + x = (int32) get_uint (gbuf, 8, I_M_DST, &r); if ((r != SCPE_OK) || (x < 2)) return NULL; pflag = pflag | A_NX; } @@ -786,10 +818,10 @@ char gbuf[CBUFSIZE]; t_stat r; cptr = get_glyph (cptr, gbuf, ','); /* get register */ -val[0] = get_uint (gbuf, 8, I_M_SRC, &r); +val[0] = (int32) 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); +val[1] = (int32) get_uint (gbuf, 8, I_M_DST, &r); if (r != SCPE_OK) return NULL; return cptr; } @@ -837,13 +869,13 @@ 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); + d = (int32) 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); + d = (int32) 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 */ @@ -852,13 +884,13 @@ case I_V_D: /* IOT dev */ (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); + d = (int32) 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); + d = (int32) 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 */ @@ -889,33 +921,33 @@ case I_V_2AC: /* reg, reg */ 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); + d = (int32) 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); + d = (int32) 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); + val[1] = (int32) 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); + d = (int32) 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); + val[1] = (int32) 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); + d = (int32) 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 */ @@ -927,7 +959,7 @@ case I_V_LM: /* long mem */ 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); + d = (int32) 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); @@ -948,7 +980,7 @@ case I_V_XP: /* XOP */ 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); + d = (int32) 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 */ diff --git a/NOVA/nova_tt.c b/NOVA/nova_tt.c index f745b08e..dd1368a7 100644 --- a/NOVA/nova_tt.c +++ b/NOVA/nova_tt.c @@ -1,6 +1,6 @@ /* nova_tt.c: NOVA console terminal simulator - Copyright (c) 1993-2003, Robert M. Supnik + Copyright (c) 1993-2004, Robert M. Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -26,6 +26,7 @@ tti terminal input tto terminal output + 29-Dec-03 RMS Added console backpressure support 25-Apr-03 RMS Revised for extended file support 05-Jan-02 RMS Fixed calling sequence for setmod 03-Oct-02 RMS Added DIBs @@ -188,14 +189,17 @@ return 0; t_stat tto_svc (UNIT *uptr) { -int32 c, temp; +int32 c; +t_stat r; +c = tto_unit.buf & 0177; +if ((tto_unit.flags & UNIT_DASHER) && (c == 031)) c = '\b'; +if ((r = sim_putchar_s (c)) != SCPE_OK) { /* output; error? */ + sim_activate (uptr, uptr->wait); /* try again */ + return ((r == SCPE_STALL)? SCPE_OK: r); } /* !stall? report */ 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; } diff --git a/PDP1/pdp1_defs.h b/PDP1/pdp1_defs.h index e113db12..5f2280ec 100644 --- a/PDP1/pdp1_defs.h +++ b/PDP1/pdp1_defs.h @@ -23,6 +23,8 @@ 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. + 08-Dec-03 RMS Added support for parallel drum + 18-Oct-03 RMS Added DECtape off reel message 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) @@ -36,6 +38,7 @@ Automatic multiply/divide Type 10 Memory extension control Type 15 + Parallel drum Type 23 Serial drum Type 24 Line printer control Type 62 Microtape (DECtape) control Type 550 @@ -51,6 +54,7 @@ #define STOP_XCT 4 /* nested XCT's */ #define STOP_IND 5 /* nested indirects */ #define STOP_WAIT 6 /* IO wait hang */ +#define STOP_DTOFF 7 /* DECtape off reel */ /* Memory */ @@ -92,6 +96,7 @@ #define IOS_V_SQB 11 /* sequence break */ #define IOS_V_PNT 2 /* print done */ #define IOS_V_SPC 1 /* space done */ +#define IOS_V_DRP 0 /* parallel drum busy */ #define IOS_LPN (1 << IOS_V_LPN) #define IOS_PTR (1 << IOS_V_PTR) @@ -102,6 +107,7 @@ #define IOS_SQB (1 << IOS_V_SQB) #define IOS_PNT (1 << IOS_V_PNT) #define IOS_SPC (1 << IOS_V_SPC) +#define IOS_DRP (1 << IOS_V_DRP) /* Completion pulses */ diff --git a/PDP1/pdp1_doc.txt b/PDP1/pdp1_doc.txt index e0fda843..c20fc2c2 100644 --- a/PDP1/pdp1_doc.txt +++ b/PDP1/pdp1_doc.txt @@ -1,7 +1,7 @@ To: Users From: Bob Supnik Subj: PDP-1 Simulator Usage -Date: 15-Sep-2003 +Date: 15-Dec-2003 COPYRIGHT NOTICE @@ -65,6 +65,7 @@ PTR,PTP integral paper tape reader/punch TTY console typewriter LPT Type 62 line printer DRM Type 24 serial drum +DRP Type 23 parallel drum DT Type 550 Microtape (DECtape) The PDP-1 simulator implements the following unique stop conditions: @@ -77,6 +78,7 @@ The PDP-1 simulator implements the following unique stop conditions: instruction execution - I/O wait, and no I/O operations outstanding (i.e, no I/O completion will ever occur) + - a simulated DECtape runs off the end of its reel 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, @@ -302,7 +304,6 @@ The DECtape controller implements these registers: 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 @@ -313,10 +314,19 @@ 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 + - DCTIME needs to be at least 100 times LTIME -2.4 Type 24 Serial Drum (DRM) +Acceleration time is set to 75% of deceleration time. + +2.4 Drums + +The PDP-1 supported two drums: the Type 23 parallel drum (DRP) and +the Type 24 serial drum (DRM). Both use device addresses 061-064; +accordingly, only one can be enabled at a time. By default, the +Type 24 serial drum is enabled, and the Type 23 parallel drum is +disabled. + +2.4.1 Type 24 Serial Drum (DRM) The serial drum (DRM) implements these registers: @@ -324,7 +334,6 @@ The serial drum (DRM) implements these registers: 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 @@ -341,6 +350,35 @@ Error handling is as follows: Drum data files are buffered in memory; therefore, end of file and OS I/O errors cannot occur. +2.4.2 Type 23 Parallel Drum (DRP) + +The parallel drum (DRP) implements these registers: + + name size comments + + TA 12 track address + RDF 5 read field + RDE 1 read enable flag + WRF 5 write field + WRF 1 write enable flag + MA 16 current memory address + WC 12 word count + BUSY 1 device busy flag + ERR 1 error flag + 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 diff --git a/PDP1/pdp1_drm.c b/PDP1/pdp1_drm.c index 1d396723..a7c840be 100644 --- a/PDP1/pdp1_drm.c +++ b/PDP1/pdp1_drm.c @@ -23,8 +23,12 @@ be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. + drp Type 23 parallel drum drm Type 24 serial drum + 08-Dec-03 RMS Added parallel drum support + Fixed bug in DBL/DCN decoding + 26-Oct-03 RMS Cleaned up buffer copy code 23-Jul-03 RMS Fixed incorrect logical, missing activate 05-Dec-02 RMS Cloned from pdp18b_drm.c */ @@ -32,21 +36,36 @@ #include "pdp1_defs.h" #include -/* Constants */ +/* Serial drum 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_SIZE (DRM_NUMTR * DRM_NUMWDT) /* words/drum */ #define DRM_SMASK ((DRM_NUMTR * DRM_NUMSC) - 1) /* sector mask */ +/* Parallel drum constants */ + +#define DRP_NUMWDT 4096 /* words/track */ +#define DRP_NUMTK 32 /* tracks/drum */ +#define DRP_SIZE (DRP_NUMWDT * DRP_NUMTK) /* words/drum */ +#define DRP_V_RWE 17 /* read/write enable */ +#define DRP_V_FLD 12 /* drum field */ +#define DRP_M_FLD 037 +#define DRP_TAMASK 07777 /* track address */ +#define DRP_WCMASK 07777 /* word count */ +#define DRP_MAINCM 07777 /* mem addr incr */ +#define DRP_GETRWE(x) (((x) >> DRP_V_RWE) & 1) +#define DRP_GETRWF(x) (((x) >> DRP_V_FLD) & DRP_M_FLD) + /* Parameters in the unit descriptor */ #define FUNC u4 /* function */ #define DRM_READ 000 /* read */ #define DRM_WRITE 010 /* write */ +#define DRP_RW 000 /* read/write */ +#define DRP_BRK 001 /* break on address */ #define GET_POS(x) ((int) fmod (sim_gtime() / ((double) (x)), \ ((double) DRM_NUMWDT))) @@ -56,15 +75,34 @@ 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 */ +/* Serial drum variables */ + +uint32 drm_da = 0; /* track address */ +uint32 drm_ma = 0; /* memory address */ +uint32 drm_err = 0; /* error flag */ +uint32 drm_wlk = 0; /* write lock */ +int32 drm_time = 4; /* inter-word time */ int32 drm_stopioe = 1; /* stop on error */ +/* Parallel drum variables */ + +uint32 drp_rde = 0; /* read enable */ +uint32 drp_wre = 0; /* write enable */ +uint32 drp_rdf = 0; /* read field */ +uint32 drp_wrf = 0; /* write field */ +uint32 drp_ta = 0; /* track address */ +uint32 drp_wc = 0; /* word count */ +uint32 drp_ma = 0; /* memory address */ +uint32 drp_err = 0; /* error */ +int32 drp_time = 2; /* inter-word time */ +int32 drp_stopioe = 1; /* stop on error */ + +/* Forward declarations */ + t_stat drm_svc (UNIT *uptr); t_stat drm_reset (DEVICE *dptr); +t_stat drp_svc (UNIT *uptr); +t_stat drp_reset (DEVICE *dptr); /* DRM data structures @@ -93,6 +131,38 @@ DEVICE drm_dev = { NULL, NULL, &drm_reset, NULL, NULL, NULL, NULL, DEV_DISABLE }; + +/* DRP data structures + + drp_dev DRP device descriptor + drp_unit DRP unit descriptor + drp_reg DRP register list +*/ + +UNIT drp_unit = + { UDATA (&drp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+UNIT_MUSTBUF, + DRM_SIZE) }; + +REG drp_reg[] = { + { ORDATA (TA, drp_ta, 12) }, + { ORDATA (RDF, drp_rdf, 5) }, + { FLDATA (RDE, drp_rde, 0) }, + { FLDATA (WRF, drp_wrf, 5) }, + { FLDATA (WRE, drp_wre, 0) }, + { ORDATA (MA, drp_ma, 16) }, + { ORDATA (WC, drp_wc, 12) }, + { FLDATA (BUSY, iosta, IOS_V_DRP) }, + { FLDATA (ERR, drp_err, 0) }, + { DRDATA (TIME, drp_time, 24), REG_NZ + PV_LEFT }, + { FLDATA (STOP_IOE, drp_stopioe, 0) }, + { NULL } }; + +DEVICE drp_dev = { + "DRP", &drp_unit, drp_reg, NULL, + 1, 8, 20, 1, 8, 18, + NULL, NULL, &drp_reset, + NULL, NULL, NULL, + NULL, DEV_DISABLE | DEV_DIS }; /* IOT routines */ @@ -101,39 +171,77 @@ 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; +if ((drm_dev.flags & DEV_DIS) == 0) { /* serial enabled? */ + 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 & AMASK; /* load mem addr */ + drm_unit.FUNC = pulse & DRM_WRITE; /* save function */ + break; + case 062: /* DBL, DCN */ + if ((pulse & 010) == 0) /* DBL? */ + 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); + } /* end case */ + return dat; } /* end if serial */ + +if ((drp_dev.flags & DEV_DIS) == 0) { /* parallel enabled? */ + switch (dev) { /* switch on device */ + case 061: /* DIA, DBA */ + drp_err = 0; /* clear error */ + iosta = iosta & ~IOS_DRP; /* not busy */ + drp_rde = DRP_GETRWE (dat); /* set read enable */ + drp_rdf = DRP_GETRWF (dat); /* set read field */ + drp_ta = dat & DRP_TAMASK; /* set track addr */ + if (IR & 02000) { /* DBA? */ + t = drp_ta - GET_POS (drp_time); /* delta words */ + if (t <= 0) t = t + DRP_NUMWDT; /* wrap around? */ + sim_activate (&drp_unit, t); /* start operation */ + drp_unit.FUNC = DRP_BRK; } /* mark as break */ + else drp_unit.FUNC = DRP_RW; /* no, read/write */ + break; + case 062: /* DWC, DRA */ + if (IR & 02000) dat = GET_POS (drp_time) | /* DRA, get position */ + (drp_err? 0400000: 0); + else { /* DWC */ + drp_wre = DRP_GETRWE (dat); /* set write enable */ + drp_wrf = DRP_GETRWF (dat); /* set write field */ + drp_wc = dat & DRP_WCMASK; } /* set word count */ + break; + case 063: /* DCL */ + drp_ma = dat & AMASK; /* set mem address */ + t = drp_ta - GET_POS (drp_time); /* delta words */ + if (t <= 0) t = t + DRP_NUMWDT; /* wrap around? */ + sim_activate (&drp_unit, t); /* start operation */ + iosta = iosta | IOS_DRP; /* set busy */ + break; + case 064: /* not assigned */ + return (stop_inst << IOT_V_REASON) | dat; /* stop if requested */ + } /* end case */ + return dat; } /* end if parallel */ + +return (stop_inst << IOT_V_REASON) | dat; /* stop if requested */ } -/* Unit service - this code assumes the entire drum is buffered */ +/* Serial unit service - this code assumes the entire drum is buffered */ t_stat drm_svc (UNIT *uptr) { uint32 i, da; +uint32 *fbuf = uptr->filebuf; if ((uptr->flags & UNIT_BUF) == 0) { /* not buf? abort */ drm_err = 1; /* set error */ @@ -143,15 +251,15 @@ if ((uptr->flags & UNIT_BUF) == 0) { /* not buf? abort */ da = drm_da * DRM_NUMWDS; /* compute dev addr */ for (i = 0; i < DRM_NUMWDS; i++, da++) { /* do transfer */ - if (uptr->FUNC == DRM_READ) { - if (MEM_ADDR_OK (drm_ma)) /* read, check nxm */ - M[drm_ma] = *(((int32 *) uptr->filebuf) + da); } - else { + if (uptr->FUNC == DRM_READ) { /* read? */ + if (MEM_ADDR_OK (drm_ma)) /* if !nxm */ + M[drm_ma] = fbuf[da]; } /* read word */ + else { /* write */ if ((drm_wlk >> (drm_da >> 4)) & 1) drm_err = 1; - else { - *(((int32 *) uptr->filebuf) + da) = M[drm_ma]; + else { /* not locked */ + fbuf[da] = M[drm_ma]; /* write word */ if (da >= uptr->hwmark) uptr->hwmark = da + 1; } } - drm_ma = (drm_ma + 1) & 0177777; } /* incr mem addr */ + drm_ma = (drm_ma + 1) & AMASK; } /* 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 */ @@ -162,8 +270,57 @@ return SCPE_OK; t_stat drm_reset (DEVICE *dptr) { +if ((drm_dev.flags & DEV_DIS) == 0) + drp_dev.flags = drp_dev.flags | DEV_DIS; drm_da = drm_ma = drm_err = 0; iosta = iosta & ~IOS_DRM; sim_cancel (&drm_unit); +drm_unit.FUNC = 0; +return SCPE_OK; +} + +/* Parallel unit service - this code assumes the entire drum is buffered */ + +t_stat drp_svc (UNIT *uptr) +{ +uint32 i, lim; +uint32 *fbuf = uptr->filebuf; + +if ((uptr->flags & UNIT_BUF) == 0) { /* not buf? abort */ + drp_err = 1; /* set error */ + iosta = iosta & ~IOS_DRP; /* clear busy */ + if (uptr->FUNC) sbs = sbs | SB_RQ; /* req intr */ + return IORETURN (drp_stopioe, SCPE_UNATT); } + +if (uptr->FUNC == DRP_RW) { /* read/write? */ + lim = drp_wc? drp_wc: DRP_TAMASK + 1; /* eff word count */ + for (i = 0; i < lim; i++) { /* do transfer */ + if (drp_wre) /* write enabled? */ + fbuf[(drp_wrf << DRP_V_FLD) | drp_ta] = M[drp_ma]; + if (drp_rde && MEM_ADDR_OK (drp_ma)) /* read enabled? */ + M[drp_ma] = fbuf[(drp_rdf << DRP_V_FLD) | drp_ta]; + drp_ta = (drp_ta + 1) & DRP_TAMASK; /* incr track addr */ + drp_ma = ((drp_ma & ~DRP_MAINCM) | ((drp_ma + 1) & DRP_MAINCM)); + } /* end for */ + } /* end if */ +iosta = iosta & ~IOS_DRP; /* clear busy */ +if (uptr->FUNC) sbs = sbs | SB_RQ; /* req intr */ +return SCPE_OK; +} + +/* Reset routine */ + +t_stat drp_reset (DEVICE *dptr) +{ +if ((drp_dev.flags & DEV_DIS) == 0) + drm_dev.flags = drm_dev.flags | DEV_DIS; +drp_ta = 0; +drp_rde = drp_rdf = drp_wre = drp_wrf = 0; +drp_err = 0; +drp_ma = 0; +drp_wc = 0; +iosta = iosta & ~IOS_DRP; +sim_cancel (&drp_unit); +drp_unit.FUNC = 0; return SCPE_OK; } diff --git a/PDP1/pdp1_dt.c b/PDP1/pdp1_dt.c index bbafc553..7b9f379a 100644 --- a/PDP1/pdp1_dt.c +++ b/PDP1/pdp1_dt.c @@ -25,6 +25,8 @@ dt Type 550/555 DECtape + 26-Oct-03 RMS Cleaned up buffer copy code + 18-Oct-03 RMS Added DECtape off reel message, simplified timing 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 @@ -41,13 +43,16 @@ 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 + Tape density is nominally 300 lines per inch. The format of a DECtape (as + taken from the TD8E formatter) is: - reverse end zone 36000 lines ~ 10 feet + reverse end zone 8192 reverse end zone codes ~ 10 feet + reverse buffer 200 interblock codes block 0 : block n - forward end zone 36000 lines ~ 10 feet + forward buffer 200 interblock codes + forward end zone 8192 forward end zone codes ~ 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 @@ -64,9 +69,9 @@ header word 0 0 header word 1 block number (for forward reads) header words 2,3 0 - header word 4 0 + header word 4 checksum (for reverse reads) : - trailer word 4 checksum + trailer word 4 checksum (for forward reads) trailer words 3,2 0 trailer word 1 block number (for reverse reads) trailer word 0 0 @@ -97,13 +102,15 @@ /* 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 */ +#define DT_LPERMC 6 /* lines per mark track */ +#define DT_BLKWD 1 /* blk no word in h/t */ +#define DT_CSMWD 4 /* checksum word in h/t */ +#define DT_HTWRD 5 /* header/trailer words */ +#define DT_EZLIN (8192 * DT_LPERMC) /* end zone length */ +#define DT_BFLIN (200 * DT_LPERMC) /* buffer length */ +#define DT_BLKLN (DT_BLKWD * DT_LPERMC) /* blk no line in h/t */ +#define DT_CSMLN (DT_CSMWD * DT_LPERMC) /* csum line in h/t */ +#define DT_HTLIN (DT_HTWRD * DT_LPERMC) /* header/trailer lines */ /* 16b, 18b, 36b DECtape constants */ @@ -249,8 +256,7 @@ 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_dctime = 40000; /* decel time */ int32 dt_substate = 0; int32 dt_log = 0; int32 dt_logblk = 0; @@ -306,7 +312,6 @@ REG dt_reg[] = { { 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 }, @@ -441,7 +446,7 @@ 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 */ + sim_activate (uptr, dt_dctime - (dt_dctime >> 2)); /* sched accel */ DTS_SETSTA (DTS_ACCF | new_dir, 0); /* state = accel */ DTS_SET2ND (DTS_ATSF | new_dir, new_fnc); /* next = fnc */ return; } @@ -467,7 +472,7 @@ if (prev_dir ^ new_dir) { /* dir chg? */ 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 */ + sim_activate (uptr, dt_dctime - (dt_dctime >> 2)); /* sched accel */ DTS_SETSTA (DTS_ACCF | new_dir, 0); /* state = accel */ DTS_SET2ND (DTS_ATSF | new_dir, new_fnc); /* next = fnc */ return; } @@ -588,11 +593,13 @@ case DTS_STOP: /* stop */ delta = 0; break; case DTS_DECF: /* slowing */ - ulin = ut / (uint32) dt_ltime; udelt = dt_dctime / dt_ltime; + 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; + ulin = ut / (uint32) dt_ltime; + udelt = (dt_dctime - (dt_dctime >> 2)) / dt_ltime; delta = (ulin * ulin) / (2 * udelt); break; case DTS_ATSF: /* at speed */ @@ -621,7 +628,7 @@ 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 *fbuf = uptr->filebuf; int32 unum = uptr - dt_dev.units; int32 blk, wrd, ma, relpos; uint32 ba; @@ -635,10 +642,10 @@ uint32 ba; switch (mot) { case DTS_DECF: case DTS_DECR: /* decelerating */ - if (dt_setpos (uptr)) return SCPE_OK; /* update pos */ + if (dt_setpos (uptr)) return STOP_DTOFF; /* update pos */ uptr->STATE = DTS_NXTSTA (uptr->STATE); /* advance state */ if (uptr->STATE) /* not stopped? */ - sim_activate (uptr, dt_actime); /* must be reversing */ + sim_activate (uptr, dt_dctime - (dt_dctime >> 2)); /* reversing */ return SCPE_OK; case DTS_ACCF: case DTS_ACCR: /* accelerating */ dt_newfnc (uptr, DTS_NXTSTA (uptr->STATE)); /* adv state, sched */ @@ -656,7 +663,7 @@ default: /* other */ Off reel - detach unit (it must be deselected) */ -if (dt_setpos (uptr)) return SCPE_OK; /* update pos */ +if (dt_setpos (uptr)) return STOP_DTOFF; /* update pos */ if (DT_QEZ (uptr)) { /* in end zone? */ dt_seterr (uptr, DTB_END); /* end zone error */ return SCPE_OK; } @@ -693,7 +700,7 @@ case FNC_READ: case FNC_RALL: (relpos < (DTU_LPERB (uptr) - DT_HTLIN))) { wrd = DT_LIN2WD (uptr->pos, uptr); ba = (blk * DTU_BSIZE (uptr)) + wrd; - dtdb = bptr[ba]; /* get tape word */ + dtdb = fbuf[ba]; /* get tape word */ dtsb = dtsb | DTB_DTF; } /* set flag */ else { ma = (2 * DT_HTWRD) + DTU_BSIZE (uptr) - DT_CSMWD - 1; @@ -722,8 +729,8 @@ case FNC_WRIT: case FNC_WALL: (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 (dir) fbuf[ba] = dt_comobv (dtdb); /* get data word */ + else fbuf[ba] = dtdb; if (ba >= uptr->hwmark) uptr->hwmark = ba + 1; if (wrd == (dir? 0: DTU_BSIZE (uptr) - 1)) dtsb = dtsb | DTB_BEF; /* end block */ @@ -791,13 +798,13 @@ return dat; int32 dt_csum (UNIT *uptr, int32 blk) { -int32 *bptr = uptr->filebuf; +int32 *fbuf = 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 */ + wrd = fbuf[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 */ @@ -868,7 +875,7 @@ t_stat dt_attach (UNIT *uptr, char *cptr) { uint16 pdp8b[D8_NBSIZE]; uint16 pdp11b[D18_BSIZE]; -uint32 ba, sz, k, *bptr; +uint32 ba, sz, k, *fbuf; int32 u = uptr - dt_dev.units; t_stat r; @@ -891,7 +898,7 @@ 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 */ +fbuf = 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"); @@ -903,9 +910,9 @@ if (uptr->flags & UNIT_8FMT) { /* 12b? */ 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) | + fbuf[ba] = ((uint32) (pdp8b[k] & 07777) << 6) | ((uint32) (pdp8b[k + 1] >> 6) & 077); - bptr[ba + 1] = ((uint32) (pdp8b[k + 1] & 077) << 12) | + fbuf[ba + 1] = ((uint32) (pdp8b[k + 1] & 077) << 12) | (pdp8b[k + 2] & 07777); ba = ba + 2; } /* end blk loop */ } /* end file loop */ @@ -916,7 +923,7 @@ else if (uptr->flags & UNIT_11FMT) { /* 16b? */ if (k == 0) break; for ( ; k < D18_BSIZE; k++) pdp11b[k] = 0; for (k = 0; k < D18_BSIZE; k++) - bptr[ba++] = pdp11b[k]; } + fbuf[ba++] = pdp11b[k]; } uptr->hwmark = ba; } /* end elif */ else uptr->hwmark = fxread (uptr->filebuf, sizeof (int32), uptr->capac, uptr->fileref); @@ -939,27 +946,27 @@ t_stat dt_detach (UNIT* uptr) { uint16 pdp8b[D8_NBSIZE]; uint16 pdp11b[D18_BSIZE]; -uint32 ba, k, *bptr; +uint32 ba, k, *fbuf; int32 u = uptr - dt_dev.units; -if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; +if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; /* attached? */ 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 */ +fbuf = 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; + pdp8b[k] = (fbuf[ba] >> 6) & 07777; + pdp8b[k + 1] = ((fbuf[ba] & 077) << 6) | + ((fbuf[ba + 1] >> 12) & 077); + pdp8b[k + 2] = fbuf[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 */ @@ -967,7 +974,7 @@ if (uptr->hwmark && ((uptr->flags & UNIT_RO) == 0)) { /* any data? */ 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; + pdp11b[k] = fbuf[ba++] & 0177777; fxwrite (pdp11b, sizeof (int16), D18_BSIZE, uptr->fileref); if (ferror (uptr->fileref)) break; } /* end loop file */ } /* end if 16b */ diff --git a/PDP1/pdp1_lp.c b/PDP1/pdp1_lp.c index d2c2fc2e..b57e4728 100644 --- a/PDP1/pdp1_lp.c +++ b/PDP1/pdp1_lp.c @@ -143,27 +143,27 @@ if (cpls & CPLS_LPT) { /* completion pulse? */ 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? */ + if ((uptr->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? */ + fputs (lpt_cc[lpt_spc & 07], uptr->fileref); /* print cctl */ + if (ferror (uptr->fileref)) { /* error? */ perror ("LPT I/O error"); - clearerr (lpt_unit.fileref); + clearerr (uptr->fileref); return SCPE_IOERR; } lpt_ovrpr = 0; } /* dont overprint */ else { iosta = iosta | IOS_PNT; /* print */ - if ((lpt_unit.flags & UNIT_ATT) == 0) /* attached? */ + if ((uptr->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 */ + if (lpt_ovrpr) fputc ('\r', uptr->fileref); /* overprint? */ + fputs (lpt_buf, uptr->fileref); /* print buffer */ + if (ferror (uptr->fileref)) { /* test error */ perror ("LPT I/O error"); - clearerr (lpt_unit.fileref); + clearerr (uptr->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 */ +lpt_unit.pos = ftell (uptr->fileref); /* update position */ return SCPE_OK; } diff --git a/PDP1/pdp1_stddev.c b/PDP1/pdp1_stddev.c index 98f95aa8..ed211419 100644 --- a/PDP1/pdp1_stddev.c +++ b/PDP1/pdp1_stddev.c @@ -28,6 +28,7 @@ tti keyboard tto teleprinter + 29-Oct-03 RMS Added PTR FIODEC-to-ASCII translation (from Phil Budne) 07-Sep-03 RMS Changed ioc to ios 30-Aug-03 RMS Revised PTR to conform to Maintenance Manual; added deadlock prevention on errors @@ -42,10 +43,14 @@ 07-Sep-01 RMS Moved function prototypes 10-Jun-01 RMS Fixed comment 30-Oct-00 RMS Standardized device naming + + Note: PTP timeout must be >10X faster that TTY output timeout for Macro + to work correctly! */ #include "pdp1_defs.h" +#define FIODEC_STOP 013 /* stop code */ #define FIODEC_UC 074 #define FIODEC_LC 072 #define UC_V 6 /* upper case */ @@ -55,10 +60,16 @@ #define TT_WIDTH 077 #define TTI 0 #define TTO 1 +#define UNIT_V_ASCII (UNIT_V_UF + 0) /* ASCII/binary mode */ +#define UNIT_ASCII (1 << UNIT_V_ASCII) +#define PTR_LEADER 20 /* ASCII leader chars */ int32 ptr_state = 0; int32 ptr_wait = 0; int32 ptr_stopioe = 0; +int32 ptr_uc = 0; /* upper/lower case */ +int32 ptr_hold = 0; /* holding buffer */ +int32 ptr_leader = PTR_LEADER; /* leader count */ int32 ptp_stopioe = 0; int32 tti_hold = 0; /* tti hold buf */ int32 tty_buf = 0; /* tty buffer */ @@ -68,6 +79,7 @@ extern int32 sbs, ios, ioh, cpls, iosta; extern int32 PF, IO, PC, TA; extern int32 M[]; +int ptr_get_ascii (UNIT *uptr); t_stat ptr_svc (UNIT *uptr); t_stat ptp_svc (UNIT *uptr); t_stat tti_svc (UNIT *uptr); @@ -76,6 +88,7 @@ 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); +t_stat ptr_attach (UNIT *uptr, char *cptr); /* Character translation tables */ @@ -128,20 +141,28 @@ UNIT ptr_unit = { REG ptr_reg[] = { { ORDATA (BUF, ptr_unit.buf, 18) }, + { FLDATA (UC, ptr_uc, UC_V) }, { FLDATA (DONE, iosta, IOS_V_PTR) }, { FLDATA (RPLS, cpls, CPLS_V_PTR) }, + { ORDATA (HOLD, ptr_hold, 9), REG_HRO }, { 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 }, + { DRDATA (LEADER, ptr_leader, 6), REG_HRO }, { FLDATA (STOP_IOE, ptr_stopioe, 0) }, { NULL } }; +MTAB ptr_mod[] = { + { UNIT_ASCII, UNIT_ASCII, "ASCII", "ASCII", NULL }, + { UNIT_ASCII, 0, "FIODEC", "FIODEC", NULL }, + { 0 } }; + DEVICE ptr_dev = { - "PTR", &ptr_unit, ptr_reg, NULL, + "PTR", &ptr_unit, ptr_reg, ptr_mod, 1, 10, 31, 1, 8, 8, NULL, NULL, &ptr_reset, - &ptr_boot, NULL, NULL, + &ptr_boot, &ptr_attach, NULL, NULL, 0 }; /* PTP data structures @@ -179,7 +200,7 @@ DEVICE ptp_dev = { UNIT tty_unit[] = { { UDATA (&tti_svc, 0, 0), KBD_POLL_WAIT }, - { UDATA (&tto_svc, 0, 0), SERIAL_OUT_WAIT } }; + { UDATA (&tto_svc, 0, 0), SERIAL_OUT_WAIT * 10 } }; REG tty_reg[] = { { ORDATA (BUF, tty_buf, 6) }, @@ -240,35 +261,74 @@ t_stat ptr_svc (UNIT *uptr) { int32 temp; -if ((ptr_unit.flags & UNIT_ATT) == 0) { /* attached? */ +if ((uptr->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 ((uptr->flags & UNIT_ASCII) && (ptr_state == 0)) /* ASCII mode, alpha read? */ + temp = ptr_get_ascii (uptr); /* get processed char */ +else if ((temp = getc (uptr->fileref)) != EOF) /* no, get raw char */ + uptr->pos = uptr->pos + 1; /* if not eof, count */ +if (temp == EOF) { /* end of file? */ if (ptr_wait) ptr_wait = ioh = 0; /* if wait, clr ioh */ - if (feof (ptr_unit.fileref)) { + if (feof (uptr->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); + clearerr (uptr->fileref); return SCPE_IOERR; } -ptr_unit.pos = ptr_unit.pos + 1; -if (ptr_state == 0) ptr_unit.buf = temp & 0377; /* alpha */ +if (ptr_state == 0) uptr->buf = temp & 0377; /* alpha */ else if (temp & 0200) { /* binary */ ptr_state = ptr_state - 6; - ptr_unit.buf = ptr_unit.buf | ((temp & 077) << ptr_state); } + uptr->buf = uptr->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 */ + IO = uptr->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 */ +else sim_activate (uptr, uptr->wait); /* get next char */ return SCPE_OK; } + +/* Read next ASCII character */ + +int ptr_get_ascii (UNIT *uptr) +{ +int c; +int32 in; + +if (ptr_leader > 0) { /* leader? */ + ptr_leader = ptr_leader - 1; /* count down */ + return 0; } +if (ptr_hold & CW) { /* char waiting? */ + in = ptr_hold & TT_WIDTH; /* return char */ + ptr_hold = 0; } /* not waiting */ +else { for (;;) { /* until valid char */ + if ((c = getc (uptr->fileref)) == EOF) /* get next char, EOF? */ + return FIODEC_STOP; /* return STOP */ + uptr->pos = uptr->pos + 1; /* count char */ + c = c & 0177; /* cut to 7b */ + if (c == '\n') c = '\r'; /* NL -> CR */ + else if (c == '\r') continue; /* ignore CR */ + in = ascii_to_fiodec[c]; /* convert char */ + if ((in == 0) && (c != ' ')) continue; /* ignore unknowns */ + if ((in & BOTH) || ((in & UC) == ptr_uc)) /* case match? */ + in = in & TT_WIDTH; /* cut to 6b */ + else { /* no, case shift */ + ptr_hold = in | CW; /* set char waiting */ + ptr_uc = in & UC; /* set case */ + in = ptr_uc? FIODEC_UC: FIODEC_LC; } /* return case */ + break; } + } /* end else */ +in = in * 010040201; /* even parity from */ +in = in | 027555555400; /* HACKMEM 167 */ +in = in % (9 << 7); +return in & 0377; +} /* Reset routine */ @@ -276,6 +336,8 @@ t_stat ptr_reset (DEVICE *dptr) { ptr_state = 0; /* clear state */ ptr_wait = 0; +ptr_hold = 0; +ptr_uc = 0; ptr_unit.buf = 0; cpls = cpls & ~CPLS_PTR; iosta = iosta & ~IOS_PTR; /* clear flag */ @@ -283,6 +345,14 @@ sim_cancel (&ptr_unit); /* deactivate unit */ return SCPE_OK; } +/* Attach routine */ + +t_stat ptr_attach (UNIT *uptr, char *cptr) +{ +ptr_leader = PTR_LEADER; /* set up leader */ +return attach_unit (uptr, cptr); +} + /* Bootstrap routine */ int32 ptr_getw (UNIT *uptr) @@ -341,13 +411,13 @@ if (cpls & CPLS_PTP) { /* completion pulse? */ 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? */ +if ((uptr->flags & UNIT_ATT) == 0) /* not attached? */ return IORETURN (ptp_stopioe, SCPE_UNATT); -if (putc (ptp_unit.buf, ptp_unit.fileref) == EOF) { /* I/O error? */ +if (putc (uptr->buf, uptr->fileref) == EOF) { /* I/O error? */ perror ("PTP I/O error"); - clearerr (ptp_unit.fileref); + clearerr (uptr->fileref); return SCPE_IOERR; } -ptp_unit.pos = ptp_unit.pos + 1; +uptr->pos = uptr->pos + 1; return SCPE_OK; } @@ -417,24 +487,22 @@ return SCPE_OK; t_stat tto_svc (UNIT *uptr) { -int32 out; +int32 c; +t_stat r; +if (tty_buf == FIODEC_UC) tty_uc = UC; /* upper case? */ +else if (tty_buf == FIODEC_LC) tty_uc = 0; /* lower case? */ +else { c = fiodec_to_ascii[tty_buf | tty_uc]; /* translate */ + if (c && ((r = sim_putchar_s (c)) != SCPE_OK)) {/* output; error? */ + sim_activate (uptr, uptr->wait); /* retry */ + return ((r == SCPE_STALL)? SCPE_OK: r); } } 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 */ +if (c == '\r') { /* cr? add lf */ sim_putchar ('\n'); uptr->pos = uptr->pos + 1; } return SCPE_OK; diff --git a/PDP1/pdp1_sys.c b/PDP1/pdp1_sys.c index 4a30a798..87946792 100644 --- a/PDP1/pdp1_sys.c +++ b/PDP1/pdp1_sys.c @@ -23,6 +23,8 @@ 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. + 08-Dec-03 RMS Added parallel drum support, drum mnemonics + 18-Oct-03 RMS Added DECtape off reel message 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 @@ -48,6 +50,7 @@ extern DEVICE tty_dev; extern DEVICE lpt_dev; extern DEVICE dt_dev; extern DEVICE drm_dev; +extern DEVICE drp_dev; extern UNIT cpu_unit; extern REG cpu_reg[]; extern int32 M[]; @@ -80,6 +83,7 @@ DEVICE *sim_devices[] = { &lpt_dev, &dt_dev, &drm_dev, + &drp_dev, NULL }; const char *sim_stop_messages[] = { @@ -89,11 +93,12 @@ const char *sim_stop_messages[] = { "Breakpoint", "Nested XCT's", "Nested indirect addresses", - "Infinite I/O wait state" }; + "Infinite I/O wait state", + "DECtape off reel" }; /* Binary loader - supports both RIM format and Macro block format */ -int32 getw (FILE *inf) +int32 pdp1_getw (FILE *inf) { int32 i, tmp, word; @@ -111,11 +116,11 @@ t_stat rim_load (FILE *inf, int32 fld) int32 origin, val; for (;;) { - if ((val = getw (inf)) < 0) return SCPE_FMT; + if ((val = pdp1_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; + if ((val = pdp1_getw (inf)) < 0) return SCPE_FMT; M[fld | origin] = val; } else if ((val & 0760000) == OP_JMP) { /* JMP? */ PC = fld | (val & DAMASK); @@ -130,23 +135,23 @@ 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 = pdp1_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 = pdp1_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; + if ((val = pdp1_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 = pdp1_getw (inf)) < 0) return SCPE_FMT; if (val != csum) return SCPE_CSUM; } else if ((val & 0760000) == OP_JMP) { /* JMP? */ PC = fld | (val & DAMASK); @@ -213,6 +218,9 @@ static const char *opcode[] = { "LSM", "ESM", "CBS", "LEM", "EEM", "CKS", "MSE", "MLC", "MRD", "MWR", "MRS", + "DIA", "DBA", "DWC", "DRA", "DCL", + "DRD", "DWR", "DBL", "DCN", + "DTD", "DSE", "DSP", "SKP", "SKP I", "CLO", "SFT", "LAW", "OPR", @@ -265,6 +273,9 @@ static const int32 opc_val[] = { 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, + 0720061+I_NPN, 0722061+I_NPN, 0720062+I_NPN, 0722062+I_NPN, 0720063+I_NPN, + 0720161+I_NPN, 0721161+I_NPN, 0720162+I_NPN, 0721162+I_NPN, + 0720163+I_NPN, 0720164+I_NPN, 0721164+I_NPN, 0640000+I_NPN, 0650000+I_NPN, 0651600+I_NPN, 0660000+I_NPN, 0700000+I_LAW, 0760000+I_NPN, diff --git a/PDP10/pdp10_defs.h b/PDP10/pdp10_defs.h index a92ef0d0..c4d42286 100644 --- a/PDP10/pdp10_defs.h +++ b/PDP10/pdp10_defs.h @@ -1,6 +1,6 @@ /* pdp10_defs.h: PDP-10 simulator definitions - Copyright (c) 1993-2003, Robert M Supnik + Copyright (c) 1993-2004, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -23,6 +23,7 @@ be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. + 29-Dec-03 RMS Added Q18 definition for PDP11 compatibility 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 @@ -609,9 +610,11 @@ typedef struct pdp_dib DIB; #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_V_Q18 (DEV_V_UF + 2) /* Qbus, mem <= 256KB */ +#define DEV_V_FLTA (DEV_V_UF + 3) /* float addr */ #define DEV_UBUS (1u << DEV_V_UBUS) #define DEV_QBUS (1u << DEV_V_QBUS) +#define DEV_Q18 (1u << DEV_V_Q18) #define DEV_FLTA (1u << DEV_V_FLTA) #define UNIBUS TRUE /* 18b only */ diff --git a/PDP10/pdp10_fe.c b/PDP10/pdp10_fe.c index e0f9d1cf..0bc74579 100644 --- a/PDP10/pdp10_fe.c +++ b/PDP10/pdp10_fe.c @@ -1,6 +1,6 @@ /* pdp10_fe.c: PDP-10 front end (console terminal) simulator - Copyright (c) 1993-2003, Robert M Supnik + Copyright (c) 1993-2004, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -25,6 +25,7 @@ fe KS10 console front end + 29-Dec-03 RMS Added console backpressure support 25-Apr-03 RMS Revised for extended file support 22-Dec-02 RMS Added break support 30-May-02 RMS Widened COUNT to 32b @@ -108,9 +109,8 @@ 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 */ + sim_activate (&feo_unit, feo_unit.wait); } /* 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 */ @@ -119,6 +119,11 @@ return; t_stat feo_svc (UNIT *uptr) { +t_stat r; + +if ((r = sim_putchar_s (uptr->buf)) != SCPE_OK) { /* output; error? */ + sim_activate (uptr, uptr->wait); /* try again */ + return ((r == SCPE_STALL)? SCPE_OK: r); } /* !stall? report */ M[FE_CTYOUT] = 0; /* clear char */ apr_flg = apr_flg | APRF_CON; /* interrupt KS10 */ return SCPE_OK; diff --git a/PDP10/pdp10_lp20.c b/PDP10/pdp10_lp20.c index 343994ae..804e4e40 100644 --- a/PDP10/pdp10_lp20.c +++ b/PDP10/pdp10_lp20.c @@ -1,6 +1,6 @@ /* pdp10_lp20.c: PDP-10 LP20 line printer simulator - Copyright (c) 1993-2003, Robert M Supnik + Copyright (c) 1993-2004, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -25,6 +25,7 @@ lp20 line printer + 29-Dec-03 RMS Fixed bug in scheduling 25-Apr-03 RMS Revised for extended file support 29-Sep-02 RMS Added variable vector support Modified to use common Unibus routines @@ -283,7 +284,7 @@ case 00: /* LPCSA */ 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); } } + sim_activate (&lp20_unit, lp20_unit.wait); } } else sim_cancel (&lp20_unit); /* go clr, stop DMA */ lpcsa = (lpcsa & ~CSA_RW) | (data & CSA_RW); break; diff --git a/PDP11/pdp11_cpu.c b/PDP11/pdp11_cpu.c index 5e987a4a..e025dbef 100644 --- a/PDP11/pdp11_cpu.c +++ b/PDP11/pdp11_cpu.c @@ -1,6 +1,6 @@ /* pdp11_cpu.c: PDP-11 CPU simulator - Copyright (c) 1993-2003, Robert M Supnik + Copyright (c) 1993-2004, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -25,6 +25,8 @@ cpu PDP-11 CPU (J-11 microprocessor) + 29-Dec-03 RMS Formalized 18b Qbus support + 21-Dec-03 RMS Added autoconfiguration controls 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 @@ -276,6 +278,7 @@ 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 */ +int32 autcon_enb = 1; /* autoconfig enable */ uint16 pcq[PCQ_SIZE] = { 0 }; /* PC queue */ int32 pcq_p = 0; /* PC queue ptr */ REG *pcq_r = NULL; /* PC queue reg ptr */ @@ -323,6 +326,8 @@ 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 set_autocon (UNIT *uptr, int32 val, char *cptr, void *desc); +extern t_stat show_autocon (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); @@ -532,6 +537,7 @@ REG cpu_reg[] = { { GRDATA (UDPAR7, APRFILE[077], 8, 16, 16) }, { GRDATA (UDPDR7, APRFILE[077], 8, 16, 0) }, { BRDATA (UBMAP, ub_map, 8, 22, UBM_LNT_LW) }, + { FLDATA (AUTOCON, autcon_enb, 0), REG_HRO }, { BRDATA (PCQ, pcq, 8, 16, PCQ_SIZE), REG_RO+REG_CIRC }, { ORDATA (PCQP, pcq_p, 6), REG_HRO }, { ORDATA (WRU, sim_int_char, 8) }, @@ -539,10 +545,10 @@ REG cpu_reg[] = { { NULL} }; MTAB cpu_mod[] = { - { UNIT_MAP, UNIT_18B, "18b addressing", "18B", NULL }, + { UNIT_MAP, UNIT_18B, "18b Unibus", "U18", &cpu_set_bus }, { 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_MAP, 0, "22b Qbus", "Q22", &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}, @@ -566,6 +572,10 @@ MTAB cpu_mod[] = { { UNIT_MSIZE, 4186112, NULL, "4M", &cpu_set_size}, { MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, "IOSPACE", NULL, NULL, &show_iospace }, + { MTAB_XTD|MTAB_VDV, 1, "AUTOCONFIG", "AUTOCONFIG", + &set_autocon, &show_autocon }, + { MTAB_XTD|MTAB_VDV, 0, NULL, "NOAUTOCONFIG", + &set_autocon, NULL }, { 0 } }; DEVICE cpu_dev = { @@ -2467,23 +2477,24 @@ 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); } +return cpu_set_bus (uptr, cpu_unit.flags, 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; +uint32 i, mask; -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 */ +if ((val & UNIT_MAP) || (val & UNIT_18B)) /* Unibus variant? */ + mask = DEV_UBUS; +else if (MEMSIZE <= UNIMEMSIZE) /* 18b Qbus? */ + mask = DEV_QBUS | DEV_Q18; +else mask = DEV_QBUS; /* must be 22b */ 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)) { + ((dptr->flags & mask) == 0)) { /* not allowed? */ 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; } } diff --git a/PDP11/pdp11_defs.h b/PDP11/pdp11_defs.h index 2c460e80..00323c38 100644 --- a/PDP11/pdp11_defs.h +++ b/PDP11/pdp11_defs.h @@ -26,6 +26,8 @@ The author gratefully acknowledges the help of Max Burnet, Megan Gentry, and John Wilson in resolving questions about the PDP-11 + 22-Dec-03 RMS Added second DEUNA/DELUA support + 18-Oct-03 RMS Added DECtape off reel message 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 @@ -295,6 +297,7 @@ typedef struct fpac fpac_t; #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 STOP_DTOFF (TRAP_V_MAX + 8) /* DECtape off reel */ #define IORETURN(f,v) ((f)? (v): SCPE_OK) /* cond error return */ /* Timers */ @@ -312,9 +315,11 @@ typedef struct fpac fpac_t; #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_V_Q18 (DEV_V_UF + 2) /* Qbus with <= 256KB */ +#define DEV_V_FLTA (DEV_V_UF + 3) /* flt addr */ #define DEV_UBUS (1u << DEV_V_UBUS) #define DEV_QBUS (1u << DEV_V_QBUS) +#define DEV_Q18 (1u << DEV_V_Q18) #define DEV_FLTA (1u << DEV_V_FLTA) #define UNIBUS (cpu_18b || cpu_ubm) /* T if 18b */ @@ -341,11 +346,13 @@ struct pdp_dib { typedef struct pdp_dib DIB; -/* I/O page layout - RQB,RQC,RQD float based on number of DZ's */ +/* I/O page layout - XUB, 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 IOBA_XUB (IOPAGEBASE + 000330 + (020 * (DZ_MUXES / 2))) +#define IOLN_XUB 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 diff --git a/PDP11/pdp11_doc.txt b/PDP11/pdp11_doc.txt index 1acebe08..e7b4541d 100644 --- a/PDP11/pdp11_doc.txt +++ b/PDP11/pdp11_doc.txt @@ -1,7 +1,7 @@ To: Users From: Bob Supnik Subj: PDP-11 Simulator Usage -Date: 15-Sep-2003 +Date: 15-Dec-2003 COPYRIGHT NOTICE @@ -127,6 +127,7 @@ The PDP-11 simulator implements several unique stop conditions: - 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) + - a simulated DECtape runs off the end of its reel The PDP-11 loader supports standard binary format tapes. The DUMP command is not implemented. @@ -289,11 +290,13 @@ 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. +uses autoconfiguration DISABLES autoconfiguration for that device and for +the entire system. 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. Auto- +configuration can be restored for the entire system with the SET CPU +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 (*). @@ -994,7 +997,6 @@ The TC controller implements these registers: 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 @@ -1005,8 +1007,9 @@ 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 + - DCTIME needs to be at least 100 times LTIME + +Acceleration time is set to 75% of deceleration time. 2.9 Magnetic Tape Controllers diff --git a/PDP11/pdp11_hk.c b/PDP11/pdp11_hk.c index 31f35e52..b7dc2e3e 100644 --- a/PDP11/pdp11_hk.c +++ b/PDP11/pdp11_hk.c @@ -25,6 +25,7 @@ hk RK611/RK06/RK07 disk + 29-Dec-03 RMS Added 18b Qbus support 25-Apr-03 RMS Revised for extended file support This is a somewhat abstracted implementation of the RK611, more closely @@ -438,7 +439,7 @@ DEVICE hk_dev = { 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 }; + &hk_dib, DEV_DISABLE | DEV_UBUS | DEV_Q18 }; /* I/O dispatch routines, I/O addresses 17777440 - 17777476 */ diff --git a/PDP11/pdp11_io.c b/PDP11/pdp11_io.c index bae93443..3d6e7f89 100644 --- a/PDP11/pdp11_io.c +++ b/PDP11/pdp11_io.c @@ -23,6 +23,8 @@ 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-Dec-03 RMS Fixed bug in autoconfigure vector assignment; added controls + 21-Nov-03 RMS Added check for interrupt slot conflict (found by Dave Hittner) 12-Mar-03 RMS Added logical name support 08-Oct-02 RMS Trimmed I/O bus addresses Added support for dynamic tables @@ -43,6 +45,7 @@ extern UNIT cpu_unit; extern int32 cpu_bme, cpu_18b, cpu_ubm; extern int32 trap_req, ipl; extern int32 cpu_log; +extern int32 autcon_enb; extern FILE *sim_log; extern DEVICE *sim_devices[]; @@ -297,6 +300,24 @@ else { /* physical */ return (lim - alim); } } +/* Enable/disable autoconfiguration */ + +t_stat set_autocon (UNIT *uptr, int32 val, char *cptr, void *desc) +{ +if (cptr != NULL) return SCPE_ARG; +autcon_enb = val; +return auto_config (0, 0); +} + +/* Show autoconfiguration status */ + +t_stat show_autocon (FILE *st, UNIT *uptr, int32 val, void *desc) +{ +fprintf (st, "autoconfiguration "); +fprintf (st, autcon_enb? "enabled": "disabled"); +return SCPE_OK; +} + /* Change device address */ t_stat set_addr (UNIT *uptr, int32 val, char *cptr, void *desc) @@ -318,7 +339,8 @@ 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 */ +autcon_enb = 0; /* autoconfig off */ +return SCPE_OK; } /* Show device address */ @@ -374,6 +396,8 @@ 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; +dptr->flags = dptr->flags & ~DEV_FLTA; /* not floating */ +autcon_enb = 0; /* autoconfig off */ return SCPE_OK; } @@ -427,14 +451,20 @@ return FALSE; /* Build interrupt tables */ -void build_int_vec (int32 vloc, int32 ivec, int32 (*iack)(void) ) +t_bool 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; +if (iack != NULL) { + if (int_ack[ilvl][ibit] && + (int_ack[ilvl][ibit] != iack)) return TRUE; + int_ack[ilvl][ibit] = iack; } +else if (ivec != 0) { + if (int_vec[ilvl][ibit] && + (int_vec[ilvl][ibit] != ivec)) return TRUE; + int_vec[ilvl][ibit] = ivec; } +return FALSE; } /* Build dib_tab from device list */ @@ -453,9 +483,15 @@ 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]); + for (k = 0; k < dibp->vnum; k++) { /* loop thru vec */ + if (build_int_vec (dibp->vloc + k, /* add vector */ + dibp->vec + (k * 4), dibp->ack[k])) { + printf ("Device %s interrupt slot conflict at %d\n", + sim_dname (dptr), dibp->vloc + k); + if (sim_log) fprintf (sim_log, + "Device %s interrupt slot conflict at %d\n", + sim_dname (dptr), dibp->vloc + k); + return SCPE_IERR; } } 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? */ @@ -575,6 +611,7 @@ DIB *dibp; int32 i, j, k; extern DEVICE *find_dev (char *ptr); +if (autcon_enb == 0) return SCPE_OK; /* enabled? */ 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 */ diff --git a/PDP11/pdp11_rk.c b/PDP11/pdp11_rk.c index 5dc8b1e2..5fbc17d7 100644 --- a/PDP11/pdp11_rk.c +++ b/PDP11/pdp11_rk.c @@ -1,6 +1,6 @@ -/* pdp11_rk.c: RK11 cartridge disk simulator +/* pdp11_rk.c: RK11/RKV11 cartridge disk simulator - Copyright (c) 1993-2003, Robert M Supnik + Copyright (c) 1993-2004, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -23,8 +23,9 @@ 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 + rk RK11/RKV11/RK05 cartridge disk + 29-Dec-03 RMS Added RKV11 support 29-Sep-02 RMS Added variable address support to bootstrap Added vector change/display support Revised mapping mnemonics @@ -261,7 +262,7 @@ DEVICE rk_dev = { RK_NUMDR, 8, 24, 1, 8, 16, NULL, NULL, &rk_reset, &rk_boot, NULL, NULL, - &rk_dib, DEV_DISABLE | DEV_UBUS }; + &rk_dib, DEV_DISABLE | DEV_UBUS | DEV_Q18 }; /* I/O dispatch routine, I/O addresses 17777400 - 17777416 diff --git a/PDP11/pdp11_rq.c b/PDP11/pdp11_rq.c index 0007e840..3bc002cb 100644 --- a/PDP11/pdp11_rq.c +++ b/PDP11/pdp11_rq.c @@ -26,6 +26,8 @@ rq RQDX3 disk controller + 07-Oct-03 RMS Fixed problem with multiple RAUSER drives + 17-Sep-03 RMS Fixed MB to LBN conversion to be more accurate 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 @@ -1422,7 +1424,8 @@ 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 */ +uint32 maxlbn = uptr->capac / RQ_NUMBY; /* get max lbn */ +/* 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 */ @@ -1866,6 +1869,7 @@ return; void rq_putr_unit (MSC *cp, int32 pkt, UNIT *uptr, uint32 lu, t_bool all) { uint32 dtyp = GET_DTYPE (uptr->flags); /* get drive type */ +uint32 maxlbn = uptr->capac / RQ_NUMBY; /* get max lbn */ cp->pak[pkt].d[ONL_MLUN] = lu; /* unit */ cp->pak[pkt].d[ONL_UFL] = uptr->uf | UF_RPL | RQ_WPH (uptr) | RQ_RMV (uptr); @@ -1878,7 +1882,7 @@ 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 */ + PUTP32 (pkt, ONL_SIZL, maxlbn); /* user LBNs */ cp->pak[pkt].d[ONL_VSNL] = 01234 + lu; /* vol serial # */ cp->pak[pkt].d[ONL_VSNH] = 0; } return; @@ -2012,13 +2016,13 @@ 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); } + drv_tab[val].lbn = cap * 1954; } 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) */ +/* Show unit type */ t_stat rq_show_type (FILE *st, UNIT *uptr, int32 val, void *desc) { @@ -2034,7 +2038,6 @@ 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; diff --git a/PDP11/pdp11_rx.c b/PDP11/pdp11_rx.c index ea10d132..a8b8ca09 100644 --- a/PDP11/pdp11_rx.c +++ b/PDP11/pdp11_rx.c @@ -121,7 +121,7 @@ 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_bptr = 0; /* buffer pointer */ int32 rx_enb = 1; /* device enable */ DEVICE rx_dev; @@ -157,7 +157,7 @@ REG rx_reg[] = { { ORDATA (RXTA, rx_track, 8) }, { ORDATA (RXSA, rx_sector, 8) }, { DRDATA (STAPTR, rx_state, 3), REG_RO }, - { DRDATA (BUFPTR, bptr, 7) }, + { DRDATA (BUFPTR, rx_bptr, 7) }, { FLDATA (INT, IREQ (RX), INT_V_RX) }, { FLDATA (ERR, rx_csr, RXCS_V_ERR) }, { FLDATA (TR, rx_csr, RXCS_V_TR) }, @@ -237,7 +237,7 @@ case 0: /* RXCS */ 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 */ + rx_bptr = 0; /* clear buf pointer */ switch (RXCS_GETFNC (data)) { /* case on func */ case RXCS_FILL: rx_state = FILL; /* state = fill */ @@ -287,10 +287,10 @@ return SCPE_OK; 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 + FILL copy ir to rx_buf[rx_bptr], advance ptr + if rx_bptr > max, finish command, else set tr + EMPTY if rx_bptr > max, finish command, else + copy rx_buf[rx_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 @@ -302,6 +302,7 @@ t_stat rx_svc (UNIT *uptr) { int32 i, func; uint32 da; +int8 *fbuf = uptr->filebuf; func = RXCS_GETFNC (rx_csr); /* get function */ switch (rx_state) { /* case on state */ @@ -310,17 +311,17 @@ case IDLE: /* idle */ return SCPE_IERR; /* done */ case EMPTY: /* empty buffer */ - if (bptr >= RX_NUMBY) rx_done (0, 0); /* done all? */ + if (rx_bptr >= RX_NUMBY) rx_done (0, 0); /* done all? */ else { - rx_dbr = rx_buf[bptr]; /* get next */ - bptr = bptr + 1; + rx_dbr = rx_buf[rx_bptr]; /* get next */ + rx_bptr = rx_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 */ + rx_buf[rx_bptr] = rx_dbr; /* write next */ + rx_bptr = rx_bptr + 1; + if (rx_bptr < RX_NUMBY) rx_csr = rx_csr | RXCS_TR; /* more? set xfer */ else rx_done (0, 0); /* else done */ break; @@ -350,13 +351,13 @@ case RWXFR: 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); } + rx_buf[i] = fbuf[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]; + fbuf[da + i] = rx_buf[i]; da = da + RX_NUMBY; if (da > uptr->hwmark) uptr->hwmark = da; } rx_done (0, 0); /* done */ @@ -377,7 +378,7 @@ case INIT_COMPLETE: /* init complete */ break; } da = CALC_DA (1, 1); /* track 1, sector 1 */ for (i = 0; i < RX_NUMBY; i++) /* read sector */ - rx_buf[i] = *(((int8 *) uptr->filebuf) + da + i); + rx_buf[i] = fbuf[da + i]; rx_done (RXES_ID, 0); /* set done */ if ((rx_unit[1].flags & UNIT_ATT) == 0) rx_ecode = 0020; break; } /* end case state */ diff --git a/PDP11/pdp11_ry.c b/PDP11/pdp11_ry.c index 1a17cd9b..a383fa02 100644 --- a/PDP11/pdp11_ry.c +++ b/PDP11/pdp11_ry.c @@ -1,6 +1,6 @@ -/* pdp11_ry.c: RY11/RX02 floppy disk simulator +/* pdp11_ry.c: RX211/RXV21/RX02 floppy disk simulator - Copyright (c) 1993-2003, Robert M Supnik + Copyright (c) 1993-2004, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -23,8 +23,9 @@ 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 + ry RX211/RXV21/RX02 floppy disk + 29-Dec-03 RMS Added RXV21 support 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 @@ -146,7 +147,6 @@ 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); @@ -227,7 +227,7 @@ DEVICE ry_dev = { 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 }; + &ry_dib, DEV_FLTA | DEV_DISABLE | DEV_DIS | DEV_UBUS | DEV_Q18 }; /* I/O dispatch routine, I/O addresses 17777170 - 17777172 @@ -341,6 +341,7 @@ t_stat ry_svc (UNIT *uptr) int32 i, t, func, bps; static uint8 estat[8]; uint32 ba, da; +int8 *fbuf = uptr->filebuf; func = RYCS_GETFNC (ry_csr); /* get function */ bps = (ry_csr & RYCS_DEN)? RY_NUMBY: RX_NUMBY; /* get sector size */ @@ -401,12 +402,12 @@ case RWXFR: /* read/write */ 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); } + rx2xb[i] = fbuf[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]; + fbuf[da + i] = rx2xb[i]; da = da + bps; if (da > uptr->hwmark) uptr->hwmark = da; } ry_done (0, 0); /* done */ @@ -420,8 +421,7 @@ case SDCNF: /* confirm set density */ 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; + for (i = 0; i < (int32) uptr->capac; i++) fbuf[i] = 0; uptr->hwmark = uptr->capac; if (ry_csr & RYCS_DEN) uptr->flags = uptr->flags | UNIT_DEN; else uptr->flags = uptr->flags & ~UNIT_DEN; @@ -462,7 +462,7 @@ case INIT_COMPLETE: /* init complete */ 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); + rx2xb[i] = fbuf[da + i]; ry_done (RYES_ID, 0); /* set done */ if ((ry_unit[1].flags & UNIT_ATT) == 0) ry_ecode = 0020; break; } /* end case state */ diff --git a/PDP11/pdp11_stddev.c b/PDP11/pdp11_stddev.c index f9c4b24d..c5d11569 100644 --- a/PDP11/pdp11_stddev.c +++ b/PDP11/pdp11_stddev.c @@ -1,6 +1,6 @@ /* pdp11_stddev.c: PDP-11 standard I/O devices simulator - Copyright (c) 1993-2003, Robert M Supnik + Copyright (c) 1993-2004, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -26,6 +26,7 @@ tti,tto DL11 terminal input/output clk KW11L line frequency clock + 29-Dec-03 RMS Added console backpressure support 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 @@ -319,10 +320,12 @@ t_stat tto_svc (UNIT *uptr) int32 c; t_stat r; +c = tto_unit.buf & ((tto_unit.flags & UNIT_8B)? 0377: 0177); +if ((r = sim_putchar_s (c)) != SCPE_OK) { /* output; error? */ + sim_activate (uptr, uptr->wait); /* try again */ + return ((r == SCPE_STALL)? SCPE_OK: r); } /* !stall? report */ 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; } diff --git a/PDP11/pdp11_sys.c b/PDP11/pdp11_sys.c index 2a140b75..b6f230f2 100644 --- a/PDP11/pdp11_sys.c +++ b/PDP11/pdp11_sys.c @@ -23,8 +23,10 @@ be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. + 22-Dec-03 RMS Added second DEUNA/DELUA support + 18-Oct-03 RMS Added DECtape off reel message 06-May-03 RMS Added support for second DEQNA/DELQA - 09-Jan-03 RMS Added DELUA support + 09-Jan-03 RMS Added DELUA/DEUNA 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 @@ -64,7 +66,7 @@ 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 DEVICE xu_dev, xub_dev; extern UNIT cpu_unit; extern REG cpu_reg[]; extern uint16 *M; @@ -113,6 +115,7 @@ DEVICE *sim_devices[] = { &xq_dev, &xqb_dev, &xu_dev, + &xub_dev, NULL }; const char *sim_stop_messages[] = { @@ -138,7 +141,8 @@ const char *sim_stop_messages[] = { "Trap vector fetch abort", "Trap stack push abort", "RQDX3 consistency error", - "Sanity timer expired" }; + "Sanity timer expired" + "DECtape off reel" }; /* Binary loader. diff --git a/PDP11/pdp11_tc.c b/PDP11/pdp11_tc.c index 414dee28..943f7fca 100644 --- a/PDP11/pdp11_tc.c +++ b/PDP11/pdp11_tc.c @@ -1,6 +1,6 @@ /* pdp11_tc.c: PDP-11 DECtape simulator - Copyright (c) 1993-2003, Robert M Supnik + Copyright (c) 1993-2004, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -25,6 +25,10 @@ tc TC11/TU56 DECtape + 29-Dec-03 RMS Changed initial status to disabled (in Qbus system) + 18-Oct-03 RMS Fixed reverse checksum in read all + Added DECtape off reel message + Simplified timing 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 @@ -58,13 +62,16 @@ 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 + Tape density is nominally 300 lines per inch. The format of a DECtape (as + taken from the TD8E formatter) is: - reverse end zone 36000 lines ~ 10 feet + reverse end zone 8192 reverse end zone codes ~ 10 feet + reverse buffer 200 interblock codes block 0 : block n - forward end zone 36000 lines ~ 10 feet + forward buffer 200 interblock codes + forward end zone 8192 forward end zone codes ~ 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 @@ -79,9 +86,9 @@ header word 0 0 header word 1 block number (for forward reads) header words 2,3 0 - header word 4 0 + header word 4 checksum (for reverse reads) : - trailer word 4 checksum + trailer word 4 checksum (for forward reads) trailer words 3,2 0 trailer word 1 block number (for reverse reads) trailer word 0 0 @@ -106,13 +113,15 @@ /* 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 */ +#define DT_LPERMC 6 /* lines per mark track */ +#define DT_BLKWD 1 /* blk no word in h/t */ +#define DT_CSMWD 4 /* checksum word in h/t */ +#define DT_HTWRD 5 /* header/trailer words */ +#define DT_EZLIN (8192 * DT_LPERMC) /* end zone length */ +#define DT_BFLIN (200 * DT_LPERMC) /* buffer length */ +#define DT_BLKLN (DT_BLKWD * DT_LPERMC) /* blk no line in h/t */ +#define DT_CSMLN (DT_CSMWD * DT_LPERMC) /* csum line in h/t */ +#define DT_HTLIN (DT_HTWRD * DT_LPERMC) /* header/trailer lines */ /* 16b, 18b, 36b DECtape constants */ @@ -270,8 +279,7 @@ 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_dctime = 40000; /* decel time */ int32 dt_substate = 0; int32 dt_logblk = 0; @@ -340,7 +348,6 @@ REG dt_reg[] = { { 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 }, @@ -371,7 +378,7 @@ DEVICE dt_dev = { DT_NUMDR + 1, 8, 24, 1, 8, 18, NULL, NULL, &dt_reset, &dt_boot, &dt_attach, &dt_detach, - &dt_dib, DEV_DISABLE | DEV_UBUS }; + &dt_dib, DEV_DISABLE | DEV_DIS | DEV_UBUS }; /* IO dispatch routines, I/O addresses 17777340 - 17777350 */ @@ -523,7 +530,7 @@ if (new_fnc == FNC_SSEL) { /* stop unit? */ 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 */ + sim_activate (uptr, dt_dctime - (dt_dctime >> 2)); /* sched accel */ DTS_SETSTA (DTS_ACCF | new_dir, 0); /* state = accel */ DTS_SET2ND (DTS_ATSF | new_dir, new_fnc); /* next = fnc */ return; } @@ -537,7 +544,7 @@ if (prev_dir ^ new_dir) { /* dir chg? */ 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 */ + sim_activate (uptr, dt_dctime - (dt_dctime >> 2)); /* sched accel */ DTS_SETSTA (DTS_ACCF | new_dir, 0); /* state = accel */ DTS_SET2ND (DTS_ATSF | new_dir, new_fnc); /* next = fnc */ return; } @@ -674,11 +681,13 @@ case DTS_STOP: /* stop */ delta = 0; break; case DTS_DECF: /* slowing */ - ulin = ut / (uint32) dt_ltime; udelt = dt_dctime / dt_ltime; + 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; + ulin = ut / (uint32) dt_ltime; + udelt = (dt_dctime - (dt_dctime >> 2)) / dt_ltime; delta = (ulin * ulin) / (2 * udelt); break; case DTS_ATSF: /* at speed */ @@ -715,7 +724,7 @@ 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 *fbuf = uptr->filebuf; int32 blk, wrd, relpos, dat; uint32 ba, ma, mma; @@ -728,10 +737,10 @@ uint32 ba, ma, mma; switch (mot) { case DTS_DECF: case DTS_DECR: /* decelerating */ - if (dt_setpos (uptr)) return SCPE_OK; /* update pos */ + if (dt_setpos (uptr)) return STOP_DTOFF; /* update pos */ uptr->STATE = DTS_NXTSTA (uptr->STATE); /* advance state */ if (uptr->STATE) /* not stopped? */ - sim_activate (uptr, dt_actime); /* must be reversing */ + sim_activate (uptr, dt_dctime - (dt_dctime >> 2)); /* reversing */ return SCPE_OK; case DTS_ACCF: case DTS_ACCR: /* accelerating */ dt_newfnc (uptr, DTS_NXTSTA (uptr->STATE)); /* adv state, sched */ @@ -748,7 +757,7 @@ default: /* other */ Off reel - detach unit (it must be deselected) */ -if (dt_setpos (uptr)) return SCPE_OK; /* update pos */ +if (dt_setpos (uptr)) return STOP_DTOFF; /* update pos */ if (DT_QEZ (uptr)) { /* in end zone? */ dt_seterr (uptr, STA_END); /* end zone error */ return SCPE_OK; } @@ -785,7 +794,7 @@ case FNC_READ: /* read */ dt_seterr (uptr, STA_NXM); break; } ba = (blk * DTU_BSIZE (uptr)) + wrd; /* buffer ptr */ - M[mma >> 1] = tcdt = bptr[ba] & DMASK; /* read word */ + M[mma >> 1] = tcdt = fbuf[ba] & DMASK; /* read word */ tcwc = (tcwc + 1) & DMASK; /* incr MA, WC */ tcba = (tcba + 2) & DMASK; if (tcba <= 1) tccm = CSR_INCMEX (tccm); @@ -822,7 +831,7 @@ case FNC_WRIT: /* write */ tcba = (tcba + 2) & DMASK; if (tcba <= 1) tccm = CSR_INCMEX (tccm); } ba = (blk * DTU_BSIZE (uptr)) + wrd; /* buffer ptr */ - bptr[ba] = tcdt; /* write word */ + fbuf[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? */ @@ -844,7 +853,7 @@ case FNC_RALL: (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 */ + dat = fbuf[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 */ @@ -866,7 +875,7 @@ case FNC_WALL: 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 */ + fbuf[ba] = dat; /* write word */ if (ba >= uptr->hwmark) uptr->hwmark = ba + 1; } /* else /* ignore hdr */ sim_activate (uptr, DT_WSIZE * dt_ltime); @@ -941,13 +950,13 @@ return dat; int32 dt_csum (UNIT *uptr, int32 blk) { -int32 *bptr = uptr->filebuf; +int32 *fbuf = 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 */ + wrd = fbuf[ba + i] ^ 0777777; /* get ~word */ csum = csum ^ (wrd >> 12) ^ (wrd >> 6) ^ wrd; } return (csum & 077); } @@ -959,6 +968,7 @@ 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 077; /* rev csum */ 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 */ @@ -1067,7 +1077,7 @@ t_stat dt_attach (UNIT *uptr, char *cptr) { uint16 pdp8b[D8_NBSIZE]; uint16 pdp11b[D18_BSIZE]; -uint32 ba, sz, k, *bptr; +uint32 ba, sz, k, *fbuf; int32 u = uptr - dt_dev.units; t_stat r; @@ -1089,7 +1099,7 @@ 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 */ +fbuf = 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"); @@ -1101,9 +1111,9 @@ if (uptr->flags & UNIT_8FMT) { /* 12b? */ 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) | + fbuf[ba] = ((uint32) (pdp8b[k] & 07777) << 6) | ((uint32) (pdp8b[k + 1] >> 6) & 077); - bptr[ba + 1] = ((pdp8b[k + 1] & 077) << 12) | + fbuf[ba + 1] = ((pdp8b[k + 1] & 077) << 12) | ((uint32) (pdp8b[k + 2] & 07777)); ba = ba + 2; } /* end blk loop */ } /* end file loop */ @@ -1114,7 +1124,7 @@ else if (uptr->flags & UNIT_11FMT) { /* 16b? */ if (k == 0) break; for ( ; k < D18_BSIZE; k++) pdp11b[k] = 0; for (k = 0; k < D18_BSIZE; k++) - bptr[ba++] = pdp11b[k]; } + fbuf[ba++] = pdp11b[k]; } uptr->hwmark = ba; } /* end elif */ else uptr->hwmark = fxread (uptr->filebuf, sizeof (int32), uptr->capac, uptr->fileref); @@ -1137,7 +1147,7 @@ t_stat dt_detach (UNIT* uptr) { uint16 pdp8b[D8_NBSIZE]; uint16 pdp11b[D18_BSIZE]; -uint32 ba, k, *bptr; +uint32 ba, k, *fbuf; int32 u = uptr - dt_dev.units; if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; @@ -1148,17 +1158,17 @@ if (sim_is_active (uptr)) { /* active? cancel op */ tccm = tccm | CSR_ERR | CSR_DONE; if (tccm & CSR_IE) SET_INT (DTA); } uptr->STATE = uptr->pos = 0; } -bptr = uptr->filebuf; /* file buffer */ +fbuf = 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; + pdp8b[k] = (fbuf[ba] >> 6) & 07777; + pdp8b[k + 1] = ((fbuf[ba] & 077) << 6) | + ((fbuf[ba + 1] >> 12) & 077); + pdp8b[k + 2] = fbuf[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 */ @@ -1166,7 +1176,7 @@ if (uptr->hwmark && ((uptr->flags & UNIT_RO) == 0)) { /* any data? */ 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; + pdp11b[k] = fbuf[ba++] & DMASK; fxwrite (pdp11b, sizeof (int16), D18_BSIZE, uptr->fileref); if (ferror (uptr->fileref)) break; } /* end loop file */ } /* end if 16b */ diff --git a/PDP11/pdp11_tm.c b/PDP11/pdp11_tm.c index e6872b36..8d7be404 100644 --- a/PDP11/pdp11_tm.c +++ b/PDP11/pdp11_tm.c @@ -1,6 +1,6 @@ /* pdp11_tm.c: PDP-11 magnetic tape simulator - Copyright (c) 1993-2003, Robert M Supnik + Copyright (c) 1993-2004, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -25,6 +25,7 @@ tm TM11/TU10 magtape + 29-Dec-03 RMS Added 18b Qbus support 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 @@ -231,7 +232,7 @@ DEVICE tm_dev = { TM_NUMDR, 10, 31, 1, 8, 8, NULL, NULL, &tm_reset, &tm_boot, &tm_attach, &tm_detach, - &tm_dib, DEV_DISABLE | DEV_UBUS }; + &tm_dib, DEV_DISABLE | DEV_UBUS | DEV_Q18 }; /* I/O dispatch routine, I/O addresses 17772520 - 17772532 diff --git a/PDP11/pdp11_xq.c b/PDP11/pdp11_xq.c index 8b3e96a9..9d832d80 100644 --- a/PDP11/pdp11_xq.c +++ b/PDP11/pdp11_xq.c @@ -69,6 +69,27 @@ Modification history: + 03-Dec-03 DTH Added minimum name length to show xq eth + 25-Nov-03 DTH Reworked interrupts to fix broken XQB implementation + 19-Nov-03 MP Rearranged timer reset sequencing to allow for a device to be + disabled after it had been enabled. + 17-Nov-03 DTH Standardized #include of timeb.h + 28-Sep-03 MP - Fixed bug in xq_process_setup which would leave the + device in promiscuous or all multicast mode once it + ever had been there. + - Fixed output format in show_xq_sanity to end in "\n" + - Added display of All Multicase and promiscuous to + xq_show_filters + - The stuck in All Multicast or Promiscuous issue is + worse than previously thought. See comments in + xq_process_setup. + - Change xq_setmac to also allow ":" as a address + separator character, since sim_ether's eth_mac_fmt + formats them with this separator character. + - Changed xq_sw_reset to behave more like the set of + actions described in Table 3-6 of the DELQA manua. + The manual mentions "N/A" which I'm interpreting to + mean "Not Affected". 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 @@ -92,7 +113,7 @@ 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 + the simulated CPU instruction execution throughput 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. @@ -100,7 +121,7 @@ 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 + expecially since we service receives 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 @@ -128,7 +149,7 @@ 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 + been done, xq_process_rdbl 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 @@ -216,8 +237,6 @@ 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); @@ -230,6 +249,9 @@ void xqa_read_callback(int status); void xqb_read_callback(int status); void xqa_write_callback(int status); void xqb_write_callback(int status); +void xq_setint (CTLR* xq); +void xq_clrint (CTLR* xq); +int32 xq_int (void); struct xq_device xqa = { xqa_read_callback, /* read callback routine */ @@ -249,7 +271,7 @@ struct xq_device xqb = { /* SIMH device structures */ DIB xqa_dib = { IOBA_XQ, IOLN_XQ, &xq_rd, &xq_wr, - 1, IVCL (XQ), 0, { &xq_inta } }; + 1, IVCL (XQ), 0, { &xq_int } }; UNIT xqa_unit[] = { { UDATA (&xq_svc, UNIT_ATTABLE + UNIT_DISABLE, 2047) }, /* receive timer */ @@ -268,6 +290,7 @@ REG xqa_reg[] = { { GRDATA ( XBDL, xqa.xbdl, XQ_RDX, 32, 0) }, { GRDATA ( VAR, xqa.var, XQ_RDX, 16, 0) }, { GRDATA ( CSR, xqa.csr, XQ_RDX, 16, 0) }, + { FLDATA ( INT, xqa.irq, 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}, @@ -279,7 +302,7 @@ REG xqa_reg[] = { }; DIB xqb_dib = { IOBA_XQB, IOLN_XQB, &xq_rd, &xq_wr, - 1, IVCL (XQ), 0, { &xq_intb } }; + 1, IVCL (XQ), 0, { &xq_int } }; UNIT xqb_unit[] = { { UDATA (&xq_svc, UNIT_ATTABLE + UNIT_DISABLE, 2047) }, /* receive timer */ @@ -298,6 +321,7 @@ REG xqb_reg[] = { { GRDATA ( XBDL, xqb.xbdl, XQ_RDX, 32, 0) }, { GRDATA ( VAR, xqb.var, XQ_RDX, 16, 0) }, { GRDATA ( CSR, xqb.csr, XQ_RDX, 16, 0) }, + { FLDATA ( INT, xqb.irq, 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}, @@ -372,7 +396,7 @@ void xq_csr_changes(CTLR* xq, uint16 data); void xq_var_changes(CTLR* xq, uint16 data); /* sanity timer debugging */ -#include +#include struct timeb start, finish; #endif /* XQ_DEBUG */ @@ -575,7 +599,9 @@ t_stat xq_setmac (UNIT* uptr, int32 val, char* cptr, void* desc) if (len != 17) return SCPE_ARG; /* make sure byte separators are OK */ for (i=2; i min) min = len; for (i=0; ivar->setup.macs[i], buffer); fprintf(st, " [%2d]: %s\n", i, buffer); }; + if (xq->var->setup.multicast) + fprintf(st, "All Multicast Receive Mode\n"); + if (xq->var->setup.promiscuous) + fprintf(st, "Promiscuous Receive Mode\n"); return SCPE_OK; } @@ -695,8 +727,8 @@ t_stat xq_show_sanity (FILE* st, UNIT* uptr, int32 val, void* desc) fprintf(st, "sanity="); switch (xq->var->sanity.enabled) { - case 0: fprintf(st, "OFF"); break; - case 1: fprintf(st, "ON"); break; + case 0: fprintf(st, "OFF\n"); break; + case 1: fprintf(st, "ON\n"); break; } return SCPE_OK; } @@ -724,7 +756,7 @@ t_stat xq_nxm_error(CTLR* xq) /* interrupt if required */ if (xq->var->csr & XQ_CSR_IE) - SET_INT(XQ); + xq_setint(xq); return SCPE_OK; } @@ -761,7 +793,7 @@ void xq_write_callback (CTLR* xq, int status) /* update csr */ xq->var->csr |= XQ_CSR_XI; if (xq->var->csr & XQ_CSR_IE) - SET_INT(XQ); + xq_setint(xq); /* reset sanity timer */ xq_reset_santmr(xq); @@ -846,7 +878,7 @@ t_stat xq_process_rbdl(CTLR* xq) uint16 b_length, w_length, rbl; uint32 address; struct xq_msg_itm* item; - char* rbuf; + uint8* rbuf; #ifdef XQ_DEBUG fprintf(stderr,"%s: CSR - Processing read\n", xq->dev->name); @@ -906,7 +938,7 @@ t_stat xq_process_rbdl(CTLR* xq) #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); + memset(&item->packet.msg[rbl], 0, ETH_MIN_PACKET-rbl); rbl = ETH_MIN_PACKET; }; @@ -976,7 +1008,7 @@ t_stat xq_process_rbdl(CTLR* xq) /* mark transmission complete */ xq->var->csr |= XQ_CSR_RI; if (xq->var->csr & XQ_CSR_IE) - SET_INT(XQ); + xq_setint(xq); /* set to next bdl (implicit chain) */ xq->var->rbdl_ba += 12; @@ -1059,15 +1091,42 @@ t_stat xq_process_setup(CTLR* xq) xq->var->setup.macs[i+7][j] = xq->var->write_buffer.msg[(i + 0101) + (j * 8)]; } + /* + Under VMS the setup packet that is passed to turn promiscuous + off after it has been on doesn't seem to follow the rules documented + in both the DEQNA and DELQA manuals. + These rules seem to say that setup packets less than 128 should only + modify the address filter set and probably not the All-Multicast and + Promiscuous modes, however, VMS V5-5 and V7.3 seem to send a 127 byte + packet to turn this functionality off. I'm not sure how real hardware + behaves in this case, since the only consequence is extra interrupt + load. To realize and retain the benefits of the newly added BPF + functionality in sim_ether, I've modified the logic implemented here + to disable Promiscuous mode when a "small" setup packet is processed. + I'm deliberately not modifying the All-Multicast mode the same way + since I don't have an observable case of its behavior. These two + different modes come from very different usage situations: + 1) Promiscuous mode is usually entered for relatively short periods + of time due to the needs of a specific application program which + is doing some sort of management/monitoring function (i.e. tcpdump) + 2) All-Multicast mode is only entered by the OS Kernel Port Driver + when it happens to have clients (usually network stacks or service + programs) which as a group need to listen to more multicast ethernet + addresses than the 12 (or so) which the hardware supports directly. + so, I believe that the All-Multicast mode, is first rarely used, and if + it ever is used, once set, it will probably be set either forever or for + long periods of time, and the additional interrupt processing load to + deal with the distinctly lower multicast traffic set is clearly lower than + that of the promiscuous mode. + */ + xq->var->setup.promiscuous = 0; /* 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; + xq->var->setup.multicast = (0 != (len & XQ_SETUP_MC)); + xq->var->setup.promiscuous = (0 != (len & XQ_SETUP_PM)); if (led = (len & XQ_SETUP_LD) >> 2) { switch (led) { case 1: xq->var->setup.l1 = 0; break; @@ -1214,7 +1273,7 @@ t_stat xq_process_xbdl(CTLR* xq) /* mark transmission complete */ xq->var->csr |= XQ_CSR_XI; if (xq->var->csr & XQ_CSR_IE) - SET_INT(XQ); + xq_setint(xq); /* now trigger "read" of setup or loopback packet */ if (~xq->var->csr & XQ_CSR_RL) @@ -1446,13 +1505,26 @@ void xq_sw_reset(CTLR* xq) xq->var->csr |= XQ_CSR_OK; /* clear CPU interrupts */ - CLR_INT(XQ); + xq_clrint(xq); /* flush read queue */ xq_clear_queue(&xq->var->ReadQ); /* clear setup info */ - memset (&xq->var->setup, 0, sizeof(xq->var->setup)); + xq->var->setup.multicast = 0; + xq->var->setup.promiscuous = 0; + if (xq->var->etherface) { + int count = 0; + ETH_MAC zeros = {0, 0, 0, 0, 0, 0}; + ETH_MAC filters[XQ_FILTER_MAX + 1]; + + /* 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)); + eth_filter (xq->var->etherface, count, filters, xq->var->setup.multicast, xq->var->setup.promiscuous); + } } /* write registers: */ @@ -1676,7 +1748,7 @@ t_stat xq_process_bootrom (CTLR* xq) /* mark transmission complete */ xq->var->csr |= XQ_CSR_RI; if (xq->var->csr & XQ_CSR_IE) - SET_INT(XQ); + xq_setint(xq); /* reset sanity timer */ xq_reset_santmr(xq); @@ -1724,8 +1796,8 @@ t_stat xq_wr_csr(CTLR* xq, int32 data) /* 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); + if ( old_int_state && !new_int_state) xq_clrint(xq); + if (!old_int_state && new_int_state) xq_setint(xq); #ifdef VM_PDP11 /* request boot/diagnostic rom? [PDP-11 only] */ @@ -1803,12 +1875,6 @@ t_stat xq_reset(DEVICE* dptr) /* 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) @@ -1817,6 +1883,11 @@ t_stat xq_reset(DEVICE* dptr) /* clear read queue */ xq_clear_queue(&xq->var->ReadQ); + /* 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; + /* start sanity timer if power-on SANITY is set */ switch (xq->var->type) { case XQ_T_DEQNA: @@ -1830,6 +1901,8 @@ t_stat xq_reset(DEVICE* dptr) xq_start_idtmr(xq); break; }; + } + return SCPE_OK; } @@ -1841,11 +1914,9 @@ void xq_start_santmr(CTLR* xq) /* 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); @@ -1897,12 +1968,10 @@ t_stat xq_sansvc(UNIT* uptr) If this section is entered, it means that the sanity timer has expired without being reset, and the controller must reboot the processor. */ -#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(); } @@ -1944,6 +2013,9 @@ t_stat xq_system_id (CTLR* xq, const ETH_MAC dest, uint16 receipt_id) uint8* const msg = &system_id.msg[0]; t_stat status; +#ifdef XQ_DEBUG + fprintf(stderr,"%s: SYSTEM ID BROADCAST\n", xq->dev->name); +#endif 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)); @@ -2089,6 +2161,9 @@ t_stat xq_attach(UNIT* uptr, char* cptr) /* turn on transceiver power indicator */ xq->var->csr |= XQ_CSR_OK; + /* reset the device with the new attach info */ + xq_reset(xq->dev); + return SCPE_OK; } @@ -2098,6 +2173,7 @@ t_stat xq_detach(UNIT* uptr) { t_stat status; CTLR* xq = xq_unit2ctlr(uptr); + int i; if (uptr->flags & UNIT_ATT) { status = eth_close (xq->var->etherface); @@ -2106,6 +2182,9 @@ t_stat xq_detach(UNIT* uptr) free(uptr->filename); uptr->filename = NULL; uptr->flags &= ~UNIT_ATT; + /* cancel all timers (ethernet, sanity, system_id) */ + for (i=0; i<3; i++) + sim_cancel(&xq->unit[i]); } /* turn off transceiver power indicator */ @@ -2114,14 +2193,38 @@ t_stat xq_detach(UNIT* uptr) return SCPE_OK; } -int32 xq_inta (void) +void xq_setint(CTLR* xq) { - return xqa_dib.vec; + xq->var->irq = 1; + SET_INT(XQ); + return; } -int32 xq_intb (void) +void xq_clrint(CTLR* xq) { - return xqb_dib.vec; + int i; + xq->var->irq = 0; /* set controller irq off */ + /* clear master interrupt? */ + for (i=0; iirq) { /* if any irqs enabled */ + SET_INT(XQ); /* set master interrupt on */ + return; + } + CLR_INT(XQ); /* clear master interrupt */ + return; +} + +int32 xq_int (void) +{ + int i; + for (i=0; ivar->irq) { /* if interrupt pending */ + xq_clrint(xq); /* clear interrupt */ + return xq->dib->vec; /* return vector */ + } + } + return 0; /* no interrupt request active */ } /*============================================================================== diff --git a/PDP11/pdp11_xq.h b/PDP11/pdp11_xq.h index 6f174ceb..939ebde8 100644 --- a/PDP11/pdp11_xq.h +++ b/PDP11/pdp11_xq.h @@ -28,6 +28,7 @@ Modification history: + 25-Nov-03 DTH Added interrupt request flag 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 @@ -152,6 +153,7 @@ struct xq_device { uint16 xbdl[2]; uint16 var; uint16 csr; + uint32 irq; /* interrupt request flag */ /* buffers, etc. */ struct xq_setup setup; diff --git a/PDP11/pdp11_xu.c b/PDP11/pdp11_xu.c index 02867c65..359c9528 100644 --- a/PDP11/pdp11_xu.c +++ b/PDP11/pdp11_xu.c @@ -24,6 +24,8 @@ in this Software without prior written authorization from Robert M Supnik. xu DEUNA/DELUNA Ethernet interface (stub) + + 22-Dec-03 RMS Added second (stub) device */ #if defined (VM_PDP10) /* PDP10 version */ @@ -61,3 +63,29 @@ DEVICE xu_dev = { NULL, NULL, NULL, NULL, NULL, NULL, &xu_dib, DEV_DIS | DEV_UBUS }; + +#if defined (VM_PDP11) + +/* XUB data structures + + xub_dev XUB device descriptor + xub_unit XUB unit list + xub_reg XUB register list +*/ + +DIB xub_dib = { IOBA_XUB, IOLN_XUB, NULL, NULL, + 1, IVCL (XU), VEC_XU, { NULL } }; + +UNIT xub_unit = { UDATA (NULL, 0, 0) }; + +REG xub_reg[] = { + { NULL } }; + +DEVICE xub_dev = { + "XUB", &xub_unit, xub_reg, NULL, + 1, 8, 8, 1, 8, 8, + NULL, NULL, NULL, + NULL, NULL, NULL, + &xub_dib, DEV_DIS | DEV_UBUS }; + +#endif diff --git a/PDP18B/pdp18b_cpu.c b/PDP18B/pdp18b_cpu.c index 96c3ff16..1f46dc56 100644 --- a/PDP18B/pdp18b_cpu.c +++ b/PDP18B/pdp18b_cpu.c @@ -1,6 +1,6 @@ /* pdp18b_cpu.c: 18b PDP CPU simulator - Copyright (c) 1993-2003, Robert M Supnik + Copyright (c) 1993-2004, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -25,6 +25,10 @@ cpu PDP-4/7/9/15 central processor + 31-Dec-03 RMS Fixed bug in cpu_set_hist + 02-Nov-03 RMS Changed PDP-9,-15 default to API + 26-Oct-03 RMS Fixed bug in PDP-4,-7,-9 autoincrement addressing + 19-Sep-03 RMS Changed instruction history to be dynamically sized 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 @@ -277,9 +281,11 @@ #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_PC 0x10000000 +#define HIST_MIN 64 +#define HIST_MAX 65536 #define HIST_M_LVL 0x3F #define HIST_V_LVL 6 struct InstHistory { @@ -303,7 +309,7 @@ struct InstHistory { #define PROT_DFLT 0 #define ASW_DFLT 017763 #else -#define API_DFLT UNIT_NOAPI /* for now */ +#define API_DFLT 0 #define PROT_DFLT UNIT_PROT #define ASW_DFLT 017720 #endif @@ -355,7 +361,7 @@ 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 */ +struct InstHistory *hst = NULL; /* instruction history */ extern int32 sim_int_char; extern int32 sim_interval; @@ -1510,7 +1516,7 @@ t_stat Ia (int32 ma, int32 *ea, t_bool jmp) int32 t; t_stat sta = MM_OK; -if ((ma & B_DAMASK) == 010) { /* autoindex? */ +if ((ma & B_DAMASK & ~07) == 010) { /* autoindex? */ Read (ma, &t, DF); /* add 1 before use */ t = (t + 1) & DMASK; sta = Write (ma, t, DF); } @@ -1588,7 +1594,7 @@ t_stat Ia (int32 ma, int32 *ea, t_bool jmp) int32 t; t_stat sta = MM_OK; -if ((ma & B_DAMASK) == 010) { /* autoindex? */ +if ((ma & B_DAMASK & ~07) == 010) { /* autoindex? */ ma = ma & 017; /* always in bank 0 */ Read (ma, &t, DF); /* +1 before use */ t = (t + 1) & DMASK; @@ -1799,7 +1805,7 @@ t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) 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; } + if ((int32) addr < 0) return STOP_MME; } #endif if (addr >= MEMSIZE) return SCPE_NXM; if (vptr != NULL) *vptr = M[addr] & DMASK; @@ -1814,7 +1820,7 @@ t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw) 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; } + if ((int32) addr < 0) return STOP_MME; } #endif if (addr >= MEMSIZE) return SCPE_NXM; M[addr] = val & DMASK; @@ -1933,11 +1939,20 @@ int32 i, lnt; t_stat r; if (cptr == NULL) { - for (i = 0; i < HIST_SIZE; i++) hst[i].pc = 0; + for (i = 0; i < hst_lnt; i++) hst[i].pc = 0; + hst_p = 0; return SCPE_OK; } -lnt = (int32) get_uint (cptr, 10, HIST_SIZE, &r); -if (r != SCPE_OK) return SCPE_ARG; -hst_lnt = lnt; +lnt = (int32) get_uint (cptr, 10, HIST_MAX, &r); +if ((r != SCPE_OK) || (lnt && (lnt < HIST_MIN))) return SCPE_ARG; +hst_p = 0; +if (hst_lnt) { + free (hst); + hst_lnt = 0; + hst = NULL; } +if (lnt) { + hst = calloc (sizeof (struct InstHistory), lnt); + if (hst == NULL) return SCPE_MEM; + hst_lnt = lnt; } return SCPE_OK; } @@ -1952,25 +1967,26 @@ 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 */ +fprintf (st, "PC L AC MQ IR\n\n"); +di = hst_p; /* 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? */ + h = &hst[(di++) % hst_lnt]; /* entry pointer */ + if (h->pc & HIST_PC) { /* instruction? */ + l = (h->lac >> 18) & 1; /* link */ + fprintf (st, "%06o %o %06o %06o ", h->pc & AMASK, l, h->lac & DMASK, h->mq); + sim_eval[0] = h->ir; + sim_eval[1] = h->ir1; + if ((fprint_sym (st, h->pc & AMASK, sim_eval, &cpu_unit, SWMASK ('M'))) > 0) + fprintf (st, "(undefined) %06o", h->ir); + } /* end else instruction */ + else 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); + 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 */ + else continue; /* invalid */ fputc ('\n', st); /* end line */ } /* end for */ return SCPE_OK; @@ -1980,13 +1996,17 @@ return SCPE_OK; void cpu_inst_hist (int32 addr, int32 inst) { -hst[hst_p].pc = addr; +t_value word; + +hst[hst_p].pc = addr | HIST_PC; hst[hst_p].ir = inst; -if (cpu_ex (&hst[hst_p].ir1, (addr + 1) & AMASK, &cpu_unit, SWMASK ('V'))) +if (cpu_ex (&word, (addr + 1) & AMASK, &cpu_unit, SWMASK ('V'))) hst[hst_p].ir1 = 0; +else hst[hst_p].ir1 = word; hst[hst_p].lac = LAC; hst[hst_p].mq = MQ; -hst_p = (hst_p + 1) % HIST_SIZE; +hst_p = (hst_p + 1); +if (hst_p >= hst_lnt) hst_p = 0; return; } @@ -2001,6 +2021,7 @@ for (j = 0; j < API_HLVL+1; j++) hst[hst_p].ir = hst[hst_p].ir1 = 0; hst[hst_p].lac = 0; hst[hst_p].mq = lvl; -hst_p = (hst_p + 1) % HIST_SIZE; +hst_p = (hst_p + 1); +if (hst_p >= hst_lnt) hst_p = 0; return; } diff --git a/PDP18B/pdp18b_defs.h b/PDP18B/pdp18b_defs.h index 12798f3c..120be26e 100644 --- a/PDP18B/pdp18b_defs.h +++ b/PDP18B/pdp18b_defs.h @@ -23,6 +23,7 @@ be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. + 18-Oct-03 RMS Added DECtape off reel message 18-Jul-03 RMS Added FP15 support Added XVM support Added EAE option for PDP-4 @@ -110,6 +111,7 @@ #define STOP_NONSTD 6 /* non-std dev num */ #define STOP_MME 7 /* mem mgt error */ #define STOP_FPDIS 8 /* fp inst, fpp disabled */ +#define STOP_DTOFF 9 /* DECtape off reel */ /* Peripheral configuration */ diff --git a/PDP18B/pdp18b_doc.txt b/PDP18B/pdp18b_doc.txt index 881c75f9..f1428aa0 100644 --- a/PDP18B/pdp18b_doc.txt +++ b/PDP18B/pdp18b_doc.txt @@ -154,6 +154,7 @@ The 18b PDP simulators implement several unique stop conditions: instruction execution - an FP15 instruction is decoded, the FP15 is disabled, and register STOP_FPP is set + - a simulated DECtape runs off the end of its real The PDP-4 and PDP-7 LOAD command supports only "second stage" RIM format files (alternating DAC address instructions and data): @@ -273,6 +274,16 @@ control registers for the interrupt system. "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). +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 65536 entries. + 2.2 Floating Point Processor (FPP) The PDP-15 features an optional floating point processor, the FP15 (FPP). @@ -756,7 +767,6 @@ The DECtape controller implements these registers: 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 @@ -767,8 +777,9 @@ 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 + - DCTIME needs to be at least 100 times LTIME + +Acceleration time is set to 75% of deceleration time. 2.9 TC59/TU10 Magnetic Tape (MT) diff --git a/PDP18B/pdp18b_drm.c b/PDP18B/pdp18b_drm.c index 4c3b917f..b00333dd 100644 --- a/PDP18B/pdp18b_drm.c +++ b/PDP18B/pdp18b_drm.c @@ -25,6 +25,7 @@ drm (PDP-4,PDP-7) Type 24 serial drum + 26-Oct-03 RMS Cleaned up buffer copy code 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 @@ -165,6 +166,7 @@ t_stat drm_svc (UNIT *uptr) { int32 i; uint32 da; +int32 *fbuf = uptr->filebuf; if ((uptr->flags & UNIT_BUF) == 0) { /* not buf? abort */ drm_err = 1; /* set error */ @@ -173,13 +175,13 @@ if ((uptr->flags & UNIT_BUF) == 0) { /* not buf? abort */ da = drm_da * DRM_NUMWDS; /* compute dev addr */ for (i = 0; i < DRM_NUMWDS; i++, da++) { /* do transfer */ - if (uptr->FUNC == DRM_READ) { - if (MEM_ADDR_OK (drm_ma)) /* read, check nxm */ - M[drm_ma] = *(((int32 *) uptr->filebuf) + da); } - else { + if (uptr->FUNC == DRM_READ) { /* read? */ + if (MEM_ADDR_OK (drm_ma)) /* if !nxm */ + M[drm_ma] = fbuf[da]; } /* read word */ + else { /* write */ if ((drm_wlk >> (drm_da >> 4)) & 1) drm_err = 1; - else { - *(((int32 *) uptr->filebuf) + da) = M[drm_ma]; + else { /* not locked */ + fbuf[da] = M[drm_ma]; /* write word */ 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 */ diff --git a/PDP18B/pdp18b_dt.c b/PDP18B/pdp18b_dt.c index 1a5620ae..382aad93 100644 --- a/PDP18B/pdp18b_dt.c +++ b/PDP18B/pdp18b_dt.c @@ -27,6 +27,10 @@ (PDP-9) TC02/TU55 DECtape (PDP-15) TC15/TU56 DECtape + 26-Oct-03 RMS Cleaned up buffer copy code + 18-Oct-03 RMS Fixed reverse checksum in read all + Added DECtape off reel message + Simplified timing 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 @@ -56,13 +60,16 @@ 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 + Tape density is nominally 300 lines per inch. The format of a DECtape (as + taken from the TD8E formatter) is: - reverse end zone 36000 lines ~ 10 feet + reverse end zone 8192 reverse end zone codes ~ 10 feet + reverse buffer 200 interblock codes block 0 : block n - forward end zone 36000 lines ~ 10 feet + forward buffer 200 interblock codes + forward end zone 8192 forward end zone codes ~ 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 @@ -79,9 +86,9 @@ header word 0 0 header word 1 block number (for forward reads) header words 2,3 0 - header word 4 0 + header word 4 checksum (for reverse reads) : - trailer word 4 checksum + trailer word 4 checksum (for forward reads) trailer words 3,2 0 trailer word 1 block number (for reverse reads) trailer word 0 0 @@ -112,13 +119,15 @@ /* 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 */ +#define DT_LPERMC 6 /* lines per mark track */ +#define DT_BLKWD 1 /* blk no word in h/t */ +#define DT_CSMWD 4 /* checksum word in h/t */ +#define DT_HTWRD 5 /* header/trailer words */ +#define DT_EZLIN (8192 * DT_LPERMC) /* end zone length */ +#define DT_BFLIN (200 * DT_LPERMC) /* buffer length */ +#define DT_BLKLN (DT_BLKWD * DT_LPERMC) /* blk no line in h/t */ +#define DT_CSMLN (DT_CSMWD * DT_LPERMC) /* csum line in h/t */ +#define DT_HTLIN (DT_HTWRD * DT_LPERMC) /* header/trailer lines */ /* 16b, 18b, 36b DECtape constants */ @@ -317,8 +326,7 @@ 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_dctime = 40000; /* decel time */ int32 dt_substate = 0; int32 dt_log = 0; int32 dt_logblk = 0; @@ -390,7 +398,6 @@ REG dt_reg[] = { { 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 }, @@ -579,7 +586,7 @@ 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 */ + sim_activate (uptr, dt_dctime - (dt_dctime >> 2)); /* sched accel */ DTS_SETSTA (DTS_ACCF | new_dir, 0); /* state = accel */ DTS_SET2ND (DTS_ATSF | new_dir, new_fnc); /* next = fnc */ return; } @@ -605,7 +612,7 @@ if (prev_dir ^ new_dir) { /* dir chg? */ 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 */ + sim_activate (uptr, dt_dctime - (dt_dctime >> 2)); /* sched accel */ DTS_SETSTA (DTS_ACCF | new_dir, 0); /* state = accel */ DTS_SET2ND (DTS_ATSF | new_dir, new_fnc); /* next = fnc */ return; } @@ -744,11 +751,13 @@ case DTS_STOP: /* stop */ delta = 0; break; case DTS_DECF: /* slowing */ - ulin = ut / (uint32) dt_ltime; udelt = dt_dctime / dt_ltime; + 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; + ulin = ut / (uint32) dt_ltime; + udelt = (dt_dctime - (dt_dctime >> 2)) / dt_ltime; delta = (ulin * ulin) / (2 * udelt); break; case DTS_ATSF: /* at speed */ @@ -777,7 +786,7 @@ 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 *fbuf = uptr->filebuf; int32 unum = uptr - dt_dev.units; int32 blk, wrd, ma, relpos; uint32 ba; @@ -791,10 +800,10 @@ uint32 ba; switch (mot) { case DTS_DECF: case DTS_DECR: /* decelerating */ - if (dt_setpos (uptr)) return SCPE_OK; /* update pos */ + if (dt_setpos (uptr)) return STOP_DTOFF; /* update pos */ uptr->STATE = DTS_NXTSTA (uptr->STATE); /* advance state */ if (uptr->STATE) /* not stopped? */ - sim_activate (uptr, dt_actime); /* must be reversing */ + sim_activate (uptr, dt_dctime - (dt_dctime >> 2)); /* reversing */ return SCPE_OK; case DTS_ACCF: case DTS_ACCR: /* accelerating */ dt_newfnc (uptr, DTS_NXTSTA (uptr->STATE)); /* adv state, sched */ @@ -812,7 +821,7 @@ default: /* other */ Off reel - detach unit (it must be deselected) */ -if (dt_setpos (uptr)) return SCPE_OK; /* update pos */ +if (dt_setpos (uptr)) return STOP_DTOFF; /* update pos */ if (DT_QEZ (uptr)) { /* in end zone? */ dt_seterr (uptr, DTB_END); /* end zone error */ return SCPE_OK; } @@ -872,7 +881,7 @@ case FNC_READ: /* read */ 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 */ + dtdb = fbuf[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? */ @@ -924,7 +933,7 @@ case FNC_WRIT: /* write */ 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 */ + fbuf[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? */ @@ -960,7 +969,7 @@ case FNC_RALL: (relpos < (DTU_LPERB (uptr) - DT_HTLIN))) { wrd = DT_LIN2WD (uptr->pos, uptr); ba = (blk * DTU_BSIZE (uptr)) + wrd; - dtdb = bptr[ba]; } /* get tape word */ + dtdb = fbuf[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); @@ -996,7 +1005,7 @@ case FNC_WALL: if (dir) dtdb = dt_comobv (dtdb); wrd = DT_LIN2WD (uptr->pos, uptr); ba = (blk * DTU_BSIZE (uptr)) + wrd; - bptr[ba] = dtdb; /* write word */ + fbuf[ba] = dtdb; /* write word */ if (ba >= uptr->hwmark) uptr->hwmark = ba + 1; } /* /* ignore hdr */ sim_activate (uptr, DT_WSIZE * dt_ltime); @@ -1034,7 +1043,7 @@ case FNC_READ: case FNC_RALL: (relpos < (DTU_LPERB (uptr) - DT_HTLIN))) { wrd = DT_LIN2WD (uptr->pos, uptr); ba = (blk * DTU_BSIZE (uptr)) + wrd; - dtdb = bptr[ba]; /* get tape word */ + dtdb = fbuf[ba]; /* get tape word */ dtsb = dtsb | DTB_DTF; } /* set flag */ else { ma = (2 * DT_HTWRD) + DTU_BSIZE (uptr) - DT_CSMWD - 1; @@ -1063,8 +1072,8 @@ case FNC_WRIT: case FNC_WALL: (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 (dir) fbuf[ba] = dt_comobv (dtdb); /* get data word */ + else fbuf[ba] = dtdb; if (ba >= uptr->hwmark) uptr->hwmark = ba + 1; if (wrd == (dir? 0: DTU_BSIZE (uptr) - 1)) dtsb = dtsb | DTB_BEF; /* end block */ @@ -1133,20 +1142,20 @@ return dat; int32 dt_csum (UNIT *uptr, int32 blk) { -int32 *bptr = uptr->filebuf; +int32 *fbuf = 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 */ + wrd = fbuf[ba + i] ^ DMASK; /* get ~word */ csum = csum ^ (wrd >> 12) ^ (wrd >> 6) ^ wrd; } return (csum & 077); #else /* Type 550 */ -csum = DMASK; +csum = 0777777; for (i = 0; i < DTU_BSIZE (uptr); i++) { /* loop thru buf */ - wrd = bptr[ba + i]; /* get word */ + wrd = fbuf[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 */ @@ -1160,15 +1169,15 @@ 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 077; /* rev csum */ #if defined (TC02) /* TC02/TC15 */ -if (wrd == (2 * DT_HTWRD + DTU_BSIZE (uptr) - DT_CSMWD - 1)) /* fwd csum */ +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 */ +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 */ +if (wrd == ((2 * DT_HTWRD) + DTU_BSIZE (uptr) - DT_BLKWD - 1)) /* rev blkno */ return dt_comobv (blk); return 0; /* all others */ } @@ -1223,7 +1232,7 @@ t_stat dt_attach (UNIT *uptr, char *cptr) { uint16 pdp8b[D8_NBSIZE]; uint16 pdp11b[D18_BSIZE]; -uint32 ba, sz, k, *bptr; +uint32 ba, sz, k, *fbuf; int32 u = uptr - dt_dev.units; t_stat r; @@ -1246,7 +1255,7 @@ 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 */ +fbuf = 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"); @@ -1258,9 +1267,9 @@ if (uptr->flags & UNIT_8FMT) { /* 12b? */ 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) | + fbuf[ba] = ((uint32) (pdp8b[k] & 07777) << 6) | ((uint32) (pdp8b[k + 1] >> 6) & 077); - bptr[ba + 1] = ((uint32) (pdp8b[k + 1] & 077) << 12) | + fbuf[ba + 1] = ((uint32) (pdp8b[k + 1] & 077) << 12) | (pdp8b[k + 2] & 07777); ba = ba + 2; } /* end blk loop */ } /* end file loop */ @@ -1271,7 +1280,7 @@ else if (uptr->flags & UNIT_11FMT) { /* 16b? */ if (k == 0) break; for ( ; k < D18_BSIZE; k++) pdp11b[k] = 0; for (k = 0; k < D18_BSIZE; k++) - bptr[ba++] = pdp11b[k]; } + fbuf[ba++] = pdp11b[k]; } uptr->hwmark = ba; } /* end elif */ else uptr->hwmark = fxread (uptr->filebuf, sizeof (int32), uptr->capac, uptr->fileref); @@ -1294,7 +1303,7 @@ t_stat dt_detach (UNIT* uptr) { uint16 pdp8b[D8_NBSIZE]; uint16 pdp11b[D18_BSIZE]; -uint32 ba, k, *bptr; +uint32 ba, k, *fbuf; int32 u = uptr - dt_dev.units; if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; @@ -1304,17 +1313,17 @@ if (sim_is_active (uptr)) { dtsb = dtsb | DTB_ERF | DTB_SEL | DTB_DTF; DT_UPDINT; } uptr->STATE = uptr->pos = 0; } -bptr = uptr->filebuf; /* file buffer */ +fbuf = 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; + pdp8b[k] = (fbuf[ba] >> 6) & 07777; + pdp8b[k + 1] = ((fbuf[ba] & 077) << 6) | + ((fbuf[ba + 1] >> 12) & 077); + pdp8b[k + 2] = fbuf[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 */ @@ -1322,7 +1331,7 @@ if (uptr->hwmark && ((uptr->flags & UNIT_RO) == 0)) { /* any data? */ 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; + pdp11b[k] = fbuf[ba++] & 0177777; fxwrite (pdp11b, sizeof (int16), D18_BSIZE, uptr->fileref); if (ferror (uptr->fileref)) break; } /* end loop file */ } /* end if 16b */ diff --git a/PDP18B/pdp18b_rb.c b/PDP18B/pdp18b_rb.c index e3423225..839e1fcb 100644 --- a/PDP18B/pdp18b_rb.c +++ b/PDP18B/pdp18b_rb.c @@ -25,6 +25,8 @@ rb RB09 fixed head disk + 26-Oct-03 RMS Cleaned up buffer copy code + 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. @@ -219,6 +221,7 @@ return r; t_stat rb_svc (UNIT *uptr) { int32 t, sw; +int32 *fbuf = uptr->filebuf; if ((uptr->flags & UNIT_BUF) == 0) { /* not buf? abort */ rb_updsta (RBS_NRY | RBS_DON); /* set nxd, done */ @@ -230,11 +233,11 @@ do { if (rb_sta & RBS_WR) { /* write? */ if ((rb_wlk >> sw) & 1) { /* write locked? */ rb_updsta (RBS_ILA | RBS_DON); break; } - else { - *(((int32 *) uptr->filebuf) + rb_da) = M[rb_ma]; + else { /* not locked */ + fbuf[rb_da] = M[rb_ma]; /* write word */ 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); + M[rb_ma] = fbuf[rb_da]; /* read word */ 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 */ diff --git a/PDP18B/pdp18b_rf.c b/PDP18B/pdp18b_rf.c index 86c2e60c..ff7932f7 100644 --- a/PDP18B/pdp18b_rf.c +++ b/PDP18B/pdp18b_rf.c @@ -26,6 +26,7 @@ rf (PDP-9) RF09/RF09 (PDP-15) RF15/RS09 + 26-Oct-03 RMS Cleaned up buffer copy code 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 @@ -239,6 +240,7 @@ return dat; t_stat rf_svc (UNIT *uptr) { int32 f, pa, d, t; +int32 *fbuf = uptr->filebuf; if ((uptr->flags & UNIT_BUF) == 0) { /* not buf? abort */ rf_updsta (RFS_NED | RFS_DON); /* set nxd, done */ @@ -251,9 +253,8 @@ do { if ((uint32) rf_da >= uptr->capac) { /* disk overflow? */ 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))) { + M[pa] = fbuf[rf_da]; + if ((f == FN_WCHK) && (M[pa] != fbuf[rf_da])) { /* write check? */ rf_updsta (RFS_WCE); /* flag error */ break; } if (f == FN_WRITE) { /* write? */ @@ -262,8 +263,8 @@ do { if ((uint32) rf_da >= uptr->capac) { /* disk overflow? */ if ((rf_wlk[d] >> t) & 1) { /* write locked? */ rf_updsta (RFS_WLO); break; } - else { - *(((int32 *) uptr->filebuf) + rf_da) = M[pa]; + else { /* not locked */ + fbuf[rf_da] = M[pa]; /* write word */ if (((uint32) rf_da) >= uptr->hwmark) uptr->hwmark = rf_da + 1; } } rf_da = rf_da + 1; /* incr disk addr */ } diff --git a/PDP18B/pdp18b_stddev.c b/PDP18B/pdp18b_stddev.c index dc36133b..213924bb 100644 --- a/PDP18B/pdp18b_stddev.c +++ b/PDP18B/pdp18b_stddev.c @@ -29,6 +29,7 @@ tto teleprinter clk clock + 29-Dec-03 RMS Added console backpressure support 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 @@ -839,40 +840,40 @@ t_stat tti_svc (UNIT *uptr) #if defined (KSR28) /* Baudot... */ int32 c; -sim_activate (&tti_unit, tti_unit.wait); /* continue poll */ +sim_activate (uptr, uptr->wait); /* continue poll */ if (tti_state & TTI_2ND) { /* char waiting? */ - tti_unit.buf = tti_state & TTI_MASK; /* return char */ + uptr->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; + (c & TTI_BOTH)) uptr->buf = c & TTI_MASK; else { - tti_unit.buf = (c & TTI_FIGURES)? + uptr->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 */ +sim_activate (uptr, uptr->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? */ +else if (uptr->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 */ +else c = c & ((uptr->flags & UNIT_8B)? 0377: 0177); /* no, 7b/8b */ +if ((uptr->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 */ +uptr->buf = c; /* got char */ #endif -tti_unit.pos = tti_unit.pos + 1; +uptr->pos = uptr->pos + 1; SET_INT (TTI); /* set flag */ return SCPE_OK; } @@ -926,24 +927,27 @@ 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? */ +if (uptr->buf == BAUDOT_FIGURES) /* set figures? */ tto_state = TTO_FIGURES; - return SCPE_OK; } -if (tto_unit.buf == BAUDOT_LETTERS) { /* set letters? */ +else if (uptr->buf == BAUDOT_LETTERS) /* set letters? */ tto_state = 0; - return SCPE_OK; } -c = tto_trans[tto_unit.buf + tto_state]; /* translate */ +else { c = tto_trans[uptr->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); +c = uptr->buf & 0177; /* assume 7b or KSR */ +if (!(uptr->flags & UNIT_KSR) || /* 7b/8b or */ + ((c >= 007) && (c <= 0137))) { /* in range? */ + if ((uptr->flags & UNIT_KSR) && islower (c)) /* KSR? */ + c = toupper (c); + else if (tto_unit.flags & UNIT_8B) c = uptr->buf; #endif -if ((r = sim_putchar (c)) != SCPE_OK) return r; -tto_unit.pos = tto_unit.pos + 1; + + if ((r = sim_putchar_s (c)) != SCPE_OK) { /* output; error? */ + sim_activate (uptr, uptr->wait); /* retry? */ + return ((r == SCPE_STALL)? SCPE_OK: r); } } +SET_INT (TTO); /* set flag */ +uptr->pos = uptr->pos + 1; return SCPE_OK; } diff --git a/PDP18B/pdp18b_sys.c b/PDP18B/pdp18b_sys.c index 583de1b0..683966fe 100644 --- a/PDP18B/pdp18b_sys.c +++ b/PDP18B/pdp18b_sys.c @@ -23,6 +23,7 @@ be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. + 18-Oct-03 RMS Added DECtape off reel message 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 @@ -170,7 +171,8 @@ const char *sim_stop_messages[] = { "Invalid API interrupt", "Non-standard device number", "Memory management error", - "FP15 instruction disabled" }; + "FP15 instruction disabled", + "DECtape off reel" }; /* Binary loaders */ diff --git a/PDP8/pdp8_cpu.c b/PDP8/pdp8_cpu.c index dbada524..c880d584 100644 --- a/PDP8/pdp8_cpu.c +++ b/PDP8/pdp8_cpu.c @@ -1,6 +1,6 @@ /* pdp8_cpu.c: PDP-8 CPU simulator - Copyright (c) 1993-2003, Robert M Supnik + Copyright (c) 1993-2004, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -25,6 +25,9 @@ cpu central processor + 31-Dec-03 RMS Fixed bug in set_cpu_hist + 13-Oct-03 RMS Added instruction history + Added TSC8-75 support (from Bernhard Baehr) 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 @@ -184,12 +187,23 @@ #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_ENTRY pcq[pcq_p = (pcq_p - 1) & PCQ_MASK] = MA #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) +#define HIST_PC 0x40000000 +#define HIST_MIN 64 +#define HIST_MAX 65536 +struct InstHistory { + int32 pc; + int32 ea; + int16 ir; + int16 opnd; + int16 lac; + int16 mq; }; + uint16 M[MAXMEMSIZE] = { 0 }; /* main memory */ int32 saved_LAC = 0; /* saved L'AC */ int32 saved_MQ = 0; /* saved MQ */ @@ -203,6 +217,10 @@ int32 SC = 0; /* EAE shift count */ int32 UB = 0; /* User mode Buffer */ int32 UF = 0; /* User mode Flag */ int32 OSR = 0; /* Switch Register */ +int32 tsc_ir = 0; /* TSC8-75 IR */ +int32 tsc_pc = 0; /* TSC8-75 PC */ +int32 tsc_cdf = 0; /* TSC8-75 CDF flag */ +int32 tsc_enb = 0; /* TSC8-75 enabled */ int16 pcq[PCQ_SIZE] = { 0 }; /* PC queue */ int32 pcq_p = 0; /* PC queue ptr */ REG *pcq_r = NULL; /* PC queue reg ptr */ @@ -211,6 +229,9 @@ 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 */ +int32 hst_p = 0; /* history pointer */ +int32 hst_lnt = 0; /* history length */ +struct InstHistory *hst = NULL; /* instruction history */ extern int32 sim_interval; extern int32 sim_int_char; @@ -223,6 +244,8 @@ 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); t_bool build_dev_tab (void); /* CPU data structures @@ -275,6 +298,8 @@ MTAB cpu_mod[] = { { UNIT_MSIZE, 24576, NULL, "24K", &cpu_set_size }, { UNIT_MSIZE, 28672, NULL, "28K", &cpu_set_size }, { UNIT_MSIZE, 32768, NULL, "32K", &cpu_set_size }, + { MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, "HISTORY", "HISTORY", + &cpu_set_hist, &cpu_show_hist }, { 0 } }; DEVICE cpu_dev = { @@ -335,9 +360,8 @@ sim_interval = sim_interval - 1; 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. + AND, TAD, ISZ, DCA calculate a full 15b effective address. + JMS, JMP calculate a 12b field-relative effective address. Autoindex calculations always occur within the same field as the instruction fetch. The field must exist; otherwise, the instruction @@ -346,84 +370,103 @@ sim_interval = sim_interval - 1; 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) +if (hst_lnt) { /* history enabled? */ + int32 ea; -#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 + hst_p = (hst_p + 1); /* next entry */ + if (hst_p >= hst_lnt) hst_p = 0; + hst[hst_p].pc = MA | HIST_PC; /* save PC, IR, LAC, MQ */ + hst[hst_p].ir = IR; + hst[hst_p].lac = LAC; + hst[hst_p].mq = MQ; + if (IR < 06000) { /* mem ref? */ + if (IR & 0200) ea = (MA & 077600) | (IR & 0177); + else ea = IF | (IR & 0177); /* direct addr */ + if (IR & 0400) { /* indirect? */ + if (IR < 04000) { /* mem operand? */ + if ((ea & 07770) != 00010) ea = DF | M[ea]; + else ea = DF | ((M[ea] + 1) & 07777); } + else { /* no, jms/jmp */ + if ((ea & 07770) != 00010) ea = IB | M[ea]; + else ea = IB | ((M[ea] + 1) & 07777); } + } + hst[hst_p].ea = ea; /* save eff addr */ + hst[hst_p].opnd = M[ea]; /* save operand */ + } + } switch ((IR >> 7) & 037) { /* decode IR<0:4> */ /* Opcode 0, AND */ case 000: /* AND, dir, zero */ - ZERO_PAGE; + MA = IF | (IR & 0177); /* dir addr, page zero */ LAC = LAC & (M[MA] | 010000); break; case 001: /* AND, dir, curr */ - CURR_PAGE; + MA = (MA & 077600) | (IR & 0177); /* dir addr, curr page */ LAC = LAC & (M[MA] | 010000); break; case 002: /* AND, indir, zero */ - ZERO_PAGE; - INDIRECT; + MA = IF | (IR & 0177); /* dir addr, page zero */ + if ((MA & 07770) != 00010) MA = DF | M[MA]; /* indirect; autoinc? */ + else MA = DF | (M[MA] = (M[MA] + 1) & 07777); /* incr before use */ LAC = LAC & (M[MA] | 010000); break; case 003: /* AND, indir, curr */ - CURR_PAGE; - INDIRECT; + MA = (MA & 077600) | (IR & 0177); /* dir addr, curr page */ + if ((MA & 07770) != 00010) MA = DF | M[MA]; /* indirect; autoinc? */ + else MA = DF | (M[MA] = (M[MA] + 1) & 07777); /* incr before use */ LAC = LAC & (M[MA] | 010000); break; /* Opcode 1, TAD */ case 004: /* TAD, dir, zero */ - ZERO_PAGE; + MA = IF | (IR & 0177); /* dir addr, page zero */ LAC = (LAC + M[MA]) & 017777; break; case 005: /* TAD, dir, curr */ - CURR_PAGE; + MA = (MA & 077600) | (IR & 0177); /* dir addr, curr page */ LAC = (LAC + M[MA]) & 017777; break; case 006: /* TAD, indir, zero */ - ZERO_PAGE; - INDIRECT; + MA = IF | (IR & 0177); /* dir addr, page zero */ + if ((MA & 07770) != 00010) MA = DF | M[MA]; /* indirect; autoinc? */ + else MA = DF | (M[MA] = (M[MA] + 1) & 07777); /* incr before use */ LAC = (LAC + M[MA]) & 017777; break; case 007: /* TAD, indir, curr */ - CURR_PAGE; - INDIRECT; + MA = (MA & 077600) | (IR & 0177); /* dir addr, curr page */ + if ((MA & 07770) != 00010) MA = DF | M[MA]; /* indirect; autoinc? */ + else MA = DF | (M[MA] = (M[MA] + 1) & 07777); /* incr before use */ LAC = (LAC + M[MA]) & 017777; break; /* Opcode 2, ISZ */ case 010: /* ISZ, dir, zero */ - ZERO_PAGE; + MA = IF | (IR & 0177); /* dir addr, page zero */ 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; + MA = (MA & 077600) | (IR & 0177); /* dir addr, 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; + MA = IF | (IR & 0177); /* dir addr, page zero */ + if ((MA & 07770) != 00010) MA = DF | M[MA]; /* indirect; autoinc? */ + else MA = DF | (M[MA] = (M[MA] + 1) & 07777); /* incr before use */ 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; + MA = (MA & 077600) | (IR & 0177); /* dir addr, curr page */ + if ((MA & 07770) != 00010) MA = DF | M[MA]; /* indirect; autoinc? */ + else MA = DF | (M[MA] = (M[MA] + 1) & 07777); /* incr before use */ MB = (M[MA] + 1) & 07777; if (MEM_ADDR_OK (MA)) M[MA] = MB; if (MB == 0) PC = (PC + 1) & 07777; @@ -432,91 +475,178 @@ case 013: /* ISZ, indir, curr */ /* Opcode 3, DCA */ case 014: /* DCA, dir, zero */ - ZERO_PAGE; + MA = IF | (IR & 0177); /* dir addr, page zero */ M[MA] = LAC & 07777; LAC = LAC & 010000; break; case 015: /* DCA, dir, curr */ - CURR_PAGE; + MA = (MA & 077600) | (IR & 0177); /* dir addr, curr page */ M[MA] = LAC & 07777; LAC = LAC & 010000; break; case 016: /* DCA, indir, zero */ - ZERO_PAGE; - INDIRECT; + MA = IF | (IR & 0177); /* dir addr, page zero */ + if ((MA & 07770) != 00010) MA = DF | M[MA]; /* indirect; autoinc? */ + else MA = DF | (M[MA] = (M[MA] + 1) & 07777); /* incr before use */ if (MEM_ADDR_OK (MA)) M[MA] = LAC & 07777; LAC = LAC & 010000; break; case 017: /* DCA, indir, curr */ - CURR_PAGE; - INDIRECT; + MA = (MA & 077600) | (IR & 0177); /* dir addr, curr page */ + if ((MA & 07770) != 00010) MA = DF | M[MA]; /* indirect; autoinc? */ + else MA = DF | (M[MA] = (M[MA] + 1) & 07777); /* incr before use */ if (MEM_ADDR_OK (MA)) M[MA] = LAC & 07777; LAC = LAC & 010000; break; -/* Opcode 4, JMS */ +/* Opcode 4, JMS. From Bernhard Baehr's description of the TSC8-75: + + (In user mode) the current JMS opcode is moved to the ERIOT register, the ECDF + flag is cleared. The address of the JMS instruction is loaded into the ERTB + register and the TSC8-75 I/O flag is raised. When the TSC8-75 is enabled, the + target addess of the JMS is loaded into PC, but nothing else (loading of IF, UF, + clearing the interrupt inhibit flag, storing of the return address in the first + word of the subroutine) happens. When the TSC8-75 is disabled, the JMS is performed + as usual. */ case 020: /* JMS, dir, zero */ - ZERO_PAGE_J; - CHANGE_FIELD; - MA = IF | MA; PCQ_ENTRY; - if (MEM_ADDR_OK (MA)) M[MA] = PC; + MA = IR & 0177; /* dir addr, page zero */ + if (UF) { /* user mode? */ + tsc_ir = IR; /* save instruction */ + tsc_cdf = 0; } /* clear flag */ + if (UF && tsc_enb) { /* user mode, TSC enab? */ + tsc_pc = (PC - 1) & 07777; /* save PC */ + int_req = int_req | INT_TSC; } /* request intr */ + else { /* normal */ + IF = IB; /* change IF */ + UF = UB; /* change UF */ + int_req = int_req | INT_NO_CIF_PENDING; /* clr intr inhibit */ + MA = IF | MA; + 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; + MA = (MA & 007600) | (IR & 0177); /* dir addr, curr page */ + if (UF) { /* user mode? */ + tsc_ir = IR; /* save instruction */ + tsc_cdf = 0; } /* clear flag */ + if (UF && tsc_enb) { /* user mode, TSC enab? */ + tsc_pc = (PC - 1) & 07777; /* save PC */ + int_req = int_req | INT_TSC; } /* request intr */ + else { /* normal */ + IF = IB; /* change IF */ + UF = UB; /* change UF */ + int_req = int_req | INT_NO_CIF_PENDING; /* clr intr inhibit */ + MA = IF | MA; + 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; + MA = IF | (IR & 0177); /* dir addr, page zero */ + if ((MA & 07770) != 00010) MA = M[MA]; /* indirect; autoinc? */ + else MA = (M[MA] = (M[MA] + 1) & 07777); /* incr before use */ + if (UF) { /* user mode? */ + tsc_ir = IR; /* save instruction */ + tsc_cdf = 0; } /* clear flag */ + if (UF && tsc_enb) { /* user mode, TSC enab? */ + tsc_pc = (PC - 1) & 07777; /* save PC */ + int_req = int_req | INT_TSC; } /* request intr */ + else { /* normal */ + IF = IB; /* change IF */ + UF = UB; /* change UF */ + int_req = int_req | INT_NO_CIF_PENDING; /* clr intr inhibit */ + MA = IF | MA; + 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; + MA = (MA & 077600) | (IR & 0177); /* dir addr, curr page */ + if ((MA & 07770) != 00010) MA = M[MA]; /* indirect; autoinc? */ + else MA = (M[MA] = (M[MA] + 1) & 07777); /* incr before use */ + if (UF) { /* user mode? */ + tsc_ir = IR; /* save instruction */ + tsc_cdf = 0; } /* clear flag */ + if (UF && tsc_enb) { /* user mode, TSC enab? */ + tsc_pc = (PC - 1) & 07777; /* save PC */ + int_req = int_req | INT_TSC; } /* request intr */ + else { /* normal */ + IF = IB; /* change IF */ + UF = UB; /* change UF */ + int_req = int_req | INT_NO_CIF_PENDING; /* clr intr inhibit */ + MA = IF | MA; + if (MEM_ADDR_OK (MA)) M[MA] = PC; } PC = (MA + 1) & 07777; break; + +/* Opcode 5, JMP. From Bernhard Baehr's description of the TSC8-75: -/* Opcode 5, JMP */ + (In user mode) the current JMP opcode is moved to the ERIOT register, the ECDF + flag is cleared. The address of the JMP instruction is loaded into the ERTB + register and the TSC8-75 I/O flag is raised. Then the JMP is performed as usual + (including the setting of IF, UF and clearing the interrupt inhibit flag). */ case 024: /* JMP, dir, zero */ - ZERO_PAGE_J; - CHANGE_FIELD; PCQ_ENTRY; + MA = IR & 0177; /* dir addr, page zero */ + if (UF) { /* user mode? */ + tsc_ir = IR; /* save instruction */ + tsc_cdf = 0; /* clear flag */ + if (tsc_enb) { /* TSC8 enabled? */ + tsc_pc = (PC - 1) & 07777; /* save PC */ + int_req = int_req | INT_TSC; } } /* request intr */ + IF = IB; /* change IF */ + UF = UB; /* change UF */ + int_req = int_req | INT_NO_CIF_PENDING; /* clr intr inhibit */ PC = MA; break; case 025: /* JMP, dir, curr */ - CURR_PAGE_J; - CHANGE_FIELD; PCQ_ENTRY; + MA = (MA & 007600) | (IR & 0177); /* dir addr, curr page */ + if (UF) { /* user mode? */ + tsc_ir = IR; /* save instruction */ + tsc_cdf = 0; /* clear flag */ + if (tsc_enb) { /* TSC8 enabled? */ + tsc_pc = (PC - 1) & 07777; /* save PC */ + int_req = int_req | INT_TSC; } } /* request intr */ + IF = IB; /* change IF */ + UF = UB; /* change UF */ + int_req = int_req | INT_NO_CIF_PENDING; /* clr intr inhibit */ PC = MA; break; case 026: /* JMP, indir, zero */ - ZERO_PAGE; - INDIRECT_J; - CHANGE_FIELD; PCQ_ENTRY; + MA = IF | (IR & 0177); /* dir addr, page zero */ + if ((MA & 07770) != 00010) MA = M[MA]; /* indirect; autoinc? */ + else MA = (M[MA] = (M[MA] + 1) & 07777); /* incr before use */ + if (UF) { /* user mode? */ + tsc_ir = IR; /* save instruction */ + tsc_cdf = 0; /* clear flag */ + if (tsc_enb) { /* TSC8 enabled? */ + tsc_pc = (PC - 1) & 07777; /* save PC */ + int_req = int_req | INT_TSC; } } /* request intr */ + IF = IB; /* change IF */ + UF = UB; /* change UF */ + int_req = int_req | INT_NO_CIF_PENDING; /* clr intr inhibit */ PC = MA; break; case 027: /* JMP, indir, curr */ - CURR_PAGE; - INDIRECT_J; - CHANGE_FIELD; PCQ_ENTRY; + MA = (MA & 077600) | (IR & 0177); /* dir addr, curr page */ + if ((MA & 07770) != 00010) MA = M[MA]; /* indirect; autoinc? */ + else MA = (M[MA] = (M[MA] + 1) & 07777); /* incr before use */ + if (UF) { /* user mode? */ + tsc_ir = IR; /* save instruction */ + tsc_cdf = 0; /* clear flag */ + if (tsc_enb) { /* TSC8 enabled? */ + tsc_pc = (PC - 1) & 07777; /* save PC */ + int_req = int_req | INT_TSC; } } /* request intr */ + IF = IB; /* change IF */ + UF = UB; /* change UF */ + int_req = int_req | INT_NO_CIF_PENDING; /* clr intr inhibit */ PC = MA; break; @@ -601,7 +731,11 @@ case 034:case 035: /* OPR, group 1 */ break; } /* uses address path */ break; /* end group 1 */ -/* OPR group 2 */ +/* OPR group 2. From Bernhard Baehr's description of the TSC8-75: + + (In user mode) HLT (7402), OSR (7404) and microprogrammed combinations with + HLT and OSR: Additional to raising a user mode interrupt, the current OPR + opcode is moved to the ERIOT register and the ECDF flag is cleared. */ case 036:case 037: /* OPR, groups 2, 3 */ if ((IR & 01) == 0) { /* group 2 */ @@ -657,7 +791,10 @@ case 036:case 037: /* OPR, groups 2, 3 */ 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; + if ((IR & 06) && UF) { /* user mode? */ + int_req = int_req | INT_UF; /* request intr */ + tsc_ir = IR; /* save instruction */ + tsc_cdf = 0; } /* clear flag */ else { if (IR & 04) LAC = LAC | OSR; /* OSR */ if (IR & 02) reason = STOP_HALT; } /* HLT */ @@ -745,7 +882,8 @@ case 036:case 037: /* OPR, groups 2, 3 */ case 021: /* mode B: DAD */ if (emode) { MA = IF | PC; - INDIRECT; /* defer state */ + if ((MA & 07770) != 00010) MA = DF | M[MA]; /* indirect; autoinc? */ + else MA = DF | (M[MA] = (M[MA] + 1) & 07777); /* incr before use */ MQ = MQ + M[MA]; MA = DF | ((MA + 1) & 07777); LAC = (LAC & 07777) + M[MA] + (MQ >> 12); @@ -764,7 +902,8 @@ case 036:case 037: /* OPR, groups 2, 3 */ case 022: /* mode B: DST */ if (emode) { MA = IF | PC; - INDIRECT; /* defer state */ + if ((MA & 07770) != 00010) MA = DF | M[MA]; /* indirect; autoinc? */ + else MA = DF | (M[MA] = (M[MA] + 1) & 07777); /* incr before use */ if (MEM_ADDR_OK (MA)) M[MA] = MQ & 07777; MA = DF | ((MA + 1) & 07777); if (MEM_ADDR_OK (MA)) M[MA] = LAC & 07777; @@ -773,7 +912,10 @@ case 036:case 037: /* OPR, groups 2, 3 */ LAC = LAC | SC; /* mode A: SCA then */ case 002: /* MUY */ MA = IF | PC; - if (emode) { INDIRECT; } /* mode B: defer */ + if (emode) { /* mode B: defer */ + if ((MA & 07770) != 00010) MA = DF | M[MA]; /* indirect; autoinc? */ + else MA = DF | (M[MA] = (M[MA] + 1) & 07777); /* incr before use */ + } temp = (MQ * M[MA]) + (LAC & 07777); LAC = (temp >> 12) & 07777; MQ = temp & 07777; @@ -788,7 +930,10 @@ case 036:case 037: /* OPR, groups 2, 3 */ LAC = LAC | SC; /* mode A: SCA then */ case 003: /* DVI */ MA = IF | PC; - if (emode) { INDIRECT; } /* mode B: defer */ + if (emode) { /* mode B: defer */ + if ((MA & 07770) != 00010) MA = DF | M[MA]; /* indirect; autoinc? */ + else MA = DF | (M[MA] = (M[MA] + 1) & 07777); /* incr before use */ + } if ((LAC & 07777) >= M[MA]) { /* overflow? */ LAC = LAC | 010000; /* set link */ MQ = ((MQ << 1) + 1) & 07777; /* rotate MQ */ @@ -873,11 +1018,18 @@ case 036:case 037: /* OPR, groups 2, 3 */ break; } /* end switch */ break; /* end case 7 */ -/* Opcode 6, IOT */ +/* Opcode 6, IOT. From Bernhard Baehr's description of the TSC8-75: + + (In user mode) Additional to raising a user mode interrupt, the current IOT + opcode is moved to the ERIOT register. When the IOT is a CDF instruction (62x1), + the ECDF flag is set, otherwise it is cleared. */ case 030:case 031:case 032:case 033: /* IOT */ if (UF) { /* privileged? */ - int_req = int_req | INT_UF; + int_req = int_req | INT_UF; /* request intr */ + tsc_ir = IR; /* save instruction */ + if ((IR & 07707) == 06201) tsc_cdf = 1; /* set/clear flag */ + else tsc_cdf = 0; break; } device = (IR >> 3) & 077; /* device = IR<3:8> */ pulse = IR & 07; /* pulse = IR<9:11> */ @@ -922,6 +1074,7 @@ case 030:case 031:case 032:case 033: /* IOT */ dev_done = 0; int_enable = INT_INIT_ENABLE; LAC = 0; + reset_all (1); /* reset all dev */ break; } /* end switch pulse */ break; /* end case 0 */ @@ -1143,3 +1296,58 @@ for (i = 0; (dptr = sim_devices[i]) != NULL; i++) { /* add devices */ } /* 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 < hst_lnt; i++) hst[i].pc = 0; + hst_p = 0; + return SCPE_OK; } +lnt = (int32) get_uint (cptr, 10, HIST_MAX, &r); +if ((r != SCPE_OK) || (lnt && (lnt < HIST_MIN))) return SCPE_ARG; +hst_p = 0; +if (hst_lnt) { + free (hst); + hst_lnt = 0; + hst = NULL; } +if (lnt) { + hst = calloc (sizeof (struct InstHistory), lnt); + if (hst == NULL) return SCPE_MEM; + hst_lnt = lnt; } +return SCPE_OK; +} + +/* Show history */ + +t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, void *desc) +{ +int32 l, k, di; +t_value sim_eval; +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? */ +fprintf (st, "PC L AC MQ ea IR\n\n"); +di = hst_p; /* work forward */ +for (k = 0; k < hst_lnt; k++) { /* print specified */ + h = &hst[(++di) % hst_lnt]; /* entry pointer */ + if (h->pc & HIST_PC) { /* instruction? */ + l = (h->lac >> 12) & 1; /* link */ + fprintf (st, "%05o %o %04o %04o ", h->pc & ADDRMASK, l, h->lac & 07777, h->mq); + if (h->ir < 06000) fprintf (st, "%05o ", h->ea); + else fprintf (st, " "); + sim_eval = h->ir; + if ((fprint_sym (st, h->pc & ADDRMASK, &sim_eval, &cpu_unit, SWMASK ('M'))) > 0) + fprintf (st, "(undefined) %04o", h->ir); + if (h->ir < 04000) fprintf (st, " [%04o]", h->opnd); + fputc ('\n', st); /* end line */ + } /* end else instruction */ + } /* end for */ +return SCPE_OK; +} diff --git a/PDP8/pdp8_defs.h b/PDP8/pdp8_defs.h index 74c9fed7..7d6c30b1 100644 --- a/PDP8/pdp8_defs.h +++ b/PDP8/pdp8_defs.h @@ -23,6 +23,7 @@ be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. + 13-Oct-03 RMS Added TSC8-75 support 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 @@ -45,6 +46,7 @@ #define STOP_HALT 2 /* HALT */ #define STOP_IBKPT 3 /* breakpoint */ #define STOP_NOTSTD 4 /* non-std devno */ +#define STOP_DTOFF 5 /* DECtape off reel */ /* Memory */ @@ -86,6 +88,7 @@ typedef struct pdp8_dib DIB; #define DEV_TTI 003 /* console input */ #define DEV_TTO 004 /* console output */ #define DEV_CLK 013 /* clock */ +#define DEV_TSC 036 #define DEV_KJ8 040 /* extra terminals */ #define DEV_DF 060 /* DF32 */ #define DEV_RF 060 /* RF08 */ @@ -95,6 +98,7 @@ typedef struct pdp8_dib DIB; #define DEV_RK 074 /* RK8E */ #define DEV_RX 075 /* RX8E/RX28 */ #define DEV_DTA 076 /* TC08 */ +#define DEV_TD8E 077 /* TD8E */ /* Interrupt flags @@ -143,7 +147,8 @@ typedef struct pdp8_dib DIB; #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_TSC (INT_V_DIRECT+9) /* TSC8-75 int */ +#define INT_V_OVHD (INT_V_DIRECT+10) /* 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 */ @@ -171,6 +176,7 @@ typedef struct pdp8_dib DIB; #define INT_RL (1 << INT_V_RL) #define INT_PWR (1 << INT_V_PWR) #define INT_UF (1 << INT_V_UF) +#define INT_TSC (1 << INT_V_TSC) #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) diff --git a/PDP8/pdp8_df.c b/PDP8/pdp8_df.c index 3e28847c..c4e1db73 100644 --- a/PDP8/pdp8_df.c +++ b/PDP8/pdp8_df.c @@ -25,6 +25,7 @@ df DF32 fixed head disk + 26-Oct-03 RMS Cleaned up buffer copy code 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 @@ -231,6 +232,7 @@ t_stat df_svc (UNIT *uptr) { int32 pa, t, mex; uint32 da; +int16 *fbuf = uptr->filebuf; UPDATE_PCELL; /* update photocell */ if ((uptr->flags & UNIT_BUF) == 0) { /* not buf? abort */ @@ -247,13 +249,13 @@ do { if (da >= uptr->capac) { /* nx disk addr? */ 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); } + if (MEM_ADDR_OK (pa)) M[pa] = fbuf[da]; } /* if !nxm, read wd */ else { /* write */ t = (da >> 14) & 07; /* check wr lock */ - if ((df_wlk >> t) & 1) df_sta = df_sta | DFS_WLS; + if ((df_wlk >> t) & 1) /* locked? set err */ + df_sta = df_sta | DFS_WLS; else { /* not locked */ - *(((int16 *) uptr->filebuf) + da) = M[pa]; + fbuf[da] = M[pa]; /* write word */ 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 */ diff --git a/PDP8/pdp8_doc.txt b/PDP8/pdp8_doc.txt index 08f8a218..1e4018e6 100644 --- a/PDP8/pdp8_doc.txt +++ b/PDP8/pdp8_doc.txt @@ -59,6 +59,8 @@ sim/pdp8/ pdp8_defs.h pdp8_rl.c pdp8_rx.c pdp8_sys.c + pdp8_td.c + pdp8_tsc.c pdp8_tt.c pdp8_ttx.c @@ -72,6 +74,7 @@ name(s) CPU PDP-8/E CPU with 4KW-32KW of memory - KE8E extended arithmetic element (EAE) - KM8E memory management and timeshare control +TSC TSC8-75 ETOS operating system timeshare control PTR,PTP PC8E paper tape reader/punch TTI,TTO KL8E console terminal TTIX,TTOX KL8JA additional terminals @@ -83,6 +86,7 @@ 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 +TD TD8E/TU56 DECtape controller with two drives MT TM8E/TU10 magnetic tape controller with eight drives Most devices can be disabled or enabled, by the commands: @@ -102,17 +106,28 @@ default is the RF08. To change the disk at device numbers 60-61: sim> SET DF ENABLED, or enable DF32 sim> SET RL ENABLED enable RL8A +The PDP-8 can only support one of the set {TC08, TD8E} using the default +device numbers, since both use device number 77. The default is the +TC08. To change the DECtape controller to the TD8E: + + sim> SET DT DISABLED disable TC08 + sim> SET TD ENABLED enable TD8E + Alternately, the device conflict can be eliminated by changing device numbers: sim> SET RL DEV=50 sim> SET RL ENA + sim> SET TD DEV=74 + sim> SET TD 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 simulator implements several unique stop conditions: + + - if an undefined instruction (unimplemented IOT or OPR) is + decoded, and register STOP_INST + - if a simulated DECtape runs off the end of its reel 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 @@ -172,9 +187,38 @@ control registers for the interrupt system. STOP_INST 1 stop on undefined instruction WRU 8 interrupt character -2.2 Programmed I/O Devices +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: -2.2.1 PC8E Paper Tape Reader (PTR) + 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 65536 entries. + +2.2 TSC8-75 ETOS Timeshare Control (TSC) + +ETOS is a timeshared operating system for the PDP-8, providing multiple +virtual OS/8 environments for up to 32 users. It requires a special +timeshare control option, the TSC8-75. The TSC8-75 is normally disabled; +to run ETOS, it must be enabled with the command: + + SET TSC ENABLED + +The TSC8-75 implements these registers: + + IR most recently trapped instruction + PC PC of most recently trapped instruction + CDF 1 if trapped instruction is CDF, 0 otherwise + ENB interrupt enable flag + INT interrupt pending flag + +Except for operation of ETOS, the TSC8-75 should be left disabled. + +2.3 Programmed I/O Devices + +2.3.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, @@ -207,7 +251,7 @@ Error handling is as follows: OS I/O error x report error and stop -2.2.2 PC8E Paper Tape Punch (PTP) +2.3.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 @@ -234,7 +278,7 @@ Error handling is as follows: OS I/O error x report error and stop -2.2.3 KL8E Terminal Input (TTI) +2.3.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 @@ -261,7 +305,7 @@ to simulate typing ^C: SET TTI CTRL-C -2.2.4 KL8E Terminal Output (TTO) +2.3.4 KL8E Terminal Output (TTO) The terminal output (TTO) writes to the simulator console window. It implements these registers: @@ -275,7 +319,7 @@ implements these registers: POS 32 number of characters output TIME 24 time from I/O initiation to interrupt -2.2.5 LE8E Line Printer (LPT) +2.3.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, @@ -302,7 +346,7 @@ Error handling is as follows: OS I/O error x report error and stop -2.2.6 DK8E Line-Frequency Clock (CLK) +2.3.6 DK8E Line-Frequency Clock (CLK) The real-time clock (CLK) frequency can be adjusted as follows: @@ -323,7 +367,7 @@ The clock implements these registers: 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) +2.3.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 @@ -378,9 +422,58 @@ The output device (TTOX) implements these registers: 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.8 TD8E/TU56 DECtape (TD) -2.3.1 RK8E Cartridge Disk (RK) +The TD8E is a programmed I/O, non-interrupt controller, supporting two +DECtape drives (0 and 1). The TD8E simulator puts a high burden on the +host processor, because tape activity is simulated a line (3b) at a time. +Unless the PDP-8 software requires the TD8E, the TC08 should be used +to simulate DECtapes. The TD8E is disabled by default. + +TD8E 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 TD8E supports the BOOT command. + +The TD8E 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 TD8E controller is a data-only simulator; the timing and mark +track, and block header and trailer, are not stored. Thus, read always +produces standard values for header and trailer words, and write throws +header and trailer words into the bit bucket. + +The TD8E controller implements these registers: + + name size comments + + TDCMD 4 command register + TDDAT 12 data register + TDMTK 6 mark track register + TDSLF 1 single line flag + TDQLF 1 quad line flag + TDTME 1 timing error flag + TDQL 2 quad line counter + LTIME 31 time between lines + DCTIME 31 time to decelerate to a full stop + POS[0:7] 32 position, in lines, units 0-7 + STATT[0:7] 18 unit state, units 0-7 + +The LTIME parameter should not be changed, or OS/8 may fail to run +correctly. The DCTIME parameter should always be at least 100 times +greater than LTIME. Acceleration time is 75% of deceleration time. + +2.4 Moving Head Disks + +2.4.1 RK8E Cartridge Disk (RK) RK8E options include the ability to make units write enabled or write locked: @@ -414,7 +507,7 @@ Error handling is as follows: OS I/O error x report error and stop -2.3.2 RL8A Cartridge Disk (RL) +2.4.2 RL8A Cartridge Disk (RL) RL8A options include the ability to make units write enabled or write locked: @@ -455,7 +548,7 @@ Error handling is as follows: OS I/O error x report error and stop -2.4 RX8E/RX01, RX28/RX02 Floppy Disk (RX) +2.5 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: @@ -513,12 +606,12 @@ Error handling is as follows: 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 +2.6 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) +2.6.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 @@ -564,7 +657,7 @@ Error handling is as follows: 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) +2.6.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 @@ -610,10 +703,10 @@ Error handling is as follows: DF32 data files are buffered in memory; therefore, end of file and OS I/O errors cannot occur. -2.6 TC08/TU56 DECtape (DT) +2.7 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 +TC08 options include the ability to make units write enabled or write locked. SET DTn LOCKED set unit n write locked @@ -629,7 +722,7 @@ image; the user can force a particular format with switches: -s PDP-11 format -t 18b format -The DECtape controller is a data-only simulator; the timing and mark +The TC08 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 @@ -648,7 +741,6 @@ The DECtape controller implements these registers: 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 @@ -659,10 +751,11 @@ 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 + - DCTIME needs to be at least 100 times LTIME -2.7 TM8E Magnetic Tape (MT) +Acceleration time is set to 75% of deceleration time. + +2.8 TM8E Magnetic Tape (MT) Magnetic tape options include the ability to make units write enabled or or write locked. @@ -700,7 +793,7 @@ Error handling is as follows: OS I/O error parity error; if STOP_IOE, stop -2.8 Symbolic Display and Input +2.9 Symbolic Display and Input The PDP-8 simulator implements symbolic display and input. Display is controlled by command line switches: diff --git a/PDP8/pdp8_dt.c b/PDP8/pdp8_dt.c index f2c62316..c4d02b49 100644 --- a/PDP8/pdp8_dt.c +++ b/PDP8/pdp8_dt.c @@ -25,6 +25,7 @@ dt TC08/TU56 DECtape + 18-Oct-03 RMS Fixed bugs in read all, tightened timing 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 @@ -52,13 +53,16 @@ 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 + Tape density is nominally 300 lines per inch. The format of a DECtape (as + taken from the TD8E formatter) is: - reverse end zone 36000 lines ~ 10 feet + reverse end zone 8192 reverse end zone codes ~ 10 feet + reverse buffer 200 interblock codes block 0 : block n - forward end zone 36000 lines ~ 10 feet + forward buffer 200 interblock codes + forward end zone 8192 forward end zone codes ~ 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 @@ -73,14 +77,14 @@ header word 0 0 header word 1 block number (for forward reads) header words 2,3 0 - header word 4 0 + header word 4 checksum (for reverse reads) : - trailer word 4 checksum + trailer word 4 checksum (for forward reads) 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 + Write all writes only the data words and dumps the non-data words in the bit bucket. */ @@ -101,10 +105,15 @@ /* 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_LPERMC 6 /* lines per mark track */ +#define DT_BLKWD 1 /* blk no word in h/t */ +#define DT_CSMWD 4 /* checksum word in h/t */ +#define DT_HTWRD 5 /* header/trailer words */ +#define DT_EZLIN (8192 * DT_LPERMC) /* end zone length */ +#define DT_BFLIN (200 * DT_LPERMC) /* buffer length */ +#define DT_BLKLN (DT_BLKWD * DT_LPERMC) /* blk no line in h/t */ +#define DT_CSMLN (DT_CSMWD * DT_LPERMC) /* csum line in h/t */ +#define DT_HTLIN (DT_HTWRD * DT_LPERMC) /* header/trailer lines */ /* 16b, 18b, 36b DECtape constants */ @@ -257,8 +266,7 @@ 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_dctime = 40000; /* decel time */ int32 dt_substate = 0; int32 dt_log = 0; /* debug */ int32 dt_logblk = 0; @@ -319,9 +327,8 @@ REG dt_reg[] = { { 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 }, + { DRDATA (LTIME, dt_ltime, 31), REG_NZ | PV_LEFT }, + { DRDATA (DCTIME, dt_dctime, 31), REG_NZ | PV_LEFT }, { ORDATA (SUBSTATE, dt_substate, 2) }, { ORDATA (LOG, dt_log, 4), REG_HIDDEN }, { DRDATA (LBLK, dt_logblk, 12), REG_HIDDEN }, @@ -451,7 +458,7 @@ 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 */ + sim_activate (uptr, dt_dctime - (dt_dctime >> 2)); /* schedule acc */ DTS_SETSTA (DTS_ACCF | new_dir, 0); /* state = accel */ DTS_SET2ND (DTS_ATSF | new_dir, new_fnc); /* next = fnc */ return; } @@ -477,7 +484,7 @@ if (prev_dir ^ new_dir) { /* dir chg? */ 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 */ + sim_activate (uptr, dt_dctime - (dt_dctime >> 2)); /* sched accel */ DTS_SETSTA (DTS_ACCF | new_dir, 0); /* state = accel */ DTS_SET2ND (DTS_ATSF | new_dir, new_fnc); /* next = fnc */ return; } @@ -598,11 +605,13 @@ case DTS_STOP: /* stop */ delta = 0; break; case DTS_DECF: /* slowing */ - ulin = ut / (uint32) dt_ltime; udelt = dt_dctime / dt_ltime; + 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; + ulin = ut / (uint32) dt_ltime; + udelt = (dt_dctime - (dt_dctime >> 2)) / dt_ltime; delta = (ulin * ulin) / (2 * udelt); break; case DTS_ATSF: /* at speed */ @@ -631,7 +640,7 @@ 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; +int16 *fbuf = uptr->filebuf; int32 unum = uptr - dt_dev.units; int32 blk, wrd, ma, relpos, dat; uint32 ba; @@ -645,10 +654,10 @@ uint32 ba; switch (mot) { case DTS_DECF: case DTS_DECR: /* decelerating */ - if (dt_setpos (uptr)) return SCPE_OK; /* update pos */ + if (dt_setpos (uptr)) return STOP_DTOFF; /* update pos */ uptr->STATE = DTS_NXTSTA (uptr->STATE); /* advance state */ if (uptr->STATE) /* not stopped? */ - sim_activate (uptr, dt_actime); /* must be reversing */ + sim_activate (uptr, dt_dctime - (dt_dctime >> 2)); /* must be reversing */ return SCPE_OK; case DTS_ACCF: case DTS_ACCR: /* accelerating */ dt_newfnc (uptr, DTS_NXTSTA (uptr->STATE)); /* adv state, sched */ @@ -666,7 +675,7 @@ default: /* other */ Off reel - detach unit (it must be deselected) */ -if (dt_setpos (uptr)) return SCPE_OK; /* update pos */ +if (dt_setpos (uptr)) return STOP_DTOFF; /* update pos */ if (DT_QEZ (uptr)) { /* in end zone? */ dt_seterr (uptr, DTB_END); /* end zone error */ return SCPE_OK; } @@ -721,7 +730,7 @@ case FNC_READ: /* read */ 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 */ + dat = fbuf[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? */ @@ -773,7 +782,7 @@ case FNC_WRIT: /* write */ 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 */ + fbuf[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? */ @@ -809,7 +818,7 @@ case FNC_RALL: (relpos < (DTU_LPERB (uptr) - DT_HTLIN))) { wrd = DT_LIN2WD (uptr->pos, uptr); ba = (blk * DTU_BSIZE (uptr)) + wrd; - dat = bptr[ba]; /* get tape word */ + dat = fbuf[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); @@ -845,7 +854,7 @@ case FNC_WALL: if (dir) dat = dt_comobv (dat); wrd = DT_LIN2WD (uptr->pos, uptr); ba = (blk * DTU_BSIZE (uptr)) + wrd; - bptr[ba] = dat; /* write word */ + fbuf[ba] = dat; /* write word */ if (ba >= uptr->hwmark) uptr->hwmark = ba + 1; } /* /* ignore hdr */ sim_activate (uptr, DT_WSIZE * dt_ltime); @@ -872,7 +881,7 @@ return SCPE_OK; Word Word Content Word Word Content (abs) (rel) (abs) (rel) - 137 8 rev csm'00 6 6 fwd csm'00 + 137 8 fwd csm'00 6 6 rev csm'00 138 9 0000 5 5 0000 139 10 0000 4 4 0000 140 11 0000 3 3 0000 @@ -886,7 +895,7 @@ return SCPE_OK; 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 + 7 7 rev csm 136 7 00'fwd csm */ int32 dt_gethdr (UNIT *uptr, int32 blk, int32 relpos, int32 dir) @@ -894,8 +903,8 @@ 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 6: /* rev csm */ + return 077; case 2: /* lo fwd blk */ return dt_comobv ((blk & 077) << 6); case 1: /* hi fwd blk */ @@ -904,11 +913,13 @@ if (dir) { /* reverse */ return (blk >> 6) & 07777; case 11: /* lo rev blk */ return ((blk & 077) << 6); + case 7: /* fwd csum */ + return (dt_comobv (dt_csum (uptr, blk)) << 6); default: /* others */ - return 077; } } + return 07777; } } else { /* forward */ switch (relpos / DT_WSIZE) { - case 8: /* rev csum */ + case 8: /* fwd csum */ return (dt_csum (uptr, blk) << 6); case 12: /* lo rev blk */ return dt_comobv ((blk & 077) << 6); @@ -918,6 +929,8 @@ else { /* forward */ return ((blk >> 6) & 07777); case 3: /* lo fwd blk */ return ((blk & 077) << 6); + case 7: /* rev csum */ + return 077; default: /* others */ break; } } return 0; @@ -968,13 +981,13 @@ return dat; int32 dt_csum (UNIT *uptr, int32 blk) { -int16 *bptr = uptr->filebuf; +int16 *fbuf = 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 */ + wrd = fbuf[ba + i] ^ 07777; /* get ~word */ csum = csum ^ (wrd >> 6) ^ wrd; } return (csum & 077); } @@ -1061,7 +1074,7 @@ return SCPE_OK; t_stat dt_attach (UNIT *uptr, char *cptr) { uint32 pdp18b[D18_NBSIZE]; -uint16 pdp11b[D18_NBSIZE], *bptr; +uint16 pdp11b[D18_NBSIZE], *fbuf; int32 i, k; int32 u = uptr - dt_dev.units; t_stat r; @@ -1086,7 +1099,7 @@ 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 */ +fbuf = 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"); @@ -1104,10 +1117,10 @@ else { /* 16b/18b */ 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) | + fbuf[ba] = (pdp18b[k] >> 6) & 07777; + fbuf[ba + 1] = ((pdp18b[k] & 077) << 6) | ((pdp18b[k + 1] >> 12) & 077); - bptr[ba + 2] = pdp18b[k + 1] & 07777; + fbuf[ba + 2] = pdp18b[k + 1] & 07777; ba = ba + 3; } /* end blk loop */ } /* end file loop */ uptr->hwmark = ba; } /* end else */ @@ -1128,19 +1141,19 @@ return SCPE_OK; t_stat dt_detach (UNIT* uptr) { uint32 pdp18b[D18_NBSIZE]; -uint16 pdp11b[D18_NBSIZE], *bptr; +uint16 pdp11b[D18_NBSIZE], *fbuf; int32 i, k; int32 u = uptr - dt_dev.units; uint32 ba; -if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; +if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; /* attached? */ 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 */ +fbuf = 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 */ @@ -1150,10 +1163,10 @@ if (uptr->hwmark && ((uptr->flags & UNIT_RO)== 0)) { /* any data? */ 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)); + pdp18b[k] = ((uint32) (fbuf[ba] & 07777) << 6) | + ((uint32) (fbuf[ba + 1] >> 6) & 077); + pdp18b[k + 1] = ((uint32) (fbuf[ba + 1] & 077) << 12) | + ((uint32) (fbuf[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]; diff --git a/PDP8/pdp8_rf.c b/PDP8/pdp8_rf.c index c8441147..d6ee9e34 100644 --- a/PDP8/pdp8_rf.c +++ b/PDP8/pdp8_rf.c @@ -25,6 +25,7 @@ rf RF08 fixed head disk + 26-Oct-03 RMS Cleaned up buffer copy code 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 @@ -274,6 +275,7 @@ return AC; t_stat rf_svc (UNIT *uptr) { int32 pa, t, mex; +int16 *fbuf = uptr->filebuf; UPDATE_PCELL; /* update photocell */ if ((uptr->flags & UNIT_BUF) == 0) { /* not buf? abort */ @@ -290,13 +292,14 @@ do { if ((uint32) rf_da >= rf_unit.capac) { /* disk overflow? */ 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); } + if (MEM_ADDR_OK (pa)) /* if !nxm */ + M[pa] = fbuf[rf_da]; } /* read word */ 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 ((rf_wlk >> t) & 1) /* write locked? */ + rf_sta = rf_sta | RFS_WLS; + else { /* not locked */ + fbuf[rf_da] = M[pa]; /* write word */ 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 */ diff --git a/PDP8/pdp8_rx.c b/PDP8/pdp8_rx.c index ba68fcdd..ac53b435 100644 --- a/PDP8/pdp8_rx.c +++ b/PDP8/pdp8_rx.c @@ -25,6 +25,8 @@ rx RX8E/RX01, RX28/RX02 floppy disk + 05-Nov-03 RMS Fixed bug in RX28 read status (found by Charles Dickman) + 26-Oct-03 RMS Cleaned up buffer copy code, fixed double density write 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 @@ -129,7 +131,7 @@ 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 */ +int32 rx_bptr = 0; /* buffer pointer */ DEVICE rx_dev; int32 rx (int32 IR, int32 AC); @@ -167,7 +169,7 @@ REG rx_reg[] = { { ORDATA (RXTA, rx_track, 8) }, { ORDATA (RXSA, rx_sector, 8) }, { DRDATA (STAPTR, rx_state, 4), REG_RO }, - { DRDATA (BUFPTR, bptr, 8) }, + { DRDATA (BUFPTR, rx_bptr, 8) }, { FLDATA (TR, rx_tr, 0) }, { FLDATA (ERR, rx_err, 0) }, { FLDATA (DONE, dev_done, INT_V_RX) }, @@ -226,7 +228,7 @@ case 1: /* LCD */ 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 */ + rx_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 */ @@ -287,9 +289,11 @@ switch (RXCS_GETFNC (rx_csr)) { /* decode command */ case RXCS_FILL: rx_state = FILL; /* state = fill */ rx_tr = 1; /* xfer is ready */ + rx_esr = rx_esr & RXES_ID; /* clear errors */ break; case RXCS_EMPTY: rx_state = EMPTY; /* state = empty */ + rx_esr = rx_esr & RXES_ID; /* clear errors */ sim_activate (&rx_unit[drv], rx_xwait); /* sched xfer */ break; case RXCS_READ: case RXCS_WRITE: case RXCS_WRDEL: @@ -301,6 +305,7 @@ case RXCS_SDEN: if (rx_28) { /* RX28? */ rx_state = SDCNF; /* state = get conf */ rx_tr = 1; /* xfer is ready */ + rx_esr = rx_esr & RXES_ID; /* clear errors */ break; } /* else fall thru */ default: rx_state = CMD_COMPLETE; /* state = cmd compl */ @@ -315,10 +320,10 @@ return; 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 + FILL copy dbr to rx_buf[rx_bptr], advance ptr + if rx_bptr > max, finish command, else set tr + EMPTY if rx_bptr > max, finish command, else + copy rx_buf[rx_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 @@ -329,12 +334,13 @@ return; t_stat rx_svc (UNIT *uptr) { int32 i, func, byptr, bps, wps; +int8 *fbuf = uptr->filebuf; uint32 da; #define PTR12(x) (((x) + (x) + (x)) >> 1) -if (rx_28 && (uptr->flags & UNIT_DEN)) - bps = RX2_NUMBY; -else bps = RX_NUMBY; +if (rx_28 && (uptr->flags & UNIT_DEN)) /* RX28 and double density? */ + bps = RX2_NUMBY; /* double bytes/sector */ +else bps = RX_NUMBY; /* RX8E, normal count */ wps = bps / 2; func = RXCS_GETFNC (rx_csr); /* get function */ switch (rx_state) { /* case on state */ @@ -344,40 +350,40 @@ case IDLE: /* idle */ case EMPTY: /* empty buffer */ if (rx_csr & RXCS_MODE) { /* 8b xfer? */ - if (bptr >= bps) { /* done? */ + if (rx_bptr >= bps) { /* done? */ rx_done (0, 0); /* set done */ break; } /* and exit */ - rx_dbr = rx_buf[bptr]; } /* else get data */ + rx_dbr = rx_buf[rx_bptr]; } /* else get data */ else { - byptr = PTR12 (bptr); /* 12b xfer */ - if (bptr >= wps) { /* done? */ + byptr = PTR12 (rx_bptr); /* 12b xfer */ + if (rx_bptr >= wps) { /* done? */ rx_done (0, 0); /* set done */ break; } /* and exit */ - rx_dbr = (bptr & 1)? /* get data */ + rx_dbr = (rx_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_bptr = rx_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 */ + rx_buf[rx_bptr] = rx_dbr; /* fill buffer */ + rx_bptr = rx_bptr + 1; + if (rx_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? */ + byptr = PTR12 (rx_bptr); /* 12b xfer */ + if (rx_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 */ + rx_bptr = rx_bptr + 1; + if (rx_bptr < wps) rx_tr = 1; /* if more, set xfer */ else { - for (i = PTR12 (RX_NUMWD); i < RX_NUMBY; i++) + for (i = PTR12 (wps); i < bps; i++) rx_buf[i] = 0; /* else fill sector */ rx_done (0, 0); } } /* set done */ break; @@ -412,15 +418,13 @@ case RWXFR: /* transfer */ 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); } + for (i = 0; i < bps; i++) rx_buf[i] = fbuf[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; + for (i = 0; i < bps; i++) fbuf[da + i] = rx_buf[i]; + da = da + bps; if (da > uptr->hwmark) uptr->hwmark = da; } rx_done (0, 0); /* done */ break; @@ -433,8 +437,7 @@ case SDCNF: /* confirm set density */ 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; + for (i = 0; i < (int32) uptr->capac; i++) fbuf[i] = 0; uptr->hwmark = uptr->capac; if (rx_csr & RXCS_DEN) uptr->flags = uptr->flags | UNIT_DEN; else uptr->flags = uptr->flags & ~UNIT_DEN; @@ -445,7 +448,13 @@ 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); + else if (rx_28) { /* no, read sta; RX28? */ + rx_esr = rx_esr & ~RXES_DERR; /* assume dens match */ + if (((uptr->flags & UNIT_DEN) != 0) ^ /* densities mismatch? */ + ((rx_csr & RXCS_DEN) != 0)) + rx_done (RXES_DERR, 0240); /* yes, error */ + else rx_done (0, 0); } /* no, ok */ + else rx_done (0, 0); /* RX8E status */ break; case INIT_COMPLETE: /* init complete */ @@ -456,7 +465,7 @@ case INIT_COMPLETE: /* init complete */ 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_buf[i] = fbuf[da + i]; rx_done (RXES_ID, 0); /* set done */ if ((rx_unit[1].flags & UNIT_ATT) == 0) rx_ecode = 0020; break; } /* end case state */ @@ -475,7 +484,7 @@ 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_28) rx_esr = rx_esr | RXES_RX02; /* RX28? */ 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 */ diff --git a/PDP8/pdp8_sys.c b/PDP8/pdp8_sys.c index 9149e149..bb8268a1 100644 --- a/PDP8/pdp8_sys.c +++ b/PDP8/pdp8_sys.c @@ -23,6 +23,7 @@ be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. + 17-Oct-03 RMS Added TSC8-75, TD8E support, DECtape off reel message 25-Apr-03 RMS Revised for extended file support 30-Dec-01 RMS Revised for new TTX 26-Nov-01 RMS Added RL8A support @@ -43,13 +44,15 @@ extern DEVICE cpu_dev; extern UNIT cpu_unit; +extern DEVICE tsc_dev; 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 dt_dev, td_dev; +extern DEVICE mt_dev; extern DEVICE ttix_dev, ttox_dev; extern REG cpu_reg[]; extern uint16 M[]; @@ -74,14 +77,23 @@ 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, + &tsc_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, + &df_dev, + &rf_dev, + &dt_dev, + &td_dev, + &mt_dev, NULL }; const char *sim_stop_messages[] = { @@ -89,7 +101,8 @@ const char *sim_stop_messages[] = { "Unimplemented instruction", "HALT instruction", "Breakpoint", - "Non-standard device number" }; + "Non-standard device number", + "DECtape off reel" }; /* Binary loader @@ -230,6 +243,8 @@ static const char *opcode[] = { "RLCB", "RLSA", "RLWC", "RRER", "RRWC", "RRCA", "RRCB", "RRSA", "RRSI", "RLSE", + "ETDS", "ESKP", "ECTF", "ECDF", + "ERTB", "ESME", "ERIOT", "ETEN", "CDF", "CIF", "CIF CDF", "AND", "TAD", "ISZ", "DCA", "JMS", "JMP", "IOT", @@ -287,6 +302,8 @@ static const int32 opc_val[] = { 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, + 06360+I_NPN, 06361+I_NPN, 06362+I_NPN, 06363+I_NPN, + 06364+I_NPN, 06365+I_NPN, 06366+I_NPN, 06367+I_NPN, 06201+I_FLD, 06202+I_FLD, 06203+I_FLD, 00000+I_MRF, 01000+I_MRF, 02000+I_MRF, 03000+I_MRF, @@ -411,7 +428,7 @@ for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */ 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 */ + break; } /* end case */ return SCPE_OK; } /* end if */ } /* end for */ return SCPE_ARG; diff --git a/PDP8/pdp8_td.c b/PDP8/pdp8_td.c new file mode 100644 index 00000000..40f20c6e --- /dev/null +++ b/PDP8/pdp8_td.c @@ -0,0 +1,847 @@ +/* pdp8_td.c: PDP-8 simple DECtape controller (TD8E) 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 was inspired by Gerold Pauler's TD8E simulator for Doug Jones' + PDP8 simulator but tracks the hardware implementation more closely. + + td TD8E/TU56 DECtape + + PDP-8 DECtapes are represented in memory by fixed length buffer of 12b 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/36b 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 (as + taken from the TD8E formatter) is: + + reverse end zone 8192 reverse end zone codes ~ 10 feet + reverse buffer 200 interblock codes + block 0 + : + block n + forward buffer 200 interblock codes + forward end zone 8192 forward end zone codes ~ 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 non-data words. Read 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 checksum (for reverse reads) + : + trailer word 4 checksum (for forward reads) + trailer words 3,2 0 + trailer word 1 block number (for reverse reads) + trailer word 0 0 + + Write modifies only the data words and dumps the non-data words in the + bit bucket. +*/ + +#include "pdp8_defs.h" + +#define DT_NUMDR 2 /* #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 UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */ + +/* System independent DECtape constants */ + +#define DT_LPERMC 6 /* lines per mark track */ +#define DT_EZLIN (8192 * DT_LPERMC) /* end zone length */ +#define DT_BFLIN (200 * DT_LPERMC) /* end zone buffer */ +#define DT_HTLIN (5 * DT_LPERMC) /* lines per hdr/trlr */ + +/* 16b, 18b, 36b DECtape constants */ + +#define D18_WSIZE 6 /* word sizein 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)) + +/* Command register */ + +#define TDC_UNIT 04000 /* unit select */ +#define TDC_FWDRV 02000 /* fwd/rev */ +#define TDC_STPGO 01000 /* stop/go */ +#define TDC_RW 00400 /* read/write */ +#define TDC_MASK 07400 /* implemented */ +#define TDC_GETUNIT(x) (((x) & TDC_UNIT)? 1: 0) + +/* Status register */ + +#define TDS_WLO 00200 /* write lock */ +#define TDS_TME 00100 /* timing/sel err */ + +/* Mark track register and codes */ + +#define MTK_MASK 077 +#define MTK_REV_END 055 /* rev end zone */ +#define MTK_INTER 025 /* interblock */ +#define MTK_FWD_BLK 026 /* fwd block */ +#define MTK_REV_GRD 032 /* reverse guard */ +#define MTK_FWD_PRE 010 /* lock, etc */ +#define MTK_DATA 070 /* data */ +#define MTK_REV_PRE 073 /* lock, etc */ +#define MTK_FWD_GRD 051 /* fwd guard */ +#define MTK_REV_BLK 045 /* rev block */ +#define MTK_FWD_END 022 /* fwd end zone */ + +/* DECtape state */ + +#define STA_STOP 0 /* stopped */ +#define STA_DEC 2 /* decelerating */ +#define STA_ACC 4 /* accelerating */ +#define STA_UTS 6 /* up to speed */ +#define STA_DIR 1 /* fwd/rev */ + +#define ABS(x) (((x) < 0)? (-(x)): (x)) +#define MTK_BIT(c,p) (((c) >> (DT_LPERMC - 1 - ((p) % DT_LPERMC))) & 1) + +/* State and declarations */ + +int32 td_cmd = 0; /* command */ +int32 td_dat = 0; /* data */ +int32 td_mtk = 0; /* mark track */ +int32 td_slf = 0; /* single line flag */ +int32 td_qlf = 0; /* quad line flag */ +int32 td_tme = 0; /* timing error flag */ +int32 td_csum = 0; /* save check sum */ +int32 td_qlctr = 0; /* quad line ctr */ +int32 td_ltime = 20; /* interline time */ +int32 td_dctime = 40000; /* decel time */ +static uint8 tdb_mtk[DT_NUMDR][D18_LPERB]; /* mark track bits */ + +DEVICE td_dev; +int32 td77 (int32 IR, int32 AC); +t_stat td_svc (UNIT *uptr); +t_stat td_reset (DEVICE *dptr); +t_stat td_attach (UNIT *uptr, char *cptr); +t_stat td_detach (UNIT *uptr); +t_stat td_boot (int32 unitno, DEVICE *dptr); +t_bool td_newsa (int32 newf); +t_bool td_setpos (UNIT *uptr); +int32 td_header (UNIT *uptr, int32 blk, int32 line); +int32 td_trailer (UNIT *uptr, int32 blk, int32 line); +int32 td_read (UNIT *uptr, int32 blk, int32 line); +void td_write (UNIT *uptr, int32 blk, int32 line, int32 datb); +int32 td_set_mtk (int32 code, int32 u, int32 k); +t_stat td_show_pos (FILE *st, UNIT *uptr, int32 val, void *desc); + +extern uint16 M[]; +extern int32 sim_switches; +extern int32 sim_is_running; + +/* TD data structures + + td_dev DT device descriptor + td_unit DT unit list + td_reg DT register list + td_mod DT modifier list +*/ + +DIB td_dib = { DEV_TD8E, 1, { &td77 } }; + +UNIT td_unit[] = { + { UDATA (&td_svc, UNIT_8FMT+UNIT_FIX+UNIT_ATTABLE+ + UNIT_DISABLE+UNIT_ROABLE, DT_CAPAC) }, + { UDATA (&td_svc, UNIT_8FMT+UNIT_FIX+UNIT_ATTABLE+ + UNIT_DISABLE+UNIT_ROABLE, DT_CAPAC) } }; + +REG td_reg[] = { + { GRDATA (TDCMD, td_cmd, 8, 4, 8) }, + { ORDATA (TDDAT, td_dat, 12) }, + { ORDATA (TDMTK, td_mtk, 6) }, + { FLDATA (TDSLF, td_slf, 0) }, + { FLDATA (TDQLF, td_qlf, 0) }, + { FLDATA (TDTME, td_tme, 0) }, + { ORDATA (TDQL, td_qlctr, 2) }, + { ORDATA (TDCSUM, td_csum, 6), REG_RO }, + { DRDATA (LTIME, td_ltime, 31), REG_NZ | PV_LEFT }, + { DRDATA (DCTIME, td_dctime, 31), REG_NZ | PV_LEFT }, + { URDATA (POS, td_unit[0].pos, 10, T_ADDR_W, 0, + DT_NUMDR, PV_LEFT | REG_RO) }, + { URDATA (STATT, td_unit[0].STATE, 8, 18, 0, + DT_NUMDR, REG_RO) }, + { URDATA (LASTT, td_unit[0].LASTT, 10, 32, 0, + DT_NUMDR, REG_HRO) }, + { ORDATA (DEVNUM, td_dib.dev, 6), REG_HRO }, + { NULL } }; + +MTAB td_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 }, + { MTAB_XTD|MTAB_VUN|MTAB_NMO, 0, "POSITION", NULL, NULL, &td_show_pos }, + { 0 } }; + +DEVICE td_dev = { + "TD", td_unit, td_reg, td_mod, + DT_NUMDR, 8, 24, 1, 8, 12, + NULL, NULL, &td_reset, + &td_boot, &td_attach, &td_detach, + &td_dib, DEV_DISABLE | DEV_DIS }; + +/* IOT routines */ + +int32 td77 (int32 IR, int32 AC) +{ +int32 pulse = IR & 07; +int32 u = TDC_GETUNIT (td_cmd); /* get unit */ +int32 diff, t; + +switch (pulse) { +case 01: /* SDSS */ + if (td_slf) return AC | IOT_SKP; + break; +case 02: /* SDST */ + if (td_tme) return AC | IOT_SKP; + break; +case 03: /* SDSQ */ + if (td_qlf) return AC | IOT_SKP; + break; +case 04: /* SDLC */ + td_tme = 0; /* clear tim err */ + diff = (td_cmd ^ AC) & TDC_MASK; /* cmd changes */ + td_cmd = AC & TDC_MASK; /* update cmd */ + if ((diff != 0) && (diff != TDC_RW)) { /* signif change? */ + if (td_newsa (td_cmd)) /* new command */ + return AC | (STOP_DTOFF << IOT_V_REASON); } + break; +case 05: /* SDLD */ + td_slf = 0; /* clear flags */ + td_qlf = 0; + td_qlctr = 0; + td_dat = AC; /* load data reg */ + break; +case 06: /* SDRC */ + td_slf = 0; /* clear flags */ + td_qlf = 0; + td_qlctr = 0; + t = td_cmd | td_mtk; /* form status */ + if (td_tme || !(td_unit[u].flags & UNIT_ATT)) /* tim/sel err? */ + t = t | TDS_TME; + if (td_unit[u].flags & UNIT_WPRT) /* write locked? */ + t = t | TDS_WLO; + return t; /* return status */ +case 07: /* SDRD */ + td_slf = 0; /* clear flags */ + td_qlf = 0; + td_qlctr = 0; + return td_dat; } /* return data */ +return AC; +} + +/* Command register change (start/stop, forward/reverse, new unit) + + 1. If change in motion, stop to start + - schedule up to speed + - set function as next state + 2. If change in motion, start to stop, or change in direction + - schedule stop +*/ + +t_bool td_newsa (int32 newf) +{ +int32 prev_mving, new_mving, prev_dir, new_dir; +UNIT *uptr; + +uptr = td_dev.units + TDC_GETUNIT (newf); /* new unit */ +if ((uptr->flags & UNIT_ATT) == 0) return FALSE; /* new unit attached? */ + +new_mving = ((newf & TDC_STPGO) != 0); /* new moving? */ +prev_mving = (uptr->STATE != STA_STOP); /* previous moving? */ +new_dir = ((newf & TDC_FWDRV) != 0); /* new dir? */ +prev_dir = ((uptr->STATE & STA_DIR) != 0); /* previous dir? */ + +td_mtk = 0; /* mark trk reg cleared */ + +if (!prev_mving && !new_mving) return FALSE; /* stop from stop? */ + +if (new_mving && !prev_mving) { /* start from stop? */ + if (td_setpos (uptr)) return TRUE; /* update pos */ + sim_cancel (uptr); /* stop current */ + sim_activate (uptr, td_dctime - (td_dctime >> 2)); /* sched accel */ + uptr->STATE = STA_ACC | new_dir; /* set status */ + td_slf = td_qlf = td_qlctr = 0; /* clear state */ + return FALSE; } + +if ((prev_mving && !new_mving) || /* stop from moving? */ + (prev_dir != new_dir)) { /* dir chg while moving? */ + if (uptr->STATE >= STA_ACC) { /* not stopping? */ + if (td_setpos (uptr)) return TRUE; /* update pos */ + sim_cancel (uptr); /* stop current */ + sim_activate (uptr, td_dctime); /* schedule decel */ + uptr->STATE = STA_DEC | prev_dir; /* set status */ + td_slf = td_qlf = td_qlctr = 0; } /* clear state */ + return FALSE; } + +return FALSE; +} + +/* 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/td_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 td_setpos (UNIT *uptr) +{ +uint32 new_time, ut, ulin, udelt; +int32 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 (uptr->STATE & ~STA_DIR) { /* case on motion */ +case STA_STOP: /* stop */ + delta = 0; + break; +case STA_DEC: /* slowing */ + ulin = ut / (uint32) td_ltime; + udelt = td_dctime / td_ltime; + delta = ((ulin * udelt * 2) - (ulin * ulin)) / (2 * udelt); + break; +case STA_ACC: /* accelerating */ + ulin = ut / (uint32) td_ltime; + udelt = (td_dctime - (td_dctime >> 2)) / td_ltime; + delta = (ulin * ulin) / (2 * udelt); + break; +case STA_UTS: /* at speed */ + delta = ut / (uint32) td_ltime; + break; } +if (uptr->STATE & STA_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 */ + sim_cancel (uptr); /* no timing pulses */ + return TRUE; } +return FALSE; +} + +/* Unit service - unit is either changing speed, or it is up to speed */ + +t_stat td_svc (UNIT *uptr) +{ +int32 mot = uptr->STATE & ~STA_DIR; +int32 dir = uptr->STATE & STA_DIR; +int32 unum = uptr - td_dev.units; +int32 su = TDC_GETUNIT (td_cmd); +int32 mtkb, datb; + +/* Motion cases + + Decelerating - if go, next state must be accel as specified by td_cmd + Accelerating - next state must be up to speed, fall through + Up to speed - process line */ + +if (mot == STA_STOP) return SCPE_OK; /* stopped? done */ +if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */ + uptr->STATE = uptr->pos = 0; /* also done */ + return SCPE_UNATT; } + +switch (mot) { /* case on motion */ +case STA_DEC: /* deceleration */ + if (td_setpos (uptr)) return STOP_DTOFF; /* update pos */ + if ((unum != su) || !(td_cmd & TDC_STPGO)) /* not sel or stop? */ + uptr->STATE = 0; /* stop */ + else { /* selected and go */ + uptr->STATE = STA_ACC | /* accelerating */ + ((td_cmd & TDC_FWDRV)? STA_DIR: 0); /* in new dir */ + sim_activate (uptr, td_dctime - (td_dctime >> 2)); } + return SCPE_OK; +case STA_ACC: /* accelerating */ + if (td_setpos (uptr)) return STOP_DTOFF; /* update pos */ + uptr->STATE = STA_UTS | dir; /* set up to speed */ + break; +case STA_UTS: /* up to speed */ + if (dir) uptr->pos = uptr->pos - 1; /* adjust position */ + else uptr->pos = uptr->pos + 1; + uptr->LASTT = sim_grtime (); /* save time */ + if (((int32) uptr->pos < 0) || /* off reel? */ + (uptr->pos >= (((uint32) DTU_FWDEZ (uptr)) + DT_EZLIN))) { + detach_unit (uptr); + return STOP_DTOFF; } + break; } /* check function */ + +/* At speed - process the current line + + Once the TD8E is running at speed, it operates line by line. If reading, + the current mark track bit is shifted into the mark track register, and + the current data nibble (3b) is shifted into the data register. If + writing, the current mark track bit is shifted into the mark track + register, the top nibble from the data register is written to tape, and + the data register is shifted up. The complexity here comes from + synthesizing the mark track, based on tape position, and the header data. */ + +sim_activate (uptr, td_ltime); /* sched next line */ +if (unum != su) return SCPE_OK; /* not sel? done */ +td_slf = 1; /* set single */ +td_qlctr = (td_qlctr + 1) % DT_WSIZE; /* count words */ +if (td_qlctr == 0) { /* lines mod 4? */ + if (td_qlf) { /* quad line set? */ + td_tme = 1; /* timing error */ + td_cmd = td_cmd & ~TDC_RW; } /* clear write */ + else td_qlf = 1; } /* no, set quad */ + +datb = 0; /* assume no data */ +if (uptr->pos < (DT_EZLIN - DT_BFLIN)) /* rev end zone? */ + mtkb = MTK_BIT (MTK_REV_END, uptr->pos); +else if (uptr->pos < DT_EZLIN) /* rev buffer? */ + mtkb = MTK_BIT (MTK_INTER, uptr->pos); +else if (uptr->pos < ((uint32) DTU_FWDEZ (uptr))) { /* data zone? */ + int32 blkno = DT_LIN2BL (uptr->pos, uptr); /* block # */ + int32 lineno = DT_LIN2OF (uptr->pos, uptr); /* line # within block */ + if (lineno < DT_HTLIN) { /* header? */ + if ((td_cmd & TDC_RW) == 0) /* read? */ + datb = td_header (uptr, blkno, lineno); } /* get nibble */ + else if (lineno < (DTU_LPERB (uptr) - DT_HTLIN)) { /* data? */ + if (td_cmd & TDC_RW) /* write? */ + td_write (uptr, blkno, /* write data nibble */ + lineno - DT_HTLIN, /* data rel line num */ + (td_dat >> 9) & 07); + else datb = td_read (uptr, blkno, /* no, read */ + lineno - DT_HTLIN); } + else if ((td_cmd & TDC_RW) == 0) /* trailer; read? */ + datb = td_trailer (uptr, blkno, lineno - /* get trlr nibble */ + (DTU_LPERB (uptr) - DT_HTLIN)); + mtkb = tdb_mtk[unum][lineno]; } +else if (uptr->pos < (((uint32) DTU_FWDEZ (uptr)) + DT_BFLIN)) + mtkb = MTK_BIT (MTK_INTER, uptr->pos); /* fwd buffer? */ +else mtkb = MTK_BIT (MTK_FWD_END, uptr->pos); /* fwd end zone */ + +if (dir) { /* reverse? */ + mtkb = mtkb ^ 01; /* complement mark bit, */ + datb = datb ^ 07; } /* data bits */ +td_mtk = ((td_mtk << 1) | mtkb) & MTK_MASK; /* shift mark reg */ +td_dat = ((td_dat << 3) | datb) & 07777; /* shift data reg */ +return SCPE_OK; +} + +/* Header read - reads out 18b words in 3b increments + + word lines contents + 0 0-5 0 + 1 6-11 block number + 2 12-17 0 + 3 18-23 0 + 4 24-29 reverse checksum (0777777) +*/ + +int32 td_header (UNIT *uptr, int32 blk, int32 line) +{ +int32 nibp; + +switch (line) { +case 8: case 9: case 10: case 11: /* block num */ + nibp = 3 * (DT_LPERMC - 1 - (line % DT_LPERMC)); + return (blk >> nibp) & 07; +case 24: case 25: case 26: case 27: case 28: case 29: /* rev csum */ + return 07; /* 777777 */ +default: + return 0; } +} + +/* Trailer read - reads out 18b words in 3b increments + Checksum is stored to avoid double calculation + + word lines contents + 0 0-5 forward checksum (lines 0-1, rest 0) + 1 6-11 0 + 2 12-17 0 + 3 18-23 reverse block mark + 4 24-29 0 + + Note that the reverse block mark (when read forward) appears + as the complement obverse (3b nibbles swapped end for end and + complemented). +*/ + +int32 td_trailer (UNIT *uptr, int32 blk, int32 line) +{ +int32 nibp, i, ba; +int16 *fbuf= uptr->filebuf; + +switch (line) { +case 0: + td_csum = 07777; /* init csum */ + ba = blk * DTU_BSIZE (uptr); + for (i = 0; i < DTU_BSIZE (uptr); i++) /* loop thru buf */ + td_csum = (td_csum ^ ~fbuf[ba + i]) & 07777; + td_csum = ((td_csum >> 6) ^ td_csum) & 077; + return (td_csum >> 3) & 07; +case 1: + return (td_csum & 07); +case 18: case 19: case 20: case 21: + nibp = 3 * (line % DT_LPERMC); + return ((blk >> nibp) & 07) ^ 07; +default: + return 0; } +} + +/* Data read - convert block number/data line # to offset in data array */ + +int32 td_read (UNIT *uptr, int32 blk, int32 line) +{ +int16 *fbuf = uptr->filebuf; /* buffer */ +uint32 ba = blk * DTU_BSIZE (uptr); /* block base */ +int32 nibp = 3 * (DT_WSIZE - 1 - (line % DT_WSIZE)); /* nibble pos */ + +ba = ba + (line / DT_WSIZE); /* block addr */ +return (fbuf[ba] >> nibp) & 07; /* get data nibble */ +} + +/* Data write - convert block number/data line # to offset in data array */ + +void td_write (UNIT *uptr, int32 blk, int32 line, int32 dat) +{ +int16 *fbuf = uptr->filebuf; /* buffer */ +uint32 ba = blk * DTU_BSIZE (uptr); /* block base */ +int32 nibp = 3 * (DT_WSIZE - 1 - (line % DT_WSIZE)); /* nibble pos */ + +ba = ba + (line / DT_WSIZE); /* block addr */ +fbuf[ba] = (fbuf[ba] & ~(07 << nibp)) | (dat << nibp); /* upd data nibble */ +if (ba >= uptr->hwmark) uptr->hwmark = ba + 1; /* upd length */ +return; +} + +/* Reset routine */ + +t_stat td_reset (DEVICE *dptr) +{ +int32 i; +UNIT *uptr; + +for (i = 0; i < DT_NUMDR; i++) { /* stop all activity */ + uptr = td_dev.units + i; + if (sim_is_running) { /* CAF? */ + if (uptr->STATE >= STA_ACC) { /* accel or uts? */ + if (td_setpos (uptr)) continue; /* update pos */ + sim_cancel (uptr); + sim_activate (uptr, td_dctime); /* sched decel */ + uptr->STATE = STA_DEC | (uptr->STATE & STA_DIR); + } } + else { + sim_cancel (uptr); /* sim reset */ + uptr->STATE = 0; + uptr->LASTT = sim_grtime (); } } +td_slf = td_qlf = td_qlctr = 0; /* clear state */ +td_cmd = td_dat = td_mtk = 0; +td_csum = 0; +return SCPE_OK; +} + +/* Bootstrap routine - OS/8 only + + 1) Read reverse until reverse end zone (mark track is complement obverse + 2) Read forward until mark track code 031. This is a composite code from + the last 4b of the forward block number and the first two bits of the + reverse guard (01 -0110 01- 1010). There are 16 lines before the first + data word. + 3) Store data words from 7354 to end of page. This includes header and + trailer words. + 4) Continue at location 7400. +*/ + +#define BOOT_START 07300 +#define BOOT_LEN (sizeof (boot_rom) / sizeof (int16)) + +static const uint16 boot_rom[] = { + 01312, /* ST, TAD L4MT ;=2000, reverse */ + 04312, /* JMS L4MT ; rev lk for 022 */ + 04312, /* JMS L4MT ; fwd lk for 031 */ + 06773, /* DAT, SDSQ ; wait for 12b */ + 05303, /* JMP .-1 */ + 06777, /* SDRD ; read word */ + 03726, /* DCA I BUF ; store */ + 02326, /* ISZ BUF ; incr ptr */ + 05303, /* JMP DAT ; if not 0, cont */ + 05732, /* JMP I SCB ; jump to boot */ + 02000, /* L4MT,2000 ; overwritten */ + 01300, /* TAD ST ; =1312, go */ + 06774, /* SDLC ; new command */ + 06771, /* MTK, SDSS ; wait for mark */ + 05315, /* JMP .-1 */ + 06776, /* SDRC ; get mark code */ + 00331, /* AND K77 ; mask to 6b */ + 01327, /* CMP, TAD MCD ; got target code? */ + 07640, /* SZA CLA ; skip if yes */ + 05315, /* JMP MTK ; wait for mark */ + 02321, /* ISZ CMP ; next target */ + 05712, /* JMP I L4MT ; exit */ + 07354, /* BUF, 7354 ; loading point */ + 07756, /* MCD, -22 ; target 1 */ + 07747, /* -31 ; target 2 */ + 00077, /* 77 ; mask */ + 07400 /* SCB, 7400 ; secondary boot */ +}; + +t_stat td_boot (int32 unitno, DEVICE *dptr) +{ +int32 i; +extern int32 saved_PC; + +if (unitno) return SCPE_ARG; /* only unit 0 */ +if (td_dib.dev != DEV_TD8E) return STOP_NOTSTD; /* only std devno */ +td_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 + Set up mark track bit array +*/ + +t_stat td_attach (UNIT *uptr, char *cptr) +{ +uint32 pdp18b[D18_NBSIZE]; +uint16 pdp11b[D18_NBSIZE], *fbuf; +int32 i, k, mtkpb; +int32 u = uptr - td_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; } +fbuf = uptr->filebuf; /* file buffer */ +printf ("%s%d: ", sim_dname (&td_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 */ + fbuf[ba] = (pdp18b[k] >> 6) & 07777; + fbuf[ba + 1] = ((pdp18b[k] & 077) << 6) | + ((pdp18b[k + 1] >> 12) & 077); + fbuf[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 */ +uptr->STATE = STA_STOP; /* stopped */ + +mtkpb = (DTU_BSIZE (uptr) * DT_WSIZE) / DT_LPERMC; /* mtk codes per blk */ +k = td_set_mtk (MTK_INTER, u, 0); /* fill mark track */ +k = td_set_mtk (MTK_FWD_BLK, u, k); /* bit array */ +k = td_set_mtk (MTK_REV_GRD, u, k); +for (i = 0; i < 4; i++) k = td_set_mtk (MTK_FWD_PRE, u, k); +for (i = 0; i < (mtkpb - 4); i++) k = td_set_mtk (MTK_DATA, u, k); +for (i = 0; i < 4; i++) k = td_set_mtk (MTK_REV_PRE, u, k); +k = td_set_mtk (MTK_FWD_GRD, u, k); +k = td_set_mtk (MTK_REV_BLK, u, k); +k = td_set_mtk (MTK_INTER, u, k); +return SCPE_OK; +} + +/* Detach routine + + 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 td_detach (UNIT* uptr) +{ +uint32 pdp18b[D18_NBSIZE]; +uint16 pdp11b[D18_NBSIZE], *fbuf; +int32 i, k; +int32 u = uptr - td_dev.units; +uint32 ba; + +if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; +fbuf = uptr->filebuf; /* file buffer */ +if (uptr->hwmark && ((uptr->flags & UNIT_RO)== 0)) { /* any data? */ + printf ("%s%d: writing buffer to file\n", sim_dname (&td_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) (fbuf[ba] & 07777) << 6) | + ((uint32) (fbuf[ba + 1] >> 6) & 077); + pdp18b[k + 1] = ((uint32) (fbuf[ba + 1] & 077) << 12) | + ((uint32) (fbuf[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 */ +uptr->pos = uptr->STATE = 0; +sim_cancel (uptr); /* no more pulses */ +return detach_unit (uptr); +} + +/* Set mark track code into bit array */ + +int32 td_set_mtk (int32 code, int32 u, int32 k) +{ +int32 i; + +for (i = 5; i >= 0; i--) tdb_mtk[u][k++] = (code >> i) & 1; +return k; +} + +/* Show position */ + +t_stat td_show_pos (FILE *st, UNIT *uptr, int32 val, void *desc) +{ +if ((uptr->flags & UNIT_ATT) == 0) return SCPE_UNATT; +if (uptr->pos < DT_EZLIN) /* rev end zone? */ + fprintf (st, "Reverse end zone\n"); +else if (uptr->pos < ((uint32) DTU_FWDEZ (uptr))) { /* data zone? */ + int32 blkno = DT_LIN2BL (uptr->pos, uptr); /* block # */ + int32 lineno = DT_LIN2OF (uptr->pos, uptr); /* line # within block */ + fprintf (st, "Block %d, line %d, ", blkno, lineno); + if (lineno < DT_HTLIN) /* header? */ + fprintf (st, "header cell %d, nibble %d\n", + lineno / DT_LPERMC, lineno % DT_LPERMC); + else if (lineno < (DTU_LPERB (uptr) - DT_HTLIN)) /* data? */ + fprintf (st, "data word %d, nibble %d\n", + (lineno - DT_HTLIN) / DT_WSIZE, (lineno - DT_HTLIN) % DT_WSIZE); + else fprintf (st, "trailer cell %d, nibble %d\n", + (lineno - (DTU_LPERB (uptr) - DT_HTLIN)) / DT_LPERMC, + (lineno - (DTU_LPERB (uptr) - DT_HTLIN)) % DT_LPERMC); } +else fprintf (st, "Forward end zone\n"); /* fwd end zone */ +return SCPE_OK; +} + diff --git a/PDP8/pdp8_tsc.c b/PDP8/pdp8_tsc.c new file mode 100644 index 00000000..dd281784 --- /dev/null +++ b/PDP8/pdp8_tsc.c @@ -0,0 +1,143 @@ +/* pdp8_tsc.c: PDP-8 ETOS timesharing option board (TSC8-75) + + 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. + + This module is based on Bernhard Baehr's PDP-8/E simulator + + PDP-8/E Simulator Source Code + + Copyright ) 2001-2003 Bernhard Baehr + + TSC8iots.c - IOTs for the TSC8-75 Board plugin + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + tsc TSC8-75 option board +*/ + +#include "pdp8_defs.h" + +extern int32 int_req; +extern int32 SF; +extern int32 tsc_ir; /* "ERIOT" */ +extern int32 tsc_pc; /* "ERTB" */ +extern int32 tsc_cdf; /* "ECDF" */ +extern int32 tsc_enb; /* enable */ + +#define UNIT_V_SN699 (UNIT_V_UF + 0) /* SN 699 or above */ +#define UNIT_SN699 (1 << UNIT_V_SN699) + +DEVICE tsc_dev; +int32 tsc (int32 IR, int32 AC); +t_stat tsc_reset (DEVICE *dptr); + +/* TSC data structures + + tsc_dev TSC device descriptor + tsc_unit TSC unit descriptor + tsc_reg TSC register list +*/ + +DIB tsc_dib = { DEV_TSC, 1, { &tsc } }; + +UNIT tsc_unit = { UDATA (NULL, UNIT_SN699, 0) }; + +REG tsc_reg[] = { + { ORDATA (IR, tsc_ir, 12) }, + { ORDATA (PC, tsc_pc, 12) }, + { FLDATA (CDF, tsc_cdf, 0) }, + { FLDATA (ENB, tsc_enb, 0) }, + { FLDATA (INT, int_req, INT_V_TSC) }, + { NULL } }; + +MTAB tsc_mod[] = { + { UNIT_SN699, UNIT_SN699, "ESME", "ESME", NULL }, + { UNIT_SN699, 0, "no ESME", "NOESME", NULL }, + { 0 } }; + +DEVICE tsc_dev = { + "TSC", &tsc_unit, tsc_reg, tsc_mod, + 1, 10, 31, 1, 8, 8, + NULL, NULL, &tsc_reset, + NULL, NULL, NULL, + &tsc_dib, DEV_DISABLE | DEV_DIS }; + +/* IOT routine */ + +int32 tsc (int32 IR, int32 AC) +{ +switch (IR & 07) { /* decode IR<9:11> */ +case 0: /* ETDS */ + tsc_enb = 0; /* disable int req */ + int_req = int_req & ~INT_TSC; /* clear flag */ + break; +case 1: /* ESKP */ + return (int_req & INT_TSC)? IOT_SKP + AC: AC; /* skip on int req */ +case 2: /* ECTF */ + int_req = int_req & ~INT_TSC; /* clear int req */ + break; +case 3: /* ECDF */ + AC = AC | ((tsc_ir >> 3) & 07); /* read "ERIOT"<6:8> */ + if (tsc_cdf) AC = AC | IOT_SKP; /* if cdf, skip */ + tsc_cdf = 0; + break; +case 4: /* ERTB */ + return tsc_pc; +case 5: /* ESME */ + if (tsc_unit.flags & UNIT_SN699) { /* enabled? */ + if (tsc_cdf && ((tsc_ir & 070) >> 3) == (SF & 07)) { + AC = AC | IOT_SKP; + tsc_cdf = 0; } } + break; +case 6: /* ERIOT */ + return tsc_ir; +case 7: /* ETEN */ + tsc_enb = 1; + break; } /* end switch */ +return AC; +} + +/* Reset routine */ + +t_stat tsc_reset (DEVICE *dptr) +{ +tsc_ir = 0; +tsc_pc = 0; +tsc_cdf = 0; +tsc_enb = 0; +int_req = int_req & ~INT_TSC; +return SCPE_OK; +} diff --git a/PDP8/pdp8_tt.c b/PDP8/pdp8_tt.c index 33712fb5..eb6a595d 100644 --- a/PDP8/pdp8_tt.c +++ b/PDP8/pdp8_tt.c @@ -1,6 +1,6 @@ /* pdp8_tt.c: PDP-8 console terminal simulator - Copyright (c) 1993-2003, Robert M Supnik + Copyright (c) 1993-2004, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -25,6 +25,7 @@ tti,tto KL8E terminal input/output + 29-Dec-03 RMS Added console output backpressure support 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 @@ -233,13 +234,15 @@ 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; +if ((r = sim_putchar_s (c)) != SCPE_OK) { /* output char; error? */ + sim_activate (uptr, uptr->wait); /* try again */ + return ((r == SCPE_STALL)? SCPE_OK: r); } /* if !stall, report */ +dev_done = dev_done | INT_TTO; /* set done */ +int_req = INT_UPDATE; /* update interrupts */ tto_unit.pos = tto_unit.pos + 1; return SCPE_OK; } diff --git a/SDS/sds_drm.c b/SDS/sds_drm.c index c41d5550..08007aba 100644 --- a/SDS/sds_drm.c +++ b/SDS/sds_drm.c @@ -179,6 +179,7 @@ t_stat drm_svc (UNIT *uptr) { int32 t, rda; uint32 dpc, dwd; +uint32 *fbuf = uptr->filebuf; if (drm_sta != DRM_SXFR) { /* fetch drum prog? */ dpc = M[DRM_PC]; /* get drum PC */ @@ -225,10 +226,10 @@ else { /* transfer word */ 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 */ + fbuf[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 */ + dwd = fbuf[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 */ @@ -243,7 +244,7 @@ else { /* transfer word */ 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; + M[drm_da] = drm_par << 12; /* clobber data */ if (drm_da >= uptr->hwmark) uptr->hwmark = drm_da + 1; } #endif drm_sta = DRM_SFET; /* back to fetch */ diff --git a/SDS/sds_rad.c b/SDS/sds_rad.c index d111ba4d..498f0dd7 100644 --- a/SDS/sds_rad.c +++ b/SDS/sds_rad.c @@ -122,8 +122,8 @@ DEVICE rad_dev = { t_stat rad (uint32 fnc, uint32 inst, uint32 *dat) { int32 t, lun, new_ch; -uint32 *wptr; uint32 p; +uint32 *fbuf = rad_unit.filebuf; switch (fnc) { /* case function */ case IO_CONN: /* connect */ @@ -181,9 +181,8 @@ case IO_READ: /* read */ 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 */ + if (rad_sba & 1) *dat = fbuf[p] & 07777; /* odd byte? */ + else *dat = (fbuf[p] >> 12) & 07777; /* even */ rad_sba = rad_adjda (rad_sba, 1); /* next byte */ break; @@ -197,9 +196,8 @@ case IO_WRITE: (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 (rad_sba & 1) fbuf[p] = fbuf[p] | (*dat & 07777); /* odd byte? */ + else fbuf[p] = (*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; @@ -239,11 +237,11 @@ return SCPE_OK; t_stat rad_fill (int32 sba) { uint32 p = rad_da * RAD_NUMWD; +uint32 *fbuf = rad_unit.filebuf; 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; + for ( ; wa < RAD_NUMWD; wa++) fbuf[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; diff --git a/SDS/sds_stddev.c b/SDS/sds_stddev.c index 02892571..56049acb 100644 --- a/SDS/sds_stddev.c +++ b/SDS/sds_stddev.c @@ -28,6 +28,7 @@ tti keyboard tto teleprinter + 29-Dec-03 RMS Added console backpressure support 25-Apr-03 RMS Revised for extended file support */ @@ -468,7 +469,7 @@ 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 */ + if (temp == '\r') sim_putchar ('\n'); /* lf after cr */ xfr_req = xfr_req | XFR_TTI; } /* set xfr flag */ else sim_putchar (007); /* ding! */ return SCPE_OK; @@ -499,7 +500,7 @@ return SCPE_OK; t_stat tto (uint32 fnc, uint32 inst, uint32 *dat) { -int32 asc, new_ch; +int32 new_ch; switch (fnc) { /* case function */ case IO_CONN: @@ -517,16 +518,8 @@ case IO_DISC: /* disconnect */ 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 */ + break; case IO_WREOR: /* write eor */ break; @@ -541,7 +534,21 @@ return SCPE_OK; t_stat tto_svc (UNIT *uptr) { +int32 asc; +t_stat r; + +if (uptr->buf == TT_CR) asc = '\r'; /* control chars? */ +else if (uptr->buf == TT_BS) asc = '\b'; +else if (uptr->buf == TT_TB) asc = '\t'; +else asc = sds_to_ascii[uptr->buf]; /* translate */ +if ((r = sim_putchar_s (asc)) != SCPE_OK) { /* output; error? */ + sim_activate (uptr, uptr->wait); /* retry */ + return ((r == SCPE_STALL)? SCPE_OK: r); } /* !stall? report */ +uptr->pos = uptr->pos + 1; /* inc position */ chan_set_ordy (tto_dib.chan); /* tto rdy */ +if (asc == '\r') { /* CR? */ + sim_putchar ('\n'); /* add lf */ + uptr->pos = uptr->pos + 1; } /* inc position */ return SCPE_OK; } diff --git a/VAX/vax_cpu.c b/VAX/vax_cpu.c index 6a851f48..fd889c3b 100644 --- a/VAX/vax_cpu.c +++ b/VAX/vax_cpu.c @@ -1,6 +1,6 @@ /* vax_cpu.c: VAX CPU simulator - Copyright (c) 1998-2003, Robert M Supnik + Copyright (c) 1998-2004, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -25,6 +25,10 @@ cpu CVAX central processor + 31-Dec-03 RMS Fixed bug in set_cpu_hist + 21-Dec-03 RMS Added autoconfiguration controls + 29-Oct-03 RMS Fixed WriteB declaration (found by Mark Pizzolato) + 23-Sep-03 RMS Revised instruction history for dynamic sizing 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 @@ -172,7 +176,8 @@ Write (va + 4, rh, L_LONG, WA); } \ else { R[rn] = rl; R[rnplus1] = rh; } -#define HIST_SIZE 4096 +#define HIST_MIN 128 +#define HIST_MAX 65536 struct InstHistory { int32 iPC; int32 PSL; @@ -217,10 +222,11 @@ int32 mchk_va, mchk_ref; /* mem ref param */ int32 ibufl, ibufh; /* prefetch buf */ int32 ibcnt, ppc; /* prefetch ctl */ int32 cpu_log = 0; /* logging */ +int32 autcon_enb = 1; /* autoconfig enable */ 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 */ +struct InstHistory *hst = NULL; /* instruction history */ const uint32 byte_mask[33] = { 0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000F, @@ -312,7 +318,7 @@ 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 void WriteB (uint32 pa, int32 val); extern int32 Test (uint32 va, int32 acc, int32 *status); extern int32 ReadLP (uint32 pa); extern int32 eval_int (void); @@ -321,6 +327,8 @@ 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); +extern t_stat set_autocon (UNIT *uptr, int32 val, char *cptr, void *desc); +extern t_stat show_autocon (FILE *st, UNIT *uptr, int32 val, void *desc); t_stat cpu_reset (DEVICE *dptr); t_stat cpu_boot (int32 unitno, DEVICE *dptr); @@ -392,6 +400,7 @@ REG cpu_reg[] = { { BRDATA (PCQ, pcq, 16, 32, PCQ_SIZE), REG_RO+REG_CIRC }, { HRDATA (PCQP, pcq_p, 6), REG_HRO }, { HRDATA (BADABO, badabo, 32), REG_HRO }, + { FLDATA (AUTOCON, autcon_enb, 0), REG_HRO }, { HRDATA (WRU, sim_int_char, 8) }, { NULL } }; @@ -406,6 +415,10 @@ MTAB cpu_mod[] = { NULL, &show_iospace }, { MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, "HISTORY", "HISTORY", &cpu_set_hist, &cpu_show_hist }, + { MTAB_XTD|MTAB_VDV, 1, "AUTOCONFIG", "AUTOCONFIG", + &set_autocon, &show_autocon }, + { MTAB_XTD|MTAB_VDV, 0, NULL, "NOAUTOCONFIG", + &set_autocon, NULL }, { MTAB_XTD|MTAB_VDV, 0, NULL, "VIRTUAL", &cpu_show_virt }, { 0 } }; @@ -999,16 +1012,14 @@ else { numspec = numspec & DR_NSPMASK; /* get # specifiers */ /* 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; + hst[hst_p].iPC = fault_PC; + hst[hst_p].PSL = PSL | cc; + hst[hst_p].opc = opc; + hst[hst_p].brdest = brdisp + PC; for (i = 0; i < (numspec & DR_NSPMASK); i++) - h->opnd[i] = opnd[i]; + hst[hst_p].opnd[i] = opnd[i]; + hst_p = hst_p + 1; + if (hst_p >= hst_lnt) hst_p = 0; } /* Dispatch to instructions */ @@ -2446,11 +2457,20 @@ int32 i, lnt; t_stat r; if (cptr == NULL) { - for (i = 0; i < HIST_SIZE; i++) hst[i].iPC = 0; + for (i = 0; i < hst_lnt; i++) hst[i].iPC = 0; + hst_p = 0; return SCPE_OK; } -lnt = (int32) get_uint (cptr, 10, HIST_SIZE, &r); -if (r != SCPE_OK) return SCPE_ARG; -hst_lnt = lnt; +lnt = (int32) get_uint (cptr, 10, HIST_MAX, &r); +if ((r != SCPE_OK) || (lnt && (lnt < HIST_MIN))) return SCPE_ARG; +hst_p = 0; +if (hst_lnt) { + free (hst); + hst_lnt = 0; + hst = NULL; } +if (lnt) { + hst = calloc (sizeof (struct InstHistory), lnt); + if (hst == NULL) return SCPE_MEM; + hst_lnt = lnt; } return SCPE_OK; } @@ -2463,9 +2483,9 @@ struct InstHistory *h; extern char *opcode[]; if (hst_lnt == 0) return SCPE_NOFNC; /* enabled? */ -di = hst_p + HIST_SIZE - hst_lnt; /* work forward */ +di = hst_p; /* work forward */ for (k = 0; k < hst_lnt; k++) { /* print specified */ - h = &hst[(di++) % HIST_SIZE]; /* entry pointer */ + h = &hst[(di++) % hst_lnt]; /* 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 */ diff --git a/VAX/vax_doc.txt b/VAX/vax_doc.txt index a8c12387..c821b221 100644 --- a/VAX/vax_doc.txt +++ b/VAX/vax_doc.txt @@ -1,7 +1,7 @@ To: Users From: Bob Supnik Subj: VAX Simulator Usage -Date: 15-Jul-2003 +Date: 15-Dec-2003 COPYRIGHT NOTICE @@ -213,7 +213,7 @@ This is controlled by the SET CPU HISTORY and SHOW CPU HISTORY commands: SET CPU HISTORY=n enable history, display length = n SHOW CPU HISTORY print CPU history -The maximum length for the history is 4096 entries. +The maximum length for the history is 65536 entries. 2.1.2 Translation Buffer (TLB) @@ -328,11 +328,13 @@ 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. +uses autoconfiguration DISABLES autoconfiguration for that device and for +the entire system. 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. Auto- +configuration can be restored for the entire system with the SET CPU +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 (*). diff --git a/VAX/vax_io.c b/VAX/vax_io.c index 5074b68e..afb62c04 100644 --- a/VAX/vax_io.c +++ b/VAX/vax_io.c @@ -25,6 +25,9 @@ qba Qbus adapter + 21-Dec-03 RMS Fixed bug in autoconfigure vector assignment; added controls + 21-Nov-03 RMS Added check for interrupt slot conflict (found by Dave Hittner) + 29-Oct-03 RMS Fixed WriteX declaration (found by Mark Pizzolato) 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 @@ -100,15 +103,16 @@ extern UNIT cpu_unit; extern int32 PSL, SISR, trpirq, mem_err, hlt_pin; extern int32 p1; extern int32 ssc_bto; +extern int32 autcon_enb; 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 void WriteB (uint32 pa, int32 val); +extern void WriteW (uint32 pa, int32 val); +extern void WriteL (uint32 pa, int32 val); extern FILE *sim_log; t_stat dbl_rd (int32 *data, int32 addr, int32 access); @@ -653,6 +657,24 @@ for (i = ma = 0; i < bc; i = i + 4, buf++) { /* by lw */ return 0; } +/* Enable/disable autoconfiguration */ + +t_stat set_autocon (UNIT *uptr, int32 val, char *cptr, void *desc) +{ +if (cptr != NULL) return SCPE_ARG; +autcon_enb = val; +return auto_config (0, 0); +} + +/* Show autoconfiguration status */ + +t_stat show_autocon (FILE *st, UNIT *uptr, int32 val, void *desc) +{ +fprintf (st, "autoconfiguration "); +fprintf (st, autcon_enb? "enabled": "disabled"); +return SCPE_OK; +} + /* Change device address */ t_stat set_addr (UNIT *uptr, int32 val, char *cptr, void *desc) @@ -674,7 +696,8 @@ 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 */ +autcon_enb = 0; /* autoconfig off */ +return SCPE_OK; } /* Show device address */ @@ -730,6 +753,8 @@ 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; +dptr->flags = dptr->flags & ~DEV_FLTA; /* not floating */ +autcon_enb = 0; /* autoconfig off */ return SCPE_OK; } @@ -783,14 +808,20 @@ return FALSE; /* Build interrupt tables */ -void build_int_vec (int32 vloc, int32 ivec, int32 (*iack)(void) ) +t_bool 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; +if (iack != NULL) { + if (int_ack[ilvl][ibit] && + (int_ack[ilvl][ibit] != iack)) return TRUE; + int_ack[ilvl][ibit] = iack; } +else if (ivec != 0) { + if (int_vec[ilvl][ibit] && + (int_vec[ilvl][ibit] != ivec)) return TRUE; + int_vec[ilvl][ibit] = ivec; } +return FALSE; } /* Build dib_tab from device list */ @@ -809,9 +840,15 @@ 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]); + for (k = 0; k < dibp->vnum; k++) { /* loop thru vec */ + if (build_int_vec (dibp->vloc + k, /* add vector */ + dibp->vec + (k * 4), dibp->ack[k])) { + printf ("Device %s interrupt slot conflict at %d\n", + sim_dname (dptr), dibp->vloc + k); + if (sim_log) fprintf (sim_log, + "Device %s interrupt slot conflict at %d\n", + sim_dname (dptr), dibp->vloc + k); + return SCPE_IERR; } } 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? */ @@ -922,6 +959,7 @@ DIB *dibp; int32 i, j, k; extern DEVICE *find_dev (char *ptr); +if (autcon_enb == 0) return SCPE_OK; /* enabled? */ 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 */ diff --git a/VAX/vax_mmu.c b/VAX/vax_mmu.c index 1f131b23..f0f7df43 100644 --- a/VAX/vax_mmu.c +++ b/VAX/vax_mmu.c @@ -23,6 +23,7 @@ be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. + 19-Sep-03 RMS Fixed upper/lower case linkage problems on VMS 01-Jun-03 RMS Fixed compilation problem with USE_ADDR64 This module contains the instruction simulators for @@ -63,9 +64,9 @@ 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; +int32 d_p0br, d_p0lr; /* dynamic copies */ +int32 d_p1br, d_p1lr; /* altered per ucode */ +int32 d_sbr, d_slr; extern int32 mchk_va, mchk_ref; /* for mcheck */ TLBENT stlb[VA_TBSIZE], ptlb[VA_TBSIZE]; static const int32 insert[4] = { @@ -407,23 +408,23 @@ 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; } + if (ptidx >= d_slr) MM_ERR (PR_LNV); /* system */ + ptead = d_sbr + ptidx; } else { if (va & VA_P1) { /* P1? */ - if (ptidx < p1lr) MM_ERR (PR_LNV); - ptead = p1br + ptidx; } + if (ptidx < d_p1lr) MM_ERR (PR_LNV); + ptead = d_p1br + ptidx; } else { /* P0 */ - if (ptidx >= p0lr) + if (ptidx >= d_p0lr) MM_ERR (PR_LNV); - ptead = p0br + ptidx; } + ptead = d_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 (ptidx >= d_slr) MM_ERR (PR_PLNV); + pte = ReadLP (d_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)] | @@ -452,12 +453,12 @@ return stlb[tbi]; 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 */ +d_p0br = P0BR & ~03; +d_p1br = (P1BR - 0x800000) & ~03; /* VA<30> >> 7 */ +d_sbr = (SBR - 0x1000000) & ~03; /* VA<31> >> 7 */ +d_p0lr = (P0LR << 2); +d_p1lr = (P1LR << 2) + 0x800000; /* VA<30> >> 7 */ +d_slr = (SLR << 2) + 0x1000000; /* VA<31> >> 7 */ return; } diff --git a/VAX/vax_stddev.c b/VAX/vax_stddev.c index e33a2b40..a1878d5f 100644 --- a/VAX/vax_stddev.c +++ b/VAX/vax_stddev.c @@ -1,6 +1,6 @@ /* vax_stddev.c: VAX standard I/O devices simulator - Copyright (c) 1998-2003, Robert M Supnik + Copyright (c) 1998-2004, 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"), @@ -27,6 +27,7 @@ tto terminal output clk 100Hz and TODR clock + 29-Dec-03 RMS Added console backpressure support 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 @@ -315,10 +316,12 @@ t_stat tto_svc (UNIT *uptr) int32 c; t_stat r; +c = tto_unit.buf & ((tto_unit.flags & UNIT_8B)? 0377: 0177); +if ((r = sim_putchar_s (c)) != SCPE_OK) { /* output; error? */ + sim_activate (uptr, uptr->wait); /* retry */ + return ((r == SCPE_STALL)? SCPE_OK: r); } /* !stall? report */ 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; } diff --git a/VAX/vaxmod_defs.h b/VAX/vaxmod_defs.h index 66a72894..d2949416 100644 --- a/VAX/vaxmod_defs.h +++ b/VAX/vaxmod_defs.h @@ -1,6 +1,6 @@ /* vaxmod_defs.h: VAX model-specific definitions file - Copyright (c) 1998-2002, Robert M Supnik + Copyright (c) 1998-2004, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -23,6 +23,7 @@ be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. + 29-Dec-03 RMS Added Q18 definition for PDP11 compatibility 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 @@ -204,9 +205,11 @@ #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_V_Q18 (DEV_V_UF + 2) /* Qbus, mem <= 256KB */ +#define DEV_V_FLTA (DEV_V_UF + 3) /* flt addr */ #define DEV_UBUS (1u << DEV_V_UBUS) #define DEV_QBUS (1u << DEV_V_QBUS) +#define DEV_Q18 (1u << DEV_V_Q18) #define DEV_FLTA (1u << DEV_V_FLTA) #define UNIBUS FALSE /* 22b only */ diff --git a/descrip.mms b/descrip.mms index 81c7c01e..7d56039a 100644 --- a/descrip.mms +++ b/descrip.mms @@ -7,13 +7,12 @@ # 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. +# the SIMH package for OpenVMS using DEC C v6.0-001(AXP), v6.5-001(AXP) +# and v6.4-005(VAX). +# These compilers are available with the OpenVMS V7.3 Hobbyist CDs # -# 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. +# Notes: On VAX, the PDP-10 and Eclipse simulators will not be built +# due to the fact that INT64 is required for that simulator. # # This build script will accept the following build options. # @@ -25,6 +24,7 @@ # H316 Just Build The Honewell 316/516. # HP2100 Just Build The Hewlett-Packard HP-2100. # I1401 Just Build The IBM 1401. +# I1620 Just Build The IBM 1620. # IBM1130 Just Build The IBM 1130. # ID16 Just Build The Interdata 16-bit CPU. # ID32 Just Build The Interdata 32-bit CPU. @@ -45,7 +45,7 @@ # To build with debugging enabled (which will also enable traceback # information) use.. # -# MMK/FORCE/MACRO=(DEBUG=1) +# MMK/MACRO=(DEBUG=1) # # This will produce an executable named {Simulator}-{VAX|AXP}-DBG.EXE # @@ -67,36 +67,46 @@ LIB_DIR = SYS$DISK:[.LIB] CC_DEBUG = /DEBUG=ALL LINK_DEBUG = /DEBUG/TRACEBACK CC_OPTIMIZE = /NOOPTIMIZE -.IFDEF __ALPHA__ +.IFDEF MMSALPHA CC_FLAGS = /PREFIX=ALL ARCH = AXP-DBG +CC_DEFS = _LARGEFILE .ELSE -ARCH = VAX-DBG CC_FLAGS = $(CC_FLAGS) +ARCH = VAX-DBG +CC_DEFS = __VAX .ENDIF .ELSE CC_DEBUG = /NODEBUG LINK_DEBUG = /NODEBUG/NOTRACEBACK -.IFDEF __ALPHA__ +.IFDEF MMSALPHA CC_OPTIMIZE = /OPTIMIZE=(LEVEL=5,TUNE=HOST)/ARCH=HOST CC_FLAGS = /PREFIX=ALL ARCH = AXP +CC_DEFS = _LARGEFILE .ELSE CC_OPTIMIZE = /OPTIMIZE -ARCH = VAX CC_FLAGS = $(CC_FLAGS) +ARCH = VAX +CC_DEFS = __VAX .ENDIF .ENDIF +# +# Define The platform specific Build Directory Where The Objects Will Go. +# +BLD_DIR = SYS$DISK:[.LIB.BLD-$(ARCH)] + # # Define Our Compiler Flags # -CC_FLAGS = $(CC_FLAGS)$(CC_DEBUG)$(CC_OPTIMIZE)/NEST=PRIMARY/NAME=(AS_IS,SHORTENED) +OUR_CC_FLAGS = $(CC_FLAGS)$(CC_DEBUG)$(CC_OPTIMIZE)/NEST=PRIMARY/NAME=(AS_IS,SHORTENED) + # # Define The Compile Command. # -CC = CC/DECC$(CC_FLAGS) +CC = CC/DECC$(OUR_CC_FLAGS) # # First, Let's Check To Make Sure We Have A SYS$DISK:[.BIN] And @@ -105,6 +115,8 @@ CC = CC/DECC$(CC_FLAGS) .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) + @ IF (F$SEARCH("SYS$DISK:[.LIB]BLD-$(ARCH).DIR").EQS."") THEN CREATE/DIRECTORY $(BLD_DIR) + @ IF (F$SEARCH("$(BLD_DIR)*.*").NES."") THEN DELETE/NOLOG/NOCONFIRM $(BLD_DIR)*.*;* # # Core SIMH File Definitions. @@ -114,9 +126,37 @@ 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 + +# +# VMS PCAP File Definitions. +# +PCAP_DIR = SYS$DISK:[.PCAP-VMS.PCAP-VCI] +PCAP_LIB = $(LIB_DIR)PCAP-$(ARCH).OLB +PCAP_SOURCE = $(PCAP_DIR)PCAPVCI.C,$(PCAP_DIR)VCMUTIL.C,\ + $(PCAP_DIR)BPF_DUMP.C,$(PCAP_DIR)BPF_FILTER.C,\ + $(PCAP_DIR)BPF_IMAGE.C,$(PCAP_DIR)ETHERENT.C,\ + $(PCAP_DIR)FAD-GIFC.C,$(PCAP_DIR)GENCODE.C,\ + $(PCAP_DIR)GRAMMAR.C,$(PCAP_DIR)INET.C,\ + $(PCAP_DIR)NAMETOADDR.C,$(PCAP_DIR)OPTIMIZE.C,\ + $(PCAP_DIR)PCAP.C,$(PCAP_DIR)SAVEFILE.C,\ + $(PCAP_DIR)SCANNER.C,$(PCAP_DIR)SNPRINTF.C,\ + $(PCAP_DIR)PCAP-VMS.C +PCAP_VCMDIR = SYS$DISK:[.PCAP-VMS.PCAPVCM] +PCAP_VCM_SOURCES = $(PCAP_VCMDIR)PCAPVCM.C,$(PCAP_VCMDIR)PCAPVCM_INIT.MAR,\ + $(PCAP_VCMDIR)VCI_JACKET.MAR,$(PCAP_VCMDIR)VCMUTIL.C +PCAP_VCI = SYS$COMMON:[SYS$LDR]PCAPVCM.EXE + +# +# PCAP is not available on OpenVMS VAX +# +.IFDEF MMSALPHA +PCAP_EXECLET = $(PCAP_VCI) +PCAP_INC = ,$(PCAP_DIR) +PCAP_LIBD = $(PCAP_LIB) +PCAP_LIBR = ,$(PCAP_LIB)/LIB/SYSEXE +PCAP_DEFS = ,"USE_NETWORK=1" +PCAP_SIMH_INC = /include=($(PCAP_DIR)) +.ENDIF # # MITS Altair Simulator Definitions. @@ -125,9 +165,7 @@ 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)) +ALTAIR_OPTIONS = /INCLUDE=($(SIMH_DIR),$(ALTAIR_DIR))/DEFINE=($(CC_DEFS)) # # MITS Altair Z80 Simulator Definitions. @@ -139,12 +177,7 @@ ALTAIRZ80_SOURCE = $(ALTAIRZ80_DIR)ALTAIRZ80_CPU.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)) +ALTAIRZ80_OPTIONS = /INCLUDE=($(SIMH_DIR),$(ALTAIRZ80_DIR))/DEFINE=($(CC_DEFS)) # # Data General Nova Simulator Definitions. @@ -157,13 +190,7 @@ NOVA_SOURCE = $(NOVA_DIR)NOVA_SYS.C,$(NOVA_DIR)NOVA_CPU.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)) +NOVA_OPTIONS = /INCLUDE=($(SIMH_DIR),$(NOVA_DIR))/DEFINE=($(CC_DEFS)) # # Data General Eclipse Simulator Definitions. @@ -175,13 +202,8 @@ ECLIPSE_SOURCE = $(NOVA_DIR)ECLIPSE_CPU.C,$(NOVA_DIR)ECLIPSE_TT.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") +ECLIPSE_OPTIONS = /INCLUDE=($(SIMH_DIR),$(NOVA_DIR))\ + /DEFINE=($(CC_DEFS),"USE_INT64=1","ECLIPSE=1") # # GRI Corporation GRI-909 Simulator Definitions. @@ -189,9 +211,7 @@ ECLIPSE_OPTIONS = /INCLUDE=($(SIMH_DIR),$(NOVA_DIR))/DEFINE=("ECLIPSE=1") 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)) +GRI_OPTIONS = /INCLUDE=($(SIMH_DIR),$(GRI_DIR))/DEFINE=($(CC_DEFS)) # # Honeywell 316/516 Simulator Definitions. @@ -199,10 +219,10 @@ GRI_OPTIONS = /INCLUDE=($(SIMH_DIR),$(GRI_DIR)) 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)) + $(H316_DIR)H316_CPU.C,$(H316_DIR)H316_SYS.C,\ + $(H316_DIR)H316_FHD.C,$(H316_DIR)H316_MT.C,\ + $(H316_DIR)H316_DP.C +H316_OPTIONS = /INCLUDE=($(SIMH_DIR),$(H316_DIR))/DEFINE=($(CC_DEFS)) # # Hewlett-Packard HP-2100 Simulator Definitions. @@ -216,14 +236,7 @@ HP2100_SOURCE = $(HP2100_DIR)HP2100_STDDEV.C,$(HP2100_DIR)HP2100_DP.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)) +HP2100_OPTIONS = /INCLUDE=($(SIMH_DIR),$(HP2100_DIR))/DEFINE=($(CC_DEFS)) # # Interdata 16-bit CPU. @@ -235,13 +248,7 @@ ID16_SOURCE = $(ID16_DIR)ID16_CPU.C,$(ID16_DIR)ID16_SYS.C,$(ID16_DIR)ID_DP.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)) +ID16_OPTIONS = /INCLUDE=($(SIMH_DIR),$(ID16_DIR))/DEFINE=($(CC_DEFS)) # # Interdata 32-bit CPU. @@ -253,14 +260,7 @@ ID32_SOURCE = $(ID32_DIR)ID32_CPU.C,$(ID32_DIR)ID32_SYS.C,$(ID32_DIR)ID_DP.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)) +ID32_OPTIONS = /INCLUDE=($(SIMH_DIR),$(ID32_DIR))/DEFINE=($(CC_DEFS)) # # IBM 1130 Simulator Definitions. @@ -272,12 +272,7 @@ IBM1130_SOURCE = $(IBM1130_DIR)IBM1130_CPU.C,$(IBM1130_DIR)IBM1130_CR.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)) +IBM1130_OPTIONS = /INCLUDE=($(SIMH_DIR),$(IBM1130_DIR))/DEFINE=($(CC_DEFS)) # # IBM 1401 Simulator Definitions. @@ -288,11 +283,7 @@ 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)) +I1401_OPTIONS = /INCLUDE=($(SIMH_DIR),$(I1401_DIR))/DEFINE=($(CC_DEFS)) # @@ -304,11 +295,7 @@ 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)) +I1620_OPTIONS = /INCLUDE=($(SIMH_DIR),$(I1620_DIR))/DEFINE=($(CC_DEFS)) # # PDP-1 Simulator Definitions. @@ -318,10 +305,7 @@ 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)) +PDP1_OPTIONS = /INCLUDE=($(SIMH_DIR),$(PDP1_DIR))/DEFINE=($(CC_DEFS)) # # Digital Equipment PDP-8 Simulator Definitions. @@ -334,15 +318,9 @@ PDP8_SOURCE = $(PDP8_DIR)PDP8_CPU.C,$(PDP8_DIR)PDP8_CLK.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)) + $(PDP8_DIR)PDP8_TTX.C,$(PDP8_DIR)PDP8_RL.C,\ + $(PDP8_DIR)PDP8_TSC.C,$(PDP8_DIR)PDP8_TD.C +PDP8_OPTIONS = /INCLUDE=($(SIMH_DIR),$(PDP8_DIR))/DEFINE=($(CC_DEFS)) # # Digital Equipment PDP-4, PDP-7, PDP-9 And PDP-15 Simulator Definitions. @@ -358,47 +336,31 @@ PDP18B_SOURCE = $(PDP18B_DIR)PDP18B_DT.C,$(PDP18B_DIR)PDP18B_DRM.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") +PDP4_OPTIONS = /INCLUDE=($(SIMH_DIR),$(PDP18B_DIR))/DEFINE=($(CC_DEFS),"PDP4=1") +PDP7_OPTIONS = /INCLUDE=($(SIMH_DIR),$(PDP18B_DIR))/DEFINE=($(CC_DEFS),"PDP7=1") +PDP9_OPTIONS = /INCLUDE=($(SIMH_DIR),$(PDP18B_DIR))/DEFINE=($(CC_DEFS),"PDP9=1") +PDP15_OPTIONS = /INCLUDE=($(SIMH_DIR),$(PDP18B_DIR))/DEFINE=($(CC_DEFS),"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_LIB1 = $(LIB_DIR)PDP11L1-$(ARCH).OLB +PDP11_SOURCE1 = $(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_SYS.C,$(PDP11_DIR)PDP11_TC.C +PDP11_LIB2 = $(LIB_DIR)PDP11L2-$(ARCH).OLB +PDP11_SOURCE2 = $(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") +PDP11_OPTIONS = /INCLUDE=($(SIMH_DIR),$(PDP11_DIR)$(PCAP_INC))\ + /DEFINE=($(CC_DEFS),"VM_PDP11=1"$(PCAP_DEFS)) # # Digital Equipment PDP-10 Simulator Definitions. @@ -408,20 +370,13 @@ 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_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_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") +PDP10_OPTIONS = /INCLUDE=($(SIMH_DIR),$(PDP10_DIR),$(PDP11_DIR))\ + /DEFINE=($(CC_DEFS),"USE_INT64=1","VM_PDP10=1") # # IBM System 3 Simulator Definitions. @@ -430,9 +385,7 @@ 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)) +S3_OPTIONS = /INCLUDE=($(SIMH_DIR),$(S3_DIR))/DEFINE=($(CC_DEFS)) # # SDS 940 @@ -443,11 +396,7 @@ 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)) +SDS_OPTIONS = /INCLUDE=($(SIMH_DIR),$(SDS_DIR))/DEFINE=($(CC_DEFS)) # # Digital Equipment VAX Simulator Definitions. @@ -462,31 +411,13 @@ VAX_SOURCE = $(VAX_DIR)VAX_CPU1.C,$(VAX_DIR)VAX_CPU.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 +VAX_OPTIONS = /INCLUDE=($(SIMH_DIR),$(VAX_DIR),$(PDP11_DIR)$(PCAP_INC))\ + /DEFINE=($(CC_DEFS),"VM_VAX=1"$(PCAP_DEFS)) # -# If On Alpha, Build Everything. +# If we're not a VAX, Build Everything # -.IFDEF __ALPHA__ +.IFDEF MMSALPHA 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 @@ -494,7 +425,7 @@ ALL : ALTAIR ALTAIRZ80 ECLIPSE GRI H316 HP2100 I1401 I1620 IBM1130 ID16 ID32 \ # 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 \ +ALL : ALTAIR ALTAIRZ80 GRI H316 HP2100 I1401 I1620 IBM1130 ID16 ID32 \ NOVA PDP1 PDP4 PDP7 PDP8 PDP9 PDP11 PDP15 S3 VAX SDS .ENDIF @@ -504,299 +435,333 @@ CLEAN : $! $ IF (F$SEARCH("$(BIN_DIR)*.EXE;*").NES."") THEN - DELETE/NOLOG/NOCONFIRM $(BIN_DIR)*.EXE;* - $ IF (F$SEARCH("$(LIB_DIR)*.EXE;*").NES."") THEN - + $ IF (F$SEARCH("$(LIB_DIR)*.OLB;*").NES."") THEN - DELETE/NOLOG/NOCONFIRM $(LIB_DIR)*.OLB;* $ IF (F$SEARCH("SYS$DISK:[...]*.OBJ;*").NES."") THEN - DELETE/NOLOG/NOCONFIRM SYS$DISK:[...]*.OBJ;* + $ IF (F$SEARCH("SYS$DISK:[...]*.LIS;*").NES."") THEN - + DELETE/NOLOG/NOCONFIRM SYS$DISK:[...]*.LIS;* + $ IF (F$SEARCH("SYS$DISK:[...]*.MAP;*").NES."") THEN - + DELETE/NOLOG/NOCONFIRM SYS$DISK:[...]*.MAP;* # # 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;* +$(SIMH_LIB) : $(SIMH_SOURCE) + $! + $! Building The $(SIMH_LIB) Library. + $! + $ $(CC)/DEFINE=($(CC_DEFS)$(PCAP_DEFS))$(PCAP_SIMH_INC) - + /OBJECT=$(BLD_DIR) $(MMS$CHANGED_LIST) + $ IF (F$SEARCH("$(MMS$TARGET)").EQS."") THEN - + LIBRARY/CREATE $(MMS$TARGET) + $ LIBRARY/REPLACE $(MMS$TARGET) $(BLD_DIR)*.OBJ + $ DELETE/NOLOG/NOCONFIRM $(BLD_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;* +$(ALTAIR_LIB) : $(ALTAIR_SOURCE) + $! + $! Building The $(ALTAIR_LIB) Library. + $! + $ $(CC)$(ALTAIR_OPTIONS) - + /OBJECT=$(BLD_DIR) $(MMS$CHANGED_LIST) + $ IF (F$SEARCH("$(MMS$TARGET)").EQS."") THEN - + LIBRARY/CREATE $(MMS$TARGET) + $ LIBRARY/REPLACE $(MMS$TARGET) $(BLD_DIR)*.OBJ + $ DELETE/NOLOG/NOCONFIRM $(BLD_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;* +$(ALTAIRZ80_LIB) : $(ALTAIRZ80_SOURCE) + $! + $! Building The $(ALTAIRZ80_LIB) Library. + $! + $ $(CC)$(ALTAIRZ80_OPTIONS) - + /OBJECT=$(BLD_DIR) $(MMS$CHANGED_LIST) + $ IF (F$SEARCH("$(MMS$TARGET)").EQS."") THEN - + LIBRARY/CREATE $(MMS$TARGET) + $ LIBRARY/REPLACE $(MMS$TARGET) $(BLD_DIR)*.OBJ + $ DELETE/NOLOG/NOCONFIRM $(BLD_DIR)*.OBJ;* # -# If On Alpha, Build The PDP-10 Library. +# If Not On VAX, Build The Eclipse 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;* +.IFDEF MMSALPHA +$(ECLIPSE_LIB) : $(ECLIPSE_SOURCE) + $! + $! Building The $(ECLIPSE_LIB) Library. + $! + $ $(CC)$(ECLIPSE_OPTIONS) - + /OBJECT=$(BLD_DIR) $(MMS$CHANGED_LIST) + $ IF (F$SEARCH("$(MMS$TARGET)").EQS."") THEN - + LIBRARY/CREATE $(MMS$TARGET) + $ LIBRARY/REPLACE $(MMS$TARGET) $(BLD_DIR)*.OBJ + $ DELETE/NOLOG/NOCONFIRM $(BLD_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. - $! +$(ECLIPSE_LIB) : + $! + $! Due To The Use Of INT64 We Can't Build The + $! $(LIB_DIR)ECLIPSE-$(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;* +$(GRI_LIB) : $(GRI_SOURCE) + $! + $! Building The $(GRI_LIB) Library. + $! + $ $(CC)$(GRI_OPTIONS) - + /OBJECT=$(BLD_DIR) $(MMS$CHANGED_LIST) + $ IF (F$SEARCH("$(MMS$TARGET)").EQS."") THEN - + LIBRARY/CREATE $(MMS$TARGET) + $ LIBRARY/REPLACE $(MMS$TARGET) $(BLD_DIR)*.OBJ + $ DELETE/NOLOG/NOCONFIRM $(BLD_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;* +$(H316_LIB) : $(H316_SOURCE) + $! + $! Building The $(H316_LIB) Library. + $! + $ $(CC)$(H316_OPTIONS) - + /OBJECT=$(BLD_DIR) $(MMS$CHANGED_LIST) + $ IF (F$SEARCH("$(MMS$TARGET)").EQS."") THEN - + LIBRARY/CREATE $(MMS$TARGET) + $ LIBRARY/REPLACE $(MMS$TARGET) $(BLD_DIR)*.OBJ + $ DELETE/NOLOG/NOCONFIRM $(BLD_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;* +$(HP2100_LIB) : $(HP2100_SOURCE) + $! + $! Building The $(HP2100_LIB) Library. + $! + $ $(CC)$(HP2100_OPTIONS) - + /OBJECT=$(BLD_DIR) $(MMS$CHANGED_LIST) + $ IF (F$SEARCH("$(MMS$TARGET)").EQS."") THEN - + LIBRARY/CREATE $(MMS$TARGET) + $ LIBRARY/REPLACE $(MMS$TARGET) $(BLD_DIR)*.OBJ + $ DELETE/NOLOG/NOCONFIRM $(BLD_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;* +$(I1401_LIB) : $(I1401_SOURCE) + $! + $! Building The $(I1401_LIB) Library. + $! + $ $(CC)$(I1401_OPTIONS) - + /OBJECT=$(BLD_DIR) $(MMS$CHANGED_LIST) + $ IF (F$SEARCH("$(MMS$TARGET)").EQS."") THEN - + LIBRARY/CREATE $(MMS$TARGET) + $ LIBRARY/REPLACE $(MMS$TARGET) $(BLD_DIR)*.OBJ + $ DELETE/NOLOG/NOCONFIRM $(BLD_DIR)*.OBJ;* + +$(I1620_LIB) : $(I1620_SOURCE) + $! + $! Building The $(I1620_LIB) Library. + $! + $ $(CC)$(I1620_OPTIONS) - + /OBJECT=$(BLD_DIR) $(MMS$CHANGED_LIST) + $ IF (F$SEARCH("$(MMS$TARGET)").EQS."") THEN - + LIBRARY/CREATE $(MMS$TARGET) + $ LIBRARY/REPLACE $(MMS$TARGET) $(BLD_DIR)*.OBJ + $ DELETE/NOLOG/NOCONFIRM $(BLD_DIR)*.OBJ;* + +$(IBM1130_LIB) : $(IBM1130_SOURCE) + $! + $! Building The $(IBM1130_LIB) Library. + $! + $ $(CC)$(IBM1130_OPTIONS) - + /OBJECT=$(BLD_DIR) $(MMS$CHANGED_LIST) + $ IF (F$SEARCH("$(MMS$TARGET)").EQS."") THEN - + LIBRARY/CREATE $(MMS$TARGET) + $ LIBRARY/REPLACE $(MMS$TARGET) $(BLD_DIR)*.OBJ + $ DELETE/NOLOG/NOCONFIRM $(BLD_DIR)*.OBJ;* + +$(ID16_LIB) : $(ID16_SOURCE) + $! + $! Building The $(ID16_LIB) Library. + $! + $ $(CC)$(ID16_OPTIONS) - + /OBJECT=$(BLD_DIR) $(MMS$CHANGED_LIST) + $ IF (F$SEARCH("$(MMS$TARGET)").EQS."") THEN - + LIBRARY/CREATE $(MMS$TARGET) + $ LIBRARY/REPLACE $(MMS$TARGET) $(BLD_DIR)*.OBJ + $ DELETE/NOLOG/NOCONFIRM $(BLD_DIR)*.OBJ;* + +$(ID32_LIB) : $(ID32_SOURCE) + $! + $! Building The $(ID32_LIB) Library. + $! + $ $(CC)$(ID32_OPTIONS) - + /OBJECT=$(BLD_DIR) $(MMS$CHANGED_LIST) + $ IF (F$SEARCH("$(MMS$TARGET)").EQS."") THEN - + LIBRARY/CREATE $(MMS$TARGET) + $ LIBRARY/REPLACE $(MMS$TARGET) $(BLD_DIR)*.OBJ + $ DELETE/NOLOG/NOCONFIRM $(BLD_DIR)*.OBJ;* + +$(NOVA_LIB) : $(NOVA_SOURCE) + $! + $! Building The $(NOVA_LIB) Library. + $! + $ $(CC)$(NOVA_OPTIONS) - + /OBJECT=$(BLD_DIR) $(MMS$CHANGED_LIST) + $ IF (F$SEARCH("$(MMS$TARGET)").EQS."") THEN - + LIBRARY/CREATE $(MMS$TARGET) + $ LIBRARY/REPLACE $(MMS$TARGET) $(BLD_DIR)*.OBJ + $ DELETE/NOLOG/NOCONFIRM $(BLD_DIR)*.OBJ;* + +$(PDP1_LIB) : $(PDP1_SOURCE) + $! + $! Building The $(PDP1_LIB) Library. + $! + $ $(CC)$(PDP1_OPTIONS) - + /OBJECT=$(BLD_DIR) $(MMS$CHANGED_LIST) + $ IF (F$SEARCH("$(MMS$TARGET)").EQS."") THEN - + LIBRARY/CREATE $(MMS$TARGET) + $ LIBRARY/REPLACE $(MMS$TARGET) $(BLD_DIR)*.OBJ + $ DELETE/NOLOG/NOCONFIRM $(BLD_DIR)*.OBJ;* + +$(PDP4_LIB) : $(PDP18B_SOURCE) + $! + $! Building The $(PDP4_LIB) Library. + $! + $ $(CC)$(PDP4_OPTIONS) - + /OBJECT=$(BLD_DIR) $(MMS$CHANGED_LIST) + $ IF (F$SEARCH("$(MMS$TARGET)").EQS."") THEN - + LIBRARY/CREATE $(MMS$TARGET) + $ LIBRARY/REPLACE $(MMS$TARGET) $(BLD_DIR)*.OBJ + $ DELETE/NOLOG/NOCONFIRM $(BLD_DIR)*.OBJ;* + +$(PDP7_LIB) : $(PDP18B_SOURCE) + $! + $! Building The $(PDP7_LIB) Library. + $! + $ $(CC)$(PDP7_OPTIONS) - + /OBJECT=$(BLD_DIR) $(MMS$CHANGED_LIST) + $ IF (F$SEARCH("$(MMS$TARGET)").EQS."") THEN - + LIBRARY/CREATE $(MMS$TARGET) + $ LIBRARY/REPLACE $(MMS$TARGET) $(BLD_DIR)*.OBJ + $ DELETE/NOLOG/NOCONFIRM $(BLD_DIR)*.OBJ;* + +$(PDP8_LIB) : $(PDP8_SOURCE) + $! + $! Building The $(PDP8_LIB) Library. + $! + $ $(CC)$(PDP8_OPTIONS) - + /OBJECT=$(BLD_DIR) $(MMS$CHANGED_LIST) + $ IF (F$SEARCH("$(MMS$TARGET)").EQS."") THEN - + LIBRARY/CREATE $(MMS$TARGET) + $ LIBRARY/REPLACE $(MMS$TARGET) $(BLD_DIR)*.OBJ + $ DELETE/NOLOG/NOCONFIRM $(BLD_DIR)*.OBJ;* + +$(PDP9_LIB) : $(PDP18B_SOURCE) + $! + $! Building The $(PDP9_LIB) Library. + $! + $ $(CC)$(PDP9_OPTIONS) - + /OBJECT=$(BLD_DIR) $(MMS$CHANGED_LIST) + $ IF (F$SEARCH("$(MMS$TARGET)").EQS."") THEN - + LIBRARY/CREATE $(MMS$TARGET) + $ LIBRARY/REPLACE $(MMS$TARGET) $(BLD_DIR)*.OBJ + $ DELETE/NOLOG/NOCONFIRM $(BLD_DIR)*.OBJ;* # -# If On Alpha, Build The VAX Library. +# If Not On VAX, Build The PDP-10 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;* +.IFDEF MMSALPHA +$(PDP10_LIB) : $(PDP10_SOURCE) + $! + $! Building The $(PDP10_LIB) Library. + $! + $ $(CC)$(PDP10_OPTIONS) - + /OBJECT=$(BLD_DIR) $(MMS$CHANGED_LIST) + $ IF (F$SEARCH("$(MMS$TARGET)").EQS."") THEN - + LIBRARY/CREATE $(MMS$TARGET) + $ LIBRARY/REPLACE $(MMS$TARGET) $(BLD_DIR)*.OBJ + $ DELETE/NOLOG/NOCONFIRM $(BLD_DIR)*.OBJ;* +.ELSE +# +# We Are On VAX And Due To The Use of INT64 We Can't Build It. +# +$(PDP10_LIB) : + $! + $! Due To The Use Of INT64 We Can't Build The + $! $(LIB_DIR)PDP10-$(ARCH).OLB Library On VAX. + $! +.ENDIF +$(PDP11_LIB1) : $(PDP11_SOURCE1) + $! + $! Building The $(PDP11_LIB1) Library. + $! + $(CC)$(PDP11_OPTIONS) - + /OBJECT=$(BLD_DIR) $(MMS$CHANGED_LIST) + $ IF (F$SEARCH("$(MMS$TARGET)").EQS."") THEN - + LIBRARY/CREATE $(MMS$TARGET) + $ LIBRARY/REPLACE $(MMS$TARGET) $(BLD_DIR)*.OBJ + $ DELETE/NOLOG/NOCONFIRM $(BLD_DIR)*.OBJ;* + +$(PDP11_LIB2) : $(PDP11_SOURCE2) + $! + $! Building The $(PDP11_LIB2) Library. + $! + $(CC)$(PDP11_OPTIONS) - + /OBJECT=$(BLD_DIR) $(MMS$CHANGED_LIST) + $ IF (F$SEARCH("$(MMS$TARGET)").EQS."") THEN - + LIBRARY/CREATE $(MMS$TARGET) + $ LIBRARY/REPLACE $(MMS$TARGET) $(BLD_DIR)*.OBJ + $ DELETE/NOLOG/NOCONFIRM $(BLD_DIR)*.OBJ;* + +$(PDP15_LIB) : $(PDP18B_SOURCE) + $! + $! Building The $(PDP15_LIB) Library. + $! + $ $(CC)$(PDP15_OPTIONS) - + /OBJECT=$(BLD_DIR) $(MMS$CHANGED_LIST) + $ IF (F$SEARCH("$(MMS$TARGET)").EQS."") THEN - + LIBRARY/CREATE $(MMS$TARGET) + $ LIBRARY/REPLACE $(MMS$TARGET) $(BLD_DIR)*.OBJ + $ DELETE/NOLOG/NOCONFIRM $(BLD_DIR)*.OBJ;* + +$(S3_LIB) : $(S3_SOURCE) + $! + $! Building The $(S3_LIB) Library. + $! + $ $(CC)$(S3_OPTIONS) - + /OBJECT=$(BLD_DIR) $(MMS$CHANGED_LIST) + $ IF (F$SEARCH("$(MMS$TARGET)").EQS."") THEN - + LIBRARY/CREATE $(MMS$TARGET) + $ LIBRARY/REPLACE $(MMS$TARGET) $(BLD_DIR)*.OBJ + $ DELETE/NOLOG/NOCONFIRM $(BLD_DIR)*.OBJ;* + +$(SDS_LIB) : $(SDS_SOURCE) + $! + $! Building The $(SDS_LIB) Library. + $! + $ $(CC)$(SDS_OPTIONS) - + /OBJECT=$(BLD_DIR) $(MMS$CHANGED_LIST) + $ IF (F$SEARCH("$(MMS$TARGET)").EQS."") THEN - + LIBRARY/CREATE $(MMS$TARGET) + $ LIBRARY/REPLACE $(MMS$TARGET) $(BLD_DIR)*.OBJ + $ DELETE/NOLOG/NOCONFIRM $(BLD_DIR)*.OBJ;* + +$(VAX_LIB) : $(VAX_SOURCE) + $! + $! Building The $(VAX_LIB) Library. + $! + $ $(CC)$(VAX_OPTIONS)/OBJECT=$(VAX_DIR) - + /OBJECT=$(BLD_DIR) $(MMS$CHANGED_LIST) + $ IF (F$SEARCH("$(MMS$TARGET)").EQS."") THEN - + LIBRARY/CREATE $(MMS$TARGET) + $ LIBRARY/REPLACE $(MMS$TARGET) $(BLD_DIR)*.OBJ + $ DELETE/NOLOG/NOCONFIRM $(BLD_DIR)*.OBJ;* + +$(PCAP_LIB) : $(PCAP_SOURCE) + $! + $! Building The $(PCAP_LIB) Library. + $! + $ SET DEFAULT $(PCAP_DIR) + $ @VMS_PCAP $(DEBUG) + $ SET DEFAULT [--] + $ IF (F$SEARCH("$(PCAP_LIB)").NES."") THEN - + DELETE $(PCAP_LIB); + $ COPY $(PCAP_DIR)PCAP.OLB $(PCAP_LIB) + $ DELETE/NOLOG/NOCONFIRM $(PCAP_DIR)*.OBJ;*,$(PCAP_DIR)*.OLB;* + # # Individual Simulator Builds. # @@ -804,167 +769,167 @@ ALTAIR : $(SIMH_LIB) $(ALTAIR_LIB) $! $! Building The $(BIN_DIR)ALTAIR-$(ARCH).EXE Simulator. $! - $ $(CC)$(ALTAIR_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C + $ $(CC)$(ALTAIR_OPTIONS)/OBJECT=$(BLD_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;* + $(BLD_DIR)SCP.OBJ,$(ALTAIR_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY + $ DELETE/NOLOG/NOCONFIRM $(BLD_DIR)*.OBJ;* ALTAIRZ80 : $(SIMH_LIB) $(ALTAIRZ80_LIB) $! $! Building The $(BIN_DIR)ALTAIRZ80-$(ARCH).EXE Simulator. $! - $ $(CC)$(ALTAIRZ80_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C + $ $(CC)$(ALTAIRZ80_OPTIONS)/OBJECT=$(BLD_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;* + $(BLD_DIR)SCP.OBJ,$(ALTAIRZ80_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY + $ DELETE/NOLOG/NOCONFIRM $(BLD_DIR)*.OBJ;* ECLIPSE : $(SIMH_LIB) $(ECLIPSE_LIB) $! - $! Building The $(BIN_DIR)ECLPISE-$(ARCH).EXE Simulator. + $! Building The $(BIN_DIR)ECLIPSE-$(ARCH).EXE Simulator. $! - $ $(CC)$(ECLIPSE_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C + $ $(CC)$(ECLIPSE_OPTIONS)/OBJECT=$(BLD_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;* + $(BLD_DIR)SCP.OBJ,$(ECLIPSE_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY + $ DELETE/NOLOG/NOCONFIRM $(BLD_DIR)*.OBJ;* GRI : $(SIMH_LIB) $(GRI_LIB) $! $! Building The $(BIN_DIR)GRI-$(ARCH).EXE Simulator. $! - $ $(CC)$(GRI_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C + $ $(CC)$(GRI_OPTIONS)/OBJECT=$(BLD_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;* + $(BLD_DIR)SCP.OBJ,$(GRI_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY + $ DELETE/NOLOG/NOCONFIRM $(BLD_DIR)*.OBJ;* H316 : $(SIMH_LIB) $(H316_LIB) $! $! Building The $(BIN_DIR)H316-$(ARCH).EXE Simulator. $! - $ $(CC)$(H316_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C + $ $(CC)$(H316_OPTIONS)/OBJECT=$(BLD_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;* + $(BLD_DIR)SCP.OBJ,$(H316_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY + $ DELETE/NOLOG/NOCONFIRM $(BLD_DIR)*.OBJ;* HP2100 : $(SIMH_LIB) $(HP2100_LIB) $! $! Building The $(BIN_DIR)HP2100-$(ARCH).EXE Simulator. $! - $ $(CC)$(HP2100_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C + $ $(CC)$(HP2100_OPTIONS)/OBJECT=$(BLD_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;* + $(BLD_DIR)SCP.OBJ,$(HP2100_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY + $ DELETE/NOLOG/NOCONFIRM $(BLD_DIR)*.OBJ;* I1401 : $(SIMH_LIB) $(I1401_LIB) $! $! Building The $(BIN_DIR)I1401-$(ARCH).EXE Simulator. $! - $ $(CC)$(I1401_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C + $ $(CC)$(I1401_OPTIONS)/OBJECT=$(BLD_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;* + $(BLD_DIR)SCP.OBJ,$(I1401_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY + $ DELETE/NOLOG/NOCONFIRM $(BLD_DIR)*.OBJ;* I1620 : $(SIMH_LIB) $(I1620_LIB) $! $! Building The $(BIN_DIR)I1620-$(ARCH).EXE Simulator. $! - $ $(CC)$(I1620_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C + $ $(CC)$(I1620_OPTIONS)/OBJECT=$(BLD_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;* + $(BLD_DIR)SCP.OBJ,$(I1620_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY + $ DELETE/NOLOG/NOCONFIRM $(BLD_DIR)*.OBJ;* IBM1130 : $(SIMH_LIB) $(IBM1130_LIB) $! $! Building The $(BIN_DIR)IBM1130-$(ARCH).EXE Simulator. $! - $ $(CC)$(IBM1130_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C + $ $(CC)$(IBM1130_OPTIONS)/OBJECT=$(BLD_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;* + $(BLD_DIR)SCP.OBJ,$(IBM1130_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY + $ DELETE/NOLOG/NOCONFIRM $(BLD_DIR)*.OBJ;* ID16 : $(SIMH_LIB) $(ID16_LIB) $! $! Building The $(BIN_DIR)ID16-$(ARCH).EXE Simulator. $! - $ $(CC)$(ID16_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C + $ $(CC)$(ID16_OPTIONS)/OBJECT=$(BLD_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;* + $(BLD_DIR)SCP.OBJ,$(ID16_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY + $ DELETE/NOLOG/NOCONFIRM $(BLD_DIR)*.OBJ;* ID32 : $(SIMH_LIB) $(ID32_LIB) $! $! Building The $(BIN_DIR)ID32-$(ARCH).EXE Simulator. $! - $ $(CC)$(ID32_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C + $ $(CC)$(ID32_OPTIONS)/OBJECT=$(BLD_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;* + $(BLD_DIR)SCP.OBJ,$(ID32_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY + $ DELETE/NOLOG/NOCONFIRM $(BLD_DIR)*.OBJ;* NOVA : $(SIMH_LIB) $(NOVA_LIB) $! $! Building The $(BIN_DIR)NOVA-$(ARCH).EXE Simulator. $! - $ $(CC)$(NOVA_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C + $ $(CC)$(NOVA_OPTIONS)/OBJECT=$(BLD_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;* + $(BLD_DIR)SCP.OBJ,$(NOVA_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY + $ DELETE/NOLOG/NOCONFIRM $(BLD_DIR)*.OBJ;* PDP1 : $(SIMH_LIB) $(PDP1_LIB) $! $! Building The $(BIN_DIR)PDP1-$(ARCH).EXE Simulator. $! - $ $(CC)$(PDP1_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C + $ $(CC)$(PDP1_OPTIONS)/OBJECT=$(BLD_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;* + $(BLD_DIR)SCP.OBJ,$(PDP1_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY + $ DELETE/NOLOG/NOCONFIRM $(BLD_DIR)*.OBJ;* PDP4 : $(SIMH_LIB) $(PDP4_LIB) $! $! Building The $(BIN_DIR)PDP4-$(ARCH).EXE Simulator. $! - $ $(CC)$(PDP4_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C + $ $(CC)$(PDP4_OPTIONS)/OBJECT=$(BLD_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;* + $(BLD_DIR)SCP.OBJ,$(PDP4_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY + $ DELETE/NOLOG/NOCONFIRM $(BLD_DIR)*.OBJ;* PDP7 : $(SIMH_LIB) $(PDP7_LIB) $! $! Building The $(BIN_DIR)PDP7-$(ARCH).EXE Simulator. $! - $ $(CC)$(PDP7_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C + $ $(CC)$(PDP7_OPTIONS)/OBJECT=$(BLD_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;* + $(BLD_DIR)SCP.OBJ,$(PDP7_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY + $ DELETE/NOLOG/NOCONFIRM $(BLD_DIR)*.OBJ;* PDP8 : $(SIMH_LIB) $(PDP8_LIB) $! $! Building The $(BIN_DIR)PDP8-$(ARCH).EXE Simulator. $! - $ $(CC)$(PDP8_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C + $ $(CC)$(PDP8_OPTIONS)/OBJECT=$(BLD_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;* + $(BLD_DIR)SCP.OBJ,$(PDP8_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY + $ DELETE/NOLOG/NOCONFIRM $(BLD_DIR)*.OBJ;* PDP9 : $(SIMH_LIB) $(PDP9_LIB) $! $! Building The $(BIN_DIR)PDP9-$(ARCH).EXE Simulator. $! - $ $(CC)$(PDP9_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C + $ $(CC)$(PDP9_OPTIONS)/OBJECT=$(BLD_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;* + $(BLD_DIR)SCP.OBJ,$(PDP9_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY + $ DELETE/NOLOG/NOCONFIRM $(BLD_DIR)*.OBJ;* # -# If On Alpha, Build The PDP-10 Simulator. +# If Not On VAX, Build The PDP-10 Simulator. # -.IFDEF __ALPHA__ +.IFDEF MMSALPHA PDP10 : $(SIMH_LIB) $(PDP10_LIB) $! $! Building The $(BIN_DIR)PDP10-$(ARCH).EXE Simulator. $! - $ $(CC)$(PDP10_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C + $ $(CC)$(PDP10_OPTIONS)/OBJECT=$(BLD_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;* + $(BLD_DIR)SCP.OBJ,$(PDP10_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY + $ DELETE/NOLOG/NOCONFIRM $(BLD_DIR)*.OBJ;* .ELSE # # Else We Are On VAX And Tell The User We Can't Build On VAX @@ -977,47 +942,65 @@ PDP10 : $! .ENDIF -PDP11 : $(SIMH_LIB) $(PDP11_LIB) +PDP11 : $(SIMH_LIB) $(PCAP_LIBD) $(PDP11_LIB1) $(PDP11_LIB2) $(PCAP_EXECLET) $! $! Building The $(BIN_DIR)PDP11-$(ARCH).EXE Simulator. $! - $ $(CC)$(PDP11_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C + $ $(CC)$(PDP11_OPTIONS)/OBJECT=$(BLD_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;* + $(BLD_DIR)SCP.OBJ,$(PDP11_LIB1)/LIBRARY,$(PDP11_LIB2)/LIBRARY,$(SIMH_LIB)/LIBRARY$(PCAP_LIBR) + $ DELETE/NOLOG/NOCONFIRM $(BLD_DIR)*.OBJ;* PDP15 : $(SIMH_LIB) $(PDP15_LIB) $! $! Building The $(BIN_DIR)PDP15-$(ARCH).EXE Simulator. $! - $ $(CC)$(PDP15_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C + $ $(CC)$(PDP15_OPTIONS)/OBJECT=$(BLD_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;* + $(BLD_DIR)SCP.OBJ,$(PDP15_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY + $ DELETE/NOLOG/NOCONFIRM $(BLD_DIR)*.OBJ;* S3 : $(SIMH_LIB) $(S3_LIB) $! $! Building The $(BIN_DIR)S3-$(ARCH).EXE Simulator. $! - $ $(CC)$(S3_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C + $ $(CC)$(S3_OPTIONS)/OBJECT=$(BLD_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;* + $(BLD_DIR)SCP.OBJ,$(S3_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY + $ DELETE/NOLOG/NOCONFIRM $(BLD_DIR)*.OBJ;* SDS : $(SIMH_LIB) $(SDS_LIB) $! $! Building The $(BIN_DIR)SDS-$(ARCH).EXE Simulator. $! - $ $(CC)$(SDS_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C + $ $(CC)$(SDS_OPTIONS)/OBJECT=$(BLD_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;* + $(BLD_DIR)SCP.OBJ,$(SDS_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY + $ DELETE/NOLOG/NOCONFIRM $(BLD_DIR)*.OBJ;* -VAX : $(SIMH_LIB) $(VAX_LIB) +VAX : $(SIMH_LIB) $(PCAP_LIBD) $(VAX_LIB) $(PCAP_EXECLET) $! $! Building The $(BIN_DIR)VAX-$(ARCH).EXE Simulator. $! - $ $(CC)$(VAX_OPTIONS)/OBJECT=$(SIMH_DIR) SCP.C + $ $(CC)$(VAX_OPTIONS)/OBJECT=$(BLD_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;* + $(BLD_DIR)SCP.OBJ,$(VAX_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY$(PCAP_LIBR) + $ DELETE/NOLOG/NOCONFIRM $(BLD_DIR)*.OBJ;* + +# +# PCAP VCI Components +# + +$(PCAP_VCI) : $(PCAP_VCMDIR)PCAPVCM.EXE + $! + $! Installing the PCAP VCI Execlet in SYS$LOADABLE_IMAGES + $! + $ COPY $(PCAP_VCMDIR)PCAPVCM.EXE SYS$COMMON:[SYS$LDR]PCAPVCM.EXE + +$(PCAP_VCMDIR)PCAPVCM.EXE : $(PCAP_VCM_SOURCES) + $! + $! Building The PCAP VCI Execlet + $! + $ @SYS$DISK:[.PCAP-VMS.PCAPVCM]BUILD_PCAPVCM + $ DELETE/NOLOG/NOCONFIRM $(PCAP_VCMDIR)*.OBJ;*,$(PCAP_VCMDIR)*.MAP;* + diff --git a/makefile b/makefile index f3c30c92..5c99827c 100644 --- a/makefile +++ b/makefile @@ -5,8 +5,12 @@ # ifeq ($(WIN32),) #Unix Environments +ifeq ($(OSTYPE),solaris) +OS_CCDEFS = -lsocket -lnsl -I /usr/local/include +CC = gcc -O2 -g -lm $(OS_CCDEFS) -L /usr/local/lib -I . -D_GNU_SOURCE +else CC = gcc -O2 -lm -I . -#CC = gcc -O2 -g -lm -I . +endif ifeq ($(USE_NETWORK),) else NETWORK_OPT = -DUSE_NETWORK -lpcap @@ -53,7 +57,7 @@ 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 +ECLIPSE_OPT = -I ${NOVAD} -DECLIPSE -DUSE_INT64 @@ -108,14 +112,16 @@ 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 + ${PDP8D}pdp8_ttx.c ${PDP8D}pdp8_rl.c ${PDP8D}pdp8_tsc.c \ + ${PDP8D}pdp8_td.c PDP8_OPT = -I ${PDP8D} H316D = H316/ H316 = ${H316D}h316_stddev.c ${H316D}h316_lp.c ${H316D}h316_cpu.c \ - ${H316D}h316_sys.c + ${H316D}h316_sys.c ${H316D}h316_mt.c ${H316D}h316_fhd.c \ + ${H316D}h316_dp.c H316_OPT = -I ${H316D} diff --git a/scp.c b/scp.c index 52e5bdeb..9c3e6aa5 100644 --- a/scp.c +++ b/scp.c @@ -1,6 +1,6 @@ /* scp.c: simulator control program - Copyright (c) 1993-2003, Robert M Supnik + Copyright (c) 1993-2004, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -23,6 +23,10 @@ be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. + 29-Dec-03 RMS Added Telnet console output stall support + 01-Nov-03 RMS Cleaned up implicit detach on attach/restore + Fixed bug in command line read while logging + (found by Mark Pizzolato) 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 @@ -312,6 +316,8 @@ REG *find_reg_glob (char *ptr, char **optr, DEVICE **gdptr); /* Forward references within commands */ +t_stat scp_attach_unit (DEVICE *dptr, UNIT *uptr, char *cptr); +t_stat scp_detach_unit (DEVICE *dptr, UNIT *uptr); t_bool restore_skip_val (FILE *rfile); t_bool qdisable (DEVICE *dptr); t_stat attach_err (UNIT *uptr, t_stat stat); @@ -931,15 +937,15 @@ 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->flags & DEV_DIS) == 0) /* already enb? ok */ + return SCPE_OK; + dptr->flags = dptr->flags & ~DEV_DIS; } /* no, enable */ +else { 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; } @@ -950,10 +956,9 @@ 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 */ +else { if ((uptr->flags & UNIT_ATT) || /* offline */ + sim_is_active (uptr)) return SCPE_NOFNC; /* more tests */ + uptr->flags = uptr->flags | UNIT_DIS; } /* disable */ return SCPE_OK; } @@ -985,48 +990,48 @@ 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 (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 */ + 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 */ + 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 (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? */ + 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->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 */ + 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; } @@ -1194,17 +1199,17 @@ 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"); } + 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; } @@ -1214,11 +1219,11 @@ 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); } } + 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; } @@ -1263,30 +1268,30 @@ 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; + 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; } @@ -1369,6 +1374,7 @@ t_stat attach_cmd (int32 flag, char *cptr) char gbuf[CBUFSIZE]; DEVICE *dptr; UNIT *uptr; +t_stat r; GET_SWITCHES (cptr); /* get switches */ if (*cptr == 0) return SCPE_2FARG; /* must be more */ @@ -1378,24 +1384,33 @@ 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); +if (uptr->flags & UNIT_ATT) { /* already attached? */ + r = scp_detach_unit (dptr, uptr); /* detach it */ + if (r != SCPE_OK) return r; } /* error? */ +return scp_attach_unit (dptr, uptr, cptr); /* attach */ } +/* Call device-specific or file-oriented attach unit routine */ + +t_stat scp_attach_unit (DEVICE *dptr, UNIT *uptr, char *cptr) +{ +if (dptr->attach != NULL) /* device routine? */ + return dptr->attach (uptr, cptr); /* call it */ +return attach_unit (uptr, cptr); /* no, std routine */ +} + +/* Attach unit to file */ + 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)); +uptr->filename = calloc (CBUFSIZE, sizeof (char)); /* alloc buf for name */ if (uptr->filename == NULL) return SCPE_MEM; -strncpy (uptr->filename, cptr, CBUFSIZE); +strncpy (uptr->filename, cptr, CBUFSIZE); /* save name */ if (sim_switches & SWMASK ('R')) { /* read only? */ if ((uptr->flags & UNIT_ROABLE) == 0) /* allowed? */ return attach_err (uptr, SCPE_NORO); /* no, error */ @@ -1466,9 +1481,9 @@ 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); +if (!(uptr->flags & UNIT_ATTABLE)) return SCPE_NOATT; /* attachable? */ +if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; /* attached? */ +return scp_detach_unit (dptr, uptr); /* detach */ } /* Detach devices start..end @@ -1478,26 +1493,40 @@ return detach_unit (uptr); shutdown = TRUE if simulator shutting down Outputs: status = error status + + Note that during shutdown, detach routines for non-attachable devices + will be called. These routines can implement simulator shutdown. */ t_stat detach_all (int32 start, t_bool shutdown) { uint32 i, j; -t_stat reason; DEVICE *dptr; UNIT *uptr; +t_stat r; 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; } } } +for (i = start; (dptr = sim_devices[i]) != NULL; i++) { /* loop thru dev */ + for (j = 0; j < dptr->numunits; j++) { /* loop thru units */ + uptr = (dptr->units) + j; + if ((uptr->flags & UNIT_ATT) || /* attached? */ + (shutdown && dptr->detach && /* shutdown, spec rtn, */ + !(uptr->flags & UNIT_ATTABLE))) { /* !attachable? */ + r = scp_detach_unit (dptr, uptr); /* detach unit */ + if (r != SCPE_OK) return r; } } } return SCPE_OK; } +/* Call device-specific or file-oriented detach unit routine */ + +t_stat scp_detach_unit (DEVICE *dptr, UNIT *uptr) +{ +if (dptr->detach != NULL) return dptr->detach (uptr); /* device routine? */ +return detach_unit (uptr); /* no, standard */ +} + +/* Detach unit from file */ + t_stat detach_unit (UNIT *uptr) { DEVICE *dptr; @@ -1506,16 +1535,16 @@ 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; } + 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; @@ -1780,16 +1809,14 @@ for ( ;; ) { /* device loop */ 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); + r = scp_detach_unit (dptr, uptr); /* detach old */ 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); + r = scp_attach_unit (dptr, uptr, buf); if (r != SCPE_OK) return r; } } READ_I (high); /* memory capacity */ if (high > 0) { /* [V2.5+] any memory? */ @@ -2466,8 +2493,8 @@ 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 (sim_log) fprintf (sim_log, (cptr? "%s\n": "\n"), cptr); if (*cptr == 0) return dfltinc; } /* success */ if (uptr->flags & UNIT_RO) return SCPE_RO; /* read only? */ mask = width_mask[dptr->dwidth]; @@ -3371,6 +3398,7 @@ 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 */ +static int32 rtc_initd[SIM_NTIMERS] = { 0 }; /* initial delay */ extern t_bool rtc_avail; int32 sim_rtcn_init (int32 time, int32 tmr) @@ -3383,6 +3411,7 @@ rtc_nxintv[tmr] = 1000; rtc_ticks[tmr] = 0; rtc_based[tmr] = time; rtc_currd[tmr] = time; +rtc_initd[tmr] = time; return time; } @@ -3402,17 +3431,20 @@ if (new_rtime < rtc_rtime[tmr]) { /* time running backwards? */ 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 */ +if (delta_rtime > 30000) /* gap too big? */ + return rtc_initd[tmr]; /* can't calibr */ +if (delta_rtime == 0) /* gap too small? */ + rtc_based[tmr] = rtc_based[tmr] * ticksper; /* slew wide */ +else rtc_based[tmr] = (int32) (((double) rtc_based[tmr] * (double) rtc_nxintv[tmr]) / + ((double) delta_rtime)); /* new base rate */ 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_based[tmr] <= 0) rtc_based[tmr] = 1; /* never negative or zero! */ if (rtc_currd[tmr] <= 0) rtc_currd[tmr] = 1; /* never negative or zero! */ return rtc_currd[tmr]; } @@ -3771,3 +3803,16 @@ tmxr_putc_ln (&sim_con_ldsc, c); /* output char */ tmxr_poll_tx (&sim_con_tmxr); /* poll xmt */ return SCPE_OK; } + +t_stat sim_putchar_s (int32 c) +{ +t_stat r; + +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? */ +if (sim_con_ldsc.xmte == 0) r = SCPE_STALL; /* xmt disabled? */ +else r = tmxr_putc_ln (&sim_con_ldsc, c); /* no, Telnet output */ +tmxr_poll_tx (&sim_con_tmxr); /* poll xmt */ +return r; /* return status */ +} diff --git a/sim_defs.h b/sim_defs.h index 7bdbbd62..760418e6 100644 --- a/sim_defs.h +++ b/sim_defs.h @@ -1,6 +1,6 @@ /* sim_defs.h: simulator definitions - Copyright (c) 1993-2003, Robert M Supnik + Copyright (c) 1993-2004, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -23,6 +23,7 @@ be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. + 29-Dec-03 RMS Added output stall status 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 @@ -196,6 +197,7 @@ typedef unsigned int32 t_addr; #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_STALL (SCPE_BASE + 41) /* Telnet conn stall */ #define SCPE_KFLAG 0010000 /* tti data flag */ #define SCPE_BREAK 0020000 /* tti break flag */ @@ -474,6 +476,7 @@ 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); +t_stat sim_putchar_s (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); diff --git a/sim_ether.c b/sim_ether.c index 48a4280f..78191bd0 100644 --- a/sim_ether.c +++ b/sim_ether.c @@ -1,6 +1,5 @@ /* 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 @@ -53,6 +52,27 @@ Modification history: + 15-Dec-03 MP polished generic libpcap support. + 05-Dec-03 DTH Genericized eth_devices() and #ifdefs + 03-Dec-03 MP Added Solaris support + 02-Dec-03 DTH Corrected decnet fix to use reflection counting + 01-Dec-03 DTH Added BPF source filtering and reflection counting + 28-Nov-03 DTH Rewrote eth_devices using universal pcap_findalldevs() + 25-Nov-03 DTH Verified DECNET_FIX, reversed ifdef to mainstream code + 19-Nov-03 MP Fixed BPF functionality on Linux/BSD. + 17-Nov-03 DTH Added xBSD simplification + 14-Nov-03 DTH Added #ifdef DECNET_FIX for problematic duplicate detection code + 13-Nov-03 DTH Merged in __FreeBSD__ support + 21-Oct-03 MP Added enriched packet dumping for debugging + 20-Oct-03 MP Added support for multiple ethernet devices on VMS + 20-Sep-03 Ankan Add VMS support (Alpha only) + 29-Sep-03 MP Changed separator character in eth_fmt_mac to be ":" to + format ethernet addresses the way the BPF compile engine + wants to see them. + Added BPF support to filter packets + Added missing printf in eth_close + 07-Jun-03 MP Added WIN32 support for DECNET duplicate address detection. + 06-Jun-03 MP Fixed formatting of Ethernet Protocol Type in eth_packet_trace 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. @@ -102,19 +122,29 @@ 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 #include "sim_ether.h" +#include "sim_sock.h" extern FILE *sim_log; +/* make common BSD code a bit easier to read in this file */ +/* OS/X seems to define and compile using one of these BSD types */ +#if defined(__NetBSD__) || defined (__OpenBSD__) || defined (__FreeBSD__) +#define xBSD 1 +#endif + +/* make common winpcap code a bit easier to read in this file */ +#if defined(_WIN32) || defined(VMS) +#define WIN_PCAP 1 +#define HAS_PCAP_SENDPACKET 1 +#define PCAP_READ_TIMEOUT -1 +#else +#define PCAP_READ_TIMEOUT 1 +#endif + /*============================================================================*/ /* OS-independant ethernet routines */ /*============================================================================*/ @@ -122,7 +152,7 @@ extern FILE *sim_log; 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]); + sprintf(buff, "%02X:%02X:%02X:%02X:%02X:%02X", m[0], m[1], m[2], m[3], m[4], m[5]); return; } @@ -183,8 +213,7 @@ uint32 eth_crc32(uint32 crc, const void* vbuf, size_t len) return(crc ^ mask); } - -void eth_packet_trace(ETH_PACK* packet, char* msg) +void eth_packet_trace_ex(ETH_PACK* packet, char* msg, int dmp) { char src[20]; char dst[20]; @@ -192,8 +221,43 @@ void eth_packet_trace(ETH_PACK* packet, char* msg) 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); + printf("Eth: %s dst: %s src: %s proto: 0x%04X len: %d crc: %X\r\n", + msg, dst, src, ntohs(*proto), packet->len, crc); + if (dmp) { + int i, same, group, sidx, oidx; + char outbuf[80], strbuf[18]; + static char hex[] = "0123456789ABCDEF"; + for (i=same=0; ilen; i += 16) { + if ((i > 0) && (0 == memcmp(&packet->msg[i], &packet->msg[i-16], 16))) { + ++same; + continue; + } + if (same > 0) { + printf("%04X thru %04X same as above\r\n", i-(16*same), i-1); + same = 0; + } + group = (((packet->len - i) > 16) ? 16 : (packet->len - i)); + for (sidx=oidx=0; sidxmsg[i+sidx]>>4)&0xf]; + outbuf[oidx++] = hex[packet->msg[i+sidx]&0xf]; + if (isprint(packet->msg[i+sidx])) + strbuf[sidx] = packet->msg[i+sidx]; + else + strbuf[sidx] = '.'; + } + outbuf[oidx] = '\0'; + strbuf[sidx] = '\0'; + printf("%04X%-48s %s\r\n", i, outbuf, strbuf); + } + if (same > 0) + printf("%04X thru %04X same as above\r\n", i-(16*same), packet->len-1); + } +} + +void eth_packet_trace(ETH_PACK* packet, char* msg) +{ + eth_packet_trace_ex(packet, msg, packet->len > 1514); } char* eth_getname(int number, char* name) @@ -211,14 +275,14 @@ void eth_zero(ETH_DEV* dev) { /* set all members to NULL OR 0 */ memset(dev, 0, sizeof(ETH_DEV)); + dev->reflections = -1; /* not established yet */ } /*============================================================================*/ /* Non-implemented versions */ /*============================================================================*/ -#if !defined (_WIN32) && !defined(linux) && !defined(__NetBSD__) && \ - !defined (__OpenBSD__) || !defined (USE_NETWORK) +#if !defined (USE_NETWORK) t_stat eth_open (ETH_DEV* dev, char* name) {return SCPE_NOFNC;} t_stat eth_close (ETH_DEV* dev) @@ -235,22 +299,29 @@ int eth_devices (int max, ETH_LIST* dev) #else /* endif unimplemented */ /*============================================================================*/ -/* WIN32, Linux, NetBSD, and OpenBSD routines */ -/* Uses WinPcap and libpcap packages */ +/* WIN32, Linux, and xBSD routines use WinPcap and libpcap packages */ +/* OpenVMS Alpha uses a WinPcap port and an associated execlet */ /*============================================================================*/ -#include #include -#ifdef _WIN32 -#include -#endif /* _WIN32 */ -#if defined (__NetBSD__) || defined (__OpenBSD__) +#include +#ifdef xBSD #include -#include -#endif /* __NetBSD__ || __OpenBSD__*/ -#if defined (linux) || defined(__NetBSD__) || defined (__OpenBSD__) -#include -#endif /* linux || __NetBSD__ || __OpenBSD__ */ +#endif /* xBSD */ + +#if !defined (HAS_PCAP_SENDPACKET) +/* libpcap has no function to write a packet, so we need to implement + pcap_sendpacket() for compatibility with the WinPcap base code. + Return value: 0=Success, -1=Failure */ +int pcap_sendpacket(pcap_t* handle, u_char* msg, int len) +{ +#if defined (linux) + return (send(pcap_fileno(handle), msg, len, 0) == len)? 0 : -1; +#else + return (write(pcap_fileno(handle), msg, len) == len)? 0 : -1; +#endif /* linux */ +} +#endif /* !HAS_PCAP_SENDPACKET */ t_stat eth_open(ETH_DEV* dev, char* name) { @@ -259,6 +330,7 @@ t_stat eth_open(ETH_DEV* dev, char* name) char temp[1024]; char* savname = name; int num; + char* msg; /* initialize device */ eth_zero(dev); @@ -276,46 +348,53 @@ t_stat eth_open(ETH_DEV* dev, char* name) /* attempt to connect device */ memset(errbuf, 0, sizeof(errbuf)); - dev->handle = (void*) pcap_open_live(savname, bufsz, ETH_PROMISC, -1, errbuf); + dev->handle = (void*) pcap_open_live(savname, bufsz, ETH_PROMISC, PCAP_READ_TIMEOUT, 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); + msg = "Eth: pcap_open_live error - %s\r\n"; + printf (msg, errbuf); + if (sim_log) fprintf (sim_log, msg, errbuf); return SCPE_OPENERR; } else { - printf ("Eth: opened %s\n", savname); - if (sim_log) fprintf (sim_log, "Eth: opened %s\n", savname); + msg = "Eth: opened %s\r\n"; + printf (msg, savname); + if (sim_log) fprintf (sim_log, msg, savname); } /* save name of device */ dev->name = malloc(strlen(savname)+1); strcpy(dev->name, savname); -#if defined (__NetBSD__) || defined(__OpenBSD__) +#if defined (xBSD) /* 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 */ + This is required in order to fake the src address. */ { - int one = 1; - ioctl(pcap_fileno(dev->handle), BIOCSHDRCMPLT, &one); + 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__ */ +#endif /* xBSD */ +#if !defined (WIN_PCAP) + /* set ethernet device non-blocking so pcap_dispatch() doesn't hang */ + if (pcap_setnonblock (dev->handle, 1, errbuf) == -1) { + msg = "Eth: Failed to set non-blocking: %s\r\n"; + printf (msg, errbuf); + if (sim_log) fprintf (sim_log, msg, errbuf); + } +#endif return SCPE_OK; } t_stat eth_close(ETH_DEV* dev) { + char* msg = "Eth: closed %s\r\n"; + /* 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); + printf (msg, dev->name); + if (sim_log) fprintf (sim_log, msg, dev->name); /* clean up the mess */ free(dev->name); @@ -324,6 +403,43 @@ t_stat eth_close(ETH_DEV* dev) return SCPE_OK; } +t_stat eth_reflect(ETH_DEV* dev, ETH_MAC mac) +{ + ETH_PACK send, recv; + t_stat status; + int i; + + /* build a packet */ + memset (&send, 0, sizeof(ETH_PACK)); + send.len = ETH_MIN_PACKET; /* minimum packet size */ + memcpy(&send.msg[0], mac, sizeof(ETH_MAC)); /* target address */ + memcpy(&send.msg[6], mac, sizeof(ETH_MAC)); /* source address */ + send.msg[12] = 0x90; /* loopback packet type */ + for (i=14; ireflections = 0; + do { + memset (&recv, 0, sizeof(ETH_PACK)); + status = eth_read (dev, &recv, NULL); + if (memcmp(send.msg, recv.msg, ETH_MIN_PACKET)== 0) + dev->reflections++; + } while (recv.len > 0); + +#ifdef ETH_DEBUG + { + char* msg = "Eth: reflections = %d\r\n"; + printf (msg, dev->reflections); + if (sim_log) fprintf (sim_log, msg, dev->reflections); + } +#endif + return dev->reflections; +} + t_stat eth_write(ETH_DEV* dev, ETH_PACK* packet, ETH_PCALLBACK routine) { int status = 1; /* default to failure */ @@ -341,6 +457,11 @@ t_stat eth_write(ETH_DEV* dev, ETH_PACK* packet, ETH_PCALLBACK routine) eth_packet_trace (packet, "writing"); #endif status = pcap_sendpacket((pcap_t*)dev->handle, (u_char*)packet->msg, packet->len); + + /* detect sending of decnet loopback packet */ + if ((status == 0) && DECNET_SELF_FRAME(dev->decnet_addr, packet->msg)) + dev->decnet_self_sent += dev->reflections; + } /* if packet->len */ /* call optional write callback function */ @@ -353,42 +474,18 @@ t_stat eth_write(ETH_DEV* dev, ETH_PACK* packet, ETH_PCALLBACK routine) void eth_callback(u_char* info, const struct pcap_pkthdr* header, const u_char* data) { ETH_DEV* dev = (ETH_DEV*) info; + int to_me = 1; - /* 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. + /* detect sending of decnet loopback packet */ + if (DECNET_SELF_FRAME(dev->decnet_addr, data)) { + /* lower reflection count - if already zero, pass it on */ + if (dev->decnet_self_sent > 0) { + dev->decnet_self_sent--; + to_me = 0; + } + } - 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) { + if (to_me) { /* set data in passed read packet */ dev->read_packet->len = header->len; @@ -401,8 +498,7 @@ void eth_callback(u_char* info, const struct pcap_pkthdr* header, const u_char* /* 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) @@ -422,7 +518,7 @@ t_stat eth_read(ETH_DEV* dev, ETH_PACK* packet, ETH_PCALLBACK routine) /* set optional callback routine */ dev->read_callback = routine; - /* dispatch read request to either receive a packet (after filtering) or timeout */ + /* dispatch read request to either receive a filtered packet or timeout */ do { status = pcap_dispatch((pcap_t*)dev->handle, 1, ð_callback, (u_char*)dev); } while ((status) && (0 == packet->len)); @@ -433,6 +529,14 @@ t_stat eth_filter(ETH_DEV* dev, int addr_count, ETH_MAC* addresses, ETH_BOOL all_multicast, ETH_BOOL promiscuous) { int i; + bpf_u_int32 bpf_subnet, bpf_netmask; + char buf[110+66*ETH_FILTER_MAX]; + char errbuf[PCAP_ERRBUF_SIZE]; + struct bpf_program bpf; + char mac[20]; + char* buf2; + char* msg; + t_stat status; /* make sure device exists */ if (!dev) return SCPE_UNATT; @@ -444,7 +548,7 @@ t_stat eth_filter(ETH_DEV* dev, int addr_count, ETH_MAC* addresses, if (!addresses) return SCPE_ARG; /* clear filter array */ - memset(dev->filter_address, 0, sizeof(ETH_MAC) * ETH_FILTER_MAX); + memset(dev->filter_address, 0, sizeof(dev->filter_address)); /* set new filter addresses */ for (i = 0; i < addr_count; i++) @@ -454,178 +558,185 @@ t_stat eth_filter(ETH_DEV* dev, int addr_count, ETH_MAC* addresses, dev->all_multicast = all_multicast; dev->promiscuous = promiscuous; +#ifdef ETH_DEBUG + printf("Eth: Filter Set\r\n"); + for (i = 0; i < addr_count; i++) { + char mac[20]; + eth_mac_fmt(&dev->filter_address[i], mac); + printf(" Addr[%d]: %s\r\n", i, mac); + } + printf("%s%s\r\n", dev->all_multicast ? " All Multicast\r\n" : "", + dev->promiscuous ? " Promiscuous\r\n" : ""); +#endif + + /* test reflections */ + if (dev->reflections == -1) + status = eth_reflect(dev, dev->filter_address[0]); + + /* setup BPF filters and other fields to minimize packet delivery */ + strcpy(buf, ""); + + /* construct destination filters - since the real ethernet interface was set + into promiscuous mode by eth_open(), we need to filter out the packets that + our simulated interface doesn't want. */ + if (!dev->promiscuous) { + for (i = 0; i < addr_count; i++) { + eth_mac_fmt(&dev->filter_address[i], mac); + if (!strstr(buf, mac)) /* eliminate duplicates */ + sprintf(&buf[strlen(buf)], "%s(ether dst %s)", (*buf) ? " or " : "", mac); + } + if (dev->all_multicast) + sprintf(&buf[strlen(buf)], "%s(ether multicast)", (*buf) ? " or " : ""); + } + + /* construct source filters - this prevents packets from being reflected back + by systems where WinPcap and libpcap cause packet reflections. Note that + some systems do not reflect packets at all. This *assumes* that the + simulated NIC will not send out packets with multicast source fields. */ + if ((addr_count > 0) && (dev->reflections > 0)) { + if (strlen(buf) > 0) + sprintf(&buf[strlen(buf)], " and "); + sprintf (&buf[strlen(buf)], "not ("); + buf2 = &buf[strlen(buf)]; + for (i = 0; i < addr_count; i++) { + if (dev->filter_address[i][0] & 0x01) continue; /* skip multicast addresses */ + eth_mac_fmt(&dev->filter_address[i], mac); + if (!strstr(buf2, mac)) /* eliminate duplicates */ + sprintf(&buf2[strlen(buf2)], "%s(ether src %s)", (*buf2) ? " or " : "", mac); + } + sprintf (&buf[strlen(buf)], ")"); + } + /* When starting, DECnet sends out a packet with the source and destination + addresses set to the same value as the DECnet MAC address. This packet is + designed to find and help diagnose DECnet address conflicts. Normally, this + packet would not be seen by the sender, only by the other machine that has + the same DECnet address. If the ethernet subsystem is reflecting packets, + DECnet will fail to start if it sees the reflected packet, since it thinks + another system is using this DECnet address. We have to let these packets + through, so that if another machine has the same DECnet address that we + can detect it. Both eth_write() and eth_callback() help by checking the + reflection count - eth_write() adds the reflection count to + dev->decnet_self_sent, and eth_callback() check the value - if the + dev->decnet_self_sent count is zero, then the packet has come from another + machine with the same address, and needs to be passed on to the simulated + machine. */ + memset(dev->decnet_addr, 0, sizeof(ETH_MAC)); + /* check for decnet address in filters */ + if ((addr_count) && (dev->reflections > 0)) { + for (i = 0; i < addr_count; i++) { + eth_mac_fmt(&dev->filter_address[i], mac); + if (memcmp(mac, "AA:00:04", 8) == 0) { + memcpy(dev->decnet_addr, &dev->filter_address[i], sizeof(ETH_MAC)); + /* let packets through where dst and src are the same as our decnet address */ + sprintf (&buf[strlen(buf)], " or ((ether dst %s) and (ether src %s))", mac, mac); + break; + } + } + } + +#ifdef ETH_DEBUG + msg = "Eth: BPF string is: |%s|\r\n"; + printf (msg, buf); + if (sim_log) fprintf (sim_log, msg, buf); +#endif + + + /* get netmask, which is required for compiling */ + if (pcap_lookupnet(dev->handle, &bpf_subnet, &bpf_netmask, errbuf)<0) { + bpf_netmask = 0; + } + /* compile filter string */ + if ((status = pcap_compile(dev->handle, &bpf, buf, 1, bpf_netmask)) < 0) { + sprintf(errbuf, "%s", pcap_geterr(dev->handle)); + msg = "Eth: pcap_compile error: %s\r\n"; + printf(msg, errbuf); + if (sim_log) fprintf (sim_log, msg, errbuf); + /* show erroneous BPF string */ + msg = "Eth: BPF string is: |%s|\r\n"; + printf (msg, buf); + if (sim_log) fprintf (sim_log, msg, buf); + } else { + /* apply compiled filter string */ + if ((status = pcap_setfilter(dev->handle, &bpf)) < 0) { + sprintf(errbuf, "%s", pcap_geterr(dev->handle)); + msg = "Eth: pcap_setfilter error: %s\r\n"; + printf(msg, errbuf); + if (sim_log) fprintf (sim_log, msg, errbuf); + } else { +#if !defined (WIN_PCAP) + /* set file non-blocking */ + status = pcap_setnonblock (dev->handle, 1, errbuf); +#endif + } + pcap_freecode(&bpf); + } + return SCPE_OK; } +/* + The libpcap provided API pcap_findalldevs() on most platforms, will + leverage the getifaddrs() API if it is available in preference to + alternate platform specific methods of determining the interface list. + + A limitation of getifaddrs() is that it returns only interfaces which + have associated addresses. This may not include all of the interesting + interfaces that we are interested in since a host may have dedicated + interfaces for a simulator, which is otherwise unused by the host. + + One could hand craft the the build of libpcap to specifically use + alternate methods to implement pcap_findalldevs(). However, this can + get tricky, and would then result in a sort of deviant libpcap. + + Additionally, we're really only interested in Ethernet LAN type + interfaces here. It would be nice if the flags provided by pcap_if_t + actually told us if an interface was a Point to Point or a LAN interface + and if it was an ethernet. This isn't implemented anywhere. + + This routine exists to allow platform specific code to validate and/or + extend the set of available interfaces to include any that are not + returned by pcap_findalldevs. + +*/ +int eth_host_devices(int used, int max, ETH_LIST* list) +{ + return used; +} + 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; + pcap_if_t* alldevs; + pcap_if_t* dev; + int i; + char errbuf[PCAP_ERRBUF_SIZE]; - /* 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++; + /* retrieve the device list */ + if (pcap_findalldevs(&alldevs, errbuf) == -1) { + char* msg = "Eth: error in pcap_findalldevs: %s\r\n"; + printf (msg, errbuf); + if (sim_log) fprintf (sim_log, msg, errbuf); + } else { + /* copy device list into the passed structure */ + for (i=0, dev=alldevs; dev; dev=dev->next) { + if ((dev->flags & PCAP_IF_LOOPBACK) || (!strcmp("any", dev->name))) continue; + list[i].num = i; + sprintf(list[i].name, "%s", dev->name); + if (dev->description) + sprintf(list[i].desc, "%s", dev->description); + else + sprintf(list[i].desc, "%s", "No description available"); + if (i++ >= max) break; } + + /* free device list */ + pcap_freealldevs(alldevs); } - /* 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 */ + /* Add any host specific devices and/or validate those already found */ + i = eth_host_devices(i, max, list); + + /* return device count */ + return i; } -#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 */ - +#endif /* USE_NETWORK */ diff --git a/sim_ether.h b/sim_ether.h index b0471f57..c2df9fec 100644 --- a/sim_ether.h +++ b/sim_ether.h @@ -28,6 +28,10 @@ Modification history: + 01-Dec-03 DTH Added reflections, tweaked decnet fix items + 25-Nov-03 DTH Verified DECNET_FIX, reversed ifdef to mainstream code + 14-Nov-03 DTH Added #ifdef DECNET_FIX for problematic duplicate detection code + 07-Jun-03 MP Added WIN32 support for DECNET duplicate address detection. 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 @@ -47,14 +51,17 @@ /* 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 */ +#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_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 */ + +#define DECNET_SELF_FRAME(dnet_mac, msg) \ + ((memcmp(dnet_mac, msg , 6) == 0) && \ + (memcmp(dnet_mac, msg+6, 6) == 0)) struct eth_packet { uint8 msg[1518]; @@ -98,6 +105,9 @@ struct eth_device { ETH_MAC filter_address[ETH_FILTER_MAX]; /* filtering addresses */ ETH_BOOL promiscuous; /* promiscuous mode flag */ ETH_BOOL all_multicast; /* receive all multicast messages */ + int32 decnet_self_sent; /* loopback packets sent but not seen */ + ETH_MAC decnet_addr; /* decnet address of interface */ + int reflections; /* packet reflections on interface */ }; typedef struct eth_device ETH_DEV; diff --git a/sim_rev.h b/sim_rev.h index 73702935..88276ca0 100644 --- a/sim_rev.h +++ b/sim_rev.h @@ -1,6 +1,6 @@ /* sim_rev.h: simulator revisions and current rev level - Copyright (c) 1993-2003, Robert M Supnik + Copyright (c) 1993-2004, 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"), @@ -28,14 +28,127 @@ #define _SIM_REV_H_ 0 #define SIM_MAJOR 3 -#define SIM_MINOR 0 -#define SIM_PATCH 2 +#define SIM_MINOR 1 +#define SIM_PATCH 0 -/* V3.0 revision history +/* V3.1 revision history patch date module(s) and fix(es) - 2 tbd scp.c: + 0 29-Dec-03 sim_defs.h, scp.c: added output stall status + + all console emulators: added output stall support + + sim_ether.c (Dave Hittner, Mark Pizzolato, Anders Ahgren): + -- added Alpha/VMS support + -- added FreeBSD, Mac OS/X support + -- added TUN/TAP support + -- added DECnet duplicate address detection + + all memory buffered devices (fixed head disks, floppy disks): + -- cleaned up buffer copy code + + all DECtapes: + -- fixed reverse checksum in read all + -- added DECtape off reel message + -- simplified timing + + eclipse_cpu.c (Charles Owen): + -- added floating point support + -- added programmable interval timer support + -- bug fixes + + h316_cpu.c: + -- added instruction history + -- added DMA/DMC support + -- added device ENABLE/DISABLE support + -- change default to HSA option included + + h316_dp.c: added moving head disk support + + h316_fhd.c: added fixed head disk support + + h316_mt.c: added magtape support + + h316_sys.c: added new device support + + nova_dkp.c (Charles Owen): + -- fixed bug in flag clear sequence + -- added diagnostic mode support for disk sizing + +` nova_mt.c (Charles Owen): + -- fixed bug, space operations return record count + -- fixed bug, reset doesn't cancel rewind + + nova_sys.c: added floating point, timer support (from Charles Owen) + + i1620_cpu.c: fixed bug in branch digit (found by Dave Babcock) + + pdp1_drm.c: + -- added parallel drum support + -- fixed bug in serial drum instructin decoding + + pdp1_sys.c: added parallel drum support, mnemonics + + pdp11_cpu.c: + -- added autoconfiguration controls + -- added support for 18b-only Qbus devices + -- cleaned up addressing/bus definitions + + pdp11_rk.c, pdp11_ry.c, pdp11_tm.c, pdp11_hk.c: + -- added Q18 attribute + + pdp11_io.c: + -- added autoconfiguration controls + -- fixed bug in I/O configuration (found by Dave Hittner) + + pdp11_rq.c: + -- revised MB->LBN conversion for greater accuracy + -- fixed bug with multiple RAUSER drives + + pdp11_tc.c: changed to be off by default (base config is Qbus) + + pdp11_xq.c (Dave Hittner, Mark Pizzolato): + -- fixed second controller interrupts + -- fixed bugs in multicast and promiscuous setup + + pdp18b_cpu.c: + -- added instruction history + -- fixed PDP-4,-7,-9 autoincrement bug + -- change PDP-7,-9 default to API option included + + pdp8_defs.h, pdp8_sys.c: + -- added DECtape off reel message + -- added support for TSC8-75 (ETOS) option + -- added support for TD8E controller + + pdp8_cpu.c: added instruction history + + pdp8_rx.c: + -- fixed bug in RX28 read status (found by Charles Dickman) + -- fixed double density write + + pdp8_td.c: added TD8E controller + + pdp8_tsc.c: added TSC8-75 option + + vax_cpu.c: + -- revised instruction history for dynamic sizing + -- added autoconfiguration controls + + vax_io.c: + -- added autoconfiguration controls + -- fixed bug in I/O configuration (found by Dave Hittner) + + id16_cpu.c: revised instruction decoding + + id32_cpu.c: + -- revised instruction decoding + -- added instruction history + +/* V3.0 revision history + + 2 15-Sep-03 scp.c: -- fixed end-of-file problem in dep, idep -- fixed error on trailing spaces in dep, idep diff --git a/sim_sock.c b/sim_sock.c index e79380b3..24691611 100644 --- a/sim_sock.c +++ b/sim_sock.c @@ -182,7 +182,7 @@ SOCKET sim_accept_conn (SOCKET master, uint32 *ipaddr) int32 sta, err; #if defined (macintosh) socklen_t size; -#elif defined (_WIN32) || defined (__EMX__) +#elif defined (_WIN32) || defined (__EMX__) || defined (__APPLE__) int size; #else size_t size; diff --git a/sim_sock.h b/sim_sock.h index c31ac676..78dcc7a5 100644 --- a/sim_sock.h +++ b/sim_sock.h @@ -23,6 +23,9 @@ 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-Oct-03 MP Changed WIN32 winsock include to use winsock2.h to + avoid a conflict if sim_sock.h and sim_ether.h get + included by the same module. 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) @@ -39,7 +42,7 @@ #if defined (_WIN32) /* Windows */ #undef INT_PTR /* hack, hack */ -#include +#include #elif !defined (__OS2__) || defined (__EMX__) /* VMS, Mac, Unix, OS/2 EMX */ #define WSAGetLastError() errno /* Windows macros */ diff --git a/sim_tmxr.c b/sim_tmxr.c index e3f0f6a8..16daf280 100644 --- a/sim_tmxr.c +++ b/sim_tmxr.c @@ -26,6 +26,7 @@ Based on the original DZ11 simulator by Thord Nilson, as updated by Arthur Krewat. + 01-Nov-03 RMS Cleaned up attach routine 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) @@ -268,23 +269,23 @@ return; *lp = pointer to line descriptor chr = characters Outputs: - none + status = ok, connection lost, or stall */ -void tmxr_putc_ln (TMLN *lp, int32 chr) +t_stat tmxr_putc_ln (TMLN *lp, int32 chr) { -if (lp->conn == 0) return; /* no conn? done */ -if (lp->txbpi < TMXR_MAXBUF) { /* room for char? */ +if (lp->conn == 0) return SCPE_LOST; /* no conn? lost */ +if (lp->txbpi < (TMXR_MAXBUF - 1)) { /* room for char (+ IAC)? */ 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? */ + if ((char) chr == TN_IAC) { /* IAC? */ 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; + lp->xmte = 0; /* disable line */ + return SCPE_OK; } /* char sent */ +lp->xmte = 0; /* no room, dsbl line */ +return SCPE_STALL; /* char not sent */ } /* Poll for output @@ -362,12 +363,6 @@ 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 */ @@ -404,7 +399,7 @@ return SCPE_OK; t_stat tmxr_detach (TMXR *mp, UNIT *uptr) { -if ((uptr->flags & UNIT_ATT) == 0) return SCPE_OK; /* attached? */ +if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; /* attached? */ tmxr_close_master (mp); /* close master socket */ free (uptr->filename); /* free port string */ uptr->filename = NULL; diff --git a/sim_tmxr.h b/sim_tmxr.h index 45ffa415..6ea650a9 100644 --- a/sim_tmxr.h +++ b/sim_tmxr.h @@ -1,6 +1,6 @@ /* sim_tmxr.h: terminal multiplexor definitions - Copyright (c) 2001-2003, Robert M Supnik + Copyright (c) 2001-2004, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -26,6 +26,7 @@ Based on the original DZ11 simulator by Thord Nilson, as updated by Arthur Krewat. + 29-Dec-03 RMS Added output stall support, increased buffer size 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 @@ -38,8 +39,8 @@ #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_MAXBUF 256 /* buffer size */ +#define TMXR_GUARD 12 /* buffer guard */ #define TMXR_MAXLIN 64 /* max lines */ struct tmln { @@ -76,7 +77,7 @@ 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); +t_stat 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); diff --git a/simh_doc.txt b/simh_doc.txt index 63c75a98..1e05a202 100644 --- a/simh_doc.txt +++ b/simh_doc.txt @@ -1,7 +1,7 @@ To: Users From: Bob Supnik -Subj: Simulator Usage, V3.0-2 -Date: 15-Sep-2003 +Subj: Simulator Usage, V3.1 +Date: 15-Dec-2003 COPYRIGHT NOTICE @@ -81,7 +81,7 @@ The simulators recognize or require a few compile-time #defines: - 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. + available only on Windows, Linux, NetBSD, OpenBSD, and Alpha VMS. - The PDP-11 and VAX simulators optionally support disks and serial devices files greater than 2GB. To include large device support, @@ -794,7 +794,7 @@ 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 +paper tape y y y y y card reader - - - - - line printer y y y h y clock y y y - y @@ -817,12 +817,12 @@ 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 - - - +hard disk h y y - y +fixed disk - n - h - floppy disk - - h - - drum - n - - - DECtape - - - - - -mag tape y y y - y +mag tape y y y h y system GRI-909 1620 i16 i32 SDS940 device @@ -853,8 +853,18 @@ 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.1, Dec, 03 + Added Alpha/VMS, FreeBSD, Mac OS/X Ethernet library support + Added Eclipse floating point and interval timer support + (from Charles Owen) + Added PDP-1 parallel drum support + Added PDP-8 TSC8-75 and TD8E support + Added H316/516 DMA/DMC, magtape, fixed head disk support + Added PDP-8, PDP-15, 32b Interdata instruction history support + Rev 3.0, May, 03 Added logical name support + Added instruction history support Added multiple tape format support Added 64b address support Added PDP-4 EAE support diff --git a/simh_faq.txt b/simh_faq.txt index b101617c..009bde9c 100644 --- a/simh_faq.txt +++ b/simh_faq.txt @@ -1,4 +1,4 @@ -SIMH FAQ, 15-Sep-2003 +SIMH FAQ, 31-Dec-2003 1 General @@ -158,22 +158,22 @@ The documentation contains more details on supported models and peripherals. Host System Compiler comments OpenVMS/VAX DEC C no 64b support; no Ethernet support - OpenVMS/Alpha DEC C no Ethernet support + OpenVMS/Alpha DEC C Ethernet support provided in pcap-vms 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 + Mac OS/X requires libpcap for Ethernet support - Linux gcc + Linux gcc requires libpcap for Ethernet support 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 + NetBSD gcc requires libpcap for Ethernet support + OpenBSD gcc requires libpcap for Ethernet support + FreeBSD gcc requires libpcap for Ethernet support OS/2 EMX no Ethernet support @@ -247,6 +247,14 @@ 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. +On a VAX use: + +$ MMx + +On a Alpha use: +$ MMx/MACRO=("__ALPHA__=1") !Without ethernet support +$ MMx/MACRO=("__ALPHA__=1","__PCAP__=1") !With ethernet support + 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. @@ -254,7 +262,7 @@ 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. +emulators. Ethernet support is only available on Alpha VMS 7.3-1 and above. -------------------------------------------------------------------------------- @@ -355,7 +363,7 @@ 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. +Not yet. -------------------------------------------------------------------------------- @@ -603,4 +611,4 @@ Ethernet Adapter 0 (774440) 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 +- RSTS/E installation from magnetic tape requires that the tape be write locked. diff --git a/simh_swre.txt b/simh_swre.txt index 662a0cc5..2606d76c 100644 --- a/simh_swre.txt +++ b/simh_swre.txt @@ -421,10 +421,6 @@ does not support the SIMH sockets library. 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 @@ -691,8 +687,8 @@ 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> att -e dp0 iu7_dp0.dsk + sim> att -e dp1 iu7_dp1.dsk sim> boot dp0 Boot : dsk(1,0)unix