Notes For V3.0-0

Because some key files have changed, V3.0 should be unzipped to a
clean directory.

1. New Features in 3.0-0

1.1 SCP and Libraries

- Added ASSIGN/DEASSIGN (logical name) commands.
- Changed RESTORE to unconditionally detach files.
- Added E11 and TPC format support to magtape library.
- Fixed bug in SHOW CONNECTIONS.
- Added USE_ADDR64 support

1.2 All magtapes

- Magtapes support SIMH format, E11 format, and TPC format (read only).
- SET <tape_unit> FORMAT=format sets the specified tape unit's format.
- SHOW <tape_unit> FORMAT displays the specified tape unit's format.
- Tape format can also be set as part of the ATTACH command, using
  the -F switch.

1.3 VAX

- VAX can be compiled without USE_INT64.
- If compiled with USE_INT64 and USE_ADDR64, RQ and TQ controllers support
  files > 2GB.
- VAX ROM has speed control (SET ROM DELAY/NODELAY).

2. Bugs Fixed in 3.01-0

2.1 VAX

- Fixed CVTfi bug: integer overflow not set if exponent out of range
- Fixed EMODx bugs:
  o First and second operands reversed
  o Separated fraction received wrong exponent
  o Overflow calculation on separated integer incorrect
  o Fraction not set to zero if exponent out of range
- Fixed interval timer and ROM access to pass power-up self-test even on very
  fast host processors (fixes from Mark Pizzolato).

2.2 1401

- Fixed mnemonic, instruction lengths, and reverse scan length check bug for MCS.
- Fixed MCE bug, BS off by 1 if zero suppress.
- Fixed chaining bug, D lost if return to SCP.
- Fixed H branch, branch occurs after continue.
- Added check for invalid 8 character MCW, LCA.
- Fixed magtape load-mode end of record response.

2.3 Nova

- Fixed DSK variable size interaction with restore.

2.4 PDP-1

- Fixed DT variable size interaction with restore.

2.5 PDP-11

- Fixed DT variable size interaction with restore.
- Fixed bug in MMR1 update (found by Tim Stark).
- Added XQ features and fixed bugs:
  o Corrected XQ interrupts on IE state transition (code by Tom Evans).
  o Added XQ interrupt clear on soft reset.
  o Removed XQ interrupt when setting XL or RL (multiple people).
  o Added SET/SHOW XQ STATS.
  o Added SHOW XQ FILTERS.
  o Added ability to split received packet into multiple buffers.
  o Added explicit runt and giant packet processing.

2.6 PDP-18B

- Fixed DT, RF variable size interaction with restore.
- Fixed MT bug in MTTR.

2.7 PDP-8

- Fixed DT, DF, RF, RX variable size interaction with restore.
- Fixed MT bug in SKTR.

2.8 HP2100

- Fixed bug in DP (13210A controller only), DQ read status.
- Fixed bug in DP, DQ seek complete.

2.9 GRI

- Fixed bug in SC queue pointer management.

3. New Features in 3.0 vs prior releases

N/A

4. Bugs Fixed in 3.0 vs prior releases

N/A

5. General Notes

WARNING: The RESTORE command has changed.  RESTORE will now
detach an attached file on a unit, if that unit did not have
an attached file in the saved configuration.  This is required
to assure that the unit flags and the file state are consistent.

WARNING: The compilation scheme for the PDP-10, PDP-11, and VAX
has changed.  Use one of the supplied build files, or read the
documentation carefully, before compiling any of these simulators.
This commit is contained in:
Bob Supnik 2003-06-25 09:20:00 -07:00 committed by Mark Pizzolato
parent 43385c9616
commit 4ffd3be790
215 changed files with 12913 additions and 8563 deletions

View file

@ -1,305 +0,0 @@
Notes For V2.10-4
1. New Features in 2.10-4
1.1 SCP and Libraries
- Added .ini startup file capability (suggested by Hans Pufal).
- Added multiple switch evaluation points (suggested by Hans Pufal).
- Added multiple command per action.
- Added new library, sim_tape.c, for magtape emulation.
1.2 PDP-11
- Added user-defined disk capacity to RQ.
- Addec choice of controllers to TQ.
- Added user-defined tape capacity to TQ.
1.3 Interdata
- Added SHOW SELCH n command to display selector channel state.
1.4 Line Frequency Clocks (H316, Interdata, Nova, PDP-8, PDP-11,
PDP-18B, SDS)
- Added SET <device> {50HZ/60HZ}, to set the line frequency.
1.5 DEC Console Input (PDP-8, PDP-11, PDP-18B, VAX)
- Added SET TTI CTRL-C, to generate ^C from SIMH prompt (^C
crashes simulators compiled with Windows Visual C++).
1.6 Magtapes
- Revised to use magtape library for consistency.
2. Bugs Fixed in 2.10-4
- SCP: fixed bug in multiword deposits to files
- Interdata disks: fixed bug in cylinder overflow on writes
- Interdata tape: fixed bug, read error did not stop selector
channel
- Interdata precision clock: improved autocalibrate algorithm
for UNIX V7.
- Nova fixed head disk: fixed autosize algorithm.
- PDP-11 RQ and TQ: fixed bugs in queue process and in vector
calculation for VAXen.
- PDP-11 TQ: fixed overly strict implementation of illegal
modifiers check.
- PDP-11 RY: fixed autosize algorithm.
- PDP-18B CPU: fixed three EAE bugs (found by Hans Pufal).
- PDP-18B MT: fixed bugs in interrupt handling, BOT error handling.
- PDP-18B RF: removed extra bit from disk address, fixed autosize
algorithm.
- PDP-18B SYS: fixed bug in FMTASC usage (found by Hans Pufal).
- PDP-8 MT: fixed bug in BOT error handling.
- PDP-8 DF, RF, RX: fixed autosize algorithm.
3. New Features in 2.10 vs prior releases
3.1 SCP and Libraries
- The VT emulation package has been replaced by the capability
to remote the console to a Telnet session. Telnet clients
typically have more complete and robust VT100 emulation.
- Simulated devices may now have statically allocated buffers,
in addition to dynamically allocated buffers or disk-based
data stores.
- The DO command now takes substitutable arguments (max 9).
In command files, %n represents substitutable argument n.
- The initial command line is now interpreted as the command
name and substitutable arguments for a DO command. This is
backward compatible to prior versions.
- The initial command line parses switches. -Q is interpreted
as quiet mode; informational messages are suppressed.
- The HELP command now takes an optional argument. HELP <cmd>
types help on the specified command.
- Hooks have been added for implementing GUI-based consoles,
as well as simulator-specific command extensions. A few
internal data structures and definitions have changed.
- Two new routines (tmxr_open_master, tmxr_close_master) have
been added to sim_tmxr.c. The calling sequence for
sim_accept_conn has been changed in sim_sock.c.
- The calling sequence for the VM boot routine has been modified
to add an additional parameter.
- SAVE now saves, and GET now restores, controller and unit flags.
- Library sim_ether.c has been added for Ethernet support.
- The EVAL command will evaluate a symbolic type-in and display
it in numeric form.
- The ! command (with no arguments) will launch the host operating
system command shell. The ! command (with an argument) executes
the argument as a host operating system command. (Code from
Mark Pizzolato)
- Telnet sessions now recognize BREAK. How a BREAK is transmitted
dependent on the particular Telnet client. (Code from Mark
Pizzolato)
- The sockets library includes code for active connections as
well as listening connections.
- The RESTORE command will restore saved memory size, if the
simulator supports dynamic memory resizing.
- Added dynamic extension of the breakpoint table.
- Added breakpoint actions.
- Added VMS support for ! (from Mark Pizzolato).
3.2 VAX
- Non-volatile RAM (NVR) can behave either like a memory or like
a disk-based peripheral. If unattached, it behaves like memory
and is saved and restored by SAVE and RESTORE, respectively.
If attached, its contents are loaded from disk by ATTACH and
written back to disk at DETACH and EXIT.
- SHOW <device> VECTOR displays the device's interrupt vector.
A few devices allow the vector to be changed with SET
<device> VECTOR=nnn.
- SHOW CPU IOSPACE displays the I/O space address map.
- The TK50 (TMSCP tape) has been added.
- The DEQNA/DELQA (Qbus Ethernet controllers) have been added.
- Autoconfiguration support has been added.
- The paper tape reader has been removed from vax_stddev.c and
now references a common implementation file, dec_pt.h.
- Examine and deposit switches now work on all devices, not just
the CPU.
- Device address conflicts are not detected until simulation starts.
- If the VAX console is attached to a Telnet session, BREAK is
interpreted as console halt.
- The SET/SHOW HISTORY commands enable and display a history of
the most recently executed instructions. (Code from Mark
Pizzolato)
3.3 PDP-11
- SHOW <device> VECTOR displays the device's interrupt vector.
Most devices allow the vector to be changed with SET
<device> VECTOR=nnn.
- SHOW CPU IOSPACE displays the I/O space address map.
- The TK50 (TMSCP tape), RK611/RK06/RK07 (cartridge disk),
RX211 (double density floppy), and KW11P programmable clock
have been added.
- The DEQNA/DELQA (Qbus Ethernet controllers) have been added.
- Autoconfiguration support has been added.
- The paper tape reader has been removed from pdp11_stddev.c and
now references a common implementation file, dec_pt.h.
- Device bootstraps now use the actual CSR specified by the
SET ADDRESS command, rather than just the default CSR. Note
that PDP-11 operating systems may NOT support booting with
non-standard addresses.
- Specifying more than 256KB of memory, or changing the bus
configuration, causes all peripherals that are not compatible
with the current bus configuration to be disabled.
- Device address conflicts are not detected until simulation starts.
- The PDP-11 implements a stub DEUNA/DELUA (XU). The real XU
module will be included in a later release.
3.4 PDP-10
- SHOW <device> VECTOR displays the device's interrupt vector.
A few devices allow the vector to be changed with SET
<device> VECTOR=nnn.
- SHOW CPU IOSPACE displays the I/O space address map.
- The RX211 (double density floppy) has been added; it is off
by default.
- The paper tape now references a common implementation file,
dec_pt.h.
- Device address conflicts are not detected until simulation starts.
- The PDP-10 implements a stub DEUNA/DELUA (XU). The real XU
module will be included in a later release.
3.5 PDP-1
- DECtape (then known as MicroTape) support has been added.
- The line printer and DECtape can be disabled and enabled.
- The PDP-1 supports the Type 24 serial drum (based on recently
discovered documents).
3.6 18b PDP's
- The PDP-4 supports the Type 24 serial drum (based on recently
discovered documents).
- Added RB09 fixed head disk for the PDP-9.
- Added LP09 line printer for the PDP-9 and PDP-15.
- Added variable size support and autosizing to the RF15/RF09.
3.7 PDP-8
- The RX28 (double density floppy) has been added as an option to
the existing RX8E controller.
- SHOW <device> DEVNO displays the device's device number. Most
devices allow the device number to be changed with SET <device>
DEVNO=nnn.
- Device number conflicts are not detected until simulation starts.
- Added variable size support and autosizing to the DF32 and RF08.
3.8 Nova
- Added variable size support and autosizing to the Novadisk.
3.9 AltairZ80
- A hard drive has been added for increased storage.
- Several bugs have been fixed.
3.10 HP 2100
- The 12845A has been added and made the default line printer (LPT).
The 12653A has been renamed LPS and is off by default. It also
supports the diagnostic functions needed to run the DCPC and DMS
diagnostics.
- The 12557A/13210A disk defaults to the 13210A (7900/7901).
- The 12559A magtape is off by default.
- New CPU options (EAU/NOEAU) enable/disable the extended arithmetic
instructions for the 2116. These instructions are standard on
the 2100 and 21MX.
- New CPU options (MPR/NOMPR) enable/disable memory protect for the
2100 and 21MX.
- New CPU options (DMS/NODMS) enable/disable the dynamic mapping
instructions for the 21MX.
- The 12539 timebase generator autocalibrates.
- The IOP microinstruction set is supported for the 21MX as well
as the 2100.
- The HP2100 supports the Access Interprocessor Link (IPL).
3.11 Simulated Magtapes
- Simulated magtapes recognize end of file and the marker
0xFFFFFFFF as end of medium. Only the TMSCP tape simulator
can generate an end of medium marker.
- The error handling in simulated magtapes was overhauled to be
consistent through all simulators.
3.12 Simulated DECtapes
- Added support for RT11 image file format (256 x 16b) to DECtapes.
3.13 Terminals Multiplexors
- BREAK detection was added to the HP, DEC, and Interdata terminal
multiplexors.
4. Bugs Fixed in 2.10 vs prior releases
- TS11/TSV05 was not simulating the XS0_MOT bit, causing failures
under VMS. In addition, two of the CTL options were coded
interchanged.
- IBM 1401 tape was not setting a word mark under group mark for
load mode reads. This caused the diagnostics to crash.
- SCP bugs in ssh_break and set_logon were fixed (found by Dave
Hittner).
- Numerous bugs in the HP 2100 extended arithmetic, floating point,
21MX, DMS, and IOP instructions were fixed. Bugs were also fixed
in the memory protect and DMS functions. The moving head disks
(DP, DQ) were revised to simulate the hardware more accurately.
Missing functions in DQ (address skip, read address) were added.
- PDP-10 tape wouldn't boot, and then wouldn't read (reported by
Michael Thompson and Harris Newman, respectively)
- PDP-1 typewriter is half duplex, with only one shift state for
both input and output (found by Derek Peschel)
- PDP-11 console must default to 7b for early UNIX compatibility.
- PDP-11/VAX TMSCP emulator was using the wrong packet length for
read/write end packets.
- Telnet IAC+IAC processing was fixed, both for input and output
(found by Mark Pizzolato).
- PDP-11/VAX Ethernet setting flag bits wrong for chained
descriptors (found by Mark Pizzolato).
- 18b PDP RF15/RF09: fixed IOT decoding and address wraparound
logic (found by Hans Pufal).
- 18b PDP RP15: fixed IOT decoding and command initiation.
- HP2100 IPL: changed to full duplex (found by Mike Gemeny).
- HP2100 CPU: fixed last cycle bug in DMA outpout (found by Mike
Gemeny).
- Interdata 16b CPU: fixed bug in SETM, SETMR (found by Mark
Pizzolato).
5. General Notes
WARNING: The build procedures have changed. There is only one UNIX
makefile. To compile without Ethernet support, simply type
gmake {target|all}
To compile with Ethernet support, type
gmake USE_NETWORK=1 {target|all}
The Mingw batch files require Mingw release 2 and invoke the Unix
makefile. There are still separate batch files for compilation
with or without Ethernet support.
WARNING: V2.10 has reorganized and renamed some of the definition
files for the PDP-10, PDP-11, and VAX. Be sure to delete all
previous source files before you unpack the Zip archive, or
unpack it into a new directory structure.
WARNING: V2.10 has a new, more comprehensive save file format.
Restoring save files from previous releases will cause 'invalid
register' errors and loss of CPU option flags, device enable/
disable flags, unit online/offline flags, and unit writelock
flags.
WARNING: If you are using Visual Studio .NET through the IDE,
be sure to turn off the /Wp64 flag in the project settings, or
dozens of spurious errors will be generated.
WARNING: Compiling Ethernet support under Windows requires
extra steps; see the Ethernet readme file. Ethernet support is
currently available only for Windows, Linux, NetBSD, and OpenBSD.

110
0readme_30.txt Normal file
View file

@ -0,0 +1,110 @@
Notes For V3.0-0
Because some key files have changed, V3.0 should be unzipped to a
clean directory.
1. New Features in 3.0-0
1.1 SCP and Libraries
- Added ASSIGN/DEASSIGN (logical name) commands.
- Changed RESTORE to unconditionally detach files.
- Added E11 and TPC format support to magtape library.
- Fixed bug in SHOW CONNECTIONS.
- Added USE_ADDR64 support
1.2 All magtapes
- Magtapes support SIMH format, E11 format, and TPC format (read only).
- SET <tape_unit> FORMAT=format sets the specified tape unit's format.
- SHOW <tape_unit> FORMAT displays the specified tape unit's format.
- Tape format can also be set as part of the ATTACH command, using
the -F switch.
1.3 VAX
- VAX can be compiled without USE_INT64.
- If compiled with USE_INT64 and USE_ADDR64, RQ and TQ controllers support
files > 2GB.
- VAX ROM has speed control (SET ROM DELAY/NODELAY).
2. Bugs Fixed in 3.01-0
2.1 VAX
- Fixed CVTfi bug: integer overflow not set if exponent out of range
- Fixed EMODx bugs:
o First and second operands reversed
o Separated fraction received wrong exponent
o Overflow calculation on separated integer incorrect
o Fraction not set to zero if exponent out of range
- Fixed interval timer and ROM access to pass power-up self-test even on very
fast host processors (fixes from Mark Pizzolato).
2.2 1401
- Fixed mnemonic, instruction lengths, and reverse scan length check bug for MCS.
- Fixed MCE bug, BS off by 1 if zero suppress.
- Fixed chaining bug, D lost if return to SCP.
- Fixed H branch, branch occurs after continue.
- Added check for invalid 8 character MCW, LCA.
- Fixed magtape load-mode end of record response.
2.3 Nova
- Fixed DSK variable size interaction with restore.
2.4 PDP-1
- Fixed DT variable size interaction with restore.
2.5 PDP-11
- Fixed DT variable size interaction with restore.
- Fixed bug in MMR1 update (found by Tim Stark).
- Added XQ features and fixed bugs:
o Corrected XQ interrupts on IE state transition (code by Tom Evans).
o Added XQ interrupt clear on soft reset.
o Removed XQ interrupt when setting XL or RL (multiple people).
o Added SET/SHOW XQ STATS.
o Added SHOW XQ FILTERS.
o Added ability to split received packet into multiple buffers.
o Added explicit runt and giant packet processing.
2.6 PDP-18B
- Fixed DT, RF variable size interaction with restore.
- Fixed MT bug in MTTR.
2.7 PDP-8
- Fixed DT, DF, RF, RX variable size interaction with restore.
- Fixed MT bug in SKTR.
2.8 HP2100
- Fixed bug in DP (13210A controller only), DQ read status.
- Fixed bug in DP, DQ seek complete.
2.9 GRI
- Fixed bug in SC queue pointer management.
3. New Features in 3.0 vs prior releases
N/A
4. Bugs Fixed in 3.0 vs prior releases
N/A
5. General Notes
WARNING: The RESTORE command has changed. RESTORE will now
detach an attached file on a unit, if that unit did not have
an attached file in the saved configuration. This is required
to assure that the unit flags and the file state are consistent.
WARNING: The compilation scheme for the PDP-10, PDP-11, and VAX
has changed. Use one of the supplied build files, or read the
documentation carefully, before compiling any of these simulators.

View file

@ -2,6 +2,147 @@ This file contains information about the XQ/SIM_ETHER package.
-------------------------------------------------------------------------------
The XQ emulator is a host-independant software emulation of Digital's
DELQA (M7516) and DEQNA (M7504) Q-bus ethernet cards for the SIMH emulator.
The XQ emulator uses the Sim_Ether module to execute host-specific ethernet
packet reads and writes, since all operating systems talk to real ethernet
cards/controllers differently. The host-dependant Sim_Ether module currently
supports Windows, Linux, NetBSD, and OpenBSD.
Currently, the Sim_Ether module sets the selected ethernet card into
promiscuous mode to gather all packets, then filters out the packets that it
doesn't want. In Windows, packets having the same source MAC address as the
controller are ignored for WinPCAP compatibility (see Windows notes below).
If your ethernet card is plugged into a switch, the promiscuous mode setting
should not cause much of a problem, since the switch will still filter out
most of the undesirable traffic. You will only see "excessive" traffic if you
are on a direct or hub(repeater) segment.
-------------------------------------------------------------------------------
Windows notes:
1. The Windows-specific code uses the WinPCAP 3.0 package from
http://winpcap.polito.it. This package for windows simulates the libpcap
package that is freely available for unix systems.
2. You must *install* the WinPCAP runtime package.
3. The first time the WinPCAP driver is used, it will be dynamically loaded,
and the user must be an Administrator on the machine to do so. If you need
to run as an unprivileged user, you must set the service to autostart. See
the WinPCAP documentation for details on the static load workaround.
4. WinPCAP loops packet writes back into the read queue. This causes problems
since the XQ controller is not expecting to read it's own packet. A fix
to the packet read filter was added to reject packets from the current MAC,
but this defeats DECNET's duplicate node number detection scheme. A more
correct fix for WinPCAP will be explored as time allows.
Building on Windows:
1. Install WinPCAP 3.0.
2. Put the required .h files (bittypes,devioctl,ip6_misc,packet32,pcap,
pcap-stdinc).h from the WinPCAP 3.0 developer's kit in the compiler's path
3. Put the required .lib files (packet,wpcap).lib from the WinPCAP 3.0
developer's kit in the linker's path
4. If you're using Borland C++, use COFF2OMF to convert the .lib files into
a format that can be used by the compiler.
5. Define USE_NETWORK if you want the network functionality.
6. Build it!
-------------------------------------------------------------------------------
Linux, NetBSD, and OpenBSD notes:
1. You must run SIMH(scp) as root so that the ethernet card can be set into
promiscuous mode by the driver. Alternative methods for avoiding the
'run as root' requirement will be welcomed.
Building on Linux, NetBSD, and OpenBSD:
1. Get/install the libpcap package for your unix version. http://rpmfind.net
might be a useful site for finding the linux variants.
2. Use Make USE_NETWORK=1 if you want the network functionality.
3. Build it!
-------------------------------------------------------------------------------
VAX simulator support:
An OpenVMS VAX v7.2 system with DECNET Phase IV, MultiNet 4.4a, and LAT 5.3 has
been successfully run. Other testers have reported success booting NetBSD also.
PDP11 simulator support:
An RT-11 v5.3 system with a freeware TCP/IP stack has been successfully run.
Other testers have reported that RSX with DECNET and the NetBSD operating
systems also work. RSTS/E v10.1 has preliminary support - RSTS/E boots and
enables the XH (XQ) device - DECNET and LAT software have not been tested.
-------------------------------------------------------------------------------
Things planned for future releases:
1. PDP-11 bootstrap/bootrom
2. Full MOP implementation
3. DESQA support (if someone can get me the user manuals)
4. DETQA support [DELQA-Turbo] (I have the manual)
5. DEUNA/DELUA support
-------------------------------------------------------------------------------
Things which I need help with:
1. Porting Sim_Ether packet driver to other host platforms, especially VMS.
2. Information about Remote MOP processing
3. VAX/PDP-11 hardware diagnotics image files and docs, to test XQ thoroughly.
4. Feedback on operation with other VAX/PDP-11 OS's.
-------------------------------------------------------------------------------
Please send all patches, questions, feedback, clarifications, and help to:
dhittner AT northropgrumman DOT com
Thanks, and Enjoy!!
Dave
===============================================================================
Change Log
===============================================================================
05-Jun-03 Release:
1. Added SET/SHOW XQ STATS
2. Added SHOW XQ FILTERS
3. Added ability to split received packet into multiple buffers
4. Added explicit runt & giant packet processing
-------------------------------------------------------------------------------
30-May-03 Release:
1. Corrected bug in xq_setmac introduced in v3.0 (multiple people)
2. Made XQ receive buffer allocation dynamic to reduce scp executable size
3. Optimized some structs, removed legacy variables (Mark Pizzolato)
4. Changed #ifdef WIN32 to _WIN32 for consistancy
-------------------------------------------------------------------------------
06-May-03 Release:
1. Added second XQ controller
2. Added SIMH v3.0 compatibility
3. Removed SET ADDRESS functionality
-------------------------------------------------------------------------------
10-Apr-03 Release:
1. Added preliminary support for RSTS/E
2. Added PDP-11 bootrom load via CSR flags
3. Support for SPARC linux (thanks to Mark Pizzolato)
-------------------------------------------------------------------------------
11-Mar-03 Release:
1. Added support for RT-11 TCP/IP
2. Corrected interrupts (thanks to Tom Evans and Bob Supnik)
3. Moved change log to the bottom of the readme file, cleaned up document
-------------------------------------------------------------------------------
16-Jan-03 Release:
1. Added VMScluster support (thanks to Mark Pizzolato)
2. Verified VAX remote boot functionality (>>>B XQA0)
@ -12,176 +153,10 @@ This file contains information about the XQ/SIM_ETHER package.
-------------------------------------------------------------------------------
GOLD Changes: (08-Nov-02)
08-Nov-02 Release:
1. Added USE_NETWORK conditional to Sim_Ether
2. Fixed behaviour of SHOW XQ ETH if no devices exist
3. Added OpenBSD support to Sim_Ether (courtesy of Federico Schwindt)
4. Added ethX detection simplification (from Megan Gentry)
-------------------------------------------------------------------------------
BETA 5 Changes: (23-Oct-02)
1. Added all_multicast and promiscuous mode support
2. Finished DEQNA emulation
3. Verified LAT functionality
4. Added NXM (Non-eXistant Memory) protection (suggested by Robert Supnik)
5. Added NetBSD support to Sim_Ether (courtesy of Jason Thorpe)
6. Fixed write buffer overflow bug (discovered by Jason Thorpe)
7. Fixed unattached device behavior (discovered by Patrick Caulfield)
8. Extensive rewrite of this README
9. Debugged sanity timer
-------------------------------------------------------------------------------
BETA 4 Changes: (16-Oct-02)
1. Added stub support for all_multicast and promiscuous modes
2. Integrated with SIMH v2.10-0b1
3. Added VAX network bootstrap support
4. Added SET/SHOW XQ TYPE and SANITY commands
5. Added stub support for DEQNA mode
-------------------------------------------------------------------------------
BETA 3 Changes: (10-Oct-02)
1. Fixed off-by-one bug in setup address processing
2. Added rejection of multicast addresses to SET XQ MAC
3. Added linux support to Sim_Ether (courtesy of Patrick Caulfield)
-------------------------------------------------------------------------------
BETA 2 Changes: (08-Oct-02)
1. Integrated with SIMH v2.10-0p4
2. Added floating vectors; this also fixes pdp11 emulation problem
3. Cleaned up codebase; 100% of packet driver code moved to Sim_Ether
4. Verified TCP/IP functionality
5. Added Copyrights
-------------------------------------------------------------------------------
BETA 1 Changes: (03-Oct-02)
1. Moved most of packet driver functionality from XQ to Sim_Ether
2. Verified DECNET functionality
3. Added SET/SHOW MAC command
4. Added SHOW ETH command
-------------------------------------------------------------------------------
The XQ emulator is a host-independant software emulation of Digital's
DELQA (M7516) and DEQNA (M7504) Q-bus ethernet cards for the SIMH emulator.
See the last section of this document for XQ usage instructions.
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, and NetBSD.
Currently, the Sim_Ether module sets the selected ethernet card into
promiscuous mode to gather all packets, then filters out the packets that it
doesn't want. In Windows, Packets having the same source MAC address as the
controller are ignored for WinPCAP compatibility (see Windows notes below).
If your ethernet card is plugged into a switch, the promiscuous mode setting
should not cause much of a problem, since the switch will still filter out
most of the undesirable traffic. You will only see "excessive" traffic if you
are on a direct or hub(repeater) segment.
-------------------------------------------------------------------------------
Windows notes:
1. The Windows-specific code uses the WinPCAP 3.0 (or 2.3) package from
http://winpcap.polito.it. This package for windows simulates the libpcap
package that is freely available for unix systems.
2. You must *install* WinPCAP.
3. Note that WinPCAP DOES NOT support dual CPU environments.
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.
5. The first time the WinPCAP driver is used, it will be dynamically loaded,
and the user must be an Administrator on the machine to do so. If you need
to run as an unprivileged user, you must set the service to autostart. See
the WinPCAP documentation for details on the static load workaround.
Building on Windows:
1. Install WinPCAP 3.0.
2. Get the required .h files (bittypes.h, devioctl.h, ip6_misc.h, packet32.h,
pcap.h, pcap-stdinc.h) from the WinPCAP 3.0 developer's kit
3. Get the required .lib files (packet.lib, wpcap.lib) from the WinPCAP 3.0
developer's kit. If you're using Borland C++, use COFF2OMF to convert
the .lib files into a format that can be used by the compiler.
4. Define USE_NETWORK if you want the network functionality.
5. Build it!
-------------------------------------------------------------------------------
Linux, NetBSD, and OpenBSD notes:
1. You must run SIMH(scp) as root so that the ethernet card can be set into
promiscuous mode by the driver. Alternative suggestions will be welcomed.
Building on Linux, NetBSD, and OpenBSD:
1. Define USE_NETWORK if you want the network functionality.
-------------------------------------------------------------------------------
THE XQ/SIM_ETHER modules have been successfully tested on a Windows 2000 host,
emulating an OpenVMS 7.2 VAX system with DECNET Phase IV, MultiNet 4.4a, and
LAT 5.3.
Regression test criteria:
1. VAX shows device correctly (passed)
2. VMS boots successfully with new device emulation (passed)
3. VMS initializes device correctly (passed)
4. DECNET loads successfully (passed)
5. DECNET line stays up (passed)
6. SET HOST x.y:: works from SIMH to real DECNET machine (passed)
7. SET HOST x.y:: works from real DECNET machine to SIMH (passed)
8. DECNET copy works from SIMH to real DECNET machine (passed)
9. DECNET copy works from real DECNET machine to SIMH (passed)
10. MultiNet TCP/IP loads successfully (passed)
11. Multinet TCP/IP initializes device successfully (passed)
12. SET HOST/TELNET x.y.z.w works from SIMH to real VAX IP machine (passed)
13. SET HOST/TELNET x.y.z.w works from real VAX IP machine to SIMH (passed)
14. FTP GET from a real VAX IP machine (passed)
15. LAT loads sucessfully (passed)
16. SET HOST/LAT <nodename> works from SIMH to real VAX LAT machine (passed)
17. SET HOST/LAT <nodename> works from real VAX LAT machine to SIMH (passed)
18. SIMH node joins VMSCluster (passed)
19. SIMH node mounts other VMSCluster disks (passed)
20. SIMH node MSCP serves disks to other nodes (passed)
21. SIMH node remote boots into VMScluster (>>>B XQAO) (passed)
The following are known to NOT work:
1. PDP-11 using RSTS/E v10.1 (fails to enable device - needs bootrom support)
I have reports that the following work:
1. PDP-11 using RSX
2. VAX remote booting of NetBSD (via >>> B XQA0)
-------------------------------------------------------------------------------
Things planned for future releases:
1. Full MOP implementation
2. PDP-11 bootstrap/bootrom
3. DESQA support (if someone can get me the user manuals)
4. DETQA support [DELQA-Turbo] (I have the manual)
-------------------------------------------------------------------------------
Things which I need help with:
1. Porting Sim_Ether packet driver to other platforms, especially VMS.
2. Information about Remote MOP processing
3. PDP-11 bootstrap code.
4. VAX hardware diagnotics image file and docs, to test XQ thoroughly.
5. Feedback on operation with other VAX OS's.
6. Feedback on operation with PDP-11 OS's.
-------------------------------------------------------------------------------
Please send all patches, questions, feedback, clarifications, and help to:
dhittner AT northropgrumman DOT com
Thanks, and Enjoy!!
Dave
===============================================================================

View file

@ -1,6 +1,6 @@
/* altair_cpu.c: MITS Altair Intel 8080 CPU simulator
Copyright (c) 1997, Charles E. Owen
Copyright (c) 1997-2003, Charles E. Owen
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@ -58,7 +58,7 @@
HALT instruction
I/O error in I/O simulator
Invalid OP code (If ITRAP is set on CPU)
Invalid OP code (if ITRAP is set on CPU)
2. Interrupts.
There are 8 possible levels of interrupt, and in effect they
@ -1168,7 +1168,7 @@ t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw)
t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc)
{
int32 mc = 0;
t_addr i;
uint32 i;
if ((val <= 0) || (val > MAXMEMSIZE) || ((val & 07777) != 0))
return SCPE_ARG;

View file

@ -1,6 +1,6 @@
/* altair_defs.h: MITS Altair simulator definitions
Copyright (c) 1997, Charles E. Owen
Copyright (c) 1997-2003, Charles E. Owen
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@ -31,7 +31,7 @@
#define MAXMEMSIZE 65536 /* max memory size */
#define MEMSIZE (cpu_unit.capac) /* actual memory size */
#define ADDRMASK (MAXMEMSIZE - 1) /* address mask */
#define MEM_ADDR_OK(x) (x < MEMSIZE)
#define MEM_ADDR_OK(x) (((uint32) (x)) < MEMSIZE)
/* Simulator stop codes */

View file

@ -1,6 +1,6 @@
/* altair_dsk.c: MITS Altair 88-DISK Simulator
Copyright (c) 1997, Charles E. Owen
Copyright (c) 1997-2003, Charles E. Owen
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@ -124,8 +124,6 @@ t_stat dsk_svc (UNIT *uptr);
t_stat dsk_reset (DEVICE *dptr);
void writebuf();
extern int32 sim_activate (UNIT *uptr, int32 interval);
extern int32 sim_cancel (UNIT *uptr);
extern int32 PCX;
/* Global data on status */

View file

@ -1,6 +1,6 @@
/* altair_sio: MITS Altair serial I/O card
Copyright (c) 1997, Charles E. Owen
Copyright (c) 1997-2003, Charles E. Owen
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@ -63,11 +63,6 @@ t_stat ptp_reset (DEVICE *dptr);
int32 ptr_stopioe = 0, ptp_stopioe = 0; /* stop on error */
extern t_stat sim_activate (UNIT *uptr, int32 interval);
extern t_stat sim_cancel (UNIT *uptr);
extern t_stat sim_poll_kbd (void);
extern t_stat sim_putchar (int32 out);
/* 2SIO Standard I/O Data Structures */
UNIT sio_unit = { UDATA (&sio_svc, 0, 0),
@ -95,7 +90,7 @@ UNIT ptr_unit = { UDATA (&ptr_svc, UNIT_SEQ + UNIT_ATTABLE, 0),
REG ptr_reg[] = {
{ ORDATA (DATA, ptr_unit.buf, 8) },
{ ORDATA (STAT, ptr_unit.u3, 8) },
{ ORDATA (POS, ptr_unit.pos, 32) },
{ ORDATA (POS, ptr_unit.pos, T_ADDR_W) },
{ NULL } };
DEVICE ptr_dev = {
@ -110,7 +105,7 @@ UNIT ptp_unit = { UDATA (&ptp_svc, UNIT_SEQ + UNIT_ATTABLE, 0),
REG ptp_reg[] = {
{ ORDATA (DATA, ptp_unit.buf, 8) },
{ ORDATA (STAT, ptp_unit.u3, 8) },
{ ORDATA (POS, ptp_unit.pos, 32) },
{ ORDATA (POS, ptp_unit.pos, T_ADDR_W) },
{ NULL } };
DEVICE ptp_dev = {

View file

@ -1,6 +1,6 @@
/* altair_sys.c: MITS Altair system interface
Copyright (c) 1997, Charles E. Owen
Copyright (c) 1997-2003, Charles E. Owen
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@ -37,9 +37,6 @@ extern DEVICE ptp_dev;
extern DEVICE lpt_dev;
extern unsigned char M[];
extern int32 saved_PC;
extern char *get_glyph (char *cptr, char *gbuf, char term);
extern unsigned int32 get_uint (char *cptr, int32 radix, unsigned int32 max,
int32 *status);
/* SCP data structures

View file

@ -3,31 +3,34 @@ Altair 8800 Simulator with Z80 support
0. Revision History
Original version of this document written by Charles E Owen
- 25-Feb-2003, Peter Schorn (added support for real time simulation)
- 9-Oct-2002, Peter Schorn (added support for simulated hard disk)
- 28-Sep-2002, Peter Schorn (number of tracks per disk can be configured)
- 19-Sep-2002, Peter Schorn (added WARNROM feature)
- 31-Aug-2002, Peter Schorn (added extended ROM features suggested by Scott LaBombard)
- 31-Aug-2002, Peter Schorn (added extended ROM features suggested
by Scott LaBombard)
- 4-May-2002, Peter Schorn (added description of MP/M II sample software)
- 28-Apr-2002, Peter Schorn (added periodic timer interrupts and three
additional consoles)
- 15-Apr-2002, Peter Schorn (added memory breakpoint)
- 7-Apr-2002, Peter Schorn (added ROM / NOROM switch)
Original version of this document written by Charles E Owen
1. Background.
The MITS (Micro Instrumentation and Telemetry Systems) Altair 8800
was announced on the January 1975 cover of Popular Electronics, which
boasted you could buy and build this powerful computer kit for only $397.
The kit consisted at that time of only the parts to build a case, power
supply, card cage (18 slots), CPU card, and memory card with 256 *bytes* of
memory. Still, thousands were ordered within the first few months after the
announcement, starting the personal computer revolution as we know it today.
The MITS (Micro Instrumentation and Telemetry Systems) Altair 8800 was
announced on the January 1975 cover of Popular Electronics, which boasted
you could buy and build this powerful computer kit for only $397. The kit
consisted at that time of only the parts to build a case, power supply,
card cage (18 slots), CPU card, and memory card with 256 *bytes* of memory.
Still, thousands were ordered within the first few months after the
announcement, starting the personal computer revolution as we know it
today.
Many laugh at the small size of the that first kit, noting there
were no peripherals and the 256 byte memory size. But the computer was an
open system, and by 1977 MITS and many other small startups had added many
Many laugh at the small size of the that first kit, noting there were no
peripherals and the 256 byte memory size. But the computer was an open
system, and by 1977 MITS and many other small startups had added many
expansion cards to make the Altair quite a respectable little computer. The
"Altair Bus" that made this possible was soon called the S-100 Bus, later
adopted as an industry standard, and eventually became the IEE-696 Bus.
@ -35,8 +38,8 @@ adopted as an industry standard, and eventually became the IEE-696 Bus.
2. Hardware
We are simulating a fairly "loaded" Altair 8800 from about 1977,
with the following configuration:
We are simulating a fairly "loaded" Altair 8800 from about 1977, with the
following configuration:
device simulates
name(s)
@ -52,13 +55,13 @@ with the following configuration:
DSK MITS 88-DISK Floppy Disk controller with up
to eight drives.
2.1 CPU
We have 2 CPU options that were not present on the original
machine but are useful in the simulator. We also allow you to select
memory sizes, but be aware that some sample software requires the full
64K (i.e. CP/M) and the MITS Disk Basic and Altair DOS require about
a minimum of 24K.
We have 2 CPU options that were not present on the original machine but
are useful in the simulator. We also allow you to select memory sizes, but
be aware that some sample software requires the full 64K (i.e. CP/M) and
the MITS Disk Basic and Altair DOS require about a minimum of 24K.
SET CPU 8080 Simulates the 8080 CPU (normal)
SET CPU Z80 Simulates the Z80 CPU. Note that some software (e.g. most
@ -76,10 +79,8 @@ a minimum of 24K.
SET CPU 8K
SET CPU 12K
SET CPU 16K
......
...... (in 4K steps)
SET CPU 64K All these set various CPU memory configurations.
The 2K EPROM at the high end of memory is always
present and will always boot.
SET CPU BANKED Enables the banked memory support. The simulated memory
has eight banks with address range 0..'common' (see registers below)
@ -110,15 +111,16 @@ a minimum of 24K.
some software tries on purpose to write to ROM in order to detect
the available RAM.
The BOOT EPROM card starts at address 0FF00 if it has been enabled by 'SET
CPU ALTAIRROM'. Jumping to this address will boot drive 0 of the floppy
controller (CPU must be set to ROM or equivalent code must be present). If
no valid bootable software is present there the machine crashes. This is
historically accurate behavior.
The BOOT EPROM card starts at address 0FF00 if it has been enabled by
'SET CPU ALTAIRROM'. Jumping to this address will boot drive 0 of the
floppy controller (CPU must be set to ROM or equivalent code must be
present). If no valid bootable software is present there the machine
crashes. This is historically accurate behavior.
The real 8080, on receiving a HLT (Halt) instruction, freezes the processor
and only an interrupt or CPU hardware reset will restore it. The simulator
is alot nicer, it will halt but send you back to the simulator command line.
The real 8080, on receiving a HLT (Halt) instruction, freezes the
processor and only an interrupt or CPU hardware reset will restore it. The
simulator is alot nicer, it will halt but send you back to the simulator
command line.
CPU Registers include the following:
@ -135,20 +137,20 @@ CPU Registers include the following:
- = not used (undefined)
N = Internal sign flag
C = Carry flag.
BC 16 The BC register pair. Register B is the high 8 bits,
C is the lower 8 bits
DE 16 The DE register pair. Register D is the high 8 bits,
E is the lower 8 bits.
HL 16 The HL register pair. Register H is the high 8 bits,
L is the lower 8 bits.
AF1 16 The alternate AF register (only on Z80)
BC1 16 The alternate BC register (only on Z80)
DE1 16 The alternate DE register (only on Z80)
HL1 16 The alternate HL register (only on Z80)
IX 16 The IX index register (only on Z80)
IY 16 The IY index register (only on Z80)
IFF 8 Interrupt flag (only on Z80, no effect)
INT 8 Interrupt register (only on Z80, no effect)
BC 16 The BC register pair.
Register B is the high 8 bits, C is the lower 8 bits
DE 16 The DE register pair.
Register D is the high 8 bits, E is the lower 8 bits.
HL 16 The HL register pair.
Register H is the high 8 bits, L is the lower 8 bits.
AF1 16 The alternate AF register (on Z80 only)
BC1 16 The alternate BC register (on Z80 only)
DE1 16 The alternate DE register (on Z80 only)
HL1 16 The alternate HL register (on Z80 only)
IX 16 The IX index register (on Z80 only)
IY 16 The IY index register (on Z80 only)
IFF 8 Interrupt flag (on Z80 only)
INT 8 Interrupt register (on Z80 only)
SR 16 The front panel switches (use D SR 8 for 4k Basic).
WRU 8 The interrupt character. This starts as 5
@ -163,19 +165,24 @@ CPU Registers include the following:
value supplied to GENCPM for CP/M 3 system generation)
ROMLOW 16 The starting address of the ROM. Default is 0FF00.
ROMHIGH 16 The final address of the ROM. Default is 0FFFF.
CLOCK 32 The clock speed of the simulated CPU in kHz or 0 to run
at maximum speed. To set the clock speed for a typical
4 MHz Z80 CPU, use D CLOCK 4000. The CP/M utility SPEED
measures the clock speed of the simulated CPU.
2.2 The Serial I/O Card (2SIO)
This simple programmed I/O device provides 2 serial ports to the
outside world, which could be hardware jumpered to support RS-232 plugs or a
TTY current loop interface. The standard I/O addresses assigned by MITS
was 10-11 (hex) for the first port, and 12-13 (hex) for the second.
We follow this standard in the Simulator.
This simple programmed I/O device provides 2 serial ports to the outside
world, which could be hardware jumpered to support RS-232 plugs or a TTY
current loop interface. The standard I/O addresses assigned by MITS was
10-11 (hex) for the first port, and 12-13 (hex) for the second. We follow
this standard in the Simulator.
The simulator directs I/O to/from the first port to the screen. The
second port reads from an attachable "tape reader" file on input, and writes
to an attachable "punch file" on output. These files are considered a
simple stream of 8-bit bytes.
second port reads from an attachable "tape reader" file on input, and
writes to an attachable "punch file" on output. These files are considered
a simple stream of 8-bit bytes.
The SIO can be configured in SIMH with the following commands:
@ -199,11 +206,13 @@ simple stream of 8-bit bytes.
ATTACH SIO 23 Console IO goes via a Telnet connection on port 23
DETACH SIO Console IO goes via the regular SIMH console
2.3 The SIMH pseudo device
The SIMH pseudo device facilitates the communication between the simulated
ALTAIR and the simulator environment. This device defines a number of (most R/O)
registers (see source code) which are primarily useful for debugging purposes.
The SIMH pseudo device facilitates the communication between the
simulated ALTAIR and the simulator environment. This device defines a
number of (most R/O) registers (see source code) which are primarily useful
for debugging purposes.
The SIMH pseudo device can be configured with
@ -220,23 +229,23 @@ registers (see source code) which are primarily useful for debugging purposes.
TIMH This is the address of the interrupt handler to call for a
timer interrupt.
2.4 The 88-DISK controller.
The MITS 88-DISK is a simple programmed I/O interface to the MITS
8-inch floppy drive, which was basically a Pertec FD-400 with a power
supply and buffer board builtin. The controller supports neither interrupts
nor DMA, so floppy access required the sustained attention of the CPU.
The standard I/O addresses were 8, 9, and 0A (hex), and we follow the
standard. Details on controlling this hardware are in the altair_dsk.c
source file.
The MITS 88-DISK is a simple programmed I/O interface to the MITS 8-inch
floppy drive, which was basically a Pertec FD-400 with a power supply and
buffer board builtin. The controller supports neither interrupts nor DMA,
so floppy access required the sustained attention of the CPU. The standard
I/O addresses were 8, 9, and 0A (hex), and we follow the standard. Details
on controlling this hardware are in the altair_dsk.c source file.
The only difference is that the simulated disks may be larger than the
original ones: The original disk had 77 tracks while the simulated disks
support up to 254 tracks (only relevant for CP/M). You can change the
number of tracks per disk by setting the appropriate value in TRACKS[..].
For example "D TRACKS[0] 77" sets the number of tracks for disk 0 to
the original number of 77. The command "D TRACKS[0-7] 77" changes the
highest track number for all disks to 77.
For example "D TRACKS[0] 77" sets the number of tracks for disk 0 to the
original number of 77. The command "D TRACKS[0-7] 77" changes the highest
track number for all disks to 77.
For debugging purposes you can set the trace level of some disk I/O
functions. To do so the following bits in TRACE (a register of the disk)
@ -287,43 +296,46 @@ command "D HDTRACE 1". The default for "HDTRACE" is 0 (no trace).
3. Sample Software
Running an Altair in 1977 you would be running either MITS Disk
Extended BASIC, or the brand new and sexy CP/M Operating System from Digital
Running an Altair in 1977 you would be running either MITS Disk Extended
BASIC, or the brand new and sexy CP/M Operating System from Digital
Research. Or possibly, you ordered Altair DOS back when it was promised in
1975, and are still waiting for it to be delivered in early 1977.
We have samples of all three for you to check out. We can't go into
the details of how they work, but we'll give you a few hints.
We have samples of all three for you to check out. We can't go into the
details of how they work, but we'll give you a few hints.
3.1 CP/M Version 2.2
This version is my own port of the standard CP/M to the Altair.
There were some "official" versions but I don't have them. None were
endorsed or sold by MITS to my knowledge, however.
This version is my own port of the standard CP/M to the Altair. There
were some "official" versions but I don't have them. None were endorsed or
sold by MITS to my knowledge, however.
To boot CP/M:
sim> attach dsk cpm2.dsk
sim> boot dsk
CP/M feels like DOS, sort of. DIR will work. I have included all
the standard CP/M utilities, plus a few common public-domain ones. I also
CP/M feels like DOS, sort of. DIR will work. I have included all the
standard CP/M utilities, plus a few common public-domain ones. I also
include the sources to the customized BIOS and some other small programs.
TYPE will print an ASCII file. DUMP will dump a binary one. LS is a better
DIR than DIR. ASM will assemble .ASM files to Hex, LOAD will "load" them to
binary format (.COM). ED is a simple editor, #A command will bring the
source file to the buffer, T command will "type" lines, L will move lines,
E exits the editor. 20L20T will move down 20 lines, and type 20. Very
DECish. DDT is the debugger, DO is a batch-type command processor.
A sample batch file that will assemble and write out the bootable CP/M
image (on drive A) is "SYSCPM2.SUB". To run it, type "DO SYSCPM2".
TYPE will print an ASCII file. DUMP will dump a binary one. LS is a
better DIR than DIR. ASM will assemble .ASM files to Hex, LOAD will "load"
them to binary format (.COM). ED is a simple editor, #A command will bring
the source file to the buffer, T command will "type" lines, L will move
lines, E exits the editor. 20L20T will move down 20 lines, and type 20.
Very DECish. DDT is the debugger, DO is a batch-type command processor. A
sample batch file that will assemble and write out the bootable CP/M image
(on drive A) is "SYSCPM2.SUB". To run it, type "DO SYSCPM2".
In order to efficiently transfer files into the CP/M environment use the
included program R <filename.ext>. If you have a file named foo.ext in
the current directory (i.e. the directory where SIMH is), executing
R FOO.EXT under CP/M will transfer the file onto the CP/M disk.
Transferring a file from the CP/M environment to the SIMH environment is
accomplished by W <filename.ext>.
included program R <filename.ext>. If you have a file named foo.ext in the
current directory (i.e. the directory where SIMH is), executing R FOO.EXT
under CP/M will transfer the file onto the CP/M disk. Transferring a file
from the CP/M environment to the SIMH environment is accomplished by
W <filename.ext> for text files or by W <filename.ext> B for binary files.
The simplest way for transferring multiple files is to create a ".SUB"
batch file which contains the necessary R resp. W commands.
If you need more storage space you can use a simulated hard disk on
drives I: and J:. To use do "attach HDSK0 hdi.dsk" and issue the
@ -341,6 +353,8 @@ CBIOSX .MAC 48K ; CP/M 2 BIOS source for Altair
CCP .MAC 26K ; Console Command Processor assembler source code
COPY .COM 2K ; copy disks
CPMBOOT .COM 12K ; CP/M operating system
CPU .COM 2K ; get and set the CPU type (8080 or Z80)
CPU .MAC 2K ; source for CPU.COM
CREF80 .COM 4K ; cross reference utility
DDT .COM 6K ; 8080 debugger
DDTZ .COM 10K ; Z80 debugger
@ -349,13 +363,12 @@ DO .COM 2K ; batch processing
DSKBOOT .MAC 8K ; source for boot ROM
DUMP .COM 2K ; hex dump a file
ED .COM 8K ; line editor
ELIZA .BAS 10K ; Elisa game in Basic
EX8080 .COM 10K ; exercise 8080 instruction set
EX8080 .MAC 48K ; source for EX8080.COM
EX8080 .SUB 2K ; benchmark execution of EX8080.COM
EXZ80 .COM 10K ; exercise Z80 instruction set
EXZ80 .MAC 48K ; source for EXZ80.COM
EXZ80 .SUB 2K ; benchmark execution of EXZ80.COM
ELIZA .BAS 10K ; Eliza game in Basic
EX8080 .COM 12K ; exercise 8080 instruction set
EXZ80N .COM 12K ; exercise Z80 instruction set, No undefined status bits
EXZ80U .COM 12K ; exercise Z80 instruction set, Undefined status bits
EXZ80 .MAC 54K ; source for EX8080.COM, EXZ80N.COM, EXZ80U.COM
EX .SUB 2K ; benchmark execution of EX8080.COM, EXZ80N.COM, EXZ80U.COM
FORMAT .COM 2K ; format disks
GO .COM 0K ; start the currently loaded program at 100H
HDSKBOOT.MAC 6K ; boot code for hard disk
@ -375,11 +388,14 @@ MEMCFG .LIB 2K ; defines the memory configuration
MOVER .MAC 2K ; moves operating system in place
OTHELLO .COM 12K ; Othello (Reversi) game
PIP .COM 8K ; Peripheral Interchange Program
PRELIM .COM 2K ; preliminary CPU tests
PRELIM .MAC 6K ; source code for PRELIM.COM
R .COM 4K ; read files from SIMH environment
RSETSIMH.COM 2K ; reset SIMH interface
RSETSIMH.MAC 2K ; assembler source for RSETSIMH.COM
SHOWSEC .COM 3K ; show sectors on a disk
SID .COM 8K ; debugger for 8080
SPEED .COM 2K ; utility to measure the clock speed of the simulated CPU
STAT .COM 6K ; provide information about currently logged disks
SURVEY .COM 2K ; system survey
SURVEY .MAC 16K ; assembler source for SURVEY.COM
@ -397,15 +413,17 @@ WM .HLP 3K ; help file for WM.COM
WORM .COM 4K ; worm game for VT100 terminal
XFORMAT .COM 2K ; initialise a drive (floppy or hard disk)
XSUB .COM 2K ; support for DO.COM
ZAP .COM 10K ; SuperZap 5.2 disk editor configured for VT100
ZSID .COM 10K ; debugger for Z80
ZTRAN4 .COM 4K ; translate 8080 mnemonics into Z80 equivalents
3.2 CP/M Version 3 with banked memory
CP/M 3 is the successor to CP/M 2.2. A customised BIOS (BIOS3.MAC)
is included to facilitate modification if so desired. The defaults supplied in
GENCPM.DAT for system generation can be used. BOOTGEN.COM is used to
place the CP/M loader (LDR.COM) on the boot tracks of a disk.
CP/M 3 is the successor to CP/M 2.2. A customised BIOS (BIOS3.MAC) is
included to facilitate modification if so desired. The defaults supplied in
GENCPM.DAT for system generation can be used. BOOTGEN.COM is used to place
the CP/M loader (LDR.COM) on the boot tracks of a disk.
Running CP/M 3 with banked memory:
sim> attach dsk cpm3.dsk
@ -414,9 +432,9 @@ place the CP/M loader (LDR.COM) on the boot tracks of a disk.
sim> set cpu itrap
sim> boot dsk
Executing "DO SYSCPM3" will re-generate the banked version of CP/M 3.
You can boot CP/M 3 with or without a Z80 CPU. The Z80 CPU is needed for
both sysgens due to the use of BOOTGEN.COM which requires it.
Executing "DO SYSCPM3" will re-generate the banked version of CP/M 3. You
can boot CP/M 3 with or without a Z80 CPU. The Z80 CPU is needed for both
sysgens due to the use of BOOTGEN.COM which requires it.
The disk "cpm3.dsk" contains the following files:
ASM .COM 8K ; CP/M assembler
@ -508,10 +526,9 @@ version supports four terminals available via Telnet. To boot:
sim> boot dsk
Now connect a Telnet session to the simulator and type "MPM" at the "A>"
prompt. Now you can connect up to three additional terminals via Telnet
to the Altair running MP/M II. To re-generate the system perform
"DO SYSMPM" in the CP/M environment (not possible under MP/M since XSUB
is needed).
prompt. Now you can connect up to three additional terminals via Telnet to
the Altair running MP/M II. To re-generate the system perform "DO SYSMPM"
in the CP/M environment (not possible under MP/M since XSUB is needed).
The disk "mpm.dsk" contains the following files:
Name Ext Size Comment
@ -595,10 +612,10 @@ XREF .COM 16K ; cross reference utility
XSUB .COM 2K ; for CP/M DO
3.5 CP/M application software
3.4 CP/M application software
There is also a small collection of sample application software containing
the following items:
There is also a small collection of sample application software
containing the following items:
- SPL: a Small Programming Language with a suite of sample programs
- PROLOGZ: a Prolog interpreter written in SPL with sources
@ -616,16 +633,16 @@ Name Ext Size Comment
BOOTGEN .COM 2K
BOOTGEN .SPL 6K ; SPL source for BOOTGEN.COM
C .SUB 2K ; batch file for compiling an SPL source file
CALC .PRO 4K ; Prolog demo program calculator
CALC .PRO 4K ; Prolog demo program: Calculator
CC .SUB 2K ; compile an SPL source which is on the underlying
file system
DECLARAT. 12K ; common include file, SPL source
DIF .COM 4K
DIF .SPL 10K ; SPL source for DIF.COM
EDIT .SPL 10K ; screen editor for PROLOGZ, SPL source
FAMILY .PRO 4K ; Prolog demo program family relations
INTEGER .PRO 2K ; Prolog demo program integer arithmetic
KNAKE .PRO 2K ; Prolog demo program logic puzzle
FAMILY .PRO 4K ; Prolog demo program: Family relations
INTEGER .PRO 2K ; Prolog demo program: Integer arithmetic
KNAKE .PRO 2K ; Prolog demo program: Logic puzzle
LINKMT .COM 12K ; Pascal MT+ 5.5 linker
MAIN .SPL 14K ; main module for PROLOGZ, SPL source
MOVE .MAC 4K ; helper functions for PROLOGZ in assembler
@ -652,18 +669,21 @@ PROVE .SPL 16K ; backtrack theorem prover for PROLOGZ, SPL source
PZCLEAN .SUB 2K ; PROLOGZ: remove all created ".rel" and ".lst" files
PZLINK .SUB 2K ; PROLOGZ: create PINST, PROLOGZ and personalise the
serial number
PZMAKE .SUB 2K ; compiles the sources (you can ignore any compiler
errors)
QUEEN .PRO 2K ; Prolog demo program n-queens problem
PZMAKE .SUB 2K ; PROLOGZ: compiles the sources (you can ignore
any compiler errors)
QUEEN .PRO 2K ; Prolog demo program: N-queens problem
READ .COM 4K
READ .SPL 10K ; SPL source for R.COM
SHOWSEC .COM 4K
SHOWSEC .SPL 6K ; SPL source for SHOWSEC.COM
SPEED .COM 2K ; utility to measure the clock speed of the simulated CPU
SPEED .SPL 2K ; SPL source for SPEED.COM, requires SWLIB.MAC
SPL .COM 38K ; the SPL compiler itself
SPL .TXT 56K ; SPL language and compiler documentation in German
SPLERROR.DAT 12K ; error messages of the compiler (in German)
SPLIB .REL 6K ; SPL runtime library
STDIO . 2K ; include file for SPL programs
SWLIB .MAC 2K ; assembler utility routines needed by SPEED.SPL
SYSCOPY .COM 2K
SYSCOPY .SPL 6K ; SPL source for SYSCOPY.COM
TERMBDOS.SPL 2K ; terminal interface to CP/M for PROLOGZ, SPL source
@ -674,7 +694,7 @@ XFORMAT .COM 2K
XFORMAT .SPL 6K ; SPL source for XFORMAT.COM
3.6 MITS Disk Extended BASIC Version 4.1
3.5 MITS Disk Extended BASIC Version 4.1
This was the commonly used software for serious users of the Altair
computer. It is a powerful (but slow) BASIC with some extended commands to
@ -702,11 +722,11 @@ ran under. To boot:
[FILES]
3.7 Altair DOS Version 1.0
3.6 Altair DOS Version 1.0
This was long promised but not delivered until it was almost
irrelevant. A short attempted tour will reveal it to be a dog, far inferior
to CP/M. To boot:
This was long promised but not delivered until it was almost irrelevant.
A short attempted tour will reveal it to be a dog, far inferior to CP/M. To
boot:
sim> d tracks[0-7] 77 ;set to Altair settings
sim> set cpu altairrom
@ -728,9 +748,10 @@ to CP/M. To boot:
.[DIR 0]
3.8 Altair Basic 3.2 (4k)
In order to run the famous 4k Basic, use the following commands (the trick
is to get the Switch Register right).
3.7 Altair Basic 3.2 (4k)
In order to run the famous 4k Basic, use the following commands (the
trick is to get the Switch Register right).
sim> set cpu 8080 ;note 4k Basic will not run on a Z80 CPU
sim> set sio upper ;4k Basic does not like lower case letters as input
@ -750,7 +771,7 @@ is to get the Switch Register right).
OK
3.9 Altair 8k Basic
3.8 Altair 8k Basic
Running 8k Basic follows the procedure for 4k Basic.
sim> set cpu 8080 ;note 8k Basic will not run on a Z80 CPU
@ -774,7 +795,8 @@ is to get the Switch Register right).
OK
3.10 Altair Basic 4.0
3.9 Altair Basic 4.0
Execute the following commands to run Altair Extended Basic:
sim> set sio upper ;Extended Basic does not like lower case letters as input
@ -794,7 +816,8 @@ is to get the Switch Register right).
OK
3.11 Altair Disk Extended Basic Version 300-5-C
3.10 Altair Disk Extended Basic Version 300-5-C
This version of Basic was provided by Scott LaBombard. To execute use the
following commands:
@ -818,6 +841,7 @@ is to get the Switch Register right).
4. Special simulator features
In addition to the regular SIMH features such as PC queue, breakpoints
etc., this simulator supports memory access breakpoints. A memory access
breakpoint is triggered when a pre-defined memory location is accessed
@ -827,8 +851,8 @@ sim> break -m <location>
Execution will stop whenever an operation accesses <location>. Note that
a memory access breakpoint is not triggered by fetching code from memory
(this is the job of regular breakpoints). This feature has been
implemented by using the typing facility of the SIMH breakpoints.
(this is the job of regular breakpoints). This feature has been implemented
by using the typing facility of the SIMH breakpoints.
5. Brief summary of all major changes to the original Altair simulator

File diff suppressed because it is too large Load diff

View file

@ -1,4 +1,4 @@
/* altairZ80_defs.h: MITS Altair simulator definitions
/* altairz80_defs.h: MITS Altair simulator definitions
Copyright (c) 2002, Peter Schorn
@ -15,7 +15,7 @@
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY 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
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.
@ -28,8 +28,7 @@
#include "sim_defs.h" /* simulator definitions */
/* Memory */
#define MAXMEMSIZE 65536 /* max memory size */
#define MAXMEMSIZE 65536 /* maximum memory size */
#define ADDRMASK (MAXMEMSIZE - 1) /* address mask */
#define bootrom_size 256 /* size of boot rom */
#define MAXBANKS 8 /* max number of memory banks */
@ -45,19 +44,19 @@
#define unitNoOffset1 0x37 /* LD A,<unitno> */
#define unitNoOffset2 0xb4 /* LD a,80h | <unitno> */
#define UNIT_V_OPSTOP (UNIT_V_UF+0) /* Stop on Invalid OP? */
#define UNIT_V_OPSTOP (UNIT_V_UF+0) /* stop on nvalid operation */
#define UNIT_OPSTOP (1 << UNIT_V_OPSTOP)
#define UNIT_V_CHIP (UNIT_V_UF+1) /* 8080 or Z80 */
#define UNIT_V_CHIP (UNIT_V_UF+1) /* 8080 or Z80 CPU */
#define UNIT_CHIP (1 << UNIT_V_CHIP)
#define UNIT_V_MSIZE (UNIT_V_UF+2) /* Memory Size */
#define UNIT_V_MSIZE (UNIT_V_UF+2) /* memory size */
#define UNIT_MSIZE (1 << UNIT_V_MSIZE)
#define UNIT_V_BANKED (UNIT_V_UF+3) /* Banked memory is used */
#define UNIT_V_BANKED (UNIT_V_UF+3) /* banked memory is used */
#define UNIT_BANKED (1 << UNIT_V_BANKED)
#define UNIT_V_ROM (UNIT_V_UF+4) /* ROM exists */
#define UNIT_ROM (1 << UNIT_V_ROM)
#define UNIT_V_ALTAIRROM (UNIT_V_UF+5) /* ALTAIR ROM exists */
#define UNIT_ALTAIRROM (1 << UNIT_V_ALTAIRROM)
#define UNIT_V_WARNROM (UNIT_V_UF+6) /* Warn if ROM is written to */
#define UNIT_V_WARNROM (UNIT_V_UF+6) /* warn if ROM is written to */
#define UNIT_WARNROM (1 << UNIT_V_WARNROM)
#define AddressFormat "[%04xh]"

View file

@ -1,6 +1,6 @@
/* altairZ80_dsk.c: MITS Altair 88-DISK Simulator
/* altairz80_dsk.c: MITS Altair 88-DISK Simulator
Copyright (c) 2002, Peter Schorn
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"),
@ -15,7 +15,7 @@
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY 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
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.
@ -108,7 +108,6 @@
*/
#include <stdio.h>
#include "altairz80_defs.h"
#define UNIT_V_DSKWLK (UNIT_V_UF + 0) /* write locked */
@ -127,18 +126,18 @@
#define TRACE_TRACK_STUCK 8
#define NUM_OF_DSK_MASK (NUM_OF_DSK - 1)
int32 dsk10(int32 port, int32 io, int32 data);
int32 dsk11(int32 port, int32 io, int32 data);
int32 dsk12(int32 port, int32 io, int32 data);
int32 dskseek(UNIT *xptr);
t_stat dsk_boot(int32 unitno, DEVICE *dptr);
t_stat dsk_reset(DEVICE *dptr);
t_stat dsk_svc(UNIT *uptr);
void writebuf(void);
t_stat dsk_set_verbose(UNIT *uptr, int32 value, char *cptr, void *desc);
void resetDSKWarningFlags(void);
int32 hasVerbose(void);
char* selectInOut(int32 io);
int32 dsk10(const int32 port, const int32 io, const int32 data);
int32 dsk11(const int32 port, const int32 io, const int32 data);
int32 dsk12(const int32 port, const int32 io, const int32 data);
static int32 dskseek(const UNIT *xptr);
static t_stat dsk_boot(int32 unitno, DEVICE *dptr);
static t_stat dsk_reset(DEVICE *dptr);
static t_stat dsk_svc(UNIT *uptr);
static void writebuf(void);
static t_stat dsk_set_verbose(UNIT *uptr, int32 value, char *cptr, void *desc);
static void resetDSKWarningFlags(void);
static int32 hasVerbose(void);
static char* selectInOut(const int32 io);
extern int32 PCX;
extern int32 saved_PC;
@ -149,27 +148,27 @@ extern char messageBuffer[];
extern int32 install_bootrom(void);
extern UNIT cpu_unit;
/* Global data on status */
/* global data on status */
int32 cur_disk = NUM_OF_DSK; /* Currently selected drive (values are 0 .. NUM_OF_DSK)
cur_disk < NUM_OF_DSK implies that the corresponding disk is attached to a file */
int32 cur_track [NUM_OF_DSK] = {0, 0, 0, 0, 0, 0, 0, 0};
int32 cur_sect [NUM_OF_DSK] = {0, 0, 0, 0, 0, 0, 0, 0};
int32 cur_byte [NUM_OF_DSK] = {0, 0, 0, 0, 0, 0, 0, 0};
int32 cur_flags [NUM_OF_DSK] = {0, 0, 0, 0, 0, 0, 0, 0};
uint8 tracks [NUM_OF_DSK] = { MAX_TRACKS, MAX_TRACKS, MAX_TRACKS, MAX_TRACKS,
static int32 current_disk = NUM_OF_DSK; /* currently selected drive (values are 0 .. NUM_OF_DSK)
current_disk < NUM_OF_DSK implies that the corresponding disk is attached to a file */
static int32 current_track [NUM_OF_DSK] = {0, 0, 0, 0, 0, 0, 0, 0};
static int32 current_sector [NUM_OF_DSK] = {0, 0, 0, 0, 0, 0, 0, 0};
static int32 current_byte [NUM_OF_DSK] = {0, 0, 0, 0, 0, 0, 0, 0};
static int32 current_flag [NUM_OF_DSK] = {0, 0, 0, 0, 0, 0, 0, 0};
static uint8 tracks [NUM_OF_DSK] = { MAX_TRACKS, MAX_TRACKS, MAX_TRACKS, MAX_TRACKS,
MAX_TRACKS, MAX_TRACKS, MAX_TRACKS, MAX_TRACKS };
int32 trace_flag = 0;
int32 in9_count = 0;
int32 in9_message = FALSE;
int32 dirty = FALSE; /* TRUE when buffer has unwritten data in it */
int32 warnLevelDSK = 3;
int32 warnLock [NUM_OF_DSK] = {0, 0, 0, 0, 0, 0, 0, 0};
int32 warnAttached[NUM_OF_DSK] = {0, 0, 0, 0, 0, 0, 0, 0};
int32 warnDSK10 = 0;
int32 warnDSK11 = 0;
int32 warnDSK12 = 0;
int8 dskbuf[DSK_SECTSIZE]; /* Data Buffer */
static int32 trace_flag = 0;
static int32 in9_count = 0;
static int32 in9_message = FALSE;
static int32 dirty = FALSE; /* TRUE when buffer has unwritten data in it */
static int32 warnLevelDSK = 3;
static int32 warnLock [NUM_OF_DSK] = {0, 0, 0, 0, 0, 0, 0, 0};
static int32 warnAttached [NUM_OF_DSK] = {0, 0, 0, 0, 0, 0, 0, 0};
static int32 warnDSK10 = 0;
static int32 warnDSK11 = 0;
static int32 warnDSK12 = 0;
static int8 dskbuf[DSK_SECTSIZE]; /* data Buffer */
/* Altair MITS modified BOOT EPROM, fits in upper 256 byte of memory */
int32 bootrom[bootrom_size] = {
@ -209,7 +208,7 @@ int32 bootrom[bootrom_size] = {
/* 88DSK Standard I/O Data Structures */
UNIT dsk_unit[] = {
static UNIT dsk_unit[] = {
{ UDATA (&dsk_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, MAX_DSK_SIZE) },
{ UDATA (&dsk_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, MAX_DSK_SIZE) },
{ UDATA (&dsk_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, MAX_DSK_SIZE) },
@ -219,15 +218,27 @@ UNIT dsk_unit[] = {
{ UDATA (&dsk_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, MAX_DSK_SIZE) },
{ UDATA (&dsk_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, MAX_DSK_SIZE) } };
REG dsk_reg[] = {
{ DRDATA (DISK, cur_disk, 4) },
{ DRDATA (DSKWL, warnLevelDSK, 32) },
{ ORDATA (TRACE, trace_flag, 8) },
static REG dsk_reg[] = {
{ DRDATA (DISK, current_disk, 4) },
{ BRDATA (CURTRACK, current_track, 10, 32, NUM_OF_DSK), REG_CIRC + REG_RO },
{ BRDATA (CURSECTOR, current_sector, 10, 32, NUM_OF_DSK), REG_CIRC + REG_RO },
{ BRDATA (CURBYTE, current_byte, 10, 32, NUM_OF_DSK), REG_CIRC + REG_RO },
{ BRDATA (CURFLAG, current_flag, 10, 32, NUM_OF_DSK), REG_CIRC + REG_RO },
{ BRDATA (TRACKS, tracks, 10, 8, NUM_OF_DSK), REG_CIRC },
{ DRDATA (IN9, in9_count, 4), REG_RO },
{ ORDATA (TRACE, trace_flag, 8) },
{ DRDATA (IN9COUNT, in9_count, 4), REG_RO },
{ DRDATA (IN9MESSAGE, in9_message, 4), REG_RO },
{ DRDATA (DIRTY, dirty, 4), REG_RO },
{ DRDATA (DSKWL, warnLevelDSK, 32) },
{ BRDATA (WARNLOCK, warnLock, 10, 32, NUM_OF_DSK), REG_CIRC + REG_RO },
{ BRDATA (WARNATTACHED, warnAttached, 10, 32, NUM_OF_DSK), REG_CIRC + REG_RO },
{ DRDATA (WARNDSK10, warnDSK10, 4), REG_RO },
{ DRDATA (WARNDSK11, warnDSK11, 4), REG_RO },
{ DRDATA (WARNDSK12, warnDSK12, 4), REG_RO },
{ BRDATA (DISKBUFFER, dskbuf, 10, 8, DSK_SECTSIZE), REG_CIRC + REG_RO },
{ NULL } };
MTAB dsk_mod[] = {
static MTAB dsk_mod[] = {
{ UNIT_DSKWLK, 0, "write enabled", "WRITEENABLED", NULL },
{ UNIT_DSKWLK, UNIT_DSKWLK, "write locked", "LOCKED", NULL },
/* quiet, no warning messages */
@ -240,9 +251,9 @@ DEVICE dsk_dev = {
"DSK", dsk_unit, dsk_reg, dsk_mod,
8, 10, 31, 1, 8, 8,
NULL, NULL, &dsk_reset,
&dsk_boot, NULL, NULL, NULL, 0 };
&dsk_boot, NULL, NULL, NULL, 0, NULL, NULL };
void resetDSKWarningFlags(void) {
static void resetDSKWarningFlags(void) {
int32 i;
for (i = 0; i < NUM_OF_DSK; i++) {
warnLock[i] = 0;
@ -253,13 +264,13 @@ void resetDSKWarningFlags(void) {
warnDSK12 = 0;
}
t_stat dsk_set_verbose(UNIT *uptr, int32 value, char *cptr, void *desc) {
static t_stat dsk_set_verbose(UNIT *uptr, int32 value, char *cptr, void *desc) {
resetDSKWarningFlags();
return SCPE_OK;
}
/* returns TRUE iff there exists a disk with VERBOSE */
int32 hasVerbose(void) {
static int32 hasVerbose(void) {
int32 i;
for (i = 0; i < NUM_OF_DSK; i++) {
if (((dsk_dev.units + i) -> flags) & UNIT_DSK_VERBOSE) {
@ -269,23 +280,23 @@ int32 hasVerbose(void) {
return FALSE;
}
char* selectInOut(int32 io) {
static char* selectInOut(const int32 io) {
return io == 0 ? "IN" : "OUT";
}
/* Service routines to handle simulator functions */
/* service routines to handle simulator functions */
/* service routine - actually gets char & places in buffer */
t_stat dsk_svc(UNIT *uptr) {
static t_stat dsk_svc(UNIT *uptr) {
return SCPE_OK;
}
/* Reset routine */
/* reset routine */
t_stat dsk_reset(DEVICE *dptr) {
static t_stat dsk_reset(DEVICE *dptr) {
resetDSKWarningFlags();
cur_disk = NUM_OF_DSK;
current_disk = NUM_OF_DSK;
trace_flag = 0;
in9_count = 0;
in9_message = FALSE;
@ -295,7 +306,7 @@ t_stat dsk_reset(DEVICE *dptr) {
/* The boot routine modifies the boot ROM in such a way that subsequently
the specified disk is used for boot purposes.
*/
t_stat dsk_boot(int32 unitno, DEVICE *dptr) {
static t_stat dsk_boot(int32 unitno, DEVICE *dptr) {
if (cpu_unit.flags & (UNIT_ALTAIRROM | UNIT_BANKED)) {
if (install_bootrom()) {
printf("ALTAIR boot ROM installed.\n");
@ -333,50 +344,50 @@ t_stat dsk_boot(int32 unitno, DEVICE *dptr) {
simulation requirement that they are reversed in hardware.
*/
int32 dsk10(int32 port, int32 io, int32 data) {
int32 cur_flag;
int32 dsk10(const int32 port, const int32 io, const int32 data) {
int32 current_disk_flags;
in9_count = 0;
if (io == 0) { /* IN: return flags */
if (cur_disk >= NUM_OF_DSK) {
if (current_disk >= NUM_OF_DSK) {
if (hasVerbose() && (warnDSK10 < warnLevelDSK)) {
warnDSK10++;
/*01*/ message1("Attempt of IN 0x08 on unattached disk - ignored.\n");
}
return 0xff; /* no drive selected - can do nothing */
}
return (~cur_flags[cur_disk]) & 0xff; /* Return the COMPLEMENT! */
return (~current_flag[current_disk]) & 0xff; /* return the COMPLEMENT! */
}
/* OUT: Controller set/reset/enable/disable */
if (dirty) {/* implies that cur_disk < NUM_OF_DSK */
if (dirty) { /* implies that current_disk < NUM_OF_DSK */
writebuf();
}
if (trace_flag & TRACE_IN_OUT) {
message2("OUT 0x08: %x\n", data);
}
cur_disk = data & NUM_OF_DSK_MASK; /* 0 <= cur_disk < NUM_OF_DSK */
cur_flag = (dsk_dev.units + cur_disk) -> flags;
if ((cur_flag & UNIT_ATT) == 0) { /* nothing attached? */
if ( (cur_flag & UNIT_DSK_VERBOSE) && (warnAttached[cur_disk] < warnLevelDSK) ) {
warnAttached[cur_disk]++;
/*02*/message2("Attempt to select unattached DSK%d - ignored.\n", cur_disk);
current_disk = data & NUM_OF_DSK_MASK; /* 0 <= current_disk < NUM_OF_DSK */
current_disk_flags = (dsk_dev.units + current_disk) -> flags;
if ((current_disk_flags & UNIT_ATT) == 0) { /* nothing attached? */
if ( (current_disk_flags & UNIT_DSK_VERBOSE) && (warnAttached[current_disk] < warnLevelDSK) ) {
warnAttached[current_disk]++;
/*02*/message2("Attempt to select unattached DSK%d - ignored.\n", current_disk);
}
cur_disk = NUM_OF_DSK;
current_disk = NUM_OF_DSK;
}
else {
cur_sect[cur_disk] = 0xff; /* reset internal counters */
cur_byte[cur_disk] = 0xff;
cur_flags[cur_disk] = data & 0x80 ? 0 /* Disable drive */ :
(cur_track[cur_disk] == 0 ? 0x5a /* Enable: head move true, track 0 if there */ :
0x1a); /* Enable: head move true */
current_sector[current_disk] = 0xff; /* reset internal counters */
current_byte[current_disk] = 0xff;
current_flag[current_disk] = data & 0x80 ? 0 /* disable drive */ :
(current_track[current_disk] == 0 ? 0x5a /* enable: head move true, track 0 if there */ :
0x1a);/* enable: head move true */
}
return 0; /* ignored since OUT */
}
/* Disk Drive Status/Functions */
int32 dsk11(int32 port, int32 io, int32 data) {
if (cur_disk >= NUM_OF_DSK) {
int32 dsk11(const int32 port, const int32 io, const int32 data) {
if (current_disk >= NUM_OF_DSK) {
if (hasVerbose() && (warnDSK11 < warnLevelDSK)) {
warnDSK11++;
/*03*/message2("Attempt of %s 0x09 on unattached disk - ignored.\n", selectInOut(io));
@ -384,26 +395,26 @@ int32 dsk11(int32 port, int32 io, int32 data) {
return 0; /* no drive selected - can do nothing */
}
/* now cur_disk < NUM_OF_DSK */
if (io == 0) { /* Read sector position */
/* now current_disk < NUM_OF_DSK */
if (io == 0) { /* read sector position */
in9_count++;
if ((trace_flag & TRACE_SECTOR_STUCK) && (in9_count > 2 * DSK_SECT) && (!in9_message)) {
in9_message = TRUE;
message2("Looping on sector find %d.\n", cur_disk);
message2("Looping on sector find %d.\n", current_disk);
}
if (trace_flag & TRACE_IN_OUT) {
message1("IN 0x09\n");
}
if (dirty) {/* implies that cur_disk < NUM_OF_DSK */
if (dirty) {/* implies that current_disk < NUM_OF_DSK */
writebuf();
}
if (cur_flags[cur_disk] & 0x04) { /* head loaded? */
cur_sect[cur_disk]++;
if (cur_sect[cur_disk] >= DSK_SECT) {
cur_sect[cur_disk] = 0;
if (current_flag[current_disk] & 0x04) { /* head loaded? */
current_sector[current_disk]++;
if (current_sector[current_disk] >= DSK_SECT) {
current_sector[current_disk] = 0;
}
cur_byte[cur_disk] = 0xff;
return (((cur_sect[cur_disk] << 1) & 0x3e) /* return 'sector true' bit = 0 (true) */
current_byte[current_disk] = 0xff;
return (((current_sector[current_disk] << 1) & 0x3e) /* return 'sector true' bit = 0 (true) */
| 0xc0); /* set on 'unused' bits */
} else {
return 0; /* head not loaded - return 0 */
@ -411,83 +422,83 @@ int32 dsk11(int32 port, int32 io, int32 data) {
}
in9_count = 0;
/* Drive functions */
/* drive functions */
if (trace_flag & TRACE_IN_OUT) {
message2("OUT 0x09: %x\n", data);
}
if (data & 0x01) { /* Step head in */
if (data & 0x01) { /* step head in */
if (trace_flag & TRACE_TRACK_STUCK) {
if (cur_track[cur_disk] == (tracks[cur_disk] - 1)) {
message2("Unnecessary step in for disk %d\n", cur_disk);
if (current_track[current_disk] == (tracks[current_disk] - 1)) {
message2("Unnecessary step in for disk %d\n", current_disk);
}
}
cur_track[cur_disk]++;
if (cur_track[cur_disk] > (tracks[cur_disk] - 1)) {
cur_track[cur_disk] = (tracks[cur_disk] - 1);
current_track[current_disk]++;
if (current_track[current_disk] > (tracks[current_disk] - 1)) {
current_track[current_disk] = (tracks[current_disk] - 1);
}
if (dirty) { /* implies that cur_disk < NUM_OF_DSK */
if (dirty) { /* implies that current_disk < NUM_OF_DSK */
writebuf();
}
cur_sect[cur_disk] = 0xff;
cur_byte[cur_disk] = 0xff;
current_sector[current_disk] = 0xff;
current_byte[current_disk] = 0xff;
}
if (data & 0x02) { /* Step head out */
if (data & 0x02) { /* step head out */
if (trace_flag & TRACE_TRACK_STUCK) {
if (cur_track[cur_disk] == 0) {
message2("Unnecessary step out for disk %d\n", cur_disk);
if (current_track[current_disk] == 0) {
message2("Unnecessary step out for disk %d\n", current_disk);
}
}
cur_track[cur_disk]--;
if (cur_track[cur_disk] < 0) {
cur_track[cur_disk] = 0;
cur_flags[cur_disk] |= 0x40; /* track 0 if there */
current_track[current_disk]--;
if (current_track[current_disk] < 0) {
current_track[current_disk] = 0;
current_flag[current_disk] |= 0x40; /* track 0 if there */
}
if (dirty) { /* implies that cur_disk < NUM_OF_DSK */
if (dirty) { /* implies that current_disk < NUM_OF_DSK */
writebuf();
}
cur_sect[cur_disk] = 0xff;
cur_byte[cur_disk] = 0xff;
current_sector[current_disk] = 0xff;
current_byte[current_disk] = 0xff;
}
if (dirty) { /* implies that cur_disk < NUM_OF_DSK */
if (dirty) { /* implies that current_disk < NUM_OF_DSK */
writebuf();
}
if (data & 0x04) { /* Head load */
cur_flags[cur_disk] |= 0x04; /* turn on head loaded bit */
cur_flags[cur_disk] |= 0x80; /* turn on 'read data available' */
if (data & 0x04) { /* head load */
current_flag[current_disk] |= 0x04; /* turn on head loaded bit */
current_flag[current_disk] |= 0x80; /* turn on 'read data available' */
}
if (data & 0x08) { /* Head Unload */
cur_flags[cur_disk] &= 0xfb; /* turn off 'head loaded' bit */
cur_flags[cur_disk] &= 0x7f; /* turn off 'read data available' */
cur_sect[cur_disk] = 0xff;
cur_byte[cur_disk] = 0xff;
if (data & 0x08) { /* head unload */
current_flag[current_disk] &= 0xfb; /* turn off 'head loaded' bit */
current_flag[current_disk] &= 0x7f; /* turn off 'read data available' */
current_sector[current_disk] = 0xff;
current_byte[current_disk] = 0xff;
}
/* Interrupts & head current are ignored */
/* interrupts & head current are ignored */
if (data & 0x80) { /* write sequence start */
cur_byte[cur_disk] = 0;
cur_flags[cur_disk] |= 0x01; /* enter new write data on */
current_byte[current_disk] = 0;
current_flag[current_disk] |= 0x01; /* enter new write data on */
}
return 0; /* ignored since OUT */
}
/* Disk Data In/Out */
INLINE int32 dskseek(UNIT *xptr) {
return fseek(xptr -> fileref, DSK_TRACSIZE * cur_track[cur_disk] +
DSK_SECTSIZE * cur_sect[cur_disk], SEEK_SET);
static INLINE int32 dskseek(const UNIT *xptr) {
return fseek(xptr -> fileref, DSK_TRACSIZE * current_track[current_disk] +
DSK_SECTSIZE * current_sector[current_disk], SEEK_SET);
}
int32 dsk12(int32 port, int32 io, int32 data) {
static int32 i;
int32 dsk12(const int32 port, const int32 io, const int32 data) {
int32 i;
UNIT *uptr;
if (cur_disk >= NUM_OF_DSK) {
if (current_disk >= NUM_OF_DSK) {
if (hasVerbose() && (warnDSK12 < warnLevelDSK)) {
warnDSK12++;
/*04*/message2("Attempt of %s 0x0a on unattached disk - ignored.\n", selectInOut(io));
@ -495,64 +506,64 @@ int32 dsk12(int32 port, int32 io, int32 data) {
return 0;
}
/* now cur_disk < NUM_OF_DSK */
/* now current_disk < NUM_OF_DSK */
in9_count = 0;
uptr = dsk_dev.units + cur_disk;
uptr = dsk_dev.units + current_disk;
if (io == 0) {
if (cur_byte[cur_disk] >= DSK_SECTSIZE) {
if (current_byte[current_disk] >= DSK_SECTSIZE) {
/* physically read the sector */
if (trace_flag & TRACE_READ_WRITE) {
message4("IN 0x0a (READ) D%d T%d S%d\n", cur_disk, cur_track[cur_disk], cur_sect[cur_disk]);
message4("IN 0x0a (READ) D%d T%d S%d\n", current_disk, current_track[current_disk], current_sector[current_disk]);
}
for (i = 0; i < DSK_SECTSIZE; i++) {
dskbuf[i] = 0;
}
dskseek(uptr);
fread(dskbuf, DSK_SECTSIZE, 1, uptr -> fileref);
cur_byte[cur_disk] = 0;
current_byte[current_disk] = 0;
}
return dskbuf[cur_byte[cur_disk]++] & 0xff;
return dskbuf[current_byte[current_disk]++] & 0xff;
}
else {
if (cur_byte[cur_disk] >= DSK_SECTSIZE) {
writebuf(); /* from above we have that cur_disk < NUM_OF_DSK */
if (current_byte[current_disk] >= DSK_SECTSIZE) {
writebuf(); /* from above we have that current_disk < NUM_OF_DSK */
}
else {
dirty = TRUE; /* this guarantees for the next call to writebuf that cur_disk < NUM_OF_DSK */
dskbuf[cur_byte[cur_disk]++] = data & 0xff;
dirty = TRUE; /* this guarantees for the next call to writebuf that current_disk < NUM_OF_DSK */
dskbuf[current_byte[current_disk]++] = data & 0xff;
}
return 0; /* ignored since OUT */
}
}
/* Precondition: cur_disk < NUM_OF_DSK */
void writebuf(void) {
/* precondition: current_disk < NUM_OF_DSK */
static void writebuf(void) {
int32 i, rtn;
UNIT *uptr;
i = cur_byte[cur_disk]; /* null-fill rest of sector if any */
i = current_byte[current_disk]; /* null-fill rest of sector if any */
while (i < DSK_SECTSIZE) {
dskbuf[i++] = 0;
}
uptr = dsk_dev.units + cur_disk;
uptr = dsk_dev.units + current_disk;
if (((uptr -> flags) & UNIT_DSKWLK) == 0) { /* write enabled */
if (trace_flag & TRACE_READ_WRITE) {
message4("OUT 0x0a (WRITE) D%d T%d S%d\n", cur_disk, cur_track[cur_disk], cur_sect[cur_disk]);
message4("OUT 0x0a (WRITE) D%d T%d S%d\n", current_disk, current_track[current_disk], current_sector[current_disk]);
}
if (dskseek(uptr)) {
message4("fseek failed D%d T%d S%d\n", cur_disk, cur_track[cur_disk], cur_sect[cur_disk]);
message4("fseek failed D%d T%d S%d\n", current_disk, current_track[current_disk], current_sector[current_disk]);
}
rtn = fwrite(dskbuf, DSK_SECTSIZE, 1, uptr -> fileref);
if (rtn != 1) {
message4("fwrite failed T%d S%d Return=%d\n", cur_track[cur_disk], cur_sect[cur_disk], rtn);
message4("fwrite failed T%d S%d Return=%d\n", current_track[current_disk], current_sector[current_disk], rtn);
}
}
else if ( ((uptr -> flags) & UNIT_DSK_VERBOSE) && (warnLock[cur_disk] < warnLevelDSK) ) {
else if ( ((uptr -> flags) & UNIT_DSK_VERBOSE) && (warnLock[current_disk] < warnLevelDSK) ) {
/* write locked - print warning message if required */
warnLock[cur_disk]++;
warnLock[current_disk]++;
/*05*/
message2("Attempt to write to locked DSK%d - ignored.\n", cur_disk);
message2("Attempt to write to locked DSK%d - ignored.\n", current_disk);
}
cur_flags[cur_disk] &= 0xfe; /* ENWD off */
cur_byte[cur_disk] = 0xff;
current_flag[current_disk] &= 0xfe; /* ENWD off */
current_byte[current_disk] = 0xff;
dirty = FALSE;
}

View file

@ -1,6 +1,6 @@
/* altairZ80_sio: MITS Altair serial I/O card
/* altairz80_sio: MITS Altair serial I/O card
Copyright (c) 2002, Peter Schorn
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"),
@ -15,7 +15,7 @@
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY 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
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.
@ -49,7 +49,6 @@
to the data port writes the character to the device.
*/
#include <stdio.h>
#include <ctype.h>
#include "altairz80_defs.h"
@ -77,35 +76,36 @@
#define DELETE_CHAR 0x7f /* delete character */
#define CONTROLZ_CHAR 0x1a /* control Z character */
void resetSIOWarningFlags(void);
t_stat sio_set_verbose(UNIT *uptr, int32 value, char *cptr, void *desc);
t_stat sio_svc(UNIT *uptr);
t_stat sio_reset(DEVICE *dptr);
t_stat sio_attach(UNIT *uptr, char *cptr);
t_stat sio_detach(UNIT *uptr);
t_stat ptr_reset(DEVICE *dptr);
t_stat ptp_reset(DEVICE *dptr);
int32 nulldev (int32 port, int32 io, int32 data);
int32 sr_dev (int32 port, int32 io, int32 data);
int32 simh_dev(int32 port, int32 io, int32 data);
int32 sio0d (int32 port, int32 io, int32 data);
int32 sio0s (int32 port, int32 io, int32 data);
int32 sio1d (int32 port, int32 io, int32 data);
int32 sio1s (int32 port, int32 io, int32 data);
void reset_sio_terminals(int32 useDefault);
t_stat simh_dev_reset(DEVICE *dptr);
t_stat simh_svc(UNIT *uptr);
t_stat simh_dev_set_timeron(UNIT *uptr, int32 val, char *cptr, void *desc);
t_stat simh_dev_set_timeroff(UNIT *uptr, int32 val, char *cptr, void *desc);
int32 simh_in(void);
int32 simh_out(int32 data);
void attachCPM(UNIT *uptr);
void setClockZSDOS(void);
void setClockCPM3(void);
time_t mkCPM3Origin(void);
int32 toBCD(int32 x);
int32 fromBCD(int32 x);
static void resetSIOWarningFlags(void);
static t_stat sio_set_verbose (UNIT *uptr, int32 value, char *cptr, void *desc);
static t_stat simh_dev_set_timeron (UNIT *uptr, int32 value, char *cptr, void *desc);
static t_stat simh_dev_set_timeroff (UNIT *uptr, int32 value, char *cptr, void *desc);
static t_stat sio_svc(UNIT *uptr);
static t_stat sio_reset(DEVICE *dptr);
static t_stat sio_attach(UNIT *uptr, char *cptr);
static t_stat sio_detach(UNIT *uptr);
static t_stat ptr_reset(DEVICE *dptr);
static t_stat ptp_reset(DEVICE *dptr);
int32 nulldev (const int32 port, const int32 io, const int32 data);
int32 sr_dev (const int32 port, const int32 io, const int32 data);
int32 simh_dev(const int32 port, const int32 io, const int32 data);
int32 sio0d (const int32 port, const int32 io, const int32 data);
int32 sio0s (const int32 port, const int32 io, const int32 data);
int32 sio1d (const int32 port, const int32 io, const int32 data);
int32 sio1s (const int32 port, const int32 io, const int32 data);
static void reset_sio_terminals(const int32 useDefault);
static t_stat simh_dev_reset(DEVICE *dptr);
static t_stat simh_svc(UNIT *uptr);
static int32 simh_in(const int32 port);
static int32 simh_out(const int32 port, const int32 data);
static void attachCPM(UNIT *uptr);
static void setClockZSDOS(void);
static void setClockCPM3(void);
static time_t mkCPM3Origin(void);
static int32 toBCD(const int32 x);
static int32 fromBCD(const int32 x);
void printMessage(void);
static void warnNoRealTimeClock(void);
extern t_stat sim_activate(UNIT *uptr, int32 interval);
extern t_stat sim_cancel(UNIT *uptr);
@ -124,54 +124,50 @@ extern int32 common;
extern uint8 GetBYTEWrapper(register uint32 Addr);
extern UNIT cpu_unit;
/* the following variables define state for the SIMH pseudo device */
/* SIMH pseudo device status registers */
/* ZSDOS clock definitions */
int32 ClockZSDOSDelta = 0; /* delta between real clock and Altair clock */
int32 setClockZSDOSPos = 0; /* determines state for receiving address of parameter block */
int32 setClockZSDOSAdr = 0; /* address in M of 6 byte parameter block for setting time */
int32 getClockZSDOSPos = 0; /* determines state for sending clock information */
static int32 ClockZSDOSDelta = 0; /* delta between real clock and Altair clock */
static int32 setClockZSDOSPos = 0; /* determines state for receiving address of parameter block */
static int32 setClockZSDOSAdr = 0; /* address in M of 6 byte parameter block for setting time */
static int32 getClockZSDOSPos = 0; /* determines state for sending clock information */
/* CPM3 clock definitions */
int32 ClockCPM3Delta = 0; /* delta between real clock and Altair clock */
int32 setClockCPM3Pos = 0; /* determines state for receiving address of parameter block */
int32 setClockCPM3Adr = 0; /* address in M of 5 byte parameter block for setting time */
int32 getClockCPM3Pos = 0; /* determines state for sending clock information */
int32 daysCPM3SinceOrg = 0; /* days since 1 Jan 1978 */
static int32 ClockCPM3Delta = 0; /* delta between real clock and Altair clock */
static int32 setClockCPM3Pos = 0; /* determines state for receiving address of parameter block */
static int32 setClockCPM3Adr = 0; /* address in M of 5 byte parameter block for setting time */
static int32 getClockCPM3Pos = 0; /* determines state for sending clock information */
static int32 daysCPM3SinceOrg = 0; /* days since 1 Jan 1978 */
int32 timerDelta = 100; /* interrupt every 100 ms */
int32 tmpTimerDelta;
uint32 timeOfNextInterrupt;
/* interrupt related */
static uint32 timeOfNextInterrupt; /* time when next interrupt is scheduled */
int32 timerInterrupt = FALSE; /* timer interrupt pending */
int32 timerInterruptHandler = 0x0fc00;/* default address of interrupt handling routine */
int32 tmpTimerInterruptHandler;
int32 setTimerDeltaPos = 0; /* determines state for receiving timerDelta */
int32 setTimerInterruptAdrPos = 0; /* determines state for receiving timerInterruptHandler */
int32 markTimeSP = 0; /* stack pointer for timer stack */
int32 versionPos = 0; /* determines state for sending device identifier */
int32 lastCPMStatus = 0; /* result of last attachCPM command */
int32 lastCommand = 0; /* most recent command processed on port 0xfeh */
int32 getCommonPos = 0; /* determines state for sending the 'common' register */
int32 warnLevelSIO = 3; /* display at most 'warnLevelSIO' times the same warning */
int32 warnUnattachedPTP = 0; /* display a warning message if < warnLevel and SIO set to
static int32 setTimerInterruptAdrPos= 0; /* determines state for receiving timerInterruptHandler */
static int32 timerDelta = 100; /* interrupt every 100 ms */
static int32 setTimerDeltaPos = 0; /* determines state for receiving timerDelta */
/* stop watch and timer related */
static uint32 stopWatchDelta = 0; /* stores elapsed time of stop watch */
static int32 getStopWatchDeltaPos = 0; /* determines the state for receiving stopWatchDelta */
static uint32 stopWatchNow = 0; /* stores starting time of stop watch */
static int32 markTimeSP = 0; /* stack pointer for timer stack */
/* miscellaneous */
static int32 versionPos = 0; /* determines state for sending device identifier */
static int32 lastCPMStatus = 0; /* result of last attachCPM command */
static int32 lastCommand = 0; /* most recent command processed on port 0xfeh */
static int32 getCommonPos = 0; /* determines state for sending the 'common' register */
/* SIO status registers */
static int32 warnLevelSIO = 3; /* display at most 'warnLevelSIO' times the same warning */
static int32 warnUnattachedPTP = 0; /* display a warning message if < warnLevel and SIO set to
VERBOSE and output to PTP without an attached file */
int32 warnUnattachedPTR = 0; /* display a warning message if < warnLevel and SIO set to
static int32 warnUnattachedPTR = 0; /* display a warning message if < warnLevel and SIO set to
VERBOSE and attempt to read from PTR without an attached file */
int32 warnPTREOF = 0; /* display a warning message if < warnLevel and SIO set to
static int32 warnPTREOF = 0; /* display a warning message if < warnLevel and SIO set to
VERBOSE and attempt to read from PTR past EOF */
int32 warnUnassignedPort = 0; /* display a warning message if < warnLevel and SIO set to
static int32 warnUnassignedPort = 0; /* display a warning message if < warnLevel and SIO set to
VERBOSE andattempt to perform IN or OUT on an unassigned PORT */
char messageBuffer[256];
void printMessage(void) {
printf(messageBuffer);
if (sim_log) {
fprintf(sim_log, messageBuffer);
}
}
/* 2SIO Standard I/O Data Structures */
struct sio_terminal {
int32 data; /* data for this terminal */
int32 status; /* status information for this terminal */
@ -182,16 +178,17 @@ struct sio_terminal {
typedef struct sio_terminal SIO_TERMINAL;
SIO_TERMINAL sio_terminals[Terminals] = { {0, 0, 0x10, 0x11, 0x02},
static SIO_TERMINAL sio_terminals[Terminals] =
{ {0, 0, 0x10, 0x11, 0x02},
{0, 0, 0x14, 0x15, 0x00},
{0, 0, 0x16, 0x17, 0x00},
{0, 0, 0x18, 0x19, 0x00} };
TMLN TerminalLines[Terminals] = { {0} }; /* four terminals */
TMXR altairTMXR = {Terminals, 0, 0 }; /* mux descriptor */
static TMLN TerminalLines[Terminals] = { {0} }; /* four terminals */
static TMXR altairTMXR = {Terminals, 0, 0 }; /* mux descriptor */
UNIT sio_unit = { UDATA (&sio_svc, UNIT_ATTABLE, 0), KBD_POLL_WAIT };
static UNIT sio_unit = { UDATA (&sio_svc, UNIT_ATTABLE, 0), KBD_POLL_WAIT };
REG sio_reg[] = {
static REG sio_reg[] = {
{ HRDATA (DATA0, sio_terminals[0].data, 8) },
{ HRDATA (STAT0, sio_terminals[0].status, 8) },
{ HRDATA (DATA1, sio_terminals[1].data, 8) },
@ -207,7 +204,7 @@ REG sio_reg[] = {
{ DRDATA (WUPORT, warnUnassignedPort, 32) },
{ NULL } };
MTAB sio_mod[] = {
static MTAB sio_mod[] = {
{ UNIT_ANSI, 0, "TTY", "TTY", NULL }, /* keep bit 8 as is for output */
{ UNIT_ANSI, UNIT_ANSI, "ANSI", "ANSI", NULL }, /* set bit 8 to 0 before output */
{ UNIT_UPPER, 0, "ALL", "ALL", NULL }, /* do not change case of input characters */
@ -223,68 +220,80 @@ DEVICE sio_dev = {
"SIO", &sio_unit, sio_reg, sio_mod,
1, 10, 31, 1, 8, 8,
NULL, NULL, &sio_reset,
NULL, &sio_attach, &sio_detach, NULL, 0 };
NULL, &sio_attach, &sio_detach, NULL, 0, NULL, NULL };
UNIT ptr_unit = { UDATA (NULL, UNIT_SEQ + UNIT_ATTABLE + UNIT_ROABLE, 0),
static UNIT ptr_unit = { UDATA (NULL, UNIT_SEQ + UNIT_ATTABLE + UNIT_ROABLE, 0),
KBD_POLL_WAIT };
REG ptr_reg[] = {
static REG ptr_reg[] = {
{ HRDATA (DATA, ptr_unit.buf, 8) },
{ HRDATA (STAT, ptr_unit.u3, 8) },
{ DRDATA (POS, ptr_unit.pos, 31) },
{ DRDATA (POS, ptr_unit.pos, 32) },
{ NULL } };
DEVICE ptr_dev = {
"PTR", &ptr_unit, ptr_reg, NULL,
1, 10, 31, 1, 8, 8,
NULL, NULL, &ptr_reset,
NULL, NULL, NULL, NULL, 0 };
NULL, NULL, NULL, NULL, 0, NULL, NULL };
UNIT ptp_unit = { UDATA (NULL, UNIT_SEQ + UNIT_ATTABLE, 0),
static UNIT ptp_unit = { UDATA (NULL, UNIT_SEQ + UNIT_ATTABLE, 0),
KBD_POLL_WAIT };
REG ptp_reg[] = {
static REG ptp_reg[] = {
{ HRDATA (DATA, ptp_unit.buf, 8) },
{ HRDATA (STAT, ptp_unit.u3, 8) },
{ DRDATA (POS, ptp_unit.pos, 31) },
{ DRDATA (POS, ptp_unit.pos, 32) },
{ NULL } };
DEVICE ptp_dev = {
"PTP", &ptp_unit, ptp_reg, NULL,
1, 10, 31, 1, 8, 8,
NULL, NULL, &ptp_reset,
NULL, NULL, NULL, NULL, 0 };
NULL, NULL, NULL, NULL, 0, NULL, NULL };
/* Synthetic device SIMH for communication
between Altair and SIMH environment using port 0xfe */
UNIT simh_unit = { UDATA (&simh_svc, 0, 0), KBD_POLL_WAIT };
static UNIT simh_unit = { UDATA (&simh_svc, 0, 0), KBD_POLL_WAIT };
REG simh_reg[] = {
{ DRDATA (CZD, ClockZSDOSDelta, 31) },
static REG simh_reg[] = {
{ DRDATA (CZD, ClockZSDOSDelta, 32) },
{ DRDATA (SCZP, setClockZSDOSPos, 8), REG_RO },
{ HRDATA (SCZA, setClockZSDOSAdr, 16), REG_RO },
{ DRDATA (GCZP, getClockZSDOSPos, 8), REG_RO },
{ HRDATA (SCZA, setClockZSDOSAdr, 17), REG_RO },
{ DRDATA (CC3D, ClockCPM3Delta, 31) },
{ DRDATA (TIMD, timerDelta, 31) },
{ DRDATA (CC3D, ClockCPM3Delta, 32) },
{ DRDATA (SC3DP, setClockCPM3Pos, 8), REG_RO },
{ HRDATA (SC3DA, setClockCPM3Adr, 16), REG_RO },
{ DRDATA (GC3DP, getClockCPM3Pos, 8), REG_RO },
{ DRDATA (D3DO, daysCPM3SinceOrg, 32), REG_RO },
{ DRDATA (TOFNI, timeOfNextInterrupt, 32), REG_RO },
{ DRDATA (TIMI, timerInterrupt, 3) },
{ HRDATA (TIMH, timerInterruptHandler, 17) },
{ DRDATA (SCC3P, setClockCPM3Pos, 8), REG_RO },
{ DRDATA (GCC3P, getClockCPM3Pos, 8), REG_RO },
{ HRDATA (SCC3A, setClockCPM3Adr, 17), REG_RO },
{ HRDATA (TIMH, timerInterruptHandler, 16) },
{ DRDATA (STIAP, setTimerInterruptAdrPos,8), REG_RO },
{ DRDATA (TIMD, timerDelta, 32) },
{ DRDATA (STDP, setTimerDeltaPos, 8), REG_RO },
{ DRDATA (STPDT, stopWatchDelta, 32), REG_RO },
{ DRDATA (STPOS, getStopWatchDeltaPos, 8), REG_RO },
{ DRDATA (STPNW, stopWatchNow, 32), REG_RO },
{ DRDATA (MTSP, markTimeSP, 8), REG_RO },
{ DRDATA (VP, versionPos, 8), REG_RO },
{ DRDATA (CP, getCommonPos, 8), REG_RO },
{ DRDATA (LC, lastCommand, 8), REG_RO },
{ DRDATA (VPOS, versionPos, 8), REG_RO },
{ DRDATA (LCPMS, lastCPMStatus, 8), REG_RO },
{ DRDATA (LCMD, lastCommand, 8), REG_RO },
{ DRDATA (CPOS, getCommonPos, 8), REG_RO },
{ NULL } };
MTAB simh_mod[] = {
static MTAB simh_mod[] = {
/* quiet, no warning messages */
{ UNIT_SIMH_VERBOSE, 0, "QUIET", "QUIET", NULL },
/* verbose, display warning messages */
{ UNIT_SIMH_VERBOSE, UNIT_SIMH_VERBOSE, "VERBOSE", "VERBOSE", NULL },
/* quiet, no warning messages */
/* timer generated interrupts are off */
{ UNIT_SIMH_TIMERON, 0, "TIMEROFF", "TIMEROFF", &simh_dev_set_timeroff },
/* verbose, display warning messages */
/* timer generated interrupts are on */
{ UNIT_SIMH_TIMERON, UNIT_SIMH_TIMERON, "TIMERON", "TIMERON", &simh_dev_set_timeron },
{ 0 } };
@ -292,22 +301,30 @@ DEVICE simh_device = {
"SIMH", &simh_unit, simh_reg, simh_mod,
1, 10, 31, 1, 16, 4,
NULL, NULL, &simh_dev_reset,
NULL, NULL, NULL, NULL, 0 };
NULL, NULL, NULL, NULL, 0, NULL, NULL };
char messageBuffer[256];
void resetSIOWarningFlags(void) {
void printMessage(void) {
printf(messageBuffer);
if (sim_log) {
fprintf(sim_log, messageBuffer);
}
}
static void resetSIOWarningFlags(void) {
warnUnattachedPTP = 0;
warnUnattachedPTR = 0;
warnPTREOF = 0;
warnUnassignedPort = 0;
}
t_stat sio_set_verbose(UNIT *uptr, int32 value, char *cptr, void *desc) {
static t_stat sio_set_verbose(UNIT *uptr, int32 value, char *cptr, void *desc) {
resetSIOWarningFlags();
return SCPE_OK;
}
t_stat sio_attach(UNIT *uptr, char *cptr) {
static t_stat sio_attach(UNIT *uptr, char *cptr) {
int32 i;
for (i = 0; i < Terminals; i++) {
altairTMXR.ldsc[i] = &TerminalLines[i];
@ -316,25 +333,25 @@ t_stat sio_attach(UNIT *uptr, char *cptr) {
return tmxr_attach(&altairTMXR, uptr, cptr); /* attach mux */
}
void reset_sio_terminals(int32 useDefault) {
static void reset_sio_terminals(const int32 useDefault) {
int32 i;
for (i = 0; i < Terminals; i++) {
sio_terminals[i].status = useDefault ? sio_terminals[i].defaultStatus : 0; /* Status */
sio_terminals[i].data = 0x00; /* Data */
sio_terminals[i].status = useDefault ? sio_terminals[i].defaultStatus : 0; /* status */
sio_terminals[i].data = 0x00; /* data */
}
}
/* Detach */
t_stat sio_detach(UNIT *uptr) {
/* detach */
static t_stat sio_detach(UNIT *uptr) {
reset_sio_terminals(TRUE);
return tmxr_detach(&altairTMXR, uptr);
}
/* Service routines to handle simulator functions */
/* service routines to handle simulator functions */
/* service routine - actually gets char & places in buffer */
t_stat sio_svc(UNIT *uptr) {
static t_stat sio_svc(UNIT *uptr) {
int32 temp;
sim_activate(&sio_unit, sio_unit.wait); /* continue poll */
@ -354,16 +371,16 @@ t_stat sio_svc(UNIT *uptr) {
if ((temp = sim_poll_kbd()) < SCPE_KFLAG) {
return temp; /* no char or error? */
}
sio_terminals[0].data = temp & 0xff; /* Save char */
sio_terminals[0].status |= 0x01; /* Set status */
sio_terminals[0].data = temp & 0xff; /* save character */
sio_terminals[0].status |= 0x01; /* set status */
}
return SCPE_OK;
}
/* Reset routines */
/* reset routines */
t_stat sio_reset(DEVICE *dptr) {
static t_stat sio_reset(DEVICE *dptr) {
int32 i;
resetSIOWarningFlags();
if (sio_unit.flags & UNIT_ATT) {
@ -381,7 +398,7 @@ t_stat sio_reset(DEVICE *dptr) {
return SCPE_OK;
}
t_stat ptr_reset(DEVICE *dptr) {
static t_stat ptr_reset(DEVICE *dptr) {
resetSIOWarningFlags();
ptr_unit.buf = 0;
ptr_unit.u3 = 0;
@ -393,7 +410,7 @@ t_stat ptr_reset(DEVICE *dptr) {
return SCPE_OK;
}
t_stat ptp_reset(DEVICE *dptr) {
static t_stat ptp_reset(DEVICE *dptr) {
resetSIOWarningFlags();
ptp_unit.buf = 0;
ptp_unit.u3 = 0x02;
@ -415,7 +432,7 @@ t_stat ptp_reset(DEVICE *dptr) {
2) SIO not attached to a port (i.e. "regular" console I/O)
*/
int32 sio0s(int32 port, int32 io, int32 data) {
int32 sio0s(const int32 port, const int32 io, const int32 data) {
int32 ti;
for (ti = 0; ti < Terminals; ti++) {
if (sio_terminals[ti].statusPort == port) {
@ -449,7 +466,7 @@ int32 sio0s(int32 port, int32 io, int32 data) {
}
}
int32 sio0d(int32 port, int32 io, int32 data) {
int32 sio0d(const int32 port, const int32 io, const int32 data) {
int32 ti;
for (ti = 0; ti < Terminals; ti++) {
if (sio_terminals[ti].dataPort == port) {
@ -474,22 +491,20 @@ int32 sio0d(int32 port, int32 io, int32 data) {
return (sio_unit.flags & UNIT_UPPER) ? toupper(sio_terminals[ti].data) : sio_terminals[ti].data;
}
else { /* OUT */
if (sio_unit.flags & UNIT_ANSI) {
data &= 0x7f;
}
int32 d = sio_unit.flags & UNIT_ANSI ? data & 0x7f : data;
if (sio_unit.flags & UNIT_ATT) {
tmxr_putc_ln(altairTMXR.ldsc[ti], data);
tmxr_putc_ln(altairTMXR.ldsc[ti], d);
}
else {
sim_putchar(data);
sim_putchar(d);
}
return 0; /* ignored since OUT */
}
}
/* Port 2 controls the PTR/PTP devices */
/* port 2 controls the PTR/PTP devices */
int32 sio1s(int32 port, int32 io, int32 data) {
int32 sio1s(const int32 port, const int32 io, const int32 data) {
if (io == 0) {
/* reset I bit iff PTR unit not attached or no more data available. */
/* O bit is always set since write always possible. */
@ -500,7 +515,7 @@ int32 sio1s(int32 port, int32 io, int32 data) {
}
return 0x02;
}
return (ptr_unit.u3 != 0) ? 0x02 : 0x03;
return ptr_unit.u3 ? 0x02 : 0x03;
}
else { /* OUT */
if (data == 0x03) {
@ -515,7 +530,7 @@ int32 sio1s(int32 port, int32 io, int32 data) {
}
}
int32 sio1d(int32 port, int32 io, int32 data) {
int32 sio1d(const int32 port, const int32 io, const int32 data) {
int32 temp;
if (io == 0) { /* IN */
if (ptr_unit.u3) { /* no more data available */
@ -552,7 +567,7 @@ int32 sio1d(int32 port, int32 io, int32 data) {
}
}
int32 nulldev(int32 port, int32 io, int32 data) {
int32 nulldev(const int32 port, const int32 io, const int32 data) {
if ((sio_unit.flags & UNIT_SIO_VERBOSE) && (warnUnassignedPort < warnLevelSIO)) {
warnUnassignedPort++;
if (io == 0) {
@ -565,20 +580,20 @@ int32 nulldev(int32 port, int32 io, int32 data) {
return io == 0 ? 0xff : 0;
}
int32 sr_dev(int32 port, int32 io, int32 data) {
int32 sr_dev(const int32 port, const int32 io, const int32 data) {
return io == 0 ? SR : 0;
}
int32 toBCD(int32 x) {
static int32 toBCD(const int32 x) {
return (x / 10) * 16 + (x % 10);
}
int32 fromBCD(int32 x) {
static int32 fromBCD(const int32 x) {
return 10 * ((0xf0 & x) >> 4) + (0x0f & x);
}
/* Z80 or 8080 programs communicate with the SIMH pseudo device via port 0xfe.
The principles are as follows:
The following principles apply:
1) For commands that do not require parameters and do not return results
ld a,<cmd>
@ -610,38 +625,43 @@ int32 fromBCD(int32 x) {
*/
#define splimit 10
#define printTimeCmd 0 /* print the current time in milliseconds */
#define startTimerCmd 1 /* start a new timer on the top of the timer stack */
#define stopTimerCmd 2 /* stop timer on top of timer stack and show time difference */
#define resetPTRCmd 3 /* reset the PTR device */
#define attachPTRCmd 4 /* attach the PTR device */
#define detachPTRCmd 5 /* detach the PTR device */
#define getSIMHVersionCMD 6 /* get the current version of the SIMH pseudo device */
#define getClockZSDOSCmd 7 /* get the current time in ZSDOS format */
#define setClockZSDOSCmd 8 /* set the current time in ZSDOS format */
#define getClockCPM3Cmd 9 /* get the current time in CP/M 3 format */
#define setClockCPM3Cmd 10 /* set the current time in CP/M 3 format */
#define getBankSelectCmd 11 /* get the selected bank */
#define setBankSelectCmd 12 /* set the selected bank */
#define getCommonCmd 13 /* get the base address of the common memory segment */
#define resetSIMHInterfaceCmd 14 /* reset the SIMH pseudo device */
#define showTimerCmd 15 /* show time difference to timer on top of stack */
#define attachPTPCmd 16 /* attach PTP to the file with name at beginning of CP/M command line */
#define detachPTPCmd 17 /* detach PTP */
#define hasBankedMemoryCmd 18 /* determines whether machine has banked memory */
#define setZ80CPUCmd 19 /* set the CPU to a Z80 */
#define set8080CPUCmd 20 /* set the CPU to an 8080 */
#define startTimerInterruptsCmd 21 /* statr timer interrupts */
#define stopTimerInterruptsCmd 22 /* stop timer interrupts */
#define setTimerDeltaCmd 23 /* set the timer interval in which interrupts occur */
#define setTimerInterruptAdrCmd 24 /* set the address to call by timer interrupts */
#define cpmCommandLineLength 128
struct tm *currentTime = NULL;
uint32 markTime[splimit];
char version[] = "SIMH002";
enum simhPseudoDeviceCommands { /* do not change order or remove commands, add only at the end */
printTimeCmd, /* 0 print the current time in milliseconds */
startTimerCmd, /* 1 start a new timer on the top of the timer stack */
stopTimerCmd, /* 2 stop timer on top of timer stack and show time difference */
resetPTRCmd, /* 3 reset the PTR device */
attachPTRCmd, /* 4 attach the PTR device */
detachPTRCmd, /* 5 detach the PTR device */
getSIMHVersionCmd, /* 6 get the current version of the SIMH pseudo device */
getClockZSDOSCmd, /* 7 get the current time in ZSDOS format */
setClockZSDOSCmd, /* 8 set the current time in ZSDOS format */
getClockCPM3Cmd, /* 9 get the current time in CP/M 3 format */
setClockCPM3Cmd, /* 10 set the current time in CP/M 3 format */
getBankSelectCmd, /* 11 get the selected bank */
setBankSelectCmd, /* 12 set the selected bank */
getCommonCmd, /* 13 get the base address of the common memory segment */
resetSIMHInterfaceCmd, /* 14 reset the SIMH pseudo device */
showTimerCmd, /* 15 show time difference to timer on top of stack */
attachPTPCmd, /* 16 attach PTP to the file with name at beginning of CP/M command line*/
detachPTPCmd, /* 17 detach PTP */
hasBankedMemoryCmd, /* 18 determines whether machine has banked memory */
setZ80CPUCmd, /* 19 set the CPU to a Z80 */
set8080CPUCmd, /* 20 set the CPU to an 8080 */
startTimerInterruptsCmd,/* 21 start timer interrupts */
stopTimerInterruptsCmd, /* 22 stop timer interrupts */
setTimerDeltaCmd, /* 23 set the timer interval in which interrupts occur */
setTimerInterruptAdrCmd,/* 24 set the address to call by timer interrupts */
resetStopWatchCmd, /* 25 reset the millisecond stop watch */
readStopWatchCmd /* 26 read the millisecond stop watch */
};
t_stat simh_dev_reset(DEVICE *dptr) {
#define cpmCommandLineLength 128
#define splimit 10 /* stack depth of timer stack */
static uint32 markTime[splimit]; /* timer stack */
static struct tm *currentTime = NULL;
static char version[] = "SIMH002";
static t_stat simh_dev_reset(DEVICE *dptr) {
currentTime = NULL;
ClockZSDOSDelta = 0;
setClockZSDOSPos = 0;
@ -649,6 +669,7 @@ t_stat simh_dev_reset(DEVICE *dptr) {
ClockCPM3Delta = 0;
setClockCPM3Pos = 0;
getClockCPM3Pos = 0;
getStopWatchDeltaPos = 0;
getCommonPos = 0;
setTimerDeltaPos = 0;
setTimerInterruptAdrPos = 0;
@ -663,24 +684,30 @@ t_stat simh_dev_reset(DEVICE *dptr) {
return SCPE_OK;
}
t_stat simh_dev_set_timeron(UNIT *uptr, int32 val, char *cptr, void *desc) {
static void warnNoRealTimeClock(void) {
if (simh_unit.flags & UNIT_SIMH_VERBOSE) {
printf("Sorry - no real time clock available.\n");
}
}
static t_stat simh_dev_set_timeron(UNIT *uptr, int32 value, char *cptr, void *desc) {
if (rtc_avail) {
timeOfNextInterrupt = sim_os_msec() + timerDelta;
return sim_activate(&simh_unit, simh_unit.wait); /* activate unit */
}
else {
printf("Sorry - no real time clock available.\n");
warnNoRealTimeClock();
return SCPE_ARG;
}
}
t_stat simh_dev_set_timeroff(UNIT *uptr, int32 val, char *cptr, void *desc) {
static t_stat simh_dev_set_timeroff(UNIT *uptr, int32 value, char *cptr, void *desc) {
timerInterrupt = FALSE;
sim_cancel(&simh_unit);
return SCPE_OK;
}
t_stat simh_svc(UNIT *uptr) {
static t_stat simh_svc(UNIT *uptr) {
uint32 n = sim_os_msec();
if (n >= timeOfNextInterrupt) {
timerInterrupt = TRUE;
@ -695,8 +722,8 @@ t_stat simh_svc(UNIT *uptr) {
return SCPE_OK;
}
/* The CP/M commandline is used as the name of a file and UNIT* uptr is attached to it */
void attachCPM(UNIT *uptr) {
/* The CP/M commandline is used as the name of a file and UNIT* uptr is attached to it. */
static void attachCPM(UNIT *uptr) {
char cpmCommandLine[cpmCommandLineLength];
uint32 i, len = (GetBYTEWrapper(0x80) & 0x7f) - 1; /* 0x80 contains length of commandline, discard first char */
for (i = 0; i < len; i++) {
@ -716,7 +743,7 @@ void attachCPM(UNIT *uptr) {
}
/* setClockZSDOSAdr points to 6 byte block in M: YY MM DD HH MM SS in BCD notation */
void setClockZSDOS(void) {
static void setClockZSDOS(void) {
struct tm newTime;
int32 year = fromBCD(GetBYTEWrapper(setClockZSDOSAdr));
newTime.tm_year = year < 50 ? year + 100 : year;
@ -731,7 +758,7 @@ void setClockZSDOS(void) {
#define secondsPerMinute 60
#define secondsPerHour (60 * secondsPerMinute)
#define secondsPerDay (24 * secondsPerHour)
time_t mkCPM3Origin(void) {
static time_t mkCPM3Origin(void) {
struct tm date;
date.tm_year = 77;
date.tm_mon = 11;
@ -747,7 +774,7 @@ time_t mkCPM3Origin(void) {
2 BCD byte: HH
3 BCD byte: MM
4 BCD byte: SS */
void setClockCPM3(void) {
static void setClockCPM3(void) {
ClockCPM3Delta = mkCPM3Origin() +
(GetBYTEWrapper(setClockCPM3Adr) + GetBYTEWrapper(setClockCPM3Adr + 1) * 256) * secondsPerDay +
fromBCD(GetBYTEWrapper(setClockCPM3Adr + 2)) * secondsPerHour +
@ -755,12 +782,13 @@ void setClockCPM3(void) {
fromBCD(GetBYTEWrapper(setClockCPM3Adr + 4)) - time(NULL);
}
int32 simh_in(void) {
static int32 simh_in(const int32 port) {
int32 result;
switch(lastCommand) {
case attachPTRCmd:
case attachPTPCmd:
result = lastCPMStatus;
lastCommand = 0;
break;
case getClockZSDOSCmd:
if (currentTime) {
@ -768,40 +796,67 @@ int32 simh_in(void) {
case 0:
result = toBCD(currentTime -> tm_year > 99 ?
currentTime -> tm_year - 100 : currentTime -> tm_year);
getClockZSDOSPos = 1;
break;
case 1:
result = toBCD(currentTime -> tm_mon + 1);
getClockZSDOSPos = 2;
break;
case 2:
result = toBCD(currentTime -> tm_mday);
getClockZSDOSPos = 3;
break;
case 3:
result = toBCD(currentTime -> tm_hour);
getClockZSDOSPos = 4;
break;
case 4:
result = toBCD(currentTime -> tm_min);
getClockZSDOSPos = 5;
break;
case 5:
result = toBCD(currentTime -> tm_sec);
getClockZSDOSPos = lastCommand = 0;
break;
case 1: result = toBCD(currentTime -> tm_mon + 1); break;
case 2: result = toBCD(currentTime -> tm_mday); break;
case 3: result = toBCD(currentTime -> tm_hour); break;
case 4: result = toBCD(currentTime -> tm_min); break;
case 5: result = toBCD(currentTime -> tm_sec); break;
default: result = 0;
}
getClockZSDOSPos++;
}
else {
result = 0;
result = getClockZSDOSPos = lastCommand = 0;
}
break;
case getClockCPM3Cmd:
if (currentTime) {
switch(getClockCPM3Pos) {
case 0: result = daysCPM3SinceOrg & 0xff; break;
case 1: result = (daysCPM3SinceOrg >> 8) & 0xff; break;
case 2: result = toBCD(currentTime -> tm_hour); break;
case 3: result = toBCD(currentTime -> tm_min); break;
case 4: result = toBCD(currentTime -> tm_sec); break;
default: result = 0;
case 0:
result = daysCPM3SinceOrg & 0xff;
getClockCPM3Pos = 1;
break;
case 1:
result = (daysCPM3SinceOrg >> 8) & 0xff;
getClockCPM3Pos = 2;
break;
case 2:
result = toBCD(currentTime -> tm_hour);
getClockCPM3Pos = 3;
break;
case 3:
result = toBCD(currentTime -> tm_min);
getClockCPM3Pos = 4;
break;
case 4:
result = toBCD(currentTime -> tm_sec);
getClockCPM3Pos = lastCommand = 0;
break;
}
getClockCPM3Pos++;
}
else {
result = 0;
result = getClockCPM3Pos = lastCommand = 0;
}
break;
case getSIMHVersionCMD:
case getSIMHVersionCmd:
result = version[versionPos++];
if (result == 0) {
versionPos = 0;
versionPos = lastCommand = 0;
}
break;
case getBankSelectCmd:
@ -814,6 +869,7 @@ int32 simh_in(void) {
message1("Get selected bank ignored for non-banked memory.");
}
}
lastCommand = 0;
break;
case getCommonCmd:
if (getCommonPos == 0) {
@ -822,48 +878,56 @@ int32 simh_in(void) {
}
else {
result = (common >> 8) & 0xff;
getCommonPos = 0;
getCommonPos = lastCommand = 0;
}
break;
case hasBankedMemoryCmd:
result = cpu_unit.flags & UNIT_BANKED ? MAXBANKS : 0;
lastCommand = 0;
break;
case readStopWatchCmd:
if (getStopWatchDeltaPos == 0) {
result = stopWatchDelta & 0xff;
getStopWatchDeltaPos = 1;
}
else {
result = (stopWatchDelta >> 8) & 0xff;
getStopWatchDeltaPos = lastCommand = 0;
}
break;
default:
result = 0;
if (simh_unit.flags & UNIT_SIMH_VERBOSE) {
message2("Unnecessary IN from SIMH pseudo device on port %03xh ignored.\n",
port);
}
result = lastCommand = 0;
}
return result;
}
int32 simh_out(int32 data) {
uint32 delta;
static int32 simh_out(const int32 port, const int32 data) {
time_t now;
switch(lastCommand) {
case setClockZSDOSCmd:
switch(setClockZSDOSPos) {
case 0:
if (setClockZSDOSPos == 0) {
setClockZSDOSAdr = data;
setClockZSDOSPos++;
break;
case 1:
setClockZSDOSAdr += (data << 8);
setClockZSDOSPos = 1;
}
else {
setClockZSDOSAdr |= (data << 8);
setClockZSDOS();
lastCommand = 0;
break;
default:;
setClockZSDOSPos = lastCommand = 0;
}
break;
case setClockCPM3Cmd:
switch(setClockCPM3Pos) {
case 0:
if (setClockCPM3Pos == 0) {
setClockCPM3Adr = data;
setClockCPM3Pos++;
break;
case 1:
setClockCPM3Adr += (data << 8);
setClockCPM3Pos = 1;
}
else {
setClockCPM3Adr |= (data << 8);
setClockCPM3();
lastCommand = 0;
break;
default:;
setClockCPM3Pos = lastCommand = 0;
}
break;
case setBankSelectCmd:
@ -876,29 +940,23 @@ int32 simh_out(int32 data) {
lastCommand = 0;
break;
case setTimerDeltaCmd:
switch(setTimerDeltaPos) {
case 0:
tmpTimerDelta = data;
setTimerDeltaPos++;
break;
case 1:
timerDelta = tmpTimerDelta + (data << 8);
lastCommand = 0;
break;
default:;
if (setTimerDeltaPos == 0) {
timerDelta = data;
setTimerDeltaPos = 1;
}
else {
timerDelta |= (data << 8);
setTimerDeltaPos = lastCommand = 0;
}
break;
case setTimerInterruptAdrCmd:
switch(setTimerInterruptAdrPos) {
case 0:
tmpTimerInterruptHandler = data;
setTimerInterruptAdrPos++;
break;
case 1:
timerInterruptHandler = tmpTimerInterruptHandler + (data << 8);
lastCommand = 0;
break;
default:;
if (setTimerInterruptAdrPos == 0) {
timerInterruptHandler = data;
setTimerInterruptAdrPos = 1;
}
else {
timerInterruptHandler |= (data << 8);
setTimerInterruptAdrPos = lastCommand = 0;
}
break;
default:
@ -908,6 +966,9 @@ int32 simh_out(int32 data) {
if (rtc_avail) {
message2("Current time in milliseconds = %d.\n", sim_os_msec());
}
else {
warnNoRealTimeClock();
}
break;
case startTimerCmd: /* create a new timer on top of stack */
if (rtc_avail) {
@ -918,17 +979,23 @@ int32 simh_out(int32 data) {
message1("Timer stack overflow.\n");
}
}
else {
warnNoRealTimeClock();
}
break;
case stopTimerCmd: /* stop timer on top of stack and show time difference */
if (rtc_avail) {
if (markTimeSP > 0) {
delta = sim_os_msec() - markTime[--markTimeSP];
uint32 delta = sim_os_msec() - markTime[--markTimeSP];
message2("Timer stopped. Elapsed time in milliseconds = %d.\n", delta);
}
else {
message1("No timer active.\n");
}
}
else {
warnNoRealTimeClock();
}
break;
case resetPTRCmd: /* reset ptr device */
ptr_reset(NULL);
@ -939,7 +1006,7 @@ int32 simh_out(int32 data) {
case detachPTRCmd: /* detach ptr */
detach_unit(&ptr_unit);
break;
case getSIMHVersionCMD:
case getSIMHVersionCmd:
versionPos = 0;
break;
case getClockZSDOSCmd:
@ -962,10 +1029,9 @@ int32 simh_out(int32 data) {
setClockCPM3Pos = 0;
break;
case getBankSelectCmd:
break;
case setBankSelectCmd:
break;
case getCommonCmd:
case hasBankedMemoryCmd:
break;
case resetSIMHInterfaceCmd:
markTimeSP = 0;
@ -974,13 +1040,16 @@ int32 simh_out(int32 data) {
case showTimerCmd: /* show time difference to timer on top of stack */
if (rtc_avail) {
if (markTimeSP > 0) {
delta = sim_os_msec() - markTime[markTimeSP - 1];
uint32 delta = sim_os_msec() - markTime[markTimeSP - 1];
message2("Timer running. Elapsed in milliseconds = %d.\n", delta);
}
else {
message1("No timer active.\n");
}
}
else {
warnNoRealTimeClock();
}
break;
case attachPTPCmd: /* attach ptp to the file with name at beginning of CP/M command line */
attachCPM(&ptp_unit);
@ -988,8 +1057,6 @@ int32 simh_out(int32 data) {
case detachPTPCmd: /* detach ptp */
detach_unit(&ptp_unit);
break;
case hasBankedMemoryCmd:
break;
case setZ80CPUCmd:
cpu_unit.flags |= UNIT_CHIP;
break;
@ -1012,9 +1079,17 @@ int32 simh_out(int32 data) {
case setTimerInterruptAdrCmd:
setTimerInterruptAdrPos = 0;
break;
case resetStopWatchCmd:
stopWatchNow = rtc_avail ? sim_os_msec() : 0;
break;
case readStopWatchCmd:
getStopWatchDeltaPos = 0;
stopWatchDelta = rtc_avail ? sim_os_msec() - stopWatchNow : 0;
break;
default:
if (simh_unit.flags & UNIT_SIMH_VERBOSE) {
message2("Unknown command (%i) to SIMH pseudo device ignored.\n", data);
message3("Unknown command (%i) to SIMH pseudo device on port %03xh ignored.\n",
data, port);
}
}
}
@ -1022,6 +1097,6 @@ int32 simh_out(int32 data) {
}
/* port 0xfe is a device for communication SIMH <--> Altair machine */
int32 simh_dev(int32 port, int32 io, int32 data) {
return io == 0 ? simh_in() : simh_out(data);
int32 simh_dev(const int32 port, const int32 io, const int32 data) {
return io == 0 ? simh_in(port) : simh_out(port, data);
}

View file

@ -1,6 +1,6 @@
/* altairz80_sys.c: MITS Altair system interface
Copyright (c) 2002, Peter Schorn
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"),
@ -15,7 +15,7 @@
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY 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
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.
@ -40,27 +40,24 @@ extern DEVICE simh_device;
extern DEVICE ptr_dev;
extern DEVICE ptp_dev;
extern int32 saved_PC;
extern char *get_range(char *cptr, t_addr *lo, t_addr *hi, int rdx,
t_addr max, char term);
extern t_value get_uint(char *cptr, int radix, t_value max, t_stat *status);
extern void PutBYTEWrapper(register uint32 Addr, register uint32 Value);
extern void PutBYTEForced(register uint32 Addr, register uint32 Value);
extern uint8 GetBYTEWrapper(register uint32 Addr);
extern int32 addressIsInROM(uint32 Addr);
extern int32 addressExists(uint32 Addr);
extern uint32 ROMLow;
extern uint32 ROMHigh;
extern int32 addressIsInROM(const uint32 Addr);
extern int32 addressExists(const uint32 Addr);
extern void printROMMessage(const uint32 cntROM);
int32 sim_load(FILE *fileref, char *cptr, char *fnam, int32 flag);
int32 fprint_sym(FILE *of, int32 addr, uint32 *val, UNIT *uptr, int32 sw);
int32 checkbase(char ch, char *numString);
int32 numok(char ch, char **numString, int32 minvalue, int32 maxvalue, int32 requireSign, int32 *result);
int32 match(char *pattern, char *input, char *xy, int32 *number, int32 *star, int32 *at,
static int32 checkbase(char ch, const char *numString);
static int32 numok(char ch, const char **numString, const int32 minvalue,
const int32 maxvalue, const int32 requireSign, int32 *result);
static int32 match(const char *pattern, const char *input, char *xyFirst, char *xy, int32 *number, int32 *star, int32 *at,
int32 *hat, int32 *dollar);
int32 parse_X80(char *cptr, int32 addr, uint32 *val, char *Mnemonics[]);
static int32 parse_X80(const char *cptr, const int32 addr, uint32 *val, char *const Mnemonics[]);
int32 parse_sym(char *cptr, int32 addr, UNIT *uptr, uint32 *val, int32 sw);
int32 DAsm(char *S, uint32 *val, int32 useZ80Mnemonics, int32 addr);
int32 checkXY(char xy);
static int32 DAsm(char *S, const uint32 *val, const int32 useZ80Mnemonics, const int32 addr);
static int32 checkXY(const char xy);
/* SCP data structures
sim_name simulator name string
@ -78,14 +75,12 @@ DEVICE *sim_devices[] = { &cpu_dev, &sio_dev, &simh_device, &ptr_dev, &ptp_dev,
char memoryAccessMessage[80];
const char *sim_stop_messages[] = {
"Unknown error",
"Unknown I/O Instruction",
"HALT instruction",
"Breakpoint",
memoryAccessMessage,
"Invalid Opcode" };
static char *Mnemonics8080[] = {
static char *const Mnemonics8080[] = {
/*0/8 1/9 2/A 3/B 4/C 5/D 6/E 7/F */
"NOP", "LXI B,#h", "STAX B", "INX B", "INR B", "DCR B", "MVI B,*h", "RLC", /* 00-07 */
"DB 09h", "DAD B", "LDAX B", "DCX B", "INR C", "DCR C", "MVI C,*h", "RRC", /* 08-0f */
@ -121,7 +116,7 @@ static char *Mnemonics8080[] = {
"RM", "SPHL", "JM #h", "EI", "CM #h", "DB FDh", "CPI *h", "RST 7" /* f8-ff */
};
static char *MnemonicsZ80[256] = {
static char *const MnemonicsZ80[256] = {
/*0/8 1/9 2/A 3/B 4/C 5/D 6/E 7/F */
"NOP", "LD BC,#h", "LD (BC),A", "INC BC", "INC B", "DEC B", "LD B,*h", "RLCA", /* 00-07 */
"EX AF,AF'", "ADD HL,BC", "LD A,(BC)", "DEC BC", "INC C", "DEC C", "LD C,*h", "RRCA", /* 08-0f */
@ -157,7 +152,7 @@ static char *MnemonicsZ80[256] = {
"RET M", "LD SP,HL", "JP M,#h", "EI", "CALL M,#h", "PFX_FD", "CP *h", "RST 38h" /* f8-ff */
};
static char *MnemonicsCB[256] = {
static char *const MnemonicsCB[256] = {
/*0/8 1/9 2/A 3/B 4/C 5/D 6/E 7/F */
"RLC B", "RLC C", "RLC D", "RLC E", "RLC H", "RLC L", "RLC (HL)", "RLC A", /* 00-07 */
"RRC B", "RRC C", "RRC D", "RRC E", "RRC H", "RRC L", "RRC (HL)", "RRC A", /* 08-0f */
@ -193,7 +188,7 @@ static char *MnemonicsCB[256] = {
"SET 7,B", "SET 7,C", "SET 7,D", "SET 7,E", "SET 7,H", "SET 7,L", "SET 7,(HL)", "SET 7,A" /* f8-ff */
};
static char *MnemonicsED[256] = {
static char *const MnemonicsED[256] = {
/*0/8 1/9 2/A 3/B 4/C 5/D 6/E 7/F */
"DB EDh,00h", "DB EDh,01h", "DB EDh,02h", "DB EDh,03h", "DB EDh,04h", "DB EDh,05h", "DB EDh,06h", "DB EDh,07h", /* 00-07 */
"DB EDh,08h", "DB EDh,09h", "DB EDh,0Ah", "DB EDh,0Bh", "DB EDh,0Ch", "DB EDh,0Dh", "DB EDh,0Eh", "DB EDh,0Fh", /* 08-0f */
@ -229,32 +224,32 @@ static char *MnemonicsED[256] = {
"DB EDh,F8h", "DB EDh,F9h", "DB EDh,FAh", "DB EDh,FBh", "DB EDh,FCh", "DB EDh,FDh", "DB EDh,FEh", "DB EDh,FFh" /* f8-ff */
};
static char *MnemonicsXX[256] = {
static char *const MnemonicsXX[256] = {
/*0/8 1/9 2/A 3/B 4/C 5/D 6/E 7/F */
"NOP", "LD BC,#h", "LD (BC),A", "INC BC", "INC B", "DEC B", "LD B,*h", "RLCA", /* 00-07 */
"EX AF,AF'", "ADD I%,BC", "LD A,(BC)", "DEC BC", "INC C", "DEC C", "LD C,*h", "RRCA", /* 08-0f */
"DJNZ $h", "LD DE,#h", "LD (DE),A", "INC DE", "INC D", "DEC D", "LD D,*h", "RLA", /* 10-17 */
"JR $h", "ADD I%,DE", "LD A,(DE)", "DEC DE", "INC E", "DEC E", "LD E,*h", "RRA", /* 18-1f */
"JR NZ,$h", "LD I%,#h", "LD (#h),I%", "INC I%", "INC I%h", "DEC I%h", "LD I%h,*h", "DAA", /* 20-27 */
"JR Z,$h", "ADD I%,I%", "LD I%,(#h)", "DEC I%", "INC I%l", "DEC I%l", "LD I%l,*h", "CPL", /* 28-2f */
"JR NZ,$h", "LD I%,#h", "LD (#h),I%", "INC I%", "INC I%H", "DEC I%H", "LD I%H,*h", "DAA", /* 20-27 */
"JR Z,$h", "ADD I%,I%", "LD I%,(#h)", "DEC I%", "INC I%L", "DEC I%L", "LD I%L,*h", "CPL", /* 28-2f */
"JR NC,$h", "LD SP,#h", "LD (#h),A", "INC SP", "INC (I%+^h)", "DEC (I%+^h)", "LD (I%+^h),*h", "SCF", /* 30-37 */
"JR C,$h", "ADD I%,SP", "LD A,(#h)", "DEC SP", "INC A", "DEC A", "LD A,*h", "CCF", /* 38-3f */
"LD B,B", "LD B,C", "LD B,D", "LD B,E", "LD B,I%h", "LD B,I%l", "LD B,(I%+^h)", "LD B,A", /* 40-47 */
"LD C,B", "LD C,C", "LD C,D", "LD C,E", "LD C,I%h", "LD C,I%l", "LD C,(I%+^h)", "LD C,A", /* 48-4f */
"LD D,B", "LD D,C", "LD D,D", "LD D,E", "LD D,I%h", "LD D,I%l", "LD D,(I%+^h)", "LD D,A", /* 50-57 */
"LD E,B", "LD E,C", "LD E,D", "LD E,E", "LD E,I%h", "LD E,I%l", "LD E,(I%+^h)", "LD E,A", /* 58-5f */
"LD I%h,B", "LD I%h,C", "LD I%h,D", "LD I%h,E", "LD I%h,I%h", "LD I%h,I%l", "LD H,(I%+^h)", "LD I%h,A", /* 60-67 */
"LD I%l,B", "LD I%l,C", "LD I%l,D", "LD I%l,E", "LD I%l,I%h", "LD I%l,I%l", "LD L,(I%+^h)", "LD I%l,A", /* 68-6f */
"LD B,B", "LD B,C", "LD B,D", "LD B,E", "LD B,I%H", "LD B,I%L", "LD B,(I%+^h)", "LD B,A", /* 40-47 */
"LD C,B", "LD C,C", "LD C,D", "LD C,E", "LD C,I%H", "LD C,I%L", "LD C,(I%+^h)", "LD C,A", /* 48-4f */
"LD D,B", "LD D,C", "LD D,D", "LD D,E", "LD D,I%H", "LD D,I%L", "LD D,(I%+^h)", "LD D,A", /* 50-57 */
"LD E,B", "LD E,C", "LD E,D", "LD E,E", "LD E,I%H", "LD E,I%L", "LD E,(I%+^h)", "LD E,A", /* 58-5f */
"LD I%H,B", "LD I%H,C", "LD I%H,D", "LD I%H,E", "LD I%H,I%H", "LD I%H,I%L", "LD H,(I%+^h)", "LD I%H,A", /* 60-67 */
"LD I%L,B", "LD I%L,C", "LD I%L,D", "LD I%L,E", "LD I%L,I%H", "LD I%L,I%L", "LD L,(I%+^h)", "LD I%L,A", /* 68-6f */
"LD (I%+^h),B", "LD (I%+^h),C", "LD (I%+^h),D", "LD (I%+^h),E", "LD (I%+^h),H", "LD (I%+^h),L", "HALT", "LD (I%+^h),A", /* 70-77 */
"LD A,B", "LD A,C", "LD A,D", "LD A,E", "LD A,I%h", "LD A,I%l", "LD A,(I%+^h)", "LD A,A", /* 78-7f */
"ADD A,B", "ADD A,C", "ADD A,D", "ADD A,E", "ADD A,I%h", "ADD A,I%l", "ADD A,(I%+^h)", "ADD A,A", /* 80-87 */
"ADC A,B", "ADC A,C", "ADC A,D", "ADC A,E", "ADC A,I%h", "ADC A,I%l", "ADC A,(I%+^h)", "ADC A,A", /* 88-8f */
"SUB B", "SUB C", "SUB D", "SUB E", "SUB I%h", "SUB I%l", "SUB (I%+^h)", "SUB A", /* 90-97 */
"SBC A,B", "SBC A,C", "SBC A,D", "SBC A,E", "SBC A,I%h", "SBC A,I%l", "SBC A,(I%+^h)", "SBC A,A", /* 98-9f */
"AND B", "AND C", "AND D", "AND E", "AND I%h", "AND I%l", "AND (I%+^h)", "AND A", /* a0-a7 */
"XOR B", "XOR C", "XOR D", "XOR E", "XOR I%h", "XOR I%l", "XOR (I%+^h)", "XOR A", /* a8-af */
"OR B", "OR C", "OR D", "OR E", "OR I%h", "OR I%l", "OR (I%+^h)", "OR A", /* b0-b7 */
"CP B", "CP C", "CP D", "CP E", "CP I%h", "CP I%l", "CP (I%+^h)", "CP A", /* b8-bf */
"LD A,B", "LD A,C", "LD A,D", "LD A,E", "LD A,I%H", "LD A,I%L", "LD A,(I%+^h)", "LD A,A", /* 78-7f */
"ADD A,B", "ADD A,C", "ADD A,D", "ADD A,E", "ADD A,I%H", "ADD A,I%L", "ADD A,(I%+^h)", "ADD A,A", /* 80-87 */
"ADC A,B", "ADC A,C", "ADC A,D", "ADC A,E", "ADC A,I%H", "ADC A,I%L", "ADC A,(I%+^h)", "ADC A,A", /* 88-8f */
"SUB B", "SUB C", "SUB D", "SUB E", "SUB I%H", "SUB I%L", "SUB (I%+^h)", "SUB A", /* 90-97 */
"SBC A,B", "SBC A,C", "SBC A,D", "SBC A,E", "SBC A,I%H", "SBC A,I%L", "SBC A,(I%+^h)", "SBC A,A", /* 98-9f */
"AND B", "AND C", "AND D", "AND E", "AND I%H", "AND I%L", "AND (I%+^h)", "AND A", /* a0-a7 */
"XOR B", "XOR C", "XOR D", "XOR E", "XOR I%H", "XOR I%L", "XOR (I%+^h)", "XOR A", /* a8-af */
"OR B", "OR C", "OR D", "OR E", "OR I%H", "OR I%L", "OR (I%+^h)", "OR A", /* b0-b7 */
"CP B", "CP C", "CP D", "CP E", "CP I%H", "CP I%L", "CP (I%+^h)", "CP A", /* b8-bf */
"RET NZ", "POP BC", "JP NZ,#h", "JP #h", "CALL NZ,#h", "PUSH BC", "ADD A,*h", "RST 00h", /* c8-cf */
"RET Z", "RET", "JP Z,#h", "PFX_CB", "CALL Z,#h", "CALL #h", "ADC A,*h", "RST 08h", /* c8-cf */
"RET NC", "POP DE", "JP NC,#h", "OUT (*h),A", "CALL NC,#h", "PUSH DE", "SUB *h", "RST 10h", /* d0-d7 */
@ -265,7 +260,7 @@ static char *MnemonicsXX[256] = {
"RET M", "LD SP,I%", "JP M,#h", "EI", "CALL M,#h", "PFX_FD", "CP *h", "RST 38h" /* f8-ff */
};
static char *MnemonicsXCB[256] = {
static char *const MnemonicsXCB[256] = {
/*0/8 1/9 2/A 3/B 4/C 5/D 6/E 7/F */
"RLC B", "RLC C", "RLC D", "RLC E", "RLC H", "RLC L", "RLC (I%@h)", "RLC A", /* 00-07 */
"RRC B", "RRC C", "RRC D", "RRC E", "RRC H", "RRC L", "RRC (I%@h)", "RRC A", /* 08-0f */
@ -301,7 +296,7 @@ static char *MnemonicsXCB[256] = {
"SET 7,B", "SET 7,C", "SET 7,D", "SET 7,E", "SET 7,H", "SET 7,L", "SET 7,(I%@h)", "SET 7,A" /* f8-ff */
};
/* Symbolic disassembler
/* symbolic disassembler
Inputs:
*val = instructions to disassemble
@ -316,9 +311,9 @@ static char *MnemonicsXCB[256] = {
*/
int32 DAsm(char *S, uint32 *val, int32 useZ80Mnemonics, int32 addr) {
static int32 DAsm(char *S, const uint32 *val, const int32 useZ80Mnemonics, const int32 addr) {
char R[128], H[10], C = '\0', *T, *P;
uint8 J = 0, Offset;
uint8 J = 0, Offset = 0;
uint16 B = 0;
if (useZ80Mnemonics) {
@ -333,8 +328,7 @@ int32 DAsm(char *S, uint32 *val, int32 useZ80Mnemonics, int32 addr) {
break;
case 0xdd:
case 0xfd:
C = (val[B] == 0xdd) ? 'X' : 'Y';
B++;
C = (val[B++] == 0xdd) ? 'X' : 'Y';
if (val[B] == 0xcb) {
B++;
Offset = val[B++];
@ -411,7 +405,7 @@ int32 DAsm(char *S, uint32 *val, int32 useZ80Mnemonics, int32 addr) {
return(B);
}
/* Symbolic output
/* symbolic output
Inputs:
*of = output stream
@ -440,7 +434,7 @@ int32 fprint_sym(FILE *of, int32 addr, uint32 *val, UNIT *uptr, int32 sw) {
/* numString checks determines the base of the number (ch, *numString)
and returns FALSE if the number is bad */
int32 checkbase(char ch, char *numString) {
static int32 checkbase(char ch, const char *numString) {
int32 decimal = (ch <= '9');
if (toupper(ch) == 'H') {
return FALSE;
@ -453,7 +447,8 @@ int32 checkbase(char ch, char *numString) {
return toupper(ch) == 'H' ? 16 : (decimal ? 10 : FALSE);
}
int32 numok(char ch, char **numString, int32 minvalue, int32 maxvalue, int32 requireSign, int32 *result) {
static int32 numok(char ch, const char **numString, const int32 minvalue,
const int32 maxvalue, const int32 requireSign, int32 *result) {
int32 sign = 1, value = 0, base;
if (requireSign) {
if (ch == '+') {
@ -481,17 +476,19 @@ int32 numok(char ch, char **numString, int32 minvalue, int32 maxvalue, int32 req
return (minvalue <= value) && (value <= maxvalue);
}
int32 match(char *pattern, char *input, char *xy, int32 *number, int32 *star,
static int32 match(const char *pattern, const char *input, char *xyFirst, char *xy, int32 *number, int32 *star,
int32 *at, int32 *hat, int32 *dollar) {
char pat = *pattern++;
char inp = *input++;
while ((pat) && (inp)) {
switch(pat) {
case '_': /* patterns containting '_' should never match */
return FALSE;
case ',':
if (inp == ' ') {
inp = *input++;
continue;
}
} /* otherwise fall through */
case ' ':
if (inp != pat) {
return FALSE;
@ -502,15 +499,25 @@ int32 match(char *pattern, char *input, char *xy, int32 *number, int32 *star,
inp = *input++;
}
continue;
break;
case '%':
inp = toupper(inp);
if ((inp == 'X') || (inp == 'Y')) {
if (*xyFirst) { /* make sure that second '%' corresponds to first */
if (*xyFirst == inp) {
*xy = inp;
}
else {
return FALSE;
}
}
else { /* take note of first '%' for later */
*xyFirst = inp;
*xy = inp;
}
}
else {
return FALSE;
}
break;
case '#':
if (numok(inp, &input, 0, 65535, FALSE, number)) {
@ -566,25 +573,16 @@ int32 match(char *pattern, char *input, char *xy, int32 *number, int32 *star,
return (pat == 0) && (inp == 0);
}
INLINE int32 checkXY(char xy) {
if (xy == 'X') {
return 0xdd;
}
else if (xy == 'Y') {
return 0xfd;
}
else {
printf("X or Y expected.\n");
return FALSE;
}
static INLINE int32 checkXY(const char xy) {
return xy == 'X' ? 0xdd : 0xfd; /* else is 'Y' */
}
int32 parse_X80(char *cptr, int32 addr, uint32 *val, char *Mnemonics[]) {
char xy;
static int32 parse_X80(const char *cptr, const int32 addr, uint32 *val, char *const Mnemonics[]) {
char xyFirst = 0, xy;
int32 op, number, star, at, hat, dollar;
for (op = 0; op < 256; op++) {
number = star = at = dollar = -129;
if (match(Mnemonics[op], cptr, &xy, &number, &star, &at, &hat, &dollar)) {
if (match(Mnemonics[op], cptr, &xyFirst, &xy, &number, &star, &at, &hat, &dollar)) {
val[0] = op;
if (number >= 0) {
val[1] = (0xff) & number;
@ -598,7 +596,7 @@ int32 parse_X80(char *cptr, int32 addr, uint32 *val, char *Mnemonics[]) {
else if (at > -129) {
if ((-128 <= at) && (at <= 127)) {
val[1] = (int8)(at);
return -1;
return -1; /* one additional byte returned */
}
else {
return SCPE_ARG;
@ -624,7 +622,7 @@ int32 parse_X80(char *cptr, int32 addr, uint32 *val, char *Mnemonics[]) {
}
for (op = 0; op < 256; op++) {
if (match(MnemonicsCB[op], cptr, &xy, &number, &star, &at, &hat, &dollar)) {
if (match(MnemonicsCB[op], cptr, &xyFirst, &xy, &number, &star, &at, &hat, &dollar)) {
val[0] = 0xcb;
val[1] = op;
return -1; /* one additional byte returned */
@ -633,7 +631,7 @@ int32 parse_X80(char *cptr, int32 addr, uint32 *val, char *Mnemonics[]) {
for (op = 0; op < 256; op++) {
number = -1;
if (match(MnemonicsED[op], cptr, &xy, &number, &star, &at, &hat, &dollar)) {
if (match(MnemonicsED[op], cptr, &xyFirst, &xy, &number, &star, &at, &hat, &dollar)) {
val[0] = 0xed;
val[1] = op;
if (number >= 0) {
@ -649,8 +647,9 @@ int32 parse_X80(char *cptr, int32 addr, uint32 *val, char *Mnemonics[]) {
for (op = 0; op < 256; op++) {
number = star = hat = -1;
xy = ' ';
if (match(MnemonicsXX[op], cptr, &xy, &number, &star, &at, &hat, &dollar)) {
xy = 0;
if (match(MnemonicsXX[op], cptr, &xyFirst, &xy, &number, &star, &at, &hat, &dollar)) {
/* all matches must have contained a '%' character */
if (!(val[0] = checkXY(xy))) {
return SCPE_ARG;
}
@ -681,8 +680,9 @@ int32 parse_X80(char *cptr, int32 addr, uint32 *val, char *Mnemonics[]) {
for (op = 0; op < 256; op++) {
at = -129;
xy = ' ';
if (match(MnemonicsXCB[op], cptr, &xy, &number, &star, &at, &hat, &dollar)) {
xy = 0;
if (match(MnemonicsXCB[op], cptr, &xyFirst, &xy, &number, &star, &at, &hat, &dollar)) {
/* all matches must have contained a '%' character */
if (!(val[0] = checkXY(xy))) {
return SCPE_ARG;
}
@ -702,7 +702,7 @@ int32 parse_X80(char *cptr, int32 addr, uint32 *val, char *Mnemonics[]) {
}
/* Symbolic input
/* symbolic input
Inputs:
*cptr = pointer to input string
@ -773,9 +773,7 @@ int32 sim_load(FILE *fileref, char *cptr, char *fnam, int32 flag) {
} /* end while */
printf("%d bytes [%d page%s] loaded at %x.\n", cnt, (cnt + 255) >> 8,
((cnt + 255) >> 8) == 1 ? "" : "s", org);
if (cntROM) {
printf("Warning: %d bytes written to ROM [%04X - %04X].\n", cntROM, ROMLow, ROMHigh);
}
printROMMessage(cntROM);
if (cntNonExist) {
printf("Warning: %d bytes written to non-existing memory (for this configuration).\n", cntNonExist);
}

View file

@ -1,6 +1,6 @@
/* altairZ80_hdsk.c: simulated hard disk device to increase capacity
/* altairz80_hdsk.c: simulated hard disk device to increase capacity
Copyright (c) 2002, Peter Schorn
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"),
@ -15,7 +15,7 @@
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY 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
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.
@ -24,7 +24,6 @@
in this Software without prior written authorization from Peter Schorn.
*/
#include <stdio.h>
#include "altairz80_defs.h"
#define UNIT_V_HDSKWLK (UNIT_V_UF + 0) /* write locked */
@ -54,32 +53,32 @@ extern int32 saved_PC;
extern int32 install_bootrom(void);
extern void printMessage(void);
extern void PutBYTEBasic(const uint32 Addr, const uint32 Bank, const uint32 Value);
extern void PutBYTEWrapper(register uint32 Addr, register uint32 Value);
extern void protect(int32 l, int32 h);
extern void protect(const int32 l, const int32 h);
extern uint8 GetBYTEWrapper(register uint32 Addr);
extern int32 bootrom[bootrom_size];
t_stat hdsk_svc(UNIT *uptr);
t_stat hdsk_boot(int32 unitno, DEVICE *dptr);
int32 hdsk_hasVerbose(void);
int32 hdsk_io(int32 port, int32 io, int32 data);
int32 hdsk_in(void);
int32 hdsk_out(int32 data);
int32 checkParameters(void);
int32 doSeek(void);
int32 doRead(void);
int32 doWrite(void);
static t_stat hdsk_svc(UNIT *uptr);
static t_stat hdsk_boot(int32 unitno, DEVICE *dptr);
static int32 hdsk_hasVerbose(void);
int32 hdsk_io(const int32 port, const int32 io, const int32 data);
static int32 hdsk_in(const int32 port);
static int32 hdsk_out(const int32 data);
static int32 checkParameters(void);
static int32 doSeek(void);
static int32 doRead(void);
static int32 doWrite(void);
uint8 hdskbuf[HDSK_SECTOR_SIZE]; /* Data Buffer */
int32 hdskLastCommand = hdsk_none;
int32 hdskCommandPosition = 0;
int32 selectedDisk;
int32 selectedSector;
int32 selectedTrack;
int32 selectedDMA;
int32 hdskTrace;
static int32 hdskLastCommand = hdsk_none;
static int32 hdskCommandPosition = 0;
static int32 selectedDisk;
static int32 selectedSector;
static int32 selectedTrack;
static int32 selectedDMA;
static int32 hdskTrace;
UNIT hdsk_unit[] = {
static UNIT hdsk_unit[] = {
{ UDATA (&hdsk_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, HDSK_CAPACITY) },
{ UDATA (&hdsk_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, HDSK_CAPACITY) },
{ UDATA (&hdsk_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, HDSK_CAPACITY) },
@ -89,7 +88,7 @@ UNIT hdsk_unit[] = {
{ UDATA (&hdsk_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, HDSK_CAPACITY) },
{ UDATA (&hdsk_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, HDSK_CAPACITY) } };
REG hdsk_reg[] = {
static REG hdsk_reg[] = {
{ DRDATA (HDCMD, hdskLastCommand, 32), REG_RO },
{ DRDATA (HDPOS, hdskCommandPosition, 32), REG_RO },
{ DRDATA (HDDSK, selectedDisk, 32), REG_RO },
@ -99,7 +98,7 @@ REG hdsk_reg[] = {
{ DRDATA (HDTRACE, hdskTrace, 8), },
{ NULL } };
MTAB hdsk_mod[] = {
static MTAB hdsk_mod[] = {
{ UNIT_HDSKWLK, 0, "write enabled", "WRITEENABLED", NULL },
{ UNIT_HDSKWLK, UNIT_HDSKWLK, "write locked", "LOCKED", NULL },
/* quiet, no warning messages */
@ -112,13 +111,13 @@ DEVICE hdsk_dev = {
"HDSK", hdsk_unit, hdsk_reg, hdsk_mod,
8, 10, 31, 1, 8, 8,
NULL, NULL, NULL,
&hdsk_boot, NULL, NULL, NULL, 0 };
&hdsk_boot, NULL, NULL, NULL, 0, NULL, NULL };
t_stat hdsk_svc(UNIT *uptr) {
static t_stat hdsk_svc(UNIT *uptr) {
return SCPE_OK;
}
int32 hdskBoot[bootrom_size] = {
static const int32 hdskBoot[bootrom_size] = {
0xf3, 0x06, 0x80, 0x3e, 0x0e, 0xd3, 0xfe, 0x05, /* 5c00-5c07 */
0xc2, 0x05, 0x5c, 0x3e, 0x16, 0xd3, 0xfe, 0x3e, /* 5c08-5c0f */
0x12, 0xd3, 0xfe, 0xdb, 0xfe, 0xb7, 0xca, 0x20, /* 5c10-5c17 */
@ -153,7 +152,7 @@ int32 hdskBoot[bootrom_size] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 5cf8-5cff */
};
t_stat hdsk_boot(int32 unitno, DEVICE *dptr) {
static t_stat hdsk_boot(int32 unitno, DEVICE *dptr) {
int32 i;
if (MEMSIZE < 24*KB) {
printf("Need at least 24KB RAM to boot from hard disk.\n");
@ -173,7 +172,7 @@ t_stat hdsk_boot(int32 unitno, DEVICE *dptr) {
}
}
for (i = 0; i < bootrom_size; i++) {
M[i + hdsk_boot_address][0] = hdskBoot[i] & 0xff;
PutBYTEBasic(i + hdsk_boot_address, 0, hdskBoot[i] & 0xff);
}
saved_PC = hdsk_boot_address;
protect(hdsk_boot_address, hdsk_boot_address + bootrom_size - 1);
@ -181,7 +180,7 @@ t_stat hdsk_boot(int32 unitno, DEVICE *dptr) {
}
/* returns TRUE iff there exists a disk with VERBOSE */
int32 hdsk_hasVerbose(void) {
static int32 hdsk_hasVerbose(void) {
int32 i;
for (i = 0; i < HDSK_NUMBER; i++) {
if (((hdsk_dev.units + i) -> flags) & UNIT_HDSK_VERBOSE) {
@ -221,7 +220,7 @@ l ld a,(hl) ; get byte of parameter block
*/
/* check the parameters and return TRUE iff parameters are correct or have been repaired */
int32 checkParameters(void) {
static int32 checkParameters(void) {
int32 currentFlag;
if ((selectedDisk < 0) || (selectedDisk >= HDSK_NUMBER)) {
if (hdsk_hasVerbose()) {
@ -259,7 +258,7 @@ int32 checkParameters(void) {
return TRUE;
}
int32 doSeek(void) {
static int32 doSeek(void) {
UNIT *uptr = hdsk_dev.units + selectedDisk;
if (fseek(uptr -> fileref,
HDSK_TRACK_SIZE * selectedTrack + HDSK_SECTOR_SIZE * selectedSector, SEEK_SET)) {
@ -274,8 +273,9 @@ int32 doSeek(void) {
}
}
int32 doRead(void) {
static int32 doRead(void) {
int32 i;
uint8 hdskbuf[HDSK_SECTOR_SIZE]; /* data buffer */
UNIT *uptr = hdsk_dev.units + selectedDisk;
if (doSeek()) {
return CPM_ERROR;
@ -296,8 +296,9 @@ int32 doRead(void) {
return CPM_OK;
}
int32 doWrite(void) {
static int32 doWrite(void) {
int32 i;
uint8 hdskbuf[HDSK_SECTOR_SIZE]; /* data buffer */
UNIT *uptr = hdsk_dev.units + selectedDisk;
if (((uptr -> flags) & UNIT_HDSKWLK) == 0) { /* write enabled */
if (doSeek()) {
@ -324,7 +325,7 @@ int32 doWrite(void) {
return CPM_OK;
}
int32 hdsk_in(void) {
static int32 hdsk_in(const int32 port) {
int32 result;
if ((hdskCommandPosition == 6) && ((hdskLastCommand == hdsk_read) || (hdskLastCommand == hdsk_write))) {
result = checkParameters() ? ((hdskLastCommand == hdsk_read) ? doRead() : doWrite()) : CPM_ERROR;
@ -333,12 +334,13 @@ int32 hdsk_in(void) {
return result;
}
else if (hdsk_hasVerbose()) {
message3("Illegal IN command detected (cmd=%d, pos=%d).\n", hdskLastCommand, hdskCommandPosition);
message4("Illegal IN command detected (port=%03xh, cmd=%d, pos=%d).\n",
port, hdskLastCommand, hdskCommandPosition);
}
return CPM_OK;
}
int32 hdsk_out(int32 data) {
static int32 hdsk_out(const int32 data) {
switch(hdskLastCommand) {
case hdsk_read:
case hdsk_write:
@ -379,6 +381,6 @@ int32 hdsk_out(int32 data) {
return 0; /* ignored, since OUT */
}
int32 hdsk_io(int32 port, int32 io, int32 data) {
return io == 0 ? hdsk_in() : hdsk_out(data);
int32 hdsk_io(const int32 port, const int32 io, const int32 data) {
return io == 0 ? hdsk_in(port) : hdsk_out(data);
}

View file

@ -1,6 +1,6 @@
/* gri_cpu.c: GRI-909 CPU simulator
Copyright (c) 2001-2002, Robert M. Supnik
Copyright (c) 2001-2003, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@ -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.
cpu GRI-909 CPU
14-Mar-03 RMS Fixed bug in SC queue tracking
The system state for the GRI-909 is:
AX<0:15> arithmetic input
@ -167,6 +171,7 @@ uint32 stop_opr = 1; /* stop ill operator */
int16 scq[SCQ_SIZE] = { 0 }; /* PC queue */
int32 scq_p = 0; /* PC queue ptr */
REG *scq_r = NULL; /* PC queue reg ptr */
extern int32 sim_interval;
extern int32 sim_int_char;
extern int32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */
@ -475,7 +480,7 @@ else if ((src != U_MEM) && (dst != U_MEM)) { /* reg-reg? */
/* Memory reference. The second SC increment occurs after the first
execution cycle. For direct, defer, and immediate defer, this is
after the first memory read and before the bus transfer; but for
immediate, it is before the bus transfer.
immediate, it is after the bus transfer.
*/
else { SC = (SC + 1) & AMASK; /* incr SC */
@ -512,6 +517,7 @@ else { SC = (SC + 1) & AMASK; /* incr SC */
/* Simulation halted */
AO = ao_update (); /* update AO */
scq_r->qptr = scq_p; /* update sc q ptr */
return reason;
}
@ -871,7 +877,7 @@ return SCPE_OK;
t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc)
{
int32 mc = 0;
t_addr i;
uint32 i;
if ((val <= 0) || (val > MAXMEMSIZE) || ((val & 07777) != 0))
return SCPE_ARG;

View file

@ -1,6 +1,6 @@
/* gri_defs.h: GRI-909 simulator definitions
Copyright (c) 2001-2002, Robert M. Supnik
Copyright (c) 2001-2003, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@ -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.
25-Apr-03 RMS Revised for extended file support
19-Sep-02 RMS Fixed declarations in gdev structure
There are several discrepancies between the original GRI-909 Reference
@ -65,7 +66,7 @@
#define MAXMEMSIZE 32768 /* max memory size */
#define AMASK 077777 /* logical addr mask */
#define MEMSIZE (cpu_unit.capac) /* actual memory size */
#define MEM_ADDR_OK(x) (((t_addr) (x)) < MEMSIZE)
#define MEM_ADDR_OK(x) (((uint32) (x)) < MEMSIZE)
/* Architectural constants */

View file

@ -1,14 +1,14 @@
To: Users
From: Bob Supnik
Subj: GRI-909 Simulator Usage
Date: 15-Nov-2002
Date: 20-Apr-2003
COPYRIGHT NOTICE
The following copyright notice applies to both the SIMH source and binary:
Original code published in 1993-2002, written by Robert M Supnik
Copyright (c) 1993-2002, Robert M Supnik
Original code published in 1993-2003, written by Robert M Supnik
Copyright (c) 1993-2003, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@ -103,7 +103,7 @@ control registers for the interrupt system.
name size comments
SC 14 sequence counter
SC 15 sequence counter
AX 16 arithmetic operator input register 1
AY 16 arithmetic operator input register 2
AO 16 arithmetic operator output register
@ -126,7 +126,7 @@ control registers for the interrupt system.
ION 1 interrupts enabled
INODEF 1 interrupts not deferred
BKP 1 breakpoint request
SCQ[0:63] 16 SC prior to last jump or interrupt;
SCQ[0:63] 15 SC prior to last jump or interrupt;
most recent SC change first
STOP_OPR 1 stop on undefined operator
WRU 8 interrupt character
@ -136,8 +136,8 @@ control registers for the interrupt system.
2.2.1 S42-004 High Speed Reader (HSR)
The paper tape reader (HSR) reads data from or a disk file. The POS
register specifies the number of the next data item to be read. Thus,
by changing POS, the user can backspace or advance the reader.
register specifies the number of the next data item to be read.
Thus, by changing POS, the user can backspace or advance the reader.
The paper tape reader implements these registers:

View file

@ -1,6 +1,6 @@
/* gri_stddev.c: GRI-909 standard devices
Copyright (c) 2001-2002, Robert M Supnik
Copyright (c) 2001-2003, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@ -29,6 +29,7 @@
hsp S42-006 high speed punch
rtc real time clock
25-Apr-03 RMS Revised for extended file support
22-Dec-02 RMS Added break support
01-Nov-02 RMS Added 7b/8B support to terminal
*/
@ -73,7 +74,7 @@ REG tti_reg[] = {
{ ORDATA (BUF, tti_unit.buf, 8) },
{ FLDATA (IRDY, dev_done, INT_V_TTI) },
{ FLDATA (IENB, ISR, INT_V_TTI) },
{ DRDATA (POS, tti_unit.pos, 32), PV_LEFT },
{ DRDATA (POS, tti_unit.pos, T_ADDR_W), PV_LEFT },
{ DRDATA (TIME, tti_unit.wait, 24), REG_NZ + PV_LEFT },
{ FLDATA (UC, tti_unit.flags, UNIT_V_KSR), REG_HRO },
{ NULL } };
@ -103,7 +104,7 @@ REG tto_reg[] = {
{ ORDATA (BUF, tto_unit.buf, 8) },
{ FLDATA (ORDY, dev_done, INT_V_TTO) },
{ FLDATA (IENB, ISR, INT_V_TTO) },
{ DRDATA (POS, tto_unit.pos, 32), PV_LEFT },
{ DRDATA (POS, tto_unit.pos, T_ADDR_W), PV_LEFT },
{ DRDATA (TIME, tto_unit.wait, 24), PV_LEFT },
{ NULL } };
@ -134,7 +135,7 @@ REG hsr_reg[] = {
{ ORDATA (BUF, hsr_unit.buf, 8) },
{ FLDATA (IRDY, dev_done, INT_V_HSR) },
{ FLDATA (IENB, ISR, INT_V_HSR) },
{ DRDATA (POS, hsr_unit.pos, 32), PV_LEFT },
{ DRDATA (POS, hsr_unit.pos, T_ADDR_W), PV_LEFT },
{ DRDATA (TIME, hsr_unit.wait, 24), REG_NZ + PV_LEFT },
{ FLDATA (STOP_IOE, hsr_stopioe, 0) },
{ NULL } };
@ -159,7 +160,7 @@ REG hsp_reg[] = {
{ ORDATA (BUF, hsp_unit.buf, 8) },
{ FLDATA (ORDY, dev_done, INT_V_HSP) },
{ FLDATA (IENB, ISR, INT_V_HSP) },
{ DRDATA (POS, hsp_unit.pos, 32), PV_LEFT },
{ DRDATA (POS, hsp_unit.pos, T_ADDR_W), PV_LEFT },
{ DRDATA (TIME, hsp_unit.wait, 24), PV_LEFT },
{ FLDATA (STOP_IOE, hsp_stopioe, 0) },
{ NULL } };
@ -223,7 +224,7 @@ return 0;
/* Service routines */
t_stat tti_svc (UNIT *uhsr)
t_stat tti_svc (UNIT *uptr)
{
int32 c;
@ -240,7 +241,7 @@ tti_unit.pos = tti_unit.pos + 1;
return SCPE_OK;
}
t_stat tto_svc (UNIT *uhsr)
t_stat tto_svc (UNIT *uptr)
{
int32 c;
t_stat r;
@ -257,7 +258,7 @@ return SCPE_OK;
/* Reset routines */
t_stat tti_reset (DEVICE *dhsr)
t_stat tti_reset (DEVICE *dptr)
{
tti_unit.buf = 0; /* clear buffer */
dev_done = dev_done & ~INT_TTI; /* clear ready */
@ -265,7 +266,7 @@ sim_activate (&tti_unit, tti_unit.wait); /* activate unit */
return SCPE_OK;
}
t_stat tto_reset (DEVICE *dhsr)
t_stat tto_reset (DEVICE *dptr)
{
tto_unit.buf = 0; /* clear buffer */
dev_done = dev_done | INT_TTO; /* set ready */
@ -310,7 +311,7 @@ if (((op & PT_IRDY) && (dev_done & INT_HSR)) ||
return 0;
}
t_stat hsr_svc (UNIT *uhsr)
t_stat hsr_svc (UNIT *uptr)
{
int32 temp;
@ -329,7 +330,7 @@ hsr_unit.pos = hsr_unit.pos + 1;
return SCPE_OK;
}
t_stat hsp_svc (UNIT *uhsr)
t_stat hsp_svc (UNIT *uptr)
{
dev_done = dev_done | INT_HSP; /* set ready */
if ((hsp_unit.flags & UNIT_ATT) == 0) /* attached? */
@ -344,7 +345,7 @@ return SCPE_OK;
/* Reset routines */
t_stat hsr_reset (DEVICE *dhsr)
t_stat hsr_reset (DEVICE *dptr)
{
hsr_unit.buf = 0; /* clear buffer */
dev_done = dev_done & ~INT_HSR; /* clear ready */
@ -352,7 +353,7 @@ sim_cancel (&hsr_unit); /* deactivate unit */
return SCPE_OK;
}
t_stat hsp_reset (DEVICE *dhsr)
t_stat hsp_reset (DEVICE *dptr)
{
hsp_unit.buf = 0; /* clear buffer */
dev_done = dev_done | INT_HSP; /* set ready */
@ -377,7 +378,7 @@ if ((op & RTC_OV) && (dev_done & INT_RTC)) return 1;
return 0;
}
t_stat rtc_svc (UNIT *uhsr)
t_stat rtc_svc (UNIT *uptr)
{
M[RTC_CTR] = (M[RTC_CTR] + 1) & DMASK; /* incr counter */
if (M[RTC_CTR] == 0) dev_done = dev_done | INT_RTC; /* ovflo? set ready */
@ -385,7 +386,7 @@ sim_activate (&rtc_unit, sim_rtc_calb (rtc_tps)); /* reactivate */
return SCPE_OK;
}
t_stat rtc_reset (DEVICE *dhsr)
t_stat rtc_reset (DEVICE *dptr)
{
dev_done = dev_done & ~INT_RTC; /* clear ready */
sim_cancel (&rtc_unit); /* stop clock */

View file

@ -1,6 +1,6 @@
/* gri_sys.c: GRI-909 simulator interface
Copyright (c) 2001-2002, Robert M Supnik
Copyright (c) 2001-2003, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@ -80,7 +80,8 @@ const char *sim_stop_messages[] = {
t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag)
{
int32 c, org;
int32 c;
uint32 org;
t_stat r;
char gbuf[CBUFSIZE];
@ -114,7 +115,7 @@ return SCPE_OK;
/* Symbol tables */
#define F_V_FL 16
#define F_V_FL 16 /* class flag */
#define F_M_FL 017
#define F_V_FO 000 /* function out */
#define F_V_FOI 001 /* FO, impl reg */

View file

@ -1,6 +1,6 @@
/* h316_cpu.c: Honeywell 316/516 CPU simulator
Copyright (c) 1999-2002, Robert M. Supnik
Copyright (c) 1999-2003, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@ -195,7 +195,7 @@
#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 (1 << UNIT_V_MSIZE)
#define UNIT_MSIZE (1u << UNIT_V_MSIZE)
#define m7 0001000 /* for generics */
#define m8 0000400
#define m9 0000200
@ -229,17 +229,20 @@ int32 pcq_p = 0; /* PC queue ptr */
REG *pcq_r = NULL; /* PC queue reg ptr */
int32 dlog = 0; /* debug log */
int32 turnoff = 0;
extern int32 sim_int_char;
extern int32 sim_interval;
extern int32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */
extern FILE *sim_log;
extern t_stat fprint_sym (FILE *of, t_addr addr, t_value *val,
UNIT *uptr, int32 sw);
t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw);
t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw);
t_stat cpu_reset (DEVICE *dptr);
t_stat cpu_set_noext (UNIT *uptr, int32 val, char *cptr, void *desc);
t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc);
extern t_stat fprint_sym (FILE *of, t_addr addr, t_value *val,
UNIT *uptr, int32 sw);
/* CPU data structures
@ -323,10 +326,9 @@ int32 (*iotab[64])() = {
t_stat sim_instr (void)
{
extern int32 sim_interval;
extern UNIT clk_unit;
int32 AR, BR, MB, Y, t1, t2, t3, skip;
unsigned int32 ut;
uint32 ut;
t_stat reason;
t_stat Ea (int32 inst, int32 *addr);
void Write (int32 val, int32 addr);
@ -377,6 +379,7 @@ else { if (sim_brk_summ &&
MB = Read (Y); /* fetch instr */
PC = NEWA (Y, Y + 1); /* incr PC */
dev_ready = dev_ready | INT_NODEF; }
sim_interval = sim_interval - 1;
if (dlog && sim_log && !turnoff) { /* cycle log? */
int32 op = I_GETOP (MB) & 017; /* core opcode */
@ -389,6 +392,7 @@ if (dlog && sim_log && !turnoff) { /* cycle log? */
/* Memory reference instructions */
switch (I_GETOP (MB)) { /* case on <1:6> */
case 001: case 021: case 041: case 061: /* JMP */
if (reason = Ea (MB, &Y)) break; /* eff addr */
PCQ_ENTRY; /* save PC */
@ -401,6 +405,7 @@ case 001: case 021: case 041: case 061: /* JMP */
else turnoff = 0; } /* no, log */
if (extoff_pending) ext = extoff_pending = 0; /* cond ext off */
break;
case 002: case 022: case 042: case 062: /* LDA */
if (reason = Ea (MB, &Y)) break; /* eff addr */
if (dp) { /* double prec? */
@ -409,10 +414,12 @@ case 002: case 022: case 042: case 062: /* LDA */
sc = 0; }
else AR = Read (Y); /* no, get word */
break;
case 003: case 023: case 043: case 063: /* ANA */
if (reason = Ea (MB, &Y)) break; /* eff addr */
AR = AR & Read (Y);
break;
case 004: case 024: case 044: case 064: /* STA */
if (reason = Ea (MB, &Y)) break; /* eff addr */
if (dp) { /* double prec? */
@ -421,10 +428,12 @@ case 004: case 024: case 044: case 064: /* STA */
sc = 0; }
else Write (AR, Y); /* no, store word */
break;
case 005: case 025: case 045: case 065: /* ERA */
if (reason = Ea (MB, &Y)) break; /* eff addr */
AR = AR ^ Read (Y);
break;
case 006: case 026: case 046: case 066: /* ADD */
if (reason = Ea (MB, &Y)) break; /* eff addr */
if (dp) { /* double prec? */
@ -435,6 +444,7 @@ case 006: case 026: case 046: case 066: /* ADD */
sc = 0; }
else AR = Add16 (AR, Read (Y)); /* no, 16b add */
break;
case 007: case 027: case 047: case 067: /* SUB */
if (reason = Ea (MB, &Y)) break; /* eff addr */
if (dp) { /* double prec? */
@ -455,32 +465,38 @@ case 010: case 030: case 050: case 070: /* JST */
PCQ_ENTRY;
PC = NEWA (PC, Y + 1); /* set new PC */
break;
case 011: case 031: case 051: case 071: /* CAS */
if (reason = Ea (MB, &Y)) break; /* eff addr */
MB = Read (Y);
if (AR == MB) PC = NEWA (PC, PC + 1);
else if (SEXT (AR) < SEXT (MB)) PC = NEWA (PC, PC + 2);
break;
case 012: case 032: case 052: case 072: /* IRS */
if (reason = Ea (MB, &Y)) break; /* eff addr */
MB = (Read (Y) + 1) & DMASK; /* incr, rewrite */
Write (MB, Y);
if (MB == 0) PC = NEWA (PC, PC + 1); /* skip if zero */
break;
case 013: case 033: case 053: case 073: /* IMA */
if (reason = Ea (MB, &Y)) break; /* eff addr */
MB = Read (Y);
Write (AR, Y); /* A to mem */
AR = MB; /* mem to A */
break;
case 015: case 055: /* STX */
if (reason = Ea (MB & ~IDX, &Y)) break; /* eff addr */
Write (XR, Y); /* store XR */
break;
case 035: case 075: /* LDX */
if (reason = Ea (MB & ~IDX, &Y)) break; /* eff addr */
XR = Read (Y); /* load XR */
break;
case 016: case 036: case 056: case 076: /* MPY */
if (cpu_unit.flags & UNIT_HSA) { /* installed? */
if (reason = Ea (MB, &Y)) break; /* eff addr */
@ -489,6 +505,7 @@ case 016: case 036: case 056: case 076: /* MPY */
sc = 0; }
else reason = stop_inst;
break;
case 017: case 037: case 057: case 077: /* DIV */
if (cpu_unit.flags & UNIT_HSA) { /* installed? */
if (reason = Ea (MB, &Y)) break; /* eff addr */
@ -512,6 +529,7 @@ case 014: /* OCP */
reason = t2 >> IOT_V_REASON;
turnoff = 0;
break;
case 034: /* SKS */
t2 = iotab[MB & DEVMASK] (ioSKS, I_GETFNC (MB), AR);
reason = t2 >> IOT_V_REASON;
@ -519,6 +537,7 @@ case 034: /* SKS */
PC = NEWA (PC, PC + 1);
turnoff = 0; }
break;
case 054: /* INA */
if (MB & INCLRA) AR = 0;
t2 = iotab[MB & DEVMASK] (ioINA, I_GETFNC (MB), AR);
@ -528,6 +547,7 @@ case 054: /* INA */
turnoff = 0; }
AR = t2 & DMASK; /* data */
break;
case 074: /* OTA */
t2 = iotab[MB & DEVMASK] (ioOTA, I_GETFNC (MB), AR);
reason = t2 >> IOT_V_REASON;
@ -606,6 +626,7 @@ case 020:
sc = 0; /* clear sc */
if ((t1 = (-MB) & SHFMASK) == 0) break; /* shift count */
switch (I_GETFNC (MB)) { /* case shift fnc */
case 000: /* LRL */
if (t1 > 32) ut = 0; /* >32? all 0 */
else {
@ -614,6 +635,7 @@ case 020:
ut = ut >> t1; } /* log right */
PUTDBL_U (ut); /* store A,B */
break;
case 001: /* LRS */
if (t1 > 31) t1 = 31; /* limit to 31 */
t2 = GETDBL_S (SEXT (AR), BR); /* get A'B signed */
@ -621,6 +643,7 @@ case 020:
t2 = t2 >> t1; /* arith right */
PUTDBL_S (t2); /* store A,B */
break;
case 002: /* LRR */
t2 = t1 % 32; /* mod 32 */
ut = GETDBL_U (AR, BR); /* get A'B */
@ -628,6 +651,7 @@ case 020:
C = (ut >> 31) & 1; /* C = A<1> */
PUTDBL_U (ut); /* store A,B */
break;
case 003: /* "long right arot" */
if (reason = stop_inst) break; /* stop on undef? */
for (t2 = 0; t2 < t1; t2++) { /* bit by bit */
@ -636,22 +660,26 @@ case 020:
((BR & MMASK) >> 1);
AR = ((AR & SIGN) | (C << 15)) | (AR >> 1); }
break;
case 004: /* LGR */
if (t1 > 16) AR = 0; /* > 16? all 0 */
else {
C = (AR >> (t1 - 1)) & 1; /* C = last out */
AR = (AR >> t1) & DMASK; } /* log right */
break;
case 005: /* ARS */
if (t1 > 16) t1 = 16; /* limit to 16 */
C = ((SEXT (AR)) >> (t1 - 1)) & 1; /* C = last out */
AR = ((SEXT (AR)) >> t1) & DMASK; /* arith right */
break;
case 006: /* ARR */
t2 = t1 % 16; /* mod 16 */
AR = ((AR >> t2) | (AR << (16 - t2))) & DMASK;
C = (AR >> 15) & 1; /* C = A<1> */
break;
case 007: /* "short right arot" */
if (reason = stop_inst) break; /* stop on undef? */
for (t2 = 0; t2 < t1; t2++) { /* bit by bit */
@ -669,6 +697,7 @@ case 020:
ut = ut << t1; } /* log left */
PUTDBL_U (ut); /* store A,B */
break;
case 011: /* LLS */
if (t1 > 31) t1 = 31; /* limit to 31 */
t2 = GETDBL_S (SEXT (AR), BR); /* get A'B */
@ -677,6 +706,7 @@ case 020:
if ((t2 >> (31 - t1)) != /* shf out = sgn? */
((AR & SIGN)? -1: 0)) C = 1;
break;
case 012: /* LLR */
t2 = t1 % 32; /* mod 32 */
ut = GETDBL_U (AR, BR); /* get A'B */
@ -684,6 +714,7 @@ case 020:
C = ut & 1; /* C = B<16> */
PUTDBL_U (ut); /* store A,B */
break;
case 013: /* "long left arot" */
if (reason = stop_inst) break; /* stop on undef? */
for (t2 = 0; t2 < t1; t2++) { /* bit by bit */
@ -693,12 +724,14 @@ case 020:
if ((AR & SIGN) != ((AR >> 1) & SIGN)) C = 1;
AR = AR & DMASK; }
break;
case 014: /* LGL */
if (t1 > 16) AR = 0; /* > 16? all 0 */
else {
C = (AR >> (16 - t1)) & 1; /* C = last out */
AR = (AR << t1) & DMASK; } /* log left */
break;
case 015: /* ALS */
if (t1 > 16) t1 = 16; /* limit to 16 */
t2 = SEXT (AR); /* save AR */
@ -706,11 +739,13 @@ case 020:
if ((t2 >> (16 - t1)) != /* shf out + sgn */
((AR & SIGN)? -1: 0)) C = 1;
break;
case 016: /* ALR */
t2 = t1 % 16; /* mod 16 */
AR = ((AR << t2) | (AR >> (16 - t2))) & DMASK;
C = AR & 1; /* C = A<16> */
break;
case 017: /* "short left arot" */
if (reason = stop_inst) break; /* stop on undef? */
for (t2 = 0; t2 < t1; t2++) { /* bit by bit */
@ -826,6 +861,7 @@ return;
int32 Add16 (int32 v1, int32 v2)
{
int32 r = v1 + v2;
C = 0;
if (((v1 ^ ~v2) & (v1 ^ r)) & SIGN) C = 1;
return (r & DMASK);
@ -834,6 +870,7 @@ return (r & DMASK);
int32 Add31 (int32 v1, int32 v2)
{
int32 r = v1 + v2;
C = 0;
if (((v1 ^ ~v2) & (v1 ^ r)) & (1u << 30)) C = 1;
return r;
@ -1037,7 +1074,7 @@ return SCPE_OK;
t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc)
{
int32 mc = 0;
t_addr i;
uint32 i;
if ((val <= 0) || (val > MAXMEMSIZE) || ((val & 07777) != 0) ||
(((cpu_unit.flags & UNIT_EXT) == 0) && (val > (NX_AMASK + 1))))

View file

@ -1,6 +1,6 @@
/* h316_defs.h: Honeywell 316/516 simulator definitions
Copyright (c) 1999-2002, Robert M. Supnik
Copyright (c) 1999-2003, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@ -22,6 +22,8 @@
Except as contained in this notice, the name of Robert M Supnik shall not
be used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
25-Apr-03 RMS Revised for extended file support
*/
#include "sim_defs.h" /* simulator defns */
@ -40,7 +42,7 @@
#define MEMSIZE (cpu_unit.capac) /* actual memory size */
#define X_AMASK (MAXMEMSIZE - 1) /* ext address mask */
#define NX_AMASK ((MAXMEMSIZE / 2) - 1) /* nx address mask */
#define MEM_ADDR_OK(x) (((t_addr) (x)) < MEMSIZE)
#define MEM_ADDR_OK(x) (((uint32) (x)) < MEMSIZE)
/* Architectural constants */
@ -56,8 +58,8 @@
#define UNIT_V_EXT (UNIT_V_UF + 1) /* extended mem */
#define UNIT_V_HSA (UNIT_V_UF + 2) /* high speed arith */
#define UNIT_EXT (1 << UNIT_V_EXT)
#define UNIT_HSA (1 << UNIT_V_HSA)
#define UNIT_EXT (1u << UNIT_V_EXT)
#define UNIT_HSA (1u << UNIT_V_HSA)
/* Instruction format */

View file

@ -1,7 +1,7 @@
To: Users
From: Bob Supnik
Subj: H316 Simulator Usage
Date: 15-Mar-2003
Date: 20-Apr-2003
COPYRIGHT NOTICE

View file

@ -1,6 +1,6 @@
/* h316_lp.c: Honeywell 316/516 line printer
Copyright (c) 1999-2002, Robert M. Supnik
Copyright (c) 1999-2003, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@ -25,34 +25,10 @@
lpt line printer
25-Apr-03 RMS Revised for extended file support
30-May-02 RMS Widened POS to 32b
*/
#include "h316_defs.h"
#define LPT_WIDTH 120 /* width */
#define LPT_SCAN (LPT_WIDTH / 2) /* words/scan */
#define LPT_DRUM 64 /* drum rows */
#define LPT_SVCSH 01 /* shuttle */
#define LPT_SVCPA 02 /* paper advance */
extern int32 dev_ready, dev_enable;
extern int32 stop_inst;
int32 lpt_wdpos = 0; /* word position */
int32 lpt_drpos = 0; /* drum position */
int32 lpt_crpos = 0; /* carriage position */
int32 lpt_svcst = 0; /* service state */
int32 lpt_svcch = 0; /* service channel */
int32 lpt_xfer = 0; /* transfer flag */
int32 lpt_prdn = 1; /* printing done */
char lpt_buf[LPT_WIDTH + 1] = { 0 }; /* line buffer */
int32 lpt_xtime = 5; /* transfer time */
int32 lpt_etime = 50; /* end of scan time */
int32 lpt_ptime = 5000; /* paper adv time */
int32 lpt_stopioe = 0; /* stop on error */
t_stat lpt_svc (UNIT *uptr);
t_stat lpt_reset (DEVICE *dptr);
/* The Series 16 line printer is an unbuffered Analex shuttle printer.
The Series 16 line printer is an unbuffered Analex shuttle printer.
Because it was unbuffered, the CPU had to scan out an entire line's
worth of characters (60 words) for every character on the print drum
(64 characters). Because it was a shuttle printer, the entire
@ -81,8 +57,36 @@ t_stat lpt_reset (DEVICE *dptr);
lpt_svcch channel for paper advance (0 = no adv)
lpt_xfer transfer ready flag
lpt_prdn printing done flag
*/
LPT data structures
#include "h316_defs.h"
#define LPT_WIDTH 120 /* width */
#define LPT_SCAN (LPT_WIDTH / 2) /* words/scan */
#define LPT_DRUM 64 /* drum rows */
#define LPT_SVCSH 01 /* shuttle */
#define LPT_SVCPA 02 /* paper advance */
extern int32 dev_ready, dev_enable;
extern int32 stop_inst;
int32 lpt_wdpos = 0; /* word position */
int32 lpt_drpos = 0; /* drum position */
int32 lpt_crpos = 0; /* carriage position */
int32 lpt_svcst = 0; /* service state */
int32 lpt_svcch = 0; /* service channel */
int32 lpt_xfer = 0; /* transfer flag */
int32 lpt_prdn = 1; /* printing done */
char lpt_buf[LPT_WIDTH + 1] = { 0 }; /* line buffer */
int32 lpt_xtime = 5; /* transfer time */
int32 lpt_etime = 50; /* end of scan time */
int32 lpt_ptime = 5000; /* paper adv time */
int32 lpt_stopioe = 0; /* stop on error */
t_stat lpt_svc (UNIT *uptr);
t_stat lpt_reset (DEVICE *dptr);
/* LPT data structures
lpt_dev LPT device descriptor
lpt_unit LPT unit descriptor
@ -103,7 +107,7 @@ REG lpt_reg[] = {
{ ORDATA (SVCST, lpt_svcst, 2) },
{ ORDATA (SVCCH, lpt_svcch, 2) },
{ BRDATA (BUF, lpt_buf, 8, 8, 120) },
{ DRDATA (POS, lpt_unit.pos, 32), PV_LEFT },
{ DRDATA (POS, lpt_unit.pos, T_ADDR_W), PV_LEFT },
{ DRDATA (XTIME, lpt_xtime, 24), PV_LEFT },
{ DRDATA (ETIME, lpt_etime, 24), PV_LEFT },
{ DRDATA (PTIME, lpt_ptime, 24), PV_LEFT },
@ -115,7 +119,6 @@ DEVICE lpt_dev = {
1, 10, 31, 1, 8, 8,
NULL, NULL, &lpt_reset,
NULL, NULL, NULL };
/* IO routine */
@ -141,6 +144,7 @@ case ioOCP: /* OCP */
default:
return IOBADFNC (dat); }
break;
case ioSKS: /* SKS */
switch (fnc) { /* case on fnc */
case 000: /* if xfer rdy */
@ -180,6 +184,7 @@ case ioSKS: /* SKS */
default:
return IOBADFNC (dat); }
break;
case ioOTA: /* OTA */
if (fnc) return IOBADFNC (dat); /* only fnc 0 */
if (lpt_xfer) { /* xfer ready? */

View file

@ -28,6 +28,7 @@
tty 316/516-33 teleprinter
clk/options 316/516-12 real time clocks/internal options
25-Apr-03 RMS Revised for extended file support
01-Mar-03 RMS Added SET/SHOW CLK FREQ support
22-Dec-02 RMS Added break support
01-Nov-02 RMS Added 7b/8b support to terminal
@ -87,7 +88,7 @@ REG ptr_reg[] = {
{ ORDATA (BUF, ptr_unit.buf, 8) },
{ FLDATA (READY, dev_ready, INT_V_PTR) },
{ FLDATA (ENABLE, dev_enable, INT_V_PTR) },
{ DRDATA (POS, ptr_unit.pos, 32), PV_LEFT },
{ DRDATA (POS, ptr_unit.pos, T_ADDR_W), PV_LEFT },
{ DRDATA (TIME, ptr_unit.wait, 24), PV_LEFT },
{ FLDATA (STOP_IOE, ptr_stopioe, 0) },
{ NULL } };
@ -114,7 +115,7 @@ REG ptp_reg[] = {
{ FLDATA (READY, dev_ready, INT_V_PTP) },
{ FLDATA (ENABLE, dev_enable, INT_V_PTP) },
{ FLDATA (POWER, ptp_power, 0) },
{ DRDATA (POS, ptp_unit.pos, 32), PV_LEFT },
{ DRDATA (POS, ptp_unit.pos, T_ADDR_W), PV_LEFT },
{ DRDATA (TIME, ptp_unit.wait, 24), PV_LEFT },
{ DRDATA (PWRTIME, ptp_ptime, 24), PV_LEFT },
{ FLDATA (STOP_IOE, ptp_stopioe, 0) },
@ -147,9 +148,9 @@ REG tty_reg[] = {
{ FLDATA (MODE, tty_mode, 0) },
{ FLDATA (READY, dev_ready, INT_V_TTY) },
{ FLDATA (ENABLE, dev_enable, INT_V_TTY) },
{ DRDATA (KPOS, tty_unit[TTI].pos, 32), PV_LEFT },
{ 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, 32), PV_LEFT },
{ DRDATA (TPOS, tty_unit[TTO].pos, T_ADDR_W), PV_LEFT },
{ DRDATA (TTIME, tty_unit[TTO].wait, 24), REG_NZ + PV_LEFT },
{ NULL } };
@ -164,7 +165,7 @@ DEVICE tty_dev = {
2, 10, 31, 1, 8, 8,
NULL, NULL, &tty_reset,
NULL, NULL, NULL };
/* CLK data structures
clk_dev CLK device descriptor

View file

@ -1,6 +1,6 @@
/* h316_sys.c: Honeywell 316/516 simulator interface
Copyright (c) 1999-2002, Robert M Supnik
Copyright (c) 1999-2003, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),

View file

@ -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.
12-Mar-03 RMS Added logical name support
02-Feb-03 RMS Fixed last cycle bug in DMA output (found by Mike Gemeny)
22-Nov-02 RMS Added 21MX IOP support
24-Oct-02 RMS Fixed bugs in IOP and extended instructions
@ -2493,7 +2494,7 @@ return SCPE_OK;
t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc)
{
int32 mc = 0;
t_addr i;
uint32 i;
if ((val <= 0) || (val > PASIZE) || ((val & 07777) != 0) ||
(!(uptr->flags & UNIT_21MX) && (val > 32768)))
@ -2567,9 +2568,11 @@ for (i = 0; cdptr = sim_devices[i]; i++) {
dibp = (DIB *) dptr->ctxt;
if (dibp && !(dptr->flags & DEV_DIS) &&
(chkp != dibp) && (dno == dibp->devno)) {
printf ("%s device number conflict, devno = %d\n", dptr->name, dno);
printf ("%s device number conflict, devno = %d\n",
sim_dname (dptr), dno);
if (sim_log) fprintf (sim_log,
"%s device number conflict, devno = %d\n", dptr->name, dno);
"%s device number conflict, devno = %d\n",
sim_dname (dptr), dno);
return TRUE; } } } }
return FALSE;
}

View file

@ -1,6 +1,6 @@
/* hp2100_defs.h: HP 2100 simulator definitions
Copyright (c) 1993-2002, Robert M. Supnik
Copyright (c) 1993-2003, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@ -23,6 +23,7 @@
be used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
25-Apr-03 RMS Revised for extended file support
24-Oct-02 RMS Added indirect address interrupt
08-Feb-02 RMS Added DMS definitions
01-Feb-02 RMS Added terminal multiplexor support
@ -52,7 +53,7 @@
/* Memory */
#define MEMSIZE (cpu_unit.capac) /* actual memory size */
#define MEM_ADDR_OK(x) (((t_addr) (x)) < MEMSIZE)
#define MEM_ADDR_OK(x) (((uint32) (x)) < MEMSIZE)
#define VA_N_SIZE 15 /* virtual addr size */
#define VASIZE (1 << VA_N_SIZE)
#define VAMASK (VASIZE - 1) /* virt addr mask */

View file

@ -1,6 +1,6 @@
/* hp2100_dp.c: HP 2100 12557A/13210A disk simulator
Copyright (c) 1993-2002, Robert M. Supnik
Copyright (c) 1993-2003, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@ -26,6 +26,8 @@
dp 12557A 2871 disk subsystem
13210A 7900 disk subsystem
25-Apr-03 RMS Revised for extended file support
Fixed bug(s) in boot (found by Terry Newton)
10-Nov-02 RMS Added BOOT command, fixed numerous bugs
15-Jan-02 RMS Fixed INIT handling (found by Bill McDermith)
10-Jan-02 RMS Fixed f(x)write call (found by Bill McDermith)
@ -239,7 +241,7 @@ REG dpc_reg[] = {
DP_NUMDRV, PV_LEFT | REG_HRO) },
{ URDATA (UFNC, dpc_unit[0].FNC, 8, 8, 0,
DP_NUMDRV, REG_HRO) },
{ URDATA (CAPAC, dpc_unit[0].capac, 10, 31, 0,
{ URDATA (CAPAC, dpc_unit[0].capac, 10, T_ADDR_W, 0,
DP_NUMDRV, PV_LEFT | REG_HRO) },
{ ORDATA (DEVNO, dpc_dib.devno, 6), REG_HRO },
{ NULL } };
@ -311,6 +313,7 @@ return dat;
int32 dpcio (int32 inst, int32 IR, int32 dat)
{
int32 i, devc, fnc, drv;
int32 devd = dpd_dib.devno;
devc = IR & I_DEVMASK; /* get device no */
switch (inst) { /* case on opcode */
@ -340,21 +343,24 @@ case ioCTL: /* control clear/set */
sim_cancel (&dpd_unit); /* cancel dch */
dpd_xfer = 0; /* clr dch xfer */
dpc_busy = 0; } /* clr cch busy */
else if (!CTL (devc)) { /* set and was clr? */
else { /* STC */
setCTL (devc); /* set ctl */
if (!CMD (devc)) { /* is cmd clr? */
setCMD (devc); /* set cmd */
drv = CW_GETDRV (dpc_obuf); /* get fnc, drv */
fnc = CW_GETFNC (dpc_obuf); /* from cmd word */
switch (fnc) { /* case on fnc */
case FNC_STA: /* rd sta */
if (dp_ctype) { clrFLG (devd); } /* 13210? clr dch flag */
case FNC_SEEK: case FNC_CHK: /* seek, check */
case FNC_STA: case FNC_AR: /* rd sta, addr rec */
case FNC_AR: /* addr rec */
dp_god (fnc, drv, dpc_dtime); /* sched dch xfr */
break;
case FNC_RD: case FNC_WD: /* read, write */
case FNC_REF: case FNC_INIT: /* refine, init */
dp_goc (fnc, drv, dpc_ctime); /* sched drive */
break;
} /* end case */
break; } /* end case */
}
} /* end else */
break;
default:
@ -469,7 +475,7 @@ case FNC_AR1: /* arec, need hd/sec */
break;
case FNC_STA: /* read status */
if (CMD (devd)) { /* dch active? */
if (CMD (devd) || dp_ctype) { /* dch act or 13210? */
if (dpc_unit[drv].flags & UNIT_ATT) { /* attached? */
dpd_ibuf = dpc_sta[drv] & ~STA_ERR; /* clear err */
if (dp_ctype) dpd_ibuf = /* 13210? */
@ -480,6 +486,7 @@ case FNC_STA: /* read status */
dpd_ibuf = dpd_ibuf | STA_ERR;
setFLG (devd); /* set dch flg */
clrCMD (devd); /* clr dch cmd */
clrCMD (devc); /* clr cch cmd */
dpc_sta[drv] = dpc_sta[drv] & /* clr sta flags */
~(STA_ATN | STA_1ST | STA_OVR |
STA_RWU | STA_ACU | STA_EOC |
@ -545,7 +552,9 @@ case FNC_SEEK3: /* waiting for flag */
if (dpc_busy || FLG (devc)) { /* ctrl busy? wait */
uptr->FNC = FNC_SEEK3; /* next state */
sim_activate (uptr, dpc_xtime); }
else setFLG (devc); /* set cch flg */
else {
setFLG (devc); /* set cch flg */
clrCMD (devc); } /* clear cmd */
return SCPE_OK;
case FNC_REF: /* refine sector */

View file

@ -1,6 +1,6 @@
/* hp2100_dq.c: HP 2100 12565A disk simulator
Copyright (c) 1993-2002, Bill McDermith
Copyright (c) 1993-2003, Bill McDermith
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@ -25,6 +25,7 @@
dq 12565A 2883 disk system
25-Apr-03 RMS Fixed bug in status check
10-Nov-02 RMS Added boot command, rebuilt like 12559/13210
09-Jan-02 WOM Copied dp driver and mods for 2883
@ -303,9 +304,10 @@ case ioCTL: /* control clear/set */
sim_cancel (&dqd_unit); /* cancel dch */
dqd_xfer = 0; /* clr dch xfer */
dqc_busy = 0; } /* clr busy */
else if (!CTL (devc)) { /* set and was clr? */
else { /* STC */
setCTL (devc); /* set ctl */
if (!CMD (devc)) { /* cmd clr? */
setCMD (devc); /* set cmd, ctl */
setCTL (devc);
drv = CW_GETDRV (dqc_obuf); /* get fnc, drv */
fnc = CW_GETFNC (dqc_obuf); /* from cmd word */
switch (fnc) { /* case on fnc */
@ -319,8 +321,8 @@ case ioCTL: /* control clear/set */
case FNC_RA: case FNC_WA: /* rd addr, wr addr */
case FNC_AS: /* address skip */
dq_goc (fnc, drv, dqc_ctime); /* sched drive */
break;
} /* end case */
break; } /* end case */
} /* end if !CMD */
} /* end else */
break;
default:
@ -451,6 +453,7 @@ case FNC_STA: /* read status */
if (drv) dqd_ibuf = dqd_ibuf | STA_DID;
setFLG (devd); /* set dch flg */
clrCMD (devd); /* clr dch cmd */
clrCMD (devc); /* clr cch cmd */
dqc_sta[drv] = dqc_sta[drv] & /* clr sta flags */
~(STA_DTE | STA_FLG | STA_AER | STA_EOC | STA_ERR);
}

View file

@ -1,6 +1,6 @@
/* hp2100_dr.c: HP 2100 12606B/12610B fixed head disk/drum simulator
Copyright (c) 1993-2000, Robert M. Supnik
Copyright (c) 1993-2003, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@ -284,7 +284,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;
if (((t_addr) (da + drd_ptr)) >= uptr->hwmark)
if (((uint32) (da + drd_ptr)) >= uptr->hwmark)
uptr->hwmark = da + drd_ptr + 1; }
drd_ptr = dr_incda (trk, sec, drd_ptr); /* inc disk addr */
if (CMD (devd)) { /* dch active? */

View file

@ -1,6 +1,6 @@
/* hp2100_fp.c: HP 2100 floating point instructions
Copyright (c) 2002, Robert M. Supnik
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"),

View file

@ -25,6 +25,7 @@
ipli, iplo 12556B interprocessor link pair
09-May-03 RMS Added network device flag
31-Jan-03 RMS Links are full duplex (found by Mike Gemeny)
*/
@ -113,7 +114,7 @@ DEVICE ipli_dev = {
1, 10, 31, 1, 16, 16,
&tmxr_ex, &tmxr_dep, &ipl_reset,
&ipl_boot, &ipl_attach, &ipl_detach,
&ipli_dib, DEV_DISABLE | DEV_DIS };
&ipli_dib, DEV_NET | DEV_DISABLE | DEV_DIS };
/* IPLO data structures
@ -139,7 +140,7 @@ DEVICE iplo_dev = {
1, 10, 31, 1, 16, 16,
&tmxr_ex, &tmxr_dep, &ipl_reset,
&ipl_boot, &ipl_attach, &ipl_detach,
&iplo_dib, DEV_DISABLE | DEV_DIS };
&iplo_dib, DEV_NET | DEV_DISABLE | DEV_DIS };
/* Interprocessor link I/O routines */

View file

@ -1,6 +1,6 @@
/* hp2100_lps.c: HP 2100 12653A line printer simulator
Copyright (c) 1993-2002, Robert M. Supnik
Copyright (c) 1993-2003, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@ -26,6 +26,7 @@
lps 12653A 2767 line printer
(based on 12556B microcircuit interface)
25-Apr-03 RMS Revised for extended file support
24-Oct-02 RMS Added microcircuit test features
30-May-02 RMS Widened POS to 32b
03-Dec-01 RMS Changed DEVNO to use extended SET/SHOW
@ -72,7 +73,7 @@ REG lps_reg[] = {
{ FLDATA (CTL, lps_dib.ctl, 0) },
{ FLDATA (FLG, lps_dib.flg, 0) },
{ FLDATA (FBF, lps_dib.fbf, 0) },
{ DRDATA (POS, lps_unit.pos, 32), PV_LEFT },
{ DRDATA (POS, lps_unit.pos, T_ADDR_W), PV_LEFT },
{ DRDATA (CTIME, lps_ctime, 31), PV_LEFT },
{ DRDATA (PTIME, lps_unit.wait, 24), PV_LEFT },
{ FLDATA (STOP_IOE, lps_stopioe, 0) },
@ -159,7 +160,7 @@ if (fputc (c, lps_unit.fileref) == EOF) {
perror ("LPS I/O error");
clearerr (lps_unit.fileref);
return SCPE_IOERR; }
lps_unit.pos = ftell (lps_unit.fileref); /* update pos */
lps_unit.pos = lps_unit.pos + 1; /* update pos */
return SCPE_OK;
}

View file

@ -1,6 +1,6 @@
/* hp2100_lpt.c: HP 2100 12845A line printer simulator
Copyright (c) 1993-2002, Robert M. Supnik
Copyright (c) 1993-2003, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@ -25,6 +25,7 @@
lpt 12845A line printer
25-Apr-03 RMS Revised for extended file support
24-Oct-02 RMS Cloned from 12653A
*/
@ -74,7 +75,7 @@ REG lpt_reg[] = {
{ FLDATA (FLG, lpt_dib.flg, 0) },
{ FLDATA (FBF, lpt_dib.fbf, 0) },
{ DRDATA (LCNT, lpt_lcnt, 7) },
{ DRDATA (POS, lpt_unit.pos, 32), PV_LEFT },
{ DRDATA (POS, lpt_unit.pos, T_ADDR_W), PV_LEFT },
{ DRDATA (CTIME, lpt_ctime, 31), PV_LEFT },
{ DRDATA (PTIME, lpt_unit.wait, 24), PV_LEFT },
{ FLDATA (STOP_IOE, lpt_stopioe, 0) },

View file

@ -1,6 +1,6 @@
/* hp2100_ms.c: HP 2100 13181A/13183A magnetic tape simulator
Copyright (c) 1993-2002, Robert M. Supnik
Copyright (c) 1993-2003, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@ -26,6 +26,9 @@
ms 13181A 7970B 800bpi nine track magnetic tape
13183A 7970E 1600bpi nine track magnetic tape
25-Apr-03 RMS Revised for extended file support
28-Mar-03 RMS Added multiformat support
28-Feb-03 RMS Revised for magtape library
18-Oct-02 RMS Added BOOT command, added 13183A support
30-Sep-02 RMS Revamped error handling
29-Aug-02 RMS Added end of medium support
@ -200,7 +203,7 @@ REG msc_reg[] = {
{ FLDATA (CTL, msc_dib.ctl, 0) },
{ FLDATA (FLG, msc_dib.flg, 0) },
{ FLDATA (FBF, msc_dib.fbf, 0) },
{ URDATA (POS, msc_unit[0].pos, 10, 32, 0, MS_NUMDR, PV_LEFT) },
{ URDATA (POS, msc_unit[0].pos, 10, T_ADDR_W, 0, MS_NUMDR, PV_LEFT) },
{ URDATA (FNC, msc_unit[0].FNC, 8, 8, 0, MS_NUMDR, REG_HRO) },
{ URDATA (UST, msc_unit[0].UST, 8, 12, 0, MS_NUMDR, REG_HRO) },
{ DRDATA (CTIME, msc_ctime, 24), REG_NZ + PV_LEFT },
@ -215,6 +218,8 @@ REG msc_reg[] = {
MTAB msc_mod[] = {
{ MTUF_WLK, 0, "write enabled", "WRITEENABLED", NULL },
{ MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL },
{ MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT",
&sim_tape_set_fmt, &sim_tape_show_fmt, NULL },
{ MTAB_XTD | MTAB_VDV, 0, NULL, "13181A",
&ms_settype, NULL, NULL },
{ MTAB_XTD | MTAB_VDV, 1, NULL, "13183A",

View file

@ -25,6 +25,8 @@
mt 12559A 3030 nine track magnetic tape
25-Apr-03 RMS Revised for extended file support
28-Mar-03 RMS Added multiformat support
28-Feb-03 RMS Revised for magtape library
30-Sep-02 RMS Revamped error handling
28-Aug-02 RMS Added end of medium support
@ -138,6 +140,8 @@ REG mtd_reg[] = {
MTAB mtd_mod[] = {
{ MTUF_WLK, 0, "write enabled", "WRITEENABLED", NULL },
{ MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL },
{ MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT",
&sim_tape_set_fmt, &sim_tape_show_fmt, NULL },
{ MTAB_XTD | MTAB_VDV, 1, "DEVNO", "DEVNO",
&hp_setdev, &hp_showdev, &mtd_dev },
{ 0 } };
@ -169,7 +173,7 @@ REG mtc_reg[] = {
{ FLDATA (FBF, mtc_dib.fbf, 0) },
{ FLDATA (DTF, mtc_dtf, 0) },
{ FLDATA (FSVC, mtc_1st, 0) },
{ DRDATA (POS, mtc_unit.pos, 32), PV_LEFT },
{ DRDATA (POS, mtc_unit.pos, T_ADDR_W), PV_LEFT },
{ DRDATA (CTIME, mtc_ctime, 24), REG_NZ + PV_LEFT },
{ DRDATA (GTIME, mtc_gtime, 24), REG_NZ + PV_LEFT },
{ DRDATA (XTIME, mtc_xtime, 24), REG_NZ + PV_LEFT },

View file

@ -1,6 +1,6 @@
/* hp2100_mux.c: HP 2100 12920A terminal multiplexor simulator
Copyright (c) 2002, Robert M Supnik
Copyright (c) 2002-2003, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@ -25,6 +25,7 @@
mux,muxl,muxc 12920A terminal multiplexor
09-May-03 RMS Added network device flag
01-Nov-02 RMS Added 7B/8B support
22-Aug-02 RMS Updated for changes to sim_tmxr
@ -231,7 +232,7 @@ DEVICE muxu_dev = {
1, 10, 31, 1, 8, 8,
&tmxr_ex, &tmxr_dep, &mux_reset,
NULL, &mux_attach, &mux_detach,
&muxu_dib, DEV_DISABLE };
&muxu_dib, DEV_NET | DEV_DISABLE };
/* MUXL data structures

View file

@ -1,6 +1,6 @@
/* hp2100_stddev.c: HP2100 standard devices simulator
Copyright (c) 1993-2002, Robert M. Supnik
Copyright (c) 1993-2003, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@ -28,6 +28,7 @@
tty 12531C buffered teleprinter interface
clk 12539C time base generator
25-Apr-03 RMS Added extended file support
22-Dec-02 RMS Added break support
01-Nov-02 RMS Revised BOOT command for IBL ROMs
Fixed bug in TTY reset, TTY starts in input mode
@ -133,7 +134,7 @@ REG ptr_reg[] = {
{ FLDATA (CTL, ptr_dib.ctl, 0) },
{ FLDATA (FLG, ptr_dib.flg, 0) },
{ FLDATA (FBF, ptr_dib.fbf, 0) },
{ DRDATA (POS, ptr_unit.pos, 32), PV_LEFT },
{ DRDATA (POS, ptr_unit.pos, T_ADDR_W), PV_LEFT },
{ DRDATA (TIME, ptr_unit.wait, 24), PV_LEFT },
{ FLDATA (STOP_IOE, ptr_stopioe, 0) },
{ ORDATA (DEVNO, ptr_dib.devno, 6), REG_HRO },
@ -170,7 +171,7 @@ REG ptp_reg[] = {
{ FLDATA (CTL, ptp_dib.ctl, 0) },
{ FLDATA (FLG, ptp_dib.flg, 0) },
{ FLDATA (FBF, ptp_dib.fbf, 0) },
{ DRDATA (POS, ptp_unit.pos, 32), PV_LEFT },
{ DRDATA (POS, ptp_unit.pos, T_ADDR_W), PV_LEFT },
{ DRDATA (TIME, ptp_unit.wait, 24), PV_LEFT },
{ FLDATA (STOP_IOE, ptp_stopioe, 0) },
{ ORDATA (DEVNO, ptp_dib.devno, 6), REG_HRO },
@ -214,11 +215,11 @@ REG tty_reg[] = {
{ FLDATA (CTL, tty_dib.ctl, 0) },
{ FLDATA (FLG, tty_dib.flg, 0) },
{ FLDATA (FBF, tty_dib.fbf, 0) },
{ DRDATA (KPOS, tty_unit[TTI].pos, 32), PV_LEFT },
{ 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, 32), PV_LEFT },
{ DRDATA (TPOS, tty_unit[TTO].pos, T_ADDR_W), PV_LEFT },
{ DRDATA (TTIME, tty_unit[TTO].wait, 24), REG_NZ + PV_LEFT },
{ DRDATA (PPOS, tty_unit[TTP].pos, 32), PV_LEFT },
{ DRDATA (PPOS, tty_unit[TTP].pos, T_ADDR_W), PV_LEFT },
{ FLDATA (STOP_IOE, ttp_stopioe, 0) },
{ ORDATA (DEVNO, tty_dib.devno, 6), REG_HRO },
{ NULL } };

View file

@ -1,6 +1,6 @@
/* hp2100_sys.c: HP 2100 simulator interface
Copyright (c) 1993-2002, Robert M. Supnik
Copyright (c) 1993-2003, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),

View file

@ -1,6 +1,6 @@
/* i1401_cd.c: IBM 1402 card reader/punch
Copyright (c) 1993-2002, Robert M. Supnik
Copyright (c) 1993-2003, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@ -35,6 +35,7 @@
Cards are represented as ASCII text streams terminated by newlines.
This allows cards to be created and edited as normal files.
25-Apr-03 RMS Revised for extended file support
30-May-02 RMS Widened POS to 32b
30-Jan-02 RMS New zero footprint card bootstrap from Van Snyder
29-Nov-01 RMS Added read only unit support
@ -70,7 +71,7 @@ REG cdr_reg[] = {
{ FLDATA (ERR, ind[IN_READ], 0) },
{ FLDATA (S1, s1sel, 0) },
{ FLDATA (S2, s2sel, 0) },
{ DRDATA (POS, cdr_unit.pos, 32), PV_LEFT },
{ DRDATA (POS, cdr_unit.pos, T_ADDR_W), PV_LEFT },
{ DRDATA (TIME, cdr_unit.wait, 24), PV_LEFT },
{ BRDATA (BUF, rbuf, 8, 8, CDR_WIDTH) },
{ NULL } };
@ -95,7 +96,7 @@ REG cdp_reg[] = {
{ FLDATA (ERR, ind[IN_PNCH], 0) },
{ FLDATA (S4, s4sel, 0) },
{ FLDATA (S8, s8sel, 0) },
{ DRDATA (POS, cdp_unit.pos, 32), PV_LEFT },
{ DRDATA (POS, cdp_unit.pos, T_ADDR_W), PV_LEFT },
{ NULL } };
DEVICE cdp_dev = {
@ -119,10 +120,10 @@ UNIT stack_unit[] = {
{ UDATA (NULL, UNIT_SEQ+UNIT_ATTABLE, 0) } };
REG stack_reg[] = {
{ DRDATA (POS0, stack_unit[0].pos, 32), PV_LEFT },
{ DRDATA (POS1, stack_unit[1].pos, 32), PV_LEFT },
{ DRDATA (POS28, stack_unit[2].pos, 32), PV_LEFT },
{ DRDATA (POS4, stack_unit[4].pos, 32), PV_LEFT },
{ DRDATA (POS0, stack_unit[0].pos, T_ADDR_W), PV_LEFT },
{ DRDATA (POS1, stack_unit[1].pos, T_ADDR_W), PV_LEFT },
{ DRDATA (POS28, stack_unit[2].pos, T_ADDR_W), PV_LEFT },
{ DRDATA (POS4, stack_unit[4].pos, T_ADDR_W), PV_LEFT },
{ NULL } };
DEVICE stack_dev = {

View file

@ -1,6 +1,6 @@
/* i1401_cpu.c: IBM 1401 CPU simulator
Copyright (c) 1993-2002, Robert M. Supnik
Copyright (c) 1993-2003, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@ -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.
16-Mar-03 RMS Fixed mnemonic, instruction lengths, and reverse
scan length check bug for MCS
Fixed MCE bug, BS off by 1 if zero suppress
Fixed chaining bug, D lost if return to SCP
Fixed H branch, branch occurs after continue
Added check for invalid 8 character MCW, LCA
03-Jun-03 RMS Added 1311 support
22-May-02 RMS Added multiply and divide
30-Dec-01 RMS Added old PC queue
@ -142,7 +148,9 @@ uint8 M[MAXMEMSIZE] = { 0 }; /* main memory */
int32 saved_IS = 0; /* saved IS */
int32 AS = 0; /* AS */
int32 BS = 0; /* BS */
int32 D = 0; /* modifier */
int32 as_err = 0, bs_err = 0; /* error flags */
int32 hb_pend = 0; /* halt br pending */
uint16 pcq[PCQ_SIZE] = { 0 }; /* PC queue */
int32 pcq_p = 0; /* PC queue ptr */
REG *pcq_r = NULL; /* PC queue reg ptr */
@ -194,6 +202,7 @@ REG cpu_reg[] = {
{ DRDATA (BS, BS, 14), PV_LEFT },
{ FLDATA (ASERR, as_err, 0) },
{ FLDATA (BSERR, bs_err, 0) },
{ ORDATA (D, D, 7) },
{ FLDATA (SSA, ssa, 0) },
{ FLDATA (SSB, ind[IN_SSB], 0) },
{ FLDATA (SSC, ind[IN_SSC], 0) },
@ -208,8 +217,9 @@ REG cpu_reg[] = {
{ FLDATA (OVF, ind[IN_OVF], 0) },
{ FLDATA (IOCHK, iochk, 0) },
{ FLDATA (PRCHK, prchk, 0) },
{ FLDATA (HBPEND, hb_pend, 0) },
{ BRDATA (ISQ, pcq, 10, 14, PCQ_SIZE), REG_RO+REG_CIRC },
{ ORDATA (ISQP, pcq_p, 6), REG_HRO },
{ DRDATA (ISQP, pcq_p, 6), REG_HRO },
{ ORDATA (WRU, sim_int_char, 8) },
{ NULL } };
@ -271,7 +281,7 @@ const int32 op_table[64] = {
L1 | L8 | BREQ | BBE, /* branch if bit eq */
0, /* illegal */
L1 | L4 | L7 | AREQ | BREQ, /* 30: move zones */
L7 | AREQ | BREQ, /* move supress zero */
L1 | L4 | L7 | AREQ | BREQ, /* move supress zero */
0, /* illegal */
L1 | L4 | L7 | AREQ | BREQ | NOWM, /* set word mark */
L7 | AREQ | BREQ | MDV, /* divide */
@ -305,7 +315,7 @@ const int32 op_table[64] = {
L1 | L4 | L7 | AREQ | MLS, /* 70: store B addr */
0, /* illegal */
L1 | L4 | L7 | AREQ | BREQ, /* zero and add */
HNOP | L1 | L4, /* halt */
HNOP | L1 | L4 | L7, /* halt */
L1 | L4 | L7 | AREQ | BREQ, /* clear word mark */
0, /* illegal */
0, /* illegal */
@ -456,8 +466,8 @@ static const int32 mtf_mod[] = { BCD_B, BCD_E, BCD_M, BCD_R, BCD_U, -1 };
t_stat sim_instr (void)
{
extern int32 sim_interval;
int32 IS, D, ilnt, flags;
int32 op, xa, t, wm, dev, unit;
int32 IS, ilnt, flags;
int32 op, xa, t, wm, ioind, dev, unit;
int32 a, b, i, asave, bsave;
int32 carry, lowprd, sign, ps;
int32 quo, ahigh, qs;
@ -466,16 +476,21 @@ t_stat reason, r1, r2;
/* Restore saved state */
IS = saved_IS;
if (as_err) AS = AS | BA; /* flag bad addresses */
if (bs_err) BS = BS | BA;
as_err = bs_err = 0; /* reset error flags */
D = 0;
reason = 0;
/* Main instruction fetch/decode loop */
while (reason == 0) { /* loop until halted */
if (hb_pend) { /* halt br pending? */
hb_pend = 0; /* clear flag */
BRANCH; } /* execute branch */
saved_IS = IS; /* commit prev instr */
if (sim_interval <= 0) { /* check clock queue */
if (reason = sim_process_event ()) break; }
@ -500,7 +515,7 @@ if (op == OP_SAR) BS = AS; /* SAR? save ASTAR */
PP (IS);
if ((t = M[IS]) & WM) goto CHECK_LENGTH; /* WM? 1 char inst */
D = t; /* could be D char */
D = ioind = t; /* could be D char, % */
AS = hun_table[t]; /* could be A addr */
PP (IS); /* if %xy, BA is set */
@ -519,7 +534,7 @@ if ((t = M[IS]) & WM) { /* WM? 3 char inst */
AS = AS + one_table[t]; /* finish A addr */
unit = (t == BCD_ZERO)? 0: t; /* save char as unit */
xa = (AS >> V_INDEX) & M_INDEX; /* get index reg */
if (xa && (D != BCD_PERCNT) && (cpu_unit.flags & XSA)) { /* indexed? */
if (xa && (ioind != BCD_PERCNT) && (cpu_unit.flags & XSA)) { /* indexed? */
AS = AS + hun_table[M[xa] & CHAR] + ten_table[M[xa + 1] & CHAR] +
one_table[M[xa + 2] & CHAR];
AS = (AS & INDEXMASK) % MAXMEMSIZE; }
@ -570,7 +585,7 @@ switch (op) { /* case on opcode */
until A WM
MCM: copy A to B, preserving B WM, fetch fetch
until record or group mark
MSZ: copy A to B, clearing B WM, until A WM; fetch fetch
MCS: copy A to B, clearing B WM, until A WM; fetch fetch
reverse scan and suppress leading zeroes
MN: copy A char digit to B char digit, fetch fetch
preserving B zone and WM
@ -580,21 +595,23 @@ switch (op) { /* case on opcode */
case OP_MCW: /* move char */
if (ilnt >= 8) { /* I/O form? */
reason = iodisp (dev, unit, MD_NORM, D);
if (ioind != BCD_PERCNT) reason = STOP_INVL;
else reason = iodisp (dev, unit, MD_NORM, D);
break; }
if (ADDR_ERR (AS)) { /* check A addr */
reason = STOP_INVA;
break; }
do {
M[BS] = (M[BS] & WM) | (M[AS] & CHAR); /* move char */
wm = M[AS] | M[BS];
M[BS] = (M[BS] & WM) | (M[AS] & CHAR); /* move char */
MM (AS); MM (BS); } /* decr pointers */
while ((wm & WM) == 0); /* stop on A,B WM */
break;
case OP_LCA: /* load char */
if (ilnt >= 8) { /* I/O form? */
reason = iodisp (dev, unit, MD_WM, D);
if (ioind != BCD_PERCNT) reason = STOP_INVL;
else reason = iodisp (dev, unit, MD_WM, D);
break; }
if (ADDR_ERR (AS)) { /* check A addr */
reason = STOP_INVA;
@ -607,18 +624,18 @@ case OP_LCA: /* load char */
case OP_MCM: /* move to rec/group */
do {
M[BS] = (M[BS] & WM) | (M[AS] & CHAR); /* move char */
t = M[AS];
M[BS] = (M[BS] & WM) | (M[AS] & CHAR); /* move char */
PP (AS); PP (BS); } /* incr pointers */
while (((t & CHAR) != BCD_RECMRK) && (t != (BCD_GRPMRK + WM)));
break;
case OP_MSZ: /* move suppress zero */
case OP_MCS: /* move suppress zero */
bsave = BS; /* save B start */
qzero = 1; /* set suppress */
do {
M[BS] = M[AS] & ((BS != bsave)? CHAR: DIGIT); /* copy char */
wm = M[AS];
M[BS] = M[AS] & ((BS != bsave)? CHAR: DIGIT); /* copy char */
MM (AS); MM (BS); } /* decr pointers */
while ((wm & WM) == 0); /* stop on A WM */
if (reason) break; /* addr err? stop */
@ -631,7 +648,8 @@ case OP_MSZ: /* move suppress zero */
else if (((t == BCD_DECIMAL) && (cpu_unit.flags & EPE)) ||
(t <= BCD_NINE)) qzero = 0;
else qzero = 1; }
while (BS <= bsave);
while (BS < bsave);
PP (BS); /* BS end is B+1 */
break;
case OP_MN: /* move numeric */
@ -644,10 +662,7 @@ case OP_MZ: /* move zone */
MM (AS); MM (BS); /* decr pointers */
break;
/* Compare
A and B are checked in fetch
*/
/* Compare - A and B are checked in fetch */
case OP_C: /* compare */
if (ilnt != 1) { /* if not chained */
@ -993,7 +1008,9 @@ case OP_MCE: /* edit */
while ((b & WM) == 0);
M[BS] = M[BS] & ~WM; /* clear B WM */
if (!qdollar && !(qdecimal && qzero)) break; /* rescan again? */
if (!qdollar && !(qdecimal && qzero)) { /* rescan again? */
BS++; /* BS = addr WM + 1 */
break; }
if (qdecimal && qzero) qdollar = 0; /* no digits? clr $ */
/* Edit pass 3 (extended print only) - from right to left */
@ -1208,7 +1225,7 @@ case OP_NOP: /* nop */
break;
case OP_H: /* halt */
if (ilnt >= 4) { BRANCH; } /* branch if called */
if (ilnt == 4) hb_pend = 1; /* set pending branch */
reason = STOP_HALT; /* stop simulator */
saved_IS = IS; /* commit instruction */
break;
@ -1355,10 +1372,12 @@ t_stat cpu_reset (DEVICE *dptr)
{
int32 i;
for (i = 0; i < 64; i++) ind[i] = 0;
ind[IN_UNC] = 1;
AS = 0; as_err = 1;
BS = 0; bs_err = 1;
for (i = 0; i < 64; i++) ind[i] = 0; /* clr indicators */
ind[IN_UNC] = 1; /* ind[0] always on */
AS = 0; as_err = 1; /* clear AS */
BS = 0; bs_err = 1; /* clear BS */
D = 0; /* clear D */
hb_pend = 0; /* no halt br */
pcq_r = find_reg ("ISQ", NULL, dptr);
if (pcq_r) pcq_r->qptr = 0;
else return SCPE_IERR;
@ -1389,7 +1408,7 @@ return SCPE_OK;
t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc)
{
int32 mc = 0;
t_addr i;
uint32 i;
if ((val <= 0) || (val > MAXMEMSIZE) || ((val % 1000) != 0))
return SCPE_ARG;

View file

@ -1,3 +1,28 @@
/* i1401_dat.h: IBM 1401 character conversion tables
Copyright (c) 1993-2003, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of Robert M Supnik shall not
be used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
*/
/* ASCII to BCD conversion */

View file

@ -1,6 +1,6 @@
/* i1401_defs.h: IBM 1401 simulator definitions
Copyright (c) 1993-2002, Robert M. Supnik
Copyright (c) 1993-2003, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@ -23,7 +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.
03-Jun-03 RMS Added 1311 support
16-Mar-03 RMS Fixed mnemonic for MCS
03-Jun-02 RMS Added 1311 support
14-Apr-99 RMS Converted t_addr to unsigned
This simulator is based on the 1401 simulator written by Len Fehskens
@ -79,7 +80,7 @@
#define LPT_WIDTH 132 /* line print width */
#define CCT_LNT 132 /* car ctrl length */
#define INQ_WIDTH 80 /* inq term width */
#define ADDR_ERR(x) (((t_addr) (x)) >= MEMSIZE)
#define ADDR_ERR(x) (((uint32) (x)) >= MEMSIZE)
/* Binary address format
@ -205,7 +206,7 @@
#define OP_BWZ 025 /* branch wm or zone */
#define OP_BBE 026 /* branch bit equal */
#define OP_MZ 030 /* move zone */
#define OP_MSZ 031 /* move suppr zeroes */
#define OP_MCS 031 /* move suppr zeroes */
#define OP_SWM 033 /* set word mark */
#define OP_DIV 034 /* divide */
#define OP_SS 042 /* select stacker */

View file

@ -1,14 +1,14 @@
To: Users
From: Bob Supnik
Subj: IBM 1401 Simulator Usage
Date: 15-Nov-2002
Date: 20-Apr-2003
COPYRIGHT NOTICE
The following copyright notice applies to both the SIMH source and binary:
Original code published in 1993-2002, written by Robert M Supnik
Copyright (c) 1993-2002, Robert M Supnik
Original code published in 1993-2003, written by Robert M Supnik
Copyright (c) 1993-2003, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@ -161,7 +161,7 @@ interrupt system.
OVF 1 overflow indicator
IOCHK 1 I/O check switch
PRCHK 1 process check switch
ISQ 1 IS prior to last branch;
ISQ[0:63] 14 IS prior to last branch;
most recent IS change first
WRU 8 interrupt character
@ -184,11 +184,11 @@ the POS register specifies the number of the next data item to be read or
written. Thus, by changing POS, the user can backspace or advance these
devices.
The reader/punch registers are:
The card reader registers are:
device name size comments
name size comments
CDR LAST 1 last card indicator
LAST 1 last card indicator
ERR 1 error indicator
S1 1 stacker 1 select flag
S2 1 stacker 2 select flag
@ -196,11 +196,15 @@ The reader/punch registers are:
TIME 24 delay window for stacker select
BUF[0:79] 8 reader buffer
CDP ERR 1 error indicator
The card punch registers are:
ERR 1 error indicator
S4 1 stacker 4 select flag
S8 1 stacker 8 select flag
STKR POS0 32 position, normal reader stack
The stacker registers are:
POS0 32 position, normal reader stack
POS1 32 position, reader stacker 1
POS2 32 position, shared stacker 2/8
POS4 32 position, punch stacker 4
@ -423,7 +427,7 @@ devices can only accept single character input, without word marks.
2.7 Character Sets
The IBM 1401 used a 6b character code called BCD (binary coded decimal).
The IBM 1401 uses a 6b character code called BCD (binary coded decimal).
Some of the characters have no equivalent in ASCII and require different
representations:

View file

@ -1,6 +1,6 @@
/* i1401_dp.c: IBM 1311 disk simulator
Copyright (c) 2002, Robert M. Supnik
Copyright (c) 2002-2003, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),

View file

@ -1,6 +1,6 @@
/* i1401_iq.c: IBM 1407 inquiry terminal
Copyright (c) 1993-2002, Robert M. Supnik
Copyright (c) 1993-2003, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),

View file

@ -1,6 +1,6 @@
/* i1401_lp.c: IBM 1403 line printer simulator
Copyright (c) 1993-2002, Robert M. Supnik
Copyright (c) 1993-2003, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@ -25,6 +25,7 @@
lpt 1403 line printer
25-Apr-03 RMS Revised for extended file support
30-May-02 RMS Widened POS to 32b
13-Apr-01 RMS Revised for register arrays
*/
@ -87,7 +88,7 @@ UNIT lpt_unit = {
REG lpt_reg[] = {
{ FLDATA (ERR, ind[IN_LPT], 0) },
{ DRDATA (POS, lpt_unit.pos, 32), PV_LEFT },
{ DRDATA (POS, lpt_unit.pos, T_ADDR_W), PV_LEFT },
{ BRDATA (CCT, cct, 8, 32, CCT_LNT) },
{ DRDATA (LINES, lines, 8), PV_LEFT },
{ DRDATA (CCTP, cctptr, 8), PV_LEFT },

View file

@ -25,6 +25,9 @@
mt 7-track magtape
25-Apr-03 RMS Revised for extended file support
28-Mar-03 RMS Added multiformat support
15-Mar-03 RMS Fixed end-of-record on load read yet again
28-Feb-03 RMS Modified for magtape library
31-Oct-02 RMS Added error record handling
10-Oct-02 RMS Fixed end-of-record on load read writes WM plus GM
@ -101,17 +104,19 @@ UNIT mt_unit[] = {
REG mt_reg[] = {
{ FLDATA (END, ind[IN_END], 0) },
{ FLDATA (ERR, ind[IN_TAP], 0) },
{ DRDATA (POS1, mt_unit[1].pos, 32), PV_LEFT + REG_RO },
{ DRDATA (POS2, mt_unit[2].pos, 32), PV_LEFT + REG_RO },
{ DRDATA (POS3, mt_unit[3].pos, 32), PV_LEFT + REG_RO },
{ DRDATA (POS4, mt_unit[4].pos, 32), PV_LEFT + REG_RO },
{ DRDATA (POS5, mt_unit[5].pos, 32), PV_LEFT + REG_RO },
{ DRDATA (POS6, mt_unit[6].pos, 32), PV_LEFT + REG_RO },
{ DRDATA (POS1, mt_unit[1].pos, T_ADDR_W), PV_LEFT + REG_RO },
{ DRDATA (POS2, mt_unit[2].pos, T_ADDR_W), PV_LEFT + REG_RO },
{ DRDATA (POS3, mt_unit[3].pos, T_ADDR_W), PV_LEFT + REG_RO },
{ DRDATA (POS4, mt_unit[4].pos, T_ADDR_W), PV_LEFT + REG_RO },
{ DRDATA (POS5, mt_unit[5].pos, T_ADDR_W), PV_LEFT + REG_RO },
{ DRDATA (POS6, mt_unit[6].pos, T_ADDR_W), PV_LEFT + REG_RO },
{ NULL } };
MTAB mt_mod[] = {
{ MTUF_WLK, 0, "write enabled", "WRITEENABLED", NULL },
{ MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL },
{ MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT",
&sim_tape_set_fmt, &sim_tape_show_fmt, NULL },
{ 0 } };
DEVICE mt_dev = {
@ -173,6 +178,12 @@ return mt_map_status (st);
mod = modifier character
Outputs:
status = status
Fine point: after a read, the system writes a group mark just
beyond the end of the record. However, first it checks for a
GM + WM; if present, the GM + WM is not changed. Otherwise,
an MCW read sets a GM, preserving the current WM; while an LCA
read sets a GM and clears the WM.
*/
t_stat mt_io (int32 unit, int32 flag, int32 mod)
@ -211,8 +222,9 @@ case BCD_R: /* read */
if (ADDR_ERR (BS)) { /* check next BS */
BS = BA | (BS % MAXMEMSIZE);
return STOP_WRAP; } }
if (flag == MD_WM) M[BS] = WM | BCD_GRPMRK; /* load? set WM */
else M[BS] = (M[BS] & WM) | BCD_GRPMRK; /* move? save WM */
if (M[BS] != (BCD_GRPMRK + WM)) { /* not GM+WM at end? */
if (flag == MD_WM) M[BS] = BCD_GRPMRK; /* LCA: clear WM */
else M[BS] = (M[BS] & WM) | BCD_GRPMRK; } /* MCW: save WM */
BS++; /* adv BS */
if (ADDR_ERR (BS)) { /* check final BS */
BS = BA | (BS % MAXMEMSIZE);

View file

@ -1,6 +1,6 @@
/* i1401_sys.c: IBM 1401 simulator interface
Copyright (c) 1993-2002, Robert M. Supnik
Copyright (c) 1993-2003, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@ -23,6 +23,7 @@
be used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
16-Mar-03 RMS Fixed mnemonic for MCS
03-Jun-02 RMS Added 1311 support
18-May-02 RMS Added -D feature from Van Snyder
26-Jan-02 RMS Fixed H, NOP with no trailing wm (found by Van Snyder)
@ -158,7 +159,7 @@ const char *opcode[64] = {
NULL, "R", "W", "WR", "P", "RP", "WP", "WRP",
"RF", "WF", NULL, "MA", "MUL", NULL, NULL, NULL,
NULL, "CS", "S", NULL, "MTF", "BWZ", "BBE", NULL,
"MZ", "MSZ", NULL, "SWM", "DIV", NULL, NULL, NULL,
"MZ", "MCS", NULL, "SWM", "DIV", NULL, NULL, NULL,
NULL, NULL, "SS", "LCA", "MCW", "NOP", NULL, "MCM",
"SAR", NULL, "ZS", NULL, NULL, NULL, NULL, NULL,
NULL, "A", "B", "C", "MN", "MCE", "CC", NULL,

View file

@ -1,6 +1,6 @@
/* i1620_cd.c: IBM 1622 card reader/punch
Copyright (c) 2002, Robert M. Supnik
Copyright (c) 2002-2003, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@ -26,6 +26,8 @@
cdr 1622 card reader
cdp 1622 card punch
25-Apr-03 RMS Revised for extended file support
Cards are represented as ASCII text streams terminated by newlines.
This allows cards to be created and edited as normal files.
*/
@ -62,7 +64,7 @@ UNIT cdr_unit = {
REG cdr_reg[] = {
{ FLDATA (LAST, ind[IN_LAST], 0) },
{ DRDATA (POS, cdr_unit.pos, 32), PV_LEFT },
{ DRDATA (POS, cdr_unit.pos, T_ADDR_W), PV_LEFT },
{ NULL } };
DEVICE cdr_dev = {
@ -82,7 +84,7 @@ UNIT cdp_unit = {
UDATA (NULL, UNIT_SEQ+UNIT_ATTABLE, 0) };
REG cdp_reg[] = {
{ DRDATA (POS, cdp_unit.pos, 32), PV_LEFT },
{ DRDATA (POS, cdp_unit.pos, T_ADDR_W), PV_LEFT },
{ NULL } };
DEVICE cdp_dev = {

View file

@ -1,6 +1,6 @@
/* i1620_cpu.c: IBM 1620 CPU simulator
Copyright (c) 2002, Robert M. Supnik
Copyright (c) 2002-2003, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@ -26,6 +26,7 @@
This CPU module incorporates code and comments from the 1620 simulator by
Geoff Kuenning, with his permission.
25-Apr-03 RMS Changed t_addr to uint32 throughout
18-Oct-02 RMS Fixed bugs in invalid result testing (found by Hans Pufal)
The simulated register state for the IBM 1620 is:
@ -760,7 +761,7 @@ case OP_BCXM:
break; }
reason = add_field (GET_IDXADDR (idx), QAR, FALSE, TRUE, &sta);
if (ar_stop && ind[IN_OVF]) reason = STOP_OVERFL;
if ((ind[IN_EZ] == 0) && (sta == ADD_NOCRY)) { /* ~z, ~c, ~schg? */
if ((ind[IN_EZ] == 0) && (sta == ADD_NOCRY)) { /* ~z, ~c, ~sign chg? */
BRANCH (PAR); } /* branch */
break;
@ -954,10 +955,10 @@ cnt = 0; /* count depth */
do { indir = indir & M[alast]; /* get indirect */
if (cvt_addr (alast, lnt, FALSE, &addr)) /* cvt addr to bin */
return STOP_INVPDG; /* bad? */
idx = get_idx (ADDR_S (alast, 1)); /* get index addr */
idx = get_idx (ADDR_S (alast, 1)); /* get index reg num */
if (indexok && (idx > 0)) { /* indexable? */
idxa = GET_IDXADDR (idx); /* get idx addr */
if (cvt_addr (idxa, ADDR_LEN, TRUE, &idxv)) /* cvt idx */
idxa = GET_IDXADDR (idx); /* get idx reg addr */
if (cvt_addr (idxa, ADDR_LEN, TRUE, &idxv)) /* cvt idx reg */
return STOP_INVPDG;
addr = addr + idxv; /* add in index */
if (addr < 0) addr = addr + 100000; } /* -? 10's comp */
@ -1009,10 +1010,10 @@ return SCPE_OK;
t_stat get_idx (uint32 aidx)
{
int32 i, idx = 0;
int32 i, idx;
if (idxe == 0) return -1; /* indexing off? */
for (i = 0; i < 3; i++) { /* 3 flags worth */
for (i = idx = 0; i < 3; i++) { /* 3 flags worth */
if (M[aidx] & FLAG) idx = idx | (1 << i); /* test flag */
MM (aidx); } /* next digit */
return idx;
@ -1040,7 +1041,7 @@ return;
t_stat xmt_field (uint32 d, uint32 s, uint32 skp)
{
t_addr cnt = 0;
uint32 cnt = 0;
uint8 t;
do { t = M[d] = M[s] & (FLAG | DIGIT); /* copy src to dst */
@ -1054,7 +1055,7 @@ return SCPE_OK;
t_stat xmt_record (uint32 d, uint32 s, t_bool cpy)
{
t_addr cnt = 0;
uint32 cnt = 0;
while ((M[s] & REC_MARK) != REC_MARK) { /* until rec mark */
M[d] = M[s] & (FLAG | DIGIT); /* copy src to dst */
@ -1083,7 +1084,7 @@ return SCPE_OK;
t_stat xmt_divd (uint32 d, uint32 s)
{
t_addr cnt = 0;
uint32 cnt = 0;
M[d] = M[s] & DIGIT; /* first w/o flag */
do { MM (d); MM (s); /* decr mem addrs */
@ -1097,7 +1098,7 @@ return SCPE_OK;
t_stat xmt_tns (uint32 d, uint32 s)
{
t_addr cnt = 0;
uint32 cnt = 0;
uint8 t, z;
t = M[s] & DIGIT; /* get units */
@ -1120,7 +1121,7 @@ return SCPE_OK;
t_stat xmt_tnf (uint32 d, uint32 s)
{
t_addr cnt = 0;
uint32 cnt = 0;
uint8 t;
t = M[s]; /* get 1st digit */
@ -1242,7 +1243,7 @@ t_stat mul_field (uint32 mpc, uint32 mpy)
int32 i;
uint32 pro; /* prod pointer */
uint32 mpyd, mpyf; /* mpy digit, flag */
t_addr cnt = 0; /* counter */
uint32 cnt = 0; /* counter */
uint8 sign; /* final sign */
t_stat r;
@ -1299,7 +1300,7 @@ uint32 mpcd, mpcf; /* mpc digit, flag */
uint32 prwp; /* prod working ptr */
uint32 prod; /* product digit */
uint32 cry; /* carry */
t_addr mpcc, cryc; /* counters */
uint32 mpcc, cryc; /* counters */
mptb = MUL_TABLE + ((mpyd <= 4)? (mpyd * 2): /* set mpy table 100's, */
(((mpyd - 5) * 2) + 100)); /* 1's digits */
@ -1535,7 +1536,7 @@ t_stat div_one_digit (uint32 dvd, uint32 dvr, uint32 max,
uint32 dvrp, dvrd, dvrf; /* dvr ptr, dig, flag */
uint32 dvdp, dvdd; /* dvd ptr, dig */
uint32 qd, cry; /* quo dig, carry */
t_addr cnt;
uint32 cnt;
for (qd = 0; qd < max; qd++) { /* devel quo dig */
dvrp = dvr; /* divisor ptr */
@ -1592,7 +1593,7 @@ return SCPE_OK;
t_stat or_field (uint32 d, uint32 s)
{
t_addr cnt = 0;
uint32 cnt = 0;
int32 t;
ind[IN_EZ] = 1; /* assume result zero */
@ -1607,7 +1608,7 @@ return SCPE_OK;
t_stat and_field (uint32 d, uint32 s)
{
t_addr cnt = 0;
uint32 cnt = 0;
int32 t;
ind[IN_EZ] = 1; /* assume result zero */
@ -1622,7 +1623,7 @@ return SCPE_OK;
t_stat xor_field (uint32 d, uint32 s)
{
t_addr cnt = 0;
uint32 cnt = 0;
int32 t;
ind[IN_EZ] = 1; /* assume result zero */
@ -1637,7 +1638,7 @@ return SCPE_OK;
t_stat com_field (uint32 d, uint32 s)
{
t_addr cnt = 0;
uint32 cnt = 0;
int32 t;
ind[IN_EZ] = 1; /* assume result zero */
@ -1667,7 +1668,7 @@ return SCPE_OK;
t_stat oct_to_dec (uint32 tbl, uint32 s)
{
t_addr cnt = 0, tblc;
uint32 cnt = 0, tblc;
uint32 i, sd, sf, tf, sign;
t_stat r;
@ -1715,7 +1716,7 @@ t_stat dec_to_oct (uint32 d, uint32 tbl, int32 *ez)
{
uint32 sign, octd, t;
t_bool first = TRUE;
t_addr ctr = 0;
uint32 ctr = 0;
t_stat r;
sign = M[PROD_AREA + PROD_AREA_LEN - 1] & FLAG; /* input sign */
@ -1794,7 +1795,7 @@ return SCPE_OK;
t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc)
{
int32 mc = 0;
t_addr i;
uint32 i;
if ((val <= 0) || (val > MAXMEMSIZE) || ((val % 1000) != 0))
return SCPE_ARG;

View file

@ -1,6 +1,6 @@
/* i1620_defs.h: IBM 1620 simulator definitions
Copyright (c) 2002, Robert M. Supnik
Copyright (c) 2002-2003, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),

View file

@ -1,14 +1,14 @@
To: Users
From: Bob Supnik
Subj: IBM 1620 Simulator Usage
Date: 15-Nov-2002
Date: 15-Apr-2003
COPYRIGHT NOTICE
The following copyright notice applies to both the SIMH source and binary:
Original code published in 1993-2002, written by Robert M Supnik
Copyright (c) 1993-2002, Robert M Supnik
Original code published in 1993-2003, written by Robert M Supnik
Copyright (c) 1993-2003, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@ -138,10 +138,10 @@ standard on the Model 2.
If memory size is being reduced, and the memory being truncated contains
non-zero data, the simulator asks for confirmation. Data in the truncated
portion of memory is lost. Initially, memory size is 16K, and all special
features are enabled.
portion of memory is lost. Initially, the CPU is a Model I, memory size is
20K, and indirect addressing, editing instructions, and divide are enabled.
Memory is implemented as 5 bit BCD characters, as follows:
Memory is implemented as 5 bit BCD digits, as follows:
4 3 2 1 0
@ -177,8 +177,8 @@ interrupt system.
IND[0:99] 1 indicator array
IAE 1 indirect address enable (Model 2 only)
IDXE 1 indexing enable (Model 2 only)
IDXB 1 indexinb band select (Model 2 only)
IR1Q 1 IR1 prior to last branch;
IDXB 1 indexing band select (Model 2 only)
IR1Q[0:63] 16 IR1 prior to last branch;
most recent IR1 change first
WRU 8 interrupt character
@ -198,12 +198,12 @@ key is pressed. The typewriter has no errors.
2.3 1621 Paper Tape Reader (PTR)
The paper tape reader (PTR) reads data from a disk file. The POS
register specifies the number of the next data item to be read. Thus,
by changing POS, the user can backspace or advance the reader.
The paper tape reader (PTR) reads data from a disk file. The POS register
specifies the number of the next data item to be read. Thus, by changing
POS, the user can backspace or advance the reader.
The paper tape reader supports the BOOT command. BOOT PTR starts the
specified instruction sequence at location 0.
standard paper tape boot sequence at location 0.
The paper tape reader implements these registers:
@ -252,8 +252,8 @@ Error handling is as follows:
The IBM 1402 card/reader punch is simulated as two independent devices:
the card reader (CDR) and the card punch (CDP).
The card reader supports the BOOT command. BOOT CDR starts the
specified instruction sequence at location 0.
The card reader supports the BOOT command. BOOT CDR starts the standard
card boot sequence at location 0.
The card reader reads data from a disk file, while the punch writes data
to a disk file. Cards are simulated as ASCII text lines with terminating
@ -436,11 +436,11 @@ marks the end of the immediate Q operand; and the flags over digits
The IBM 1620 uses single digits to represent numbers, and pairs of
digits to represent characters (alphameric coding). Only a small
number of the 256 possible alphameric codings have legitimate values.
Further, the translation between alphameric and devices varied
from device to device. The simulator implements a code called
Further, the translation between alphameric and devices varied from
device to device. The simulator implements a code called 1620 ASCII,
which allows all 64 possible card codes to be represented by upper
case ASCII characters. In addition, lower case alphabetic
characters are accepted on input as equivalent to upper case.
case ASCII characters. In addition, lower case alphabetic characters
are accepted on input as equivalent to upper case.
Card code PT code RA RN LPT WA ASCII representation

View file

@ -1,6 +1,6 @@
/* i1620_dp.c: IBM 1311 disk simulator
Copyright (c) 2002, Robert M. Supnik
Copyright (c) 2002-2003, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@ -83,7 +83,7 @@ extern uint8 ind[NUM_IND];
extern UNIT cpu_unit;
int32 dp_stop = 1; /* disk err stop */
t_addr dp_ba = 0; /* buffer addr */
uint32 dp_ba = 0; /* buffer addr */
t_stat dp_reset (DEVICE *dptr);
t_stat dp_rdadr (UNIT *uptr, int32 sec, int32 qnr, int32 qwc);

View file

@ -1,6 +1,6 @@
/* i1620_fp.c: IBM 1620 floating point simulator
Copyright (c) 2002, Robert M. Supnik
Copyright (c) 2002-2003, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),

View file

@ -1,6 +1,6 @@
/* i1620_lp.c: IBM 1443 line printer simulator
Copyright (c) 2002, Robert M. Supnik
Copyright (c) 2002-2003, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@ -24,6 +24,8 @@
in this Software without prior written authorization from Robert M Supnik.
lpt 1443 line printer
25-Apr-03 RMS Revised for extended file support
*/
#include "i1620_defs.h"
@ -75,7 +77,7 @@ REG lpt_reg[] = {
{ FLDATA (PRCH9, ind[IN_PRCH9], 0) },
{ FLDATA (PRCH12, ind[IN_PRCH12], 0) },
{ FLDATA (PRBSY, ind[IN_PRBSY], 0) },
{ DRDATA (POS, lpt_unit.pos, 32), PV_LEFT },
{ DRDATA (POS, lpt_unit.pos, T_ADDR_W), PV_LEFT },
{ BRDATA (CCT, cct, 8, 32, CCT_LNT) },
{ DRDATA (CCTP, cct_ptr, 8), PV_LEFT },
{ DRDATA (CCTL, cct_lnt, 8), REG_RO + PV_LEFT },

View file

@ -1,6 +1,6 @@
/* i1620_pt.c: IBM 1621/1624 paper tape reader/punch simulator
Copyright (c) 2002, Robert M Supnik
Copyright (c) 2002-2003, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@ -25,6 +25,8 @@
ptr 1621 paper tape reader
ptp 1624 paper tape punch
25-Apr-03 RMS Revised for extended file support
*/
#include "i1620_defs.h"
@ -58,7 +60,7 @@ UNIT ptr_unit = {
UDATA (NULL, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0) };
REG ptr_reg[] = {
{ DRDATA (POS, ptr_unit.pos, 32), PV_LEFT },
{ DRDATA (POS, ptr_unit.pos, T_ADDR_W), PV_LEFT },
{ NULL } };
DEVICE ptr_dev = {
@ -78,7 +80,7 @@ UNIT ptp_unit = {
UDATA (NULL, UNIT_SEQ+UNIT_ATTABLE, 0) };
REG ptp_reg[] = {
{ DRDATA (POS, ptp_unit.pos, 32), PV_LEFT },
{ DRDATA (POS, ptp_unit.pos, T_ADDR_W), PV_LEFT },
{ NULL } };
DEVICE ptp_dev = {
@ -197,7 +199,7 @@ const int8 alp_to_ptp[256] = {
t_stat ptr (uint32 op, uint32 pa, uint32 f0, uint32 f1)
{
t_addr i;
uint32 i;
int8 mc;
uint8 ptc;
t_stat r, inv = SCPE_OK;
@ -243,7 +245,7 @@ return STOP_RWRAP;
t_stat btr (uint32 op, uint32 pa, uint32 f0, uint32 f1)
{
t_addr i;
uint32 i;
uint8 ptc;
t_stat r, inv = SCPE_OK;
@ -333,7 +335,7 @@ return SCPE_OK;
t_stat ptp (uint32 op, uint32 pa, uint32 f0, uint32 f1)
{
t_addr i;
uint32 i;
int8 ptc;
uint8 z, d;
t_stat r;
@ -366,7 +368,7 @@ return STOP_RWRAP;
t_stat btp (uint32 op, uint32 pa, uint32 f0, uint32 f1)
{
t_addr i;
uint32 i;
uint8 ptc, z, d;
t_stat r;

View file

@ -1,6 +1,6 @@
/* i1620_sys.c: IBM 1620 simulator interface
Copyright (c) 2002, Robert M. Supnik
Copyright (c) 2002-2003, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),

View file

@ -1,6 +1,6 @@
/* i1620_tty.c: IBM 1620 typewriter
Copyright (c) 2002, Robert M. Supnik
Copyright (c) 2002-2003, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),

View file

@ -15,6 +15,7 @@
10-May-02 BLK Fixed bug in MDX instruction
27-Mar-02 BLK Made BOSC work even in short form
16-Aug-02 BLK Fixed bug in multiply instruction; didn't work with negative values
18-Mar-03 BLK Fixed bug in divide instruction; didn't work with negative values
The register state for the IBM 1130 CPU is:
@ -883,7 +884,7 @@ t_stat sim_instr (void)
break;
case 0x11: /* --- AD - Add Double --- */
src = ((ACC << 16) + (EXT & 0xFFFF));
src = ((ACC << 16) | (EXT & 0xFFFF));
src2 = (ReadW(eaddr) << 16) + ReadW(eaddr|1);
dst = src + src2;
ACC = (dst >> 16) & 0xFFFF;
@ -905,7 +906,7 @@ t_stat sim_instr (void)
break;
case 0x13: /* --- SD - Subtract Double --- */
src = ((ACC << 16) + (EXT & 0xFFFF));
src = ((ACC << 16) | (EXT & 0xFFFF));
src2 = (ReadW(eaddr) << 16) + ReadW(eaddr|1);
dst = src - src2;
ACC = (dst >> 16) & 0xFFFF;
@ -918,9 +919,9 @@ t_stat sim_instr (void)
case 0x14: /* --- M - Multiply --- */
if ((src = ACC & 0xFFFF) & 0x8000) /* sign extend the values */
src |= 0xFFFF0000;
src |= ~0xFFFF;
if ((src2 = ReadW(eaddr)) & 0x8000)
src2 |= 0xFFFF0000;
src2 |= ~0xFFFF;
dst = src * src2;
ACC = (dst >> 16) & 0xFFFF; /* split the results */
@ -928,8 +929,10 @@ t_stat sim_instr (void)
break;
case 0x15: /* --- D - Divide --- */
src = ((ACC << 16) + EXT);
src2 = ReadW(eaddr);
src = ((ACC << 16) | (EXT & 0xFFFF));
if ((src2 = ReadW(eaddr)) & 0x8000)
src2 |= ~0xFFFF; /* oops: sign extend was missing, fixed 18Mar03 */
if (src2 == 0)
V = 1; /* divide by zero just sets overflow, ACC & EXT are undefined */
else {
@ -1251,7 +1254,7 @@ void xio_error (char *msg)
* register_cmd - add a command to the extensible command table
* ------------------------------------------------------------------------ */
t_stat register_cmd (char *name, t_stat (*action)(), int arg, char *help)
t_stat register_cmd (char *name, t_stat (*action)(int32, char *), int arg, char *help)
{
int i;

View file

@ -16,7 +16,12 @@
NOTE - there is a problem with this code. The Device Status Word (DSW) is
computed from current conditions when requested by an XIO load status
command; the value of DSW available to the simulator's examine & save
commands may NOT be accurate. This should probably be fixed.
commands may NOT be accurate. This should probably be fixed. (I think there's
a way to have the expression evaluator call a routine? That would be one
way to solve the problem, the other is to keep DSW up-to-date all the time).
* Update 2003-02-08: Fixed error in declaration of array list_save, pointed
out by Ray Comas.
* Update 2002-02-29: Added deck-list option. If you issue an attach
command and specify the filename as "@filename", the named file is interpreted
@ -436,8 +441,9 @@ static char tempfile[128];
static int cardnum;
static int any_punched = 0;
#define MAXARG 80 /* saved arguments to attach command */
static char list_save[MAXARG][10], *list_arg[MAXARG];
#define MAXARGLEN 80 /* max length of a saved attach command argument */
#define MAXARGS 10 /* max number of arguments to save */
static char list_save[MAXARGS][MAXARGLEN], *list_arg[MAXARGLEN];
static int list_nargs = 0;
static int16 punchstation[80];
@ -497,12 +503,12 @@ t_stat set_active_cr_code (int match)
return SCPE_OK;
}
t_stat cr_set_code (UNIT *uptr, int32 match, char *cptr, void *desc)
static t_stat cr_set_code (UNIT *uptr, int32 match, char *cptr, void *desc)
{
return set_active_cr_code(match);
}
t_stat cp_set_code (UNIT *uptr, int32 match, char *cptr, void *desc)
static t_stat cp_set_code (UNIT *uptr, int32 match, char *cptr, void *desc)
{
CPCODE *code;
int ncode;
@ -964,7 +970,6 @@ static t_stat cr_attach (UNIT *uptr, char *cptr)
// no - don't cancel pending read?
// sim_cancel(uptr); /* cancel pending operations */
CLRBIT(uptr->flags, UNIT_QUIET|UNIT_DEBUG); /* set debug/quiet flags */
if (sim_switches & SWMASK('D')) SETBIT(uptr->flags, UNIT_DEBUG);
else if (sim_switches & SWMASK('Q')) SETBIT(uptr->flags, UNIT_QUIET);
@ -972,15 +977,15 @@ static t_stat cr_attach (UNIT *uptr, char *cptr)
cr_detach(uptr); /* detach file and possibly deckfile */
CLRBIT(uptr->flags, UNIT_SCRATCH);
c = cptr;
for (list_nargs = 0; list_nargs < 10; ) { /* extract arguments */
c = cptr; /* extract arguments */
for (list_nargs = 0; list_nargs < MAXARGS; list_nargs++) {
while (*c && (*c <= ' ')) /* skip blanks */
c++;
if (! *c)
break; /* all done */
arg = c; /* save start */
while (*c && (*c > ' ')) {
if (*c == '\'' || *c == '"') { /* quoted string */
for (quote = *c++; *c;)
@ -989,11 +994,12 @@ static t_stat cr_attach (UNIT *uptr, char *cptr)
}
else c++;
}
if (*c)
*c++ = 0; /* term arg at space */
list_arg[list_nargs] = list_save[list_nargs]; /* set pointer to permanent storage location */
strncpy(list_arg[list_nargs++], arg, MAXARG); /* store copy */
strncpy(list_arg[list_nargs], arg, MAXARGLEN); /* store copy */
}
if (list_nargs <= 0) /* need at least 1 */

View file

@ -271,7 +271,7 @@ void remark_cmd (char *remark);
void stuff_cmd (char *cmd);
void update_gui (t_bool force);
void sim_init (void);
t_stat register_cmd (char *name, t_stat (*action)(), int arg, char *help);
t_stat register_cmd (char *name, t_stat (*action)(int32, char *), int arg, char *help);
/* GUI interface routines */
t_bool keyboard_is_locked (void);

View file

@ -188,7 +188,7 @@ static void Beep (void) // notify user keyboard was locked or key was bad
// tti_svc - keyboard polling (never stops)
t_stat tti_svc (UNIT *uptr)
static t_stat tti_svc (UNIT *uptr)
{
int32 temp;
@ -243,7 +243,7 @@ t_stat tti_svc (UNIT *uptr)
return SCPE_OK;
}
t_stat tti_reset (DEVICE *dptr)
static t_stat tti_reset (DEVICE *dptr)
{
tti_unit.buf = 0;
tti_dsw = 0;
@ -262,7 +262,7 @@ t_bool keyboard_is_locked (void) /* return TRUE if keyboard is not expecting
return (tti_dsw & TT_DSW_KEYBOARD_BUSY) == 0;
}
t_stat tto_svc (UNIT *uptr)
static t_stat tto_svc (UNIT *uptr)
{
int32 temp;
int ch;
@ -300,7 +300,7 @@ t_stat tto_svc (UNIT *uptr)
return SCPE_OK;
}
t_stat tto_reset (DEVICE *dptr)
static t_stat tto_reset (DEVICE *dptr)
{
tto_unit.buf = 0;
tto_dsw = 0;

View file

@ -1,3 +1,12 @@
Version: 18 March 2003
History (partial):
2003-03-18 Fixed bug in asm1130 that produced an error message
with a (legal) offset of +127 in MDX instructions.
Fixed sign bug in 1130 emulator divide instruction.
Interim 1130 distribution:
--------------------------------------------

View file

@ -1,6 +1,6 @@
/* id16_cpu.c: Interdata 16b CPU simulator
Copyright (c) 2000-2002, Robert M. Supnik
Copyright (c) 2000-2003, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@ -1683,7 +1683,7 @@ return SCPE_OK;
t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc)
{
int32 mc = 0;
t_addr i;
uint32 i;
if ((val <= 0) || ((val & 0xFFF) != 0) ||
(((uint32) val) > ((uptr->flags & UNIT_816E)? MAXMEMSIZE16E: MAXMEMSIZE16)))
@ -1700,7 +1700,7 @@ return SCPE_OK;
t_stat cpu_set_model (UNIT *uptr, int32 val, char *cptr, void *desc)
{
t_addr i;
uint32 i;
if (!(val & UNIT_816E) && (MEMSIZE > MAXMEMSIZE16)) {
MEMSIZE = MAXMEMSIZE16;

View file

@ -1,6 +1,6 @@
/* id16_dboot.c: Interdata 16b simulator disk bootstrap
Copyright (c) 2000-2002, Robert M. Supnik
Copyright (c) 2000-2003, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),

View file

@ -1993,7 +1993,7 @@ return SCPE_OK;
t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc)
{
uint32 mc = 0;
t_addr i;
uint32 i;
if ((val <= 0) || (val > MAXMEMSIZE32) || ((val & 0xFFFF) != 0))
return SCPE_ARG;

View file

@ -1,6 +1,6 @@
/* id_defs.h: Interdata 16b/32b simulator definitions
Copyright (c) 2000-2002, Robert M. Supnik
Copyright (c) 2000-2003, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@ -26,6 +26,8 @@
The author gratefully acknowledges the help of Carl Friend and Al Kossow,
who provided key documents about the Interdata product line.
21-Jun-03 RMS Changed subroutine argument for ARM compiler conflict
25-Apr-03 RMS Revised for extended file support
28-Feb-03 RMS Changed magtape device default to 0x85
*/
@ -52,7 +54,7 @@
#define PAMASK32 (MAXMEMSIZE32 - 1)
#define MEMSIZE (cpu_unit.capac) /* act memory size */
#define MEM_ADDR_OK(x) (((t_addr) (x)) < MEMSIZE)
#define MEM_ADDR_OK(x) (((uint32) (x)) < MEMSIZE)
/* Single precision floating point registers */
@ -171,8 +173,8 @@ typedef struct dpr dpr_t;
struct BlockIO {
uint32 dfl; /* devno, flags */
t_addr cur; /* current addr */
t_addr end; /* end addr */
uint32 cur; /* current addr */
uint32 end; /* end addr */
};
#define BL_RD 0x8000 /* block read */
@ -466,7 +468,7 @@ typedef struct interdib DIB;
/* Function prototypes */
int32 int_chg (uint32 irq, int32 dat, int32 arm);
int32 int_chg (uint32 irq, int32 dat, int32 armdis);
int32 io_2b (int32 val, int32 pos, int32 old);
uint32 IOReadB (uint32 loc);
void IOWriteB (uint32 loc, uint32 val);

View file

@ -46,8 +46,8 @@ sim/ sim_defs.h
sim_tmxr.c
sim/interdata/ id_defs.h
id16_cpu.c [or id32_cpu.c]
id16_dboot.c [or id32_dboot.c]
id16_cpu.c [id32_cpu.c]
id16_dboot.c [id32_dboot.c]
id_dp.c
id_fd.c
id_fp.c
@ -60,7 +60,7 @@ sim/interdata/ id_defs.h
id_tt.c
id_ttp.c
id_uvc.c
id16_sys.c [or id32_sys.c]
id16_sys.c [id32_sys.c]
2. Interdata Features
@ -235,9 +235,6 @@ control registers for the interrupt system.
R0..R15 32 active general register set
GREG[32] 32 general register sets, 16 x 2
FR0..FR14 32 single precision floating point registers
if double precision floating point; for
microcoded floating point, floating point
registers are kept in memory locations 00 - 1F
D0H..D14H 32 double precision floating point registers,
high order
D0L..D14L 32 double precision floating point registers,
@ -521,8 +518,8 @@ The programmable interval clock (PIC) implements these registers:
IENB 1 clock interrupt enable
IARM 1 clock interrupt armed
If the interval requested is longer than 1 msec, and a multiple of
1 msec, the programmable clock auto-calibrates; if not, it simply
If the interval requested is an exact multiple of 1 msec, the
programmable clock auto-calibrates; if not, it simply counts
counts instructions.
2.4.7 Floppy Disk Controller (FD)
@ -587,7 +584,7 @@ or 8B. In UC mode, lower case input and output characters are converted
automatically to upper case. In 7B mode, input and output characters are
masked to 7 bits. In 8B mode, characters are not modified. The default
mode is UC. Each line (each unit of PASL) can also be set for modem
control with the command SET PASLn DATASET. The defaults are UC mode
control with the command SET PASLn DATASET. The defaults are 7b mode
and DATASET disabled.
Once PAS is attached and the simulator is running, the terminals listen

View file

@ -25,6 +25,7 @@
dp M46-421 2.5MB/10MB cartridge disk
25-Apr-03 RMS Revised for extended file support
16-Feb-03 RMS Fixed read to test transfer ok before selch operation
*/
@ -151,7 +152,7 @@ uint32 dpd_arm[DP_NUMDR] = { 0 }; /* drives armed */
int32 dp_stime = 100; /* seek latency */
int32 dp_rtime = 100; /* rotate latency */
int32 dp_wtime = 1; /* word time */
int32 dp_log = 0; /* debug log */
uint32 dp_log = 0; /* debug log */
uint8 dp_tplte[(2 * DP_NUMDR) + 2]; /* fix/rmv + ctrl + end */
DEVICE dp_dev;
@ -210,7 +211,7 @@ REG dp_reg[] = {
DP_NUMDR, REG_RO) },
{ URDATA (UST, dp_unit[0].STD, 16, 8, 0,
DP_NUMDR, REG_RO) },
{ URDATA (CAPAC, dp_unit[0].capac, 10, 31, 0,
{ URDATA (CAPAC, dp_unit[0].capac, 10, T_ADDR_W, 0,
DP_NUMDR, PV_LEFT | REG_HRO) },
{ FLDATA (LOG, dp_log, 0), REG_HIDDEN },
{ HRDATA (DEVNO, dp_dib.dno, 8), REG_HRO },
@ -513,9 +514,10 @@ uint32 i, p;
t_stat r;
uptr->capac = drv_tab[GET_DTYPE (uptr->flags)].size;
r = attach_unit (uptr, cptr);
r = attach_unit (uptr, cptr); /* attach unit */
if (r != SCPE_OK) return r; /* error? */
uptr->CYL = 0;
if ((r != SCPE_OK) || ((uptr->flags & UNIT_AUTO) == 0)) return r;
if ((uptr->flags & UNIT_AUTO) == 0) return SCPE_OK; /* autosize? */
if (fseek (uptr->fileref, 0, SEEK_END)) return SCPE_OK;
if ((p = ftell (uptr->fileref)) == 0) return SCPE_OK;
for (i = 0; drv_tab[i].surf != 0; i++) {

View file

@ -1,6 +1,6 @@
/* id_fd.c: Interdata floppy disk simulator
Copyright (c) 2001-2002, Robert M Supnik
Copyright (c) 2001-2003, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@ -275,8 +275,7 @@ return 0;
t_stat fd_svc (UNIT *uptr)
{
uint32 i, u, tk, sc, crc, fnc;
t_addr da;
uint32 i, u, tk, sc, crc, fnc, da;
u = uptr - fd_dev.units; /* get unit number */
fnc = GET_FNC (uptr->FNC); /* get function */

View file

@ -1,6 +1,6 @@
/* id_fp.c: Interdata floating point instructions
Copyright (c) 2000-2002, Robert M. Supnik
Copyright (c) 2000-2003, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),

View file

@ -25,6 +25,7 @@
idc MSM/IDC disk controller
25-Apr-03 RMS Revised for extended file support
16-Feb-03 RMS Fixed read to test transfer ok before selch operation
Note: define flag ID_IDC to enable the extra functions of the intelligent
@ -273,7 +274,7 @@ REG idc_reg[] = {
ID_NUMDR, REG_HRO) },
{ URDATA (UST, idc_unit[0].STD, 16, 8, 0,
ID_NUMDR, REG_RO) },
{ URDATA (CAPAC, idc_unit[0].capac, 10, 31, 0,
{ URDATA (CAPAC, idc_unit[0].capac, 10, T_ADDR_W, 0,
ID_NUMDR, PV_LEFT | REG_HRO) },
{ HRDATA (DEVNO, idc_dib.dno, 8), REG_HRO },
{ HRDATA (SELCH, idc_dib.sch, 2), REG_HRO },
@ -668,9 +669,10 @@ uint32 i, p;
t_stat r;
uptr->capac = drv_tab[GET_DTYPE (uptr->flags)].size;
r = attach_unit (uptr, cptr);
r = attach_unit (uptr, cptr); /* attach unit */
if (r != SCPE_OK) return r; /* error? */
uptr->CYL = 0;
if ((r != SCPE_OK) || ((uptr->flags & UNIT_AUTO) == 0)) return r;
if ((uptr->flags & UNIT_AUTO) == 0) return SCPE_OK; /* autosize? */
if (fseek (uptr->fileref, 0, SEEK_END)) return SCPE_OK;
if ((p = ftell (uptr->fileref)) == 0) return SCPE_OK;
for (i = 0; drv_tab[i].surf != 0; i++) {

View file

@ -1,6 +1,6 @@
/* id_io.c: Interdata CPU-independent I/O routines
Copyright (c) 2001-2002, Robert M. Supnik
Copyright (c) 2001-2003, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@ -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-Jun-03 RMS Changed subroutine argument for ARM compiler conflict
Interdata I/O devices are defined by a device information block:
dno base device number
@ -391,7 +393,7 @@ return 0;
/* Update device interrupt status */
int32 int_chg (uint32 irq, int32 dat, int32 arm)
int32 int_chg (uint32 irq, int32 dat, int32 armdis)
{
int32 t = CMD_GETINT (dat); /* get int ctrl */
@ -405,7 +407,7 @@ if (t == CMD_IDSA) { /* disarm? */
CLR_ENB (irq);
CLR_INT (irq);
return 0; }
return arm;
return armdis;
}
/* Process a 2b field and return unchanged, set, clear, complement */

View file

@ -1,6 +1,6 @@
/* id_lp.c: Interdata line printer
Copyright (c) 2001-2002, Robert M. Supnik
Copyright (c) 2001-2003, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@ -24,6 +24,8 @@
in this Software without prior written authorization from Robert M Supnik.
lpt M46-206 line printer
25-Apr-03 RMS Revised for extended file support
*/
#include "id_defs.h"
@ -94,7 +96,7 @@ REG lpt_reg[] = {
{ FLDATA (IREQ, int_req[l_LPT], i_LPT) },
{ FLDATA (IENB, int_enb[l_LPT], i_LPT) },
{ FLDATA (IARM, lpt_arm, 0) },
{ DRDATA (POS, lpt_unit.pos, 32), PV_LEFT },
{ DRDATA (POS, lpt_unit.pos, T_ADDR_W), PV_LEFT },
{ DRDATA (CTIME, lpt_ctime, 24), PV_LEFT },
{ DRDATA (STIME, lpt_stime, 24), PV_LEFT },
{ FLDATA (STOP_IOE, lpt_stopioe, 0) },

View file

@ -25,6 +25,8 @@
mt M46-494 dual density 9-track magtape controller
25-Apr-03 RMS Revised for extended file support
28-Mar-03 RMS Added multiformat support
28-Feb-03 RMS Revised for magtape library
20-Feb-03 RMS Fixed read to stop selch on error
@ -135,7 +137,7 @@ REG mt_reg[] = {
{ DRDATA (RTIME, mt_rtime, 24), PV_LEFT + REG_NZ },
{ URDATA (UST, mt_unit[0].UST, 16, 8, 0, MT_NUMDR, 0) },
{ URDATA (CMD, mt_unit[0].UCMD, 16, 8, 0, MT_NUMDR, 0) },
{ URDATA (POS, mt_unit[0].pos, 10, 32, 0,
{ URDATA (POS, mt_unit[0].pos, 10, T_ADDR_W, 0,
MT_NUMDR, PV_LEFT | REG_RO) },
{ HRDATA (DEVNO, mt_dib.dno, 8), REG_HRO },
{ HRDATA (SELCH, mt_dib.sch, 1), REG_HRO },
@ -144,6 +146,8 @@ REG mt_reg[] = {
MTAB mt_mod[] = {
{ MTUF_WLK, 0, "write enabled", "WRITEENABLED", NULL },
{ MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL },
{ MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT",
&sim_tape_set_fmt, &sim_tape_show_fmt, NULL },
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO",
&set_dev, &show_dev, NULL },
{ MTAB_XTD|MTAB_VDV, 0, "SELCH", "SELCH",

View file

@ -25,6 +25,8 @@
pas Programmable asynchronous line adapter(s)
09-May-03 RMS Added network device flag
This module implements up to 32 individual serial interfaces, representing
either individual PASLA modules or combinations of the 2-line and 8-line
multiplexors, which are functionally very similar. These interfaces are mapped
@ -160,7 +162,7 @@ DEVICE pas_dev = {
1, 10, 31, 1, 16, 8,
&tmxr_ex, &tmxr_dep, &pas_reset,
NULL, &pas_attach, &pas_detach,
&pas_dib, DEV_DISABLE };
&pas_dib, DEV_NET | DEV_DISABLE };
/* PASL data structures

View file

@ -1,6 +1,6 @@
/* id_pt.c: Interdata paper tape reader
Copyright (c) 2000-2001, Robert M. Supnik
Copyright (c) 2000-2003, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@ -24,6 +24,9 @@
in this Software without prior written authorization from Robert M Supnik.
pt paper tape reader and punch
25-Apr-03 RMS Revised for extended file support
10-Apr-03 RMS Fixed type problem in ptr service (from Mark Pizzolato)
*/
#include "id_defs.h"
@ -76,11 +79,11 @@ UNIT pt_unit[] = {
REG pt_reg[] = {
{ HRDATA (STA, pt_sta, 8) },
{ HRDATA (RBUF, pt_unit[PTR].buf, 8) },
{ DRDATA (RPOS, pt_unit[PTR].pos, 32), PV_LEFT },
{ DRDATA (RPOS, pt_unit[PTR].pos, T_ADDR_W), PV_LEFT },
{ DRDATA (RTIME, pt_unit[PTR].wait, 24), PV_LEFT },
{ FLDATA (RSTOP_IOE, ptr_stopioe, 0) },
{ HRDATA (PBUF, pt_unit[PTP].buf, 8) },
{ DRDATA (PPOS, pt_unit[PTP].pos, 32), PV_LEFT },
{ DRDATA (PPOS, pt_unit[PTP].pos, T_ADDR_W), PV_LEFT },
{ DRDATA (PTIME, pt_unit[PTP].wait, 24), PV_LEFT },
{ FLDATA (PSTOP_IOE, ptp_stopioe, 0) },
{ FLDATA (IREQ, int_req[l_PT], i_PT) },
@ -164,7 +167,7 @@ return 0;
t_stat ptr_svc (UNIT *uptr)
{
uint32 temp;
int32 temp;
if ((uptr->flags & UNIT_ATT) == 0) /* attached? */
return IORETURN (ptr_stopioe, SCPE_UNATT);
@ -324,8 +327,7 @@ static uint8 load_rom[] = {
t_stat pt_dump (FILE *of, char *cptr, char *fnam)
{
t_addr i, lo, hi;
uint32 cs;
uint32 i, lo, hi, cs;
char *tptr;
extern DEVICE cpu_dev;

View file

@ -25,6 +25,7 @@
tt console
25-Apr-03 RMS Revised for extended file support
11-Jan-03 RMS Added TTP support
22-Dec-02 RMS Added break support
*/
@ -83,10 +84,10 @@ UNIT tt_unit[] = {
REG tt_reg[] = {
{ HRDATA (STA, tt_sta, 8) },
{ HRDATA (KBUF, tt_unit[TTI].buf, 8) },
{ DRDATA (KPOS, tt_unit[TTI].pos, 32), PV_LEFT },
{ DRDATA (KPOS, tt_unit[TTI].pos, T_ADDR_W), PV_LEFT },
{ DRDATA (KTIME, tt_unit[TTI].wait, 24), REG_NZ + PV_LEFT },
{ HRDATA (TBUF, tt_unit[TTO].buf, 8) },
{ DRDATA (TPOS, tt_unit[TTO].pos, 32), PV_LEFT },
{ DRDATA (TPOS, tt_unit[TTO].pos, T_ADDR_W), PV_LEFT },
{ DRDATA (TTIME, tt_unit[TTO].wait, 24), REG_NZ + PV_LEFT },
{ FLDATA (IREQ, int_req[l_TT], i_TT) },
{ FLDATA (IENB, int_enb[l_TT], i_TT) },

View file

@ -24,6 +24,8 @@
in this Software without prior written authorization from Robert M Supnik.
ttp console (on PAS)
25-Apr-03 RMS Revised for extended file support
*/
#include "id_defs.h"
@ -83,14 +85,14 @@ UNIT ttp_unit[] = {
REG ttp_reg[] = {
{ HRDATA (CMD, ttp_cmd, 16) },
{ HRDATA (KBUF, ttp_unit[TTI].buf, 8) },
{ DRDATA (KPOS, ttp_unit[TTI].pos, 32), PV_LEFT },
{ DRDATA (KPOS, ttp_unit[TTI].pos, T_ADDR_W), PV_LEFT },
{ DRDATA (KTIME, ttp_unit[TTI].wait, 24), REG_NZ + PV_LEFT },
{ FLDATA (KIREQ, int_req[l_TTP], i_TTP) },
{ FLDATA (KIENB, int_enb[l_TTP], i_TTP) },
{ FLDATA (KARM, ttp_karm, 0) },
{ FLDATA (CHP, ttp_kchp, 0) },
{ HRDATA (TBUF, ttp_unit[TTO].buf, 8) },
{ DRDATA (TPOS, ttp_unit[TTO].pos, 32), PV_LEFT },
{ DRDATA (TPOS, ttp_unit[TTO].pos, T_ADDR_W), PV_LEFT },
{ DRDATA (TTIME, ttp_unit[TTO].wait, 24), REG_NZ + PV_LEFT },
{ FLDATA (TIREQ, int_req[l_TTP], i_TTP + 1) },
{ FLDATA (TIENB, int_enb[l_TTP], i_TTP + 1) },

View file

@ -1,6 +1,6 @@
/* id_uvc.c: Interdata universal clock
Copyright (c) 2001-2002, Robert M. Supnik
Copyright (c) 2001-2003, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),

View file

@ -2,7 +2,7 @@
Modified from the original NOVA simulator by Robert Supnik.
Copyright (c) 1998-2002, Charles E Owen
Copyright (c) 1998-2003, Charles E Owen
Portions Copyright (c) 1993-2002, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a
@ -2953,7 +2953,7 @@ int32 pushrtn(int32 pc)
int32 GetMap(int32 addr)
{
int32 page;
t_addr paddr;
uint32 paddr;
switch (Usermap) {
case 0:
@ -3015,7 +3015,7 @@ int32 GetMap(int32 addr)
int32 PutMap(int32 addr, int32 data)
{
int32 page;
t_addr paddr;
uint32 paddr;
switch (Usermap) {
case 0:
@ -3060,7 +3060,7 @@ int32 PutMap(int32 addr, int32 data)
#if 0
int16 GetDCHMap(int32 map, int32 addr)
{
t_addr paddr;
uint32 paddr;
if (!(MapStat & 02)) return M[addr];
paddr = ((Map[map][(addr >> 10) & 037] & PAGEMASK) << 10) | (addr & 001777);
if (paddr < MEMSIZE)
@ -3070,7 +3070,7 @@ int16 GetDCHMap(int32 map, int32 addr)
int16 PutDCHMap(int32 map, int32 addr, int16 data)
{
t_addr paddr;
uint32 paddr;
if (!(MapStat & 02)) {
M[addr] = data;
return (data);
@ -3192,7 +3192,7 @@ return SCPE_OK;
t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc)
{
int32 mc = 0;
t_addr i;
uint32 i;
if ((val <= 0) || (val > MAXMEMSIZE) || ((val & 07777) != 0))
return SCPE_ARG;

View file

@ -1,6 +1,6 @@
/* eclipse_tt.c: Eclipse console terminal simulator
Copyright (c) 1998-2002, Charles E Owen
Copyright (c) 1998-2003, Charles E Owen
Portions copyright (c) 1993-2002, Robert M Supnik
Written by Charles Owen, used by gracious permission
Commercial use prohibited
@ -8,6 +8,7 @@
tti terminal input
tto terminal output
25-Apr-03 RMS Revised for extended file support
03-Oct-02 RMS Added DIBs
30-May-02 RMS Widened POS to 32b
28-Jan-02 RMS Cleaned up compiler warnings
@ -49,7 +50,7 @@ REG tti_reg[] = {
{ FLDATA (DONE, dev_done, INT_V_TTI) },
{ FLDATA (DISABLE, dev_disable, INT_V_TTI) },
{ FLDATA (INT, int_req, INT_V_TTI) },
{ DRDATA (POS, tti_unit.pos, 32), PV_LEFT },
{ DRDATA (POS, tti_unit.pos, T_ADDR_W), PV_LEFT },
{ DRDATA (TIME, tti_unit.wait, 24), REG_NZ + PV_LEFT },
{ NULL } };
@ -82,7 +83,7 @@ REG tto_reg[] = {
{ FLDATA (DONE, dev_done, INT_V_TTO) },
{ FLDATA (DISABLE, dev_disable, INT_V_TTO) },
{ FLDATA (INT, int_req, INT_V_TTO) },
{ DRDATA (POS, tto_unit.pos, 32), PV_LEFT },
{ DRDATA (POS, tto_unit.pos, T_ADDR_W), PV_LEFT },
{ DRDATA (TIME, tto_unit.wait, 24), PV_LEFT },
{ NULL } };

View file

@ -674,9 +674,9 @@ else { /* IOT */
case ioDOC:
if ((dstAC == 2) && (cpu_unit.flags & UNIT_MDV)) {
uint32 mddata, uAC0, uAC1, uAC2;
uAC0 = (unsigned int32) AC[0];
uAC1 = (unsigned int32) AC[1];
uAC2 = (unsigned int32) AC[2];
uAC0 = (uint32) AC[0];
uAC1 = (uint32) AC[1];
uAC2 = (uint32) AC[2];
if (pulse == iopP) { /* mul */
mddata = (uAC1 * uAC2) + uAC0;
AC[0] = (mddata >> 16) & DMASK;

View file

@ -61,7 +61,7 @@
#define MEMSIZE (cpu_unit.capac) /* actual memory size */
#define A_V_IND 15 /* ind: indirect */
#define A_IND (1 << A_V_IND)
#define MEM_ADDR_OK(x) (((t_addr) (x)) < MEMSIZE)
#define MEM_ADDR_OK(x) (((uint32) (x)) < MEMSIZE)
/* Architectural constants */

View file

@ -1,6 +1,6 @@
/* nova_dkp.c: NOVA moving head disk simulator
Copyright (c) 1993-2002, Robert M. Supnik
Copyright (c) 1993-2003, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@ -25,6 +25,7 @@
dkp moving head disk
25-Apr-03 RMS Revised autosizing
08-Oct-02 RMS Added DIB
06-Jan-02 RMS Revised enable/disable support
30-Nov-01 RMS Added read only unit, extended SET/SHOW support
@ -76,10 +77,10 @@
#define USSC_M_UNIT 03
#define USSC_UNIT (USSC_M_UNIT << USSC_V_UNIT)
#define GET_COUNT(x) (((x) >> USSC_V_COUNT) & USSC_M_COUNT)
#define GET_SECT(x,dt) ((drv_tab[dt].new)? \
#define GET_SECT(x,dt) ((drv_tab[dt].newf)? \
(((x) >> USSC_V_NSECTOR) & USSC_M_NSECTOR): \
(((x) >> USSC_V_OSECTOR) & USSC_M_OSECTOR) )
#define GET_SURF(x,dt) ((drv_tab[dt].new)? \
#define GET_SURF(x,dt) ((drv_tab[dt].newf)? \
(((x) >> USSC_V_NSURFACE) & USSC_M_NSURFACE): \
(((x) >> USSC_V_OSURFACE) & USSC_M_OSURFACE) )
#define GET_UNIT(x) (((x) >> USSC_V_UNIT) & USSC_M_UNIT)
@ -105,10 +106,10 @@
#define FCCY_SEEK 2
#define FCCY_RECAL 3
#define FCCY_FLAGS 0174000 /* flags */
#define GET_CMD(x,dt) ((drv_tab[dt].new)? \
#define GET_CMD(x,dt) ((drv_tab[dt].newf)? \
(((x) >> FCCY_V_NCMD) & FCCY_M_NCMD): \
(((x) >> FCCY_V_OCMD) & FCCY_M_OCMD) )
#define GET_CYL(x,dt) ((drv_tab[dt].new)? \
#define GET_CYL(x,dt) ((drv_tab[dt].newf)? \
(((x) >> FCCY_V_NCYL) & FCCY_M_NCYL): \
((((x) >> FCCY_V_OCYL) & FCCY_M_OCYL) | \
((dt != TYPE_D44)? 0: \
@ -254,7 +255,7 @@ struct drvtyp {
int32 surf; /* surfaces */
int32 cyl; /* cylinders */
int32 size; /* #blocks */
int32 new; /* new format flag */
int32 newf; /* new format flag */
};
struct drvtyp drv_tab[] = {
@ -323,7 +324,7 @@ REG dkp_reg[] = {
{ FLDATA (DISABLE, dev_disable, INT_V_DKP) },
{ DRDATA (STIME, dkp_swait, 24), PV_LEFT },
{ DRDATA (RTIME, dkp_rwait, 24), PV_LEFT },
{ URDATA (CAPAC, dkp_unit[0].capac, 10, 31, 0,
{ URDATA (CAPAC, dkp_unit[0].capac, 10, T_ADDR_W, 0,
DKP_NUMDR, PV_LEFT | REG_HRO) },
{ NULL } };
@ -460,7 +461,7 @@ case ioDIB: /* DIB */
break;
case ioDOB: /* DOB */
if ((dev_busy & INT_DKP) == 0) dkp_ma =
AC & (drv_tab[dtype].new? DMASK: AMASK);
AC & (drv_tab[dtype].newf? DMASK: AMASK);
break;
case ioDIC: /* DIC */
rval = dkp_ussc; /* return unit, sect */
@ -618,7 +619,7 @@ else { sc = 16 - GET_COUNT (dkp_ussc); /* get sector count */
newsect = sa % drv_tab[dtype].sect;
newsurf = (sa / drv_tab[dtype].sect) % drv_tab[dtype].surf;
dkp_ussc = (dkp_ussc & USSC_UNIT) | ((dkp_ussc + sc) & USSC_M_COUNT) |
((drv_tab[dtype].new)?
((drv_tab[dtype].newf)?
((newsurf << USSC_V_NSURFACE) | (newsect << USSC_V_NSECTOR)):
((newsurf << USSC_V_OSURFACE) | (newsect << USSC_V_OSECTOR)) );
dkp_sta = dkp_sta | STA_DONE; } /* set status */
@ -716,7 +717,7 @@ for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i];
unitno = unitno & USSC_M_UNIT;
dtype = GET_DTYPE (dkp_unit[unitno].flags);
M[BOOT_UNIT] = M[BOOT_UNIT] | (unitno << USSC_V_UNIT);
if (drv_tab[dtype].new) M[BOOT_SEEK] = 0176000;
if (drv_tab[dtype].newf) M[BOOT_SEEK] = 0176000;
saved_PC = BOOT_START;
return SCPE_OK;
}

View file

@ -25,6 +25,7 @@
dsk fixed head disk
14-Mar-03 RMS Fixed variable capacity interaction with save/restore
03-Mar-03 RMS Fixed variable capacity and autosizing
03-Oct-02 RMS Added DIB
06-Jan-02 RMS Revised enable/disable support
@ -44,6 +45,7 @@
#define UNIT_V_AUTO (UNIT_V_UF + 0) /* autosize */
#define UNIT_V_PLAT (UNIT_V_UF + 1) /* #platters - 1 */
#define UNIT_M_PLAT 07
#define UNIT_PLAT (UNIT_M_PLAT << UNIT_V_PLAT)
#define UNIT_GETP(x) ((((x) >> UNIT_V_PLAT) & UNIT_M_PLAT) + 1)
#define UNIT_AUTO (1 << UNIT_V_AUTO)
#define UNIT_PLAT (UNIT_M_PLAT << UNIT_V_PLAT)
@ -184,7 +186,7 @@ if ((pulse == iopP) && ((dsk_wlk >> GET_DISK (dsk_da)) & 1)) { /* wrt lock? */
return rval; }
if (pulse & 1) { /* read or write? */
if (((t_addr) (dsk_da * DSK_NUMWD)) >= dsk_unit.capac) { /* inv sev? */
if (((uint32) (dsk_da * DSK_NUMWD)) >= dsk_unit.capac) { /* inv sev? */
dev_done = dev_done | INT_DSK; /* set done */
int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable);
dsk_stat = DSKS_ERR + DSKS_NSD; /* set status */
@ -222,7 +224,7 @@ if (uptr->FUNC == iopP) { /* write? */
for (i = 0; i < DSK_NUMWD; i++) { /* copy sector */
pa = MapAddr (0, (dsk_ma + i) & AMASK); /* map address */
*(((int16 *) uptr->filebuf) + da + i) = M[pa]; }
if (((t_addr) (da + i)) >= uptr->hwmark) /* past end? */
if (((uint32) (da + i)) >= uptr->hwmark) /* past end? */
uptr->hwmark = da + i + 1; /* upd hwmark */
dsk_ma = (dsk_ma + DSK_NUMWD + 3) & AMASK; }
@ -271,15 +273,15 @@ return SCPE_OK;
t_stat dsk_attach (UNIT *uptr, char *cptr)
{
t_addr sz, p;
t_addr ds_bytes = DSK_DKSIZE * sizeof (int16);
uint32 sz, p;
uint32 ds_bytes = DSK_DKSIZE * sizeof (int16);
if ((uptr->flags & UNIT_AUTO) && (sz = sim_fsize (cptr))) {
p = (sz + ds_bytes - 1) / ds_bytes;
if (p == 0) p = 1;
if (p > DSK_NUMDK) p = DSK_NUMDK; }
else p = UNIT_GETP (uptr->flags); /* get # plat */
uptr->capac = p * DSK_DKSIZE; /* set capacity */
if (p >= DSK_NUMDK) p = DSK_NUMDK - 1;
uptr->flags = (uptr->flags & ~UNIT_PLAT) |
(p << UNIT_V_PLAT); }
uptr->capac = UNIT_GETP (uptr->flags) * DSK_DKSIZE; /* set capacity */
return attach_unit (uptr, cptr);
}

View file

@ -1,6 +1,6 @@
/* nova_lp.c: NOVA line printer simulator
Copyright (c) 1993-2002, Robert M. Supnik
Copyright (c) 1993-2003, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@ -25,6 +25,7 @@
lpt line printer
25-Apr-03 RMS Revised for extended file support
30-May-02 RMS Widened POS to 32b
*/
@ -56,7 +57,7 @@ REG lpt_reg[] = {
{ FLDATA (DONE, dev_done, INT_V_LPT) },
{ FLDATA (DISABLE, dev_disable, INT_V_LPT) },
{ FLDATA (INT, int_req, INT_V_LPT) },
{ DRDATA (POS, lpt_unit.pos, 32), PV_LEFT },
{ DRDATA (POS, lpt_unit.pos, T_ADDR_W), PV_LEFT },
{ DRDATA (TIME, lpt_unit.wait, 24), PV_LEFT },
{ FLDATA (STOP_IOE, lpt_stopioe, 0) },
{ NULL } };
@ -106,7 +107,7 @@ if (putc (lpt_unit.buf, lpt_unit.fileref) == EOF) {
perror ("LPT I/O error");
clearerr (lpt_unit.fileref);
return SCPE_IOERR; }
lpt_unit.pos = ftell (lpt_unit.fileref);
lpt_unit.pos = lpt_unit.pos + 1;
return SCPE_OK;
}

View file

@ -25,6 +25,8 @@
mta magnetic tape
25-Apr-03 RMS Revised for extended file support
28-Mar-03 RMS Added multiformat support
28-Feb-03 RMS Revised for magtape library
30-Oct-02 RMS Fixed BOT handling, added error record handling
08-Oct-02 RMS Added DIB
@ -203,13 +205,15 @@ REG mta_reg[] = {
{ DRDATA (CTIME, mta_cwait, 24), PV_LEFT },
{ DRDATA (RTIME, mta_rwait, 24), PV_LEFT },
{ URDATA (UST, mta_unit[0].USTAT, 8, 32, 0, MTA_NUMDR, 0) },
{ URDATA (POS, mta_unit[0].pos, 8, 32, 0,
{ URDATA (POS, mta_unit[0].pos, 8, T_ADDR_W, 0,
MTA_NUMDR, REG_RO | PV_LEFT) },
{ NULL } };
MTAB mta_mod[] = {
{ MTUF_WLK, 0, "write enabled", "WRITEENABLED", &mta_vlock },
{ MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", &mta_vlock },
{ MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT",
&sim_tape_set_fmt, &sim_tape_show_fmt, NULL },
{ 0 } };
DEVICE mta_dev = {

View file

@ -1,6 +1,6 @@
/* nova_plt.c: NOVA plotter simulator
Copyright (c) 2000-2002, Robert M. Supnik
Copyright (c) 2000-2003, Robert M. Supnik
Written by Bruce Ray and used with his gracious permission.
Permission is hereby granted, free of charge, to any person obtaining a
@ -26,6 +26,7 @@
plt plotter
25-Apr-03 RMS Revised for extended file support
03-Oct-02 RMS Added DIB
30-May-02 RMS Widened POS to 32b
06-Jan-02 RMS Revised enable/disable support
@ -61,7 +62,7 @@ REG plt_reg[] = {
{ FLDATA (DONE, dev_done, INT_V_PLT) },
{ FLDATA (DISABLE, dev_disable, INT_V_PLT) },
{ FLDATA (INT, int_req, INT_V_PLT) },
{ DRDATA (POS, plt_unit.pos, 32), PV_LEFT },
{ DRDATA (POS, plt_unit.pos, T_ADDR_W), PV_LEFT },
{ DRDATA (TIME, plt_unit.wait, 24), PV_LEFT },
{ FLDATA (STOP_IOE, plt_stopioe, 0) },
{ NULL } };

View file

@ -1,6 +1,6 @@
/* nova_pt.c: NOVA paper tape read/punch simulator
Copyright (c) 1993-2002, Robert M. Supnik
Copyright (c) 1993-2003, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@ -26,6 +26,7 @@
ptr paper tape reader
ptp paper tape punch
25-Apr-03 RMS Revised for extended file support
03-Oct-02 RMS Added DIBs
30-May-02 RMS Widened POS to 32b
29-Nov-01 RMS Added read only unit support
@ -63,7 +64,7 @@ REG ptr_reg[] = {
{ FLDATA (DONE, dev_done, INT_V_PTR) },
{ FLDATA (DISABLE, dev_disable, INT_V_PTR) },
{ FLDATA (INT, int_req, INT_V_PTR) },
{ DRDATA (POS, ptr_unit.pos, 32), PV_LEFT },
{ DRDATA (POS, ptr_unit.pos, T_ADDR_W), PV_LEFT },
{ DRDATA (TIME, ptr_unit.wait, 24), PV_LEFT },
{ FLDATA (STOP_IOE, ptr_stopioe, 0) },
{ NULL } };
@ -93,7 +94,7 @@ REG ptp_reg[] = {
{ FLDATA (DONE, dev_done, INT_V_PTP) },
{ FLDATA (DISABLE, dev_disable, INT_V_PTP) },
{ FLDATA (INT, int_req, INT_V_PTP) },
{ DRDATA (POS, ptp_unit.pos, 32), PV_LEFT },
{ DRDATA (POS, ptp_unit.pos, T_ADDR_W), PV_LEFT },
{ DRDATA (TIME, ptp_unit.wait, 24), PV_LEFT },
{ FLDATA (STOP_IOE, ptp_stopioe, 0) },
{ NULL } };

View file

@ -1,6 +1,6 @@
/* nova_sys.c: NOVA simulator interface
Copyright (c) 1993-2002, Robert M. Supnik
Copyright (c) 1993-2003, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@ -127,7 +127,7 @@ const char *sim_stop_messages[] = {
t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag)
{
int32 data, csum, count, state, i;
t_addr origin;
uint32 origin;
if ((*cptr != 0) || (flag != 0)) return SCPE_ARG;
state = 0;

View file

@ -26,6 +26,7 @@
tti terminal input
tto terminal output
25-Apr-03 RMS Revised for extended file support
05-Jan-02 RMS Fixed calling sequence for setmod
03-Oct-02 RMS Added DIBs
30-May-02 RMS Widened POS to 32b
@ -67,7 +68,7 @@ REG tti_reg[] = {
{ FLDATA (DONE, dev_done, INT_V_TTI) },
{ FLDATA (DISABLE, dev_disable, INT_V_TTI) },
{ FLDATA (INT, int_req, INT_V_TTI) },
{ DRDATA (POS, tti_unit.pos, 32), PV_LEFT },
{ DRDATA (POS, tti_unit.pos, T_ADDR_W), PV_LEFT },
{ DRDATA (TIME, tti_unit.wait, 24), REG_NZ + PV_LEFT },
{ NULL } };
@ -100,7 +101,7 @@ REG tto_reg[] = {
{ FLDATA (DONE, dev_done, INT_V_TTO) },
{ FLDATA (DISABLE, dev_disable, INT_V_TTO) },
{ FLDATA (INT, int_req, INT_V_TTO) },
{ DRDATA (POS, tto_unit.pos, 32), PV_LEFT },
{ DRDATA (POS, tto_unit.pos, T_ADDR_W), PV_LEFT },
{ DRDATA (TIME, tto_unit.wait, 24), PV_LEFT },
{ NULL } };

View file

@ -27,6 +27,7 @@
tti1 second terminal input
tto1 second terminal output
09-May-03 RMS Added network device flag
05-Jan-03 RMS Fixed calling sequence for setmod
03-Oct-02 RMS Added DIBs
22-Aug-02 RMS Updated for changes in sim_tmxr
@ -105,7 +106,7 @@ DEVICE tti1_dev = {
1, 10, 31, 1, 8, 8,
&tmxr_ex, &tmxr_dep, &tti1_reset,
NULL, &tti1_attach, &tti1_detach,
&tti1_dib, DEV_DISABLE };
&tti1_dib, DEV_NET | DEV_DISABLE };
/* TTO1 data structures

View file

@ -1,6 +1,6 @@
/* pdp1_cpu.c: PDP-1 CPU simulator
Copyright (c) 1993-2002, Robert M. Supnik
Copyright (c) 1993-2003, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@ -792,7 +792,7 @@ return SCPE_OK;
t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc)
{
int32 mc = 0;
t_addr i;
uint32 i;
if ((val <= 0) || (val > MAXMEMSIZE) || ((val & 07777) != 0))
return SCPE_ARG;

View file

@ -1,6 +1,6 @@
/* pdp1_defs.h: 18b PDP simulator definitions
Copyright (c) 1993-2002, Robert M. Supnik
Copyright (c) 1993-2003, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@ -54,7 +54,7 @@
#define MAXMEMSIZE (1u << ASIZE) /* max mem size */
#define AMASK (MAXMEMSIZE - 1) /* address mask */
#define MEMSIZE (cpu_unit.capac) /* actual memory size */
#define MEM_ADDR_OK(x) (((t_addr) (x)) < MEMSIZE)
#define MEM_ADDR_OK(x) (((uint32) (x)) < MEMSIZE)
/* Architectural constants */

View file

@ -133,7 +133,7 @@ return IO;
t_stat drm_svc (UNIT *uptr)
{
int32 i;
t_addr da;
uint32 da;
if ((uptr->flags & UNIT_BUF) == 0) { /* not buf? abort */
drm_err = 1; /* set error */

View file

@ -1,6 +1,6 @@
/* pdp1_dt.c: 18b DECtape simulator
Copyright (c) 1993-2002, Robert M Supnik
Copyright (c) 1993-2003, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@ -25,6 +25,8 @@
dt Type 550/555 DECtape
25-Apr-03 RMS Revised for extended file support
14-Mar-03 RMS Fixed variable size interaction with save/restore
17-Oct-02 RMS Fixed bug in end of reel logic
06-Oct-02 RMS Added device disable support
13-Aug-02 RMS Cloned from pdp18b_dt.c
@ -309,7 +311,7 @@ REG dt_reg[] = {
{ ORDATA (SUBSTATE, dt_substate, 2) },
{ ORDATA (LOG, dt_log, 4), REG_HIDDEN },
{ DRDATA (LBLK, dt_logblk, 12), REG_HIDDEN },
{ URDATA (POS, dt_unit[0].pos, 10, 32, 0,
{ URDATA (POS, dt_unit[0].pos, 10, T_ADDR_W, 0,
DT_NUMDR, PV_LEFT | REG_RO) },
{ URDATA (STATT, dt_unit[0].STATE, 8, 18, 0,
DT_NUMDR, REG_RO) },
@ -622,7 +624,7 @@ int32 fnc = DTS_GETFNC (uptr->STATE);
int32 *bptr = uptr->filebuf;
int32 unum = uptr - dt_dev.units;
int32 blk, wrd, ma, relpos;
t_addr ba;
uint32 ba;
/* Motion cases
@ -866,33 +868,35 @@ t_stat dt_attach (UNIT *uptr, char *cptr)
{
uint16 pdp8b[D8_NBSIZE];
uint16 pdp11b[D18_BSIZE];
uint32 k, p, *bptr;
uint32 ba, sz, k, *bptr;
int32 u = uptr - dt_dev.units;
t_stat r;
t_addr ba;
r = attach_unit (uptr, cptr); /* attach */
if (r != SCPE_OK) return r; /* error? */
if ((sim_switches & SIM_SW_REST) == 0) { /* not from rest? */
uptr->flags = uptr->flags & ~(UNIT_8FMT | UNIT_11FMT); /* default 18b */
if (sim_switches & SWMASK ('R')) /* att 12b? */
uptr->flags = uptr->flags | UNIT_8FMT;
else if (sim_switches & SWMASK ('S')) /* att 16b? */
uptr->flags = uptr->flags | UNIT_11FMT;
else if (!(sim_switches & SWMASK ('T')) && /* autosize? */
(fseek (uptr->fileref, 0, SEEK_END) == 0) &&
((p = ftell (uptr->fileref)) != 0)) {
if (p == D8_FILSIZ) uptr->flags = uptr->flags | UNIT_8FMT;
if (p == D11_FILSIZ) uptr->flags = uptr->flags | UNIT_11FMT; }
(sz = sim_fsize (cptr))) {
if (sz == D8_FILSIZ)
uptr->flags = uptr->flags | UNIT_8FMT;
else if (sz == D11_FILSIZ)
uptr->flags = uptr->flags | UNIT_11FMT; } }
uptr->capac = DTU_CAPAC (uptr); /* set capacity */
uptr->filebuf = calloc (uptr->capac, sizeof (int32));
if (uptr->filebuf == NULL) { /* can't alloc? */
detach_unit (uptr);
return SCPE_MEM; }
bptr = uptr->filebuf; /* file buffer */
if (uptr->flags & UNIT_8FMT) printf ("DT: 12b format");
else if (uptr->flags & UNIT_11FMT) printf ("DT: 16b format");
else printf ("DT: 18b/36b format");
printf ("%s%d: ", sim_dname (&dt_dev), u);
if (uptr->flags & UNIT_8FMT) printf ("12b format");
else if (uptr->flags & UNIT_11FMT) printf ("16b format");
else printf ("18b/36b format");
printf (", buffering file in memory\n");
rewind (uptr->fileref); /* start of file */
if (uptr->flags & UNIT_8FMT) { /* 12b? */
for (ba = 0; ba < uptr->capac; ) { /* loop thru file */
k = fxread (pdp8b, sizeof (int16), D8_NBSIZE, uptr->fileref);
@ -935,20 +939,19 @@ t_stat dt_detach (UNIT* uptr)
{
uint16 pdp8b[D8_NBSIZE];
uint16 pdp11b[D18_BSIZE];
uint32 k, *bptr;
int32 unum = uptr - dt_dev.units;
t_addr ba;
uint32 ba, k, *bptr;
int32 u = uptr - dt_dev.units;
if (!(uptr->flags & UNIT_ATT)) return SCPE_OK;
if (sim_is_active (uptr)) {
sim_cancel (uptr);
if ((unum == DTA_GETUNIT (dtsa)) && (dtsa & DTA_STSTP)) {
if ((u == DTA_GETUNIT (dtsa)) && (dtsa & DTA_STSTP)) {
dtsb = dtsb | DTB_ERF | DTB_SEL | DTB_DTF;
DT_UPDINT; }
uptr->STATE = uptr->pos = 0; }
bptr = uptr->filebuf; /* file buffer */
if (uptr->hwmark && ((uptr->flags & UNIT_RO) == 0)) { /* any data? */
printf ("DT: writing buffer to file\n");
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 */

View file

@ -1,6 +1,6 @@
/* pdp1_lp.c: PDP-1 line printer simulator
Copyright (c) 1993-2002, Robert M. Supnik
Copyright (c) 1993-2003, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@ -25,6 +25,7 @@
lpt Type 62 line printer for the PDP-1
25-Apr-03 RMS Revised for extended file support
30-May-02 RMS Widened POS to 32b
13-Apr-01 RMS Revised for register arrays
*/
@ -66,7 +67,7 @@ REG lpt_reg[] = {
{ FLDATA (RPLS, lpt_rpls, 0) },
{ DRDATA (BPTR, bptr, 6) },
{ ORDATA (LPT_STATE, lpt_iot, 6), REG_HRO },
{ DRDATA (POS, lpt_unit.pos, 32), PV_LEFT },
{ DRDATA (POS, lpt_unit.pos, T_ADDR_W), PV_LEFT },
{ DRDATA (TIME, lpt_unit.wait, 24), PV_LEFT },
{ FLDATA (STOP_IOE, lpt_stopioe, 0) },
{ BRDATA (LBUF, lpt_buf, 8, 8, LPT_BSIZE) },

Some files were not shown because too many files have changed in this diff Show more