Notes For V2.8
1. New Features 1.1 Directory and documentation - Only common files (SCP and libraries) are in the top level directory. Individual simulator files are in their individual directories. - simh_doc.txt has been split up. simh_doc.txt now documents only SCP. The individual simulators are documented in separate text files in their own directories. - mingw_build.bat is a batch file for the MINGW/gcc environment that will build all the simulators, assuming the root directory structure is at c:\sim. - Makefile is a UNIX make file for the gcc environment that will build all the simulators, assuming the root directory is at c:\sim. 1.2 SCP - DO <file name> executes the SCP commands in the specified file. - Replicated registers in unit structures can now be declared as arrays for examine, modify, save, and restore. Most replicated unit registers (for example, mag tape position registers) have been changed to arrays. - The ADD/REMOVE commands have been replaced by SET unit ONLINE and SET unit OFFLINE, respectively. - Register names that are unique within an entire simulator do not have to be prefaced with the device name. - The ATTACH command can attach files read only, either under user option (-r), or because the attached file is ready only. - The SET/SHOW capabilities have been extended. New forms include: SET <dev> param{=value}{ param ...} SET <unit> param{=value}{ param ...} SHOW <dev> {param param ...} SHOW <unit> {param param ...} - Multiple breakpoints have been implemented. Breakpoints are set/cleared/displayed by: BREAK addr_list{[count]} NOBREAK addr_list SHOW BREAK addr_list 1.3 PDP-11 simulator - Unibus map implemented, with 22b RP controller (URH70) or 18b RP controller (URH11) (in debug). - All DMA peripherals rewritten to use map. - Many peripherals modified for source sharing with VAX. - RQDX3 implemented. - Bugs fixed in RK11 and RL11 write check. 1.4 PDP-10 simulator - ITS 1-proceed implemented. - Bugs fixed in ITS PC sampling and LPMR 1.5 18b PDP simulator - Interrupts split out to multiple levels to allow easier expansion. 1.5 IBM System 3 Simulator - Written by Charles (Dutch) Owen. 1.6 VAX Simulator (in debug) - Simulates MicroVAX 3800 (KA655) with 16MB-64MB memory, RQDX3, RLV12, TSV11, DZV11, LPV11, PCV11. - CDROM capability has been added to the RQDX3, to allow testing with VMS hobbyist images. 1.7 SDS 940 Simulator (not tested) - Simulates SDS 940, 16K-64K memory, fixed and moving head disk, magtape, line printer, console. 1.8 Altair Z80 - Revised from Charles (Dutch) Owen's original by Peter Schorn. - MITS 8080 with full Z80 simulation. - 4K and 8K BASIC packages, Prolog package. 1.9 Interdata The I4 simulator has been withdrawn for major rework. Look for a complete 16b/32b Interdata simulator sometime next year. 2. Release Notes 2.1 SCP SCP now allows replicated registers in unit structures to be modelled as arrays. All replicated register declarations have been replaced by register array declarations. As a result, save files from prior revisions will generate errors after restoring main memory. 2.2 PDP-11 The Unibus map code is in debug. The map was implemented primarily to allow source sharing with the VAX, which requires a DMA map. DMA devices work correctly with the Unibus map disabled. The RQDX3 simulator has run a complete RSTS/E SYSGEN, with multiple drives, and booted the completed system from scratch. 2.3 VAX The VAX simulator will run the boot code up to the >>> prompt. It can successfully process a SHOW DEVICE command. It runs the HCORE instruction diagnostic. It can boot the hobbyist CD through SYSBOOT and through the date/time dialog and restore the hobbyist CD, using standalone backup. On the boot of the restored disk, it gets to the date/time dialog, and then crashes. 2.4 SDS 940 The SDS 940 is untested, awaiting real code. 2.5 GCC Optimization At -O2 and above, GCC does not correctly compile the simulators which use setjmp-longjmp (PDP-11, PDP-10, VAX). A working hypothesis is that optimized state maintained in registers is being used in the setjmp processing routine. On the PDP-11 and PDP-10, all of this state has been either made global, or volatile, to encourage GCC to keep the state up to date in memory. The VAX is still vulnerable. 3. Work list 3.1 SCP - Better ENABLE/DISABLE. 3.2 PDP-11 RQDX3 Software mapped mode, RCT read simulation, VMS debug.
This commit is contained in:
parent
654937fc88
commit
701f0fe028
145 changed files with 23190 additions and 9807 deletions
144
0readme28.txt
Normal file
144
0readme28.txt
Normal file
|
@ -0,0 +1,144 @@
|
|||
Notes For V2.8
|
||||
|
||||
1. New Features
|
||||
|
||||
1.1 Directory and documentation
|
||||
|
||||
- Only common files (SCP and libraries) are in the top level
|
||||
directory. Individual simulator files are in their individual
|
||||
directories.
|
||||
- simh_doc.txt has been split up. simh_doc.txt now documents
|
||||
only SCP. The individual simulators are documented in separate
|
||||
text files in their own directories.
|
||||
- mingw_build.bat is a batch file for the MINGW/gcc environment
|
||||
that will build all the simulators, assuming the root directory
|
||||
structure is at c:\sim.
|
||||
- Makefile is a UNIX make file for the gcc environment that will
|
||||
build all the simulators, assuming the root directory is at
|
||||
c:\sim.
|
||||
|
||||
1.2 SCP
|
||||
|
||||
- DO <file name> executes the SCP commands in the specified file.
|
||||
- Replicated registers in unit structures can now be declared as
|
||||
arrays for examine, modify, save, and restore. Most replicated
|
||||
unit registers (for example, mag tape position registers) have
|
||||
been changed to arrays.
|
||||
- The ADD/REMOVE commands have been replaced by SET unit ONLINE
|
||||
and SET unit OFFLINE, respectively.
|
||||
- Register names that are unique within an entire simulator do
|
||||
not have to be prefaced with the device name.
|
||||
- The ATTACH command can attach files read only, either under
|
||||
user option (-r), or because the attached file is ready only.
|
||||
- The SET/SHOW capabilities have been extended. New forms include:
|
||||
|
||||
SET <dev> param{=value}{ param ...}
|
||||
SET <unit> param{=value}{ param ...}
|
||||
SHOW <dev> {param param ...}
|
||||
SHOW <unit> {param param ...}
|
||||
|
||||
- Multiple breakpoints have been implemented. Breakpoints are
|
||||
set/cleared/displayed by:
|
||||
|
||||
BREAK addr_list{[count]}
|
||||
NOBREAK addr_list
|
||||
SHOW BREAK addr_list
|
||||
|
||||
1.3 PDP-11 simulator
|
||||
|
||||
- Unibus map implemented, with 22b RP controller (URH70) or 18b
|
||||
RP controller (URH11) (in debug).
|
||||
- All DMA peripherals rewritten to use map.
|
||||
- Many peripherals modified for source sharing with VAX.
|
||||
- RQDX3 implemented.
|
||||
- Bugs fixed in RK11 and RL11 write check.
|
||||
|
||||
1.4 PDP-10 simulator
|
||||
|
||||
- ITS 1-proceed implemented.
|
||||
- Bugs fixed in ITS PC sampling and LPMR
|
||||
|
||||
1.5 18b PDP simulator
|
||||
|
||||
- Interrupts split out to multiple levels to allow easier
|
||||
expansion.
|
||||
|
||||
1.5 IBM System 3 Simulator
|
||||
|
||||
- Written by Charles (Dutch) Owen.
|
||||
|
||||
1.6 VAX Simulator (in debug)
|
||||
|
||||
- Simulates MicroVAX 3800 (KA655) with 16MB-64MB memory, RQDX3,
|
||||
RLV12, TSV11, DZV11, LPV11, PCV11.
|
||||
- CDROM capability has been added to the RQDX3, to allow testing
|
||||
with VMS hobbyist images.
|
||||
|
||||
1.7 SDS 940 Simulator (not tested)
|
||||
|
||||
- Simulates SDS 940, 16K-64K memory, fixed and moving head
|
||||
disk, magtape, line printer, console.
|
||||
|
||||
1.8 Altair Z80
|
||||
|
||||
- Revised from Charles (Dutch) Owen's original by Peter Schorn.
|
||||
- MITS 8080 with full Z80 simulation.
|
||||
- 4K and 8K BASIC packages, Prolog package.
|
||||
|
||||
1.9 Interdata
|
||||
|
||||
The I4 simulator has been withdrawn for major rework. Look for
|
||||
a complete 16b/32b Interdata simulator sometime next year.
|
||||
|
||||
2. Release Notes
|
||||
|
||||
2.1 SCP
|
||||
|
||||
SCP now allows replicated registers in unit structures to be
|
||||
modelled as arrays. All replicated register declarations have
|
||||
been replaced by register array declarations. As a result,
|
||||
save files from prior revisions will generate errors after
|
||||
restoring main memory.
|
||||
|
||||
2.2 PDP-11
|
||||
|
||||
The Unibus map code is in debug. The map was implemented primarily
|
||||
to allow source sharing with the VAX, which requires a DMA map.
|
||||
DMA devices work correctly with the Unibus map disabled.
|
||||
|
||||
The RQDX3 simulator has run a complete RSTS/E SYSGEN, with multiple
|
||||
drives, and booted the completed system from scratch.
|
||||
|
||||
2.3 VAX
|
||||
|
||||
The VAX simulator will run the boot code up to the >>> prompt. It
|
||||
can successfully process a SHOW DEVICE command. It runs the HCORE
|
||||
instruction diagnostic. It can boot the hobbyist CD through SYSBOOT
|
||||
and through the date/time dialog and restore the hobbyist CD, using
|
||||
standalone backup. On the boot of the restored disk, it gets to the
|
||||
date/time dialog, and then crashes.
|
||||
|
||||
2.4 SDS 940
|
||||
|
||||
The SDS 940 is untested, awaiting real code.
|
||||
|
||||
2.5 GCC Optimization
|
||||
|
||||
At -O2 and above, GCC does not correctly compile the simulators which
|
||||
use setjmp-longjmp (PDP-11, PDP-10, VAX). A working hypothesis is
|
||||
that optimized state maintained in registers is being used in the
|
||||
setjmp processing routine. On the PDP-11 and PDP-10, all of this
|
||||
state has been either made global, or volatile, to encourage GCC to
|
||||
keep the state up to date in memory. The VAX is still vulnerable.
|
||||
|
||||
3. Work list
|
||||
|
||||
3.1 SCP
|
||||
|
||||
- Better ENABLE/DISABLE.
|
||||
|
||||
3.2 PDP-11 RQDX3
|
||||
|
||||
Software mapped mode, RCT read simulation, VMS debug.
|
||||
|
||||
|
|
@ -58,8 +58,6 @@
|
|||
|
||||
#include "altair_defs.h"
|
||||
|
||||
#define ILL_ADR_FLAG 0200000
|
||||
#define save_ibkpt (cpu_unit.u3)
|
||||
#define UNIT_V_OPSTOP (UNIT_V_UF) /* Stop on Invalid OP? */
|
||||
#define UNIT_OPSTOP (1 << UNIT_V_OPSTOP)
|
||||
#define UNIT_V_CHIP (UNIT_V_UF+1) /* 8080 or Z80 */
|
||||
|
@ -82,20 +80,19 @@ int32 saved_PC = 0; /* program counter */
|
|||
int32 SR = 0; /* switch register */
|
||||
int32 INTE = 0; /* Interrupt Enable */
|
||||
int32 int_req = 0; /* Interrupt request */
|
||||
int32 ibkpt_addr = ILL_ADR_FLAG | ADDRMASK; /* breakpoint addr */
|
||||
int32 chip = 0; /* 0 = 8080 chip, 1 = z80 chip */
|
||||
|
||||
int32 PCX; /* External view of PC */
|
||||
|
||||
extern int32 sim_int_char;
|
||||
extern int32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */
|
||||
|
||||
/* function prototypes */
|
||||
|
||||
t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw);
|
||||
t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw);
|
||||
t_stat cpu_reset (DEVICE *dptr);
|
||||
t_stat cpu_svc (UNIT *uptr);
|
||||
t_stat cpu_set_size (UNIT *uptr, int32 value);
|
||||
t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
void setarith(int32 reg);
|
||||
void setlogical(int32 reg);
|
||||
void setinc(int32 reg);
|
||||
|
@ -234,7 +231,7 @@ int32 bootrom[256] = {
|
|||
cpu_mod CPU modifiers list
|
||||
*/
|
||||
|
||||
UNIT cpu_unit = { UDATA (&cpu_svc, UNIT_FIX + UNIT_BINK,
|
||||
UNIT cpu_unit = { UDATA (NULL, UNIT_FIX + UNIT_BINK,
|
||||
MAXMEMSIZE) };
|
||||
|
||||
REG cpu_reg[] = {
|
||||
|
@ -249,11 +246,10 @@ REG cpu_reg[] = {
|
|||
{ FLDATA (AC, AC, 16) },
|
||||
{ FLDATA (S, S, 16) },
|
||||
{ FLDATA (P, P, 16) },
|
||||
{ FLDATA (INTE, INTE, 16) },
|
||||
{ FLDATA (INTE, INTE, 16) },
|
||||
{ FLDATA (Z80, cpu_unit.flags, UNIT_V_CHIP), REG_HRO },
|
||||
{ FLDATA (OPSTOP, cpu_unit.flags, UNIT_V_OPSTOP), REG_HRO },
|
||||
{ ORDATA (SR, SR, 16) },
|
||||
{ ORDATA (BREAK, ibkpt_addr, 17) },
|
||||
{ ORDATA (WRU, sim_int_char, 8) },
|
||||
{ NULL } };
|
||||
|
||||
|
@ -303,10 +299,8 @@ int32 sim_instr (void)
|
|||
|
||||
} /* end interrupt */
|
||||
|
||||
if (PC == ibkpt_addr) { /* breakpoint? */
|
||||
save_ibkpt = ibkpt_addr; /* save address */
|
||||
ibkpt_addr = ibkpt_addr | ILL_ADR_FLAG; /* disable */
|
||||
sim_activate (&cpu_unit, 1); /* sched re-enable */
|
||||
if (sim_brk_summ &&
|
||||
sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */
|
||||
reason = STOP_IBKPT; /* stop simulation */
|
||||
break;
|
||||
}
|
||||
|
@ -1125,7 +1119,8 @@ C = 0;
|
|||
Z = 0;
|
||||
saved_PC = 0;
|
||||
int_req = 0;
|
||||
return cpu_svc (&cpu_unit);
|
||||
sim_brk_types = sim_brk_dflt = SWMASK ('E');
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Memory examine */
|
||||
|
@ -1146,27 +1141,17 @@ t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw)
|
|||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Breakpoint service */
|
||||
|
||||
t_stat cpu_svc (UNIT *uptr)
|
||||
{
|
||||
if ((ibkpt_addr & ~ILL_ADR_FLAG) == save_ibkpt)
|
||||
ibkpt_addr = save_ibkpt;
|
||||
save_ibkpt = -1;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat cpu_set_size (UNIT *uptr, int32 value)
|
||||
t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
int32 mc = 0;
|
||||
t_addr i;
|
||||
|
||||
if ((value <= 0) || (value > MAXMEMSIZE) || ((value & 07777) != 0))
|
||||
if ((val <= 0) || (val > MAXMEMSIZE) || ((val & 07777) != 0))
|
||||
return SCPE_ARG;
|
||||
for (i = value; i < MEMSIZE; i++) mc = mc | M[i];
|
||||
for (i = val; i < MEMSIZE; i++) mc = mc | M[i];
|
||||
if ((mc != 0) && (!get_yn ("Really truncate memory [N]?", FALSE)))
|
||||
return SCPE_OK;
|
||||
MEMSIZE = value;
|
||||
MEMSIZE = val;
|
||||
for (i = MEMSIZE; i < MAXMEMSIZE; i++) M[i] = 0;
|
||||
return SCPE_OK;
|
||||
}
|
375
AltairZ80/altairZ80.txt
Normal file
375
AltairZ80/altairZ80.txt
Normal file
|
@ -0,0 +1,375 @@
|
|||
Altair 8800 Simulator
|
||||
=====================
|
||||
|
||||
1. Background.
|
||||
|
||||
The MITS (Micro Instrumentation and Telemetry Systems) Altair 8800
|
||||
was announced on the January 1975 cover of Popular Electronics, which
|
||||
boasted you could buy and build this powerful computer kit for only $397.
|
||||
The kit consisted at that time of only the parts to build a case, power
|
||||
supply, card cage (18 slots), CPU card, and memory card with 256 *bytes* of
|
||||
memory. Still, thousands were ordered within the first few months after the
|
||||
announcement, starting the personal computer revolution as we know it today.
|
||||
|
||||
Many laugh at the small size of the that first kit, noting there
|
||||
were no peripherals and the 256 byte memory size. But the computer was an
|
||||
open system, and by 1977 MITS and many other small startups had added many
|
||||
expansion cards to make the Altair quite a respectable little computer. The
|
||||
"Altair Bus" that made this possible was soon called the S-100 Bus, later
|
||||
adopted as an industry standard, and eventually became the IEE-696 Bus.
|
||||
|
||||
2. Hardware
|
||||
|
||||
We are simulating a fairly "loaded" Altair 8800 from about 1977,
|
||||
with the following configuration:
|
||||
|
||||
device simulates
|
||||
name(s)
|
||||
|
||||
CPU Altair 8800 with Intel 8080 CPU board, 62KB
|
||||
of RAM, 2K of EPROM with start boot ROM.
|
||||
SIO MITS 88-2SIO Dual Serial Interface Board. Port 1
|
||||
is assumed to be connected to a serial "glass
|
||||
TTY" that is your terminal running the Simulator.
|
||||
PTR Paper Tape Reader attached to port 2 of the 2SIO board.
|
||||
PTP Paper Tape Punch attached to port 2 of the
|
||||
2SIO board. This also doubles as a printer port.
|
||||
DSK MITS 88-DISK Floppy Disk controller with up
|
||||
to eight drives.
|
||||
|
||||
2.1 CPU
|
||||
|
||||
We have 2 CPU options that were not present on the original
|
||||
machine but are useful in the simulator. We also allow you to select
|
||||
memory sizes, but be aware that some sample software requires the full
|
||||
64K (i.e. CP/M) and the MITS Disk Basic and Altair DOS require about
|
||||
a minimum of 24K.
|
||||
|
||||
SET CPU 8080 Simulates the 8080 CPU (normal)
|
||||
SET CPU Z80 Simulates the Z80 CPU. Note that some software (e.g. most
|
||||
original Altair software such as 4K Basic) requires an 8080 CPU and
|
||||
will not or not properly run on a Z80. This is mainly due to the use
|
||||
of the parity flag on the 8080 which has not always the same
|
||||
semantics on the Z80.
|
||||
SET CPU ITRAP Causes the simulator to halt if an invalid opcode
|
||||
is detected (depending on the chosen CPU).
|
||||
SET CPU NOITRAP Does not stop on an invalid Opcode. This is
|
||||
how the real 8080 works.
|
||||
SET CPU 4K
|
||||
SET CPU 8K
|
||||
SET CPU 12K
|
||||
SET CPU 16K
|
||||
......
|
||||
SET CPU 64K All these set various CPU memory configurations.
|
||||
The 2K EPROM at the high end of memory is always
|
||||
present and will always boot.
|
||||
|
||||
The BOOT EPROM card starts at address FF00. Jumping to this address
|
||||
will always boot drive 0 of the floppy controller. If no valid bootable
|
||||
software is present there the machine crashes. This is historically
|
||||
accurate behavior.
|
||||
|
||||
The real 8080, on receiving a HLT (Halt) instruction, freezes the processor
|
||||
and only an interrupt or CPU hardware reset will restore it. The simulator
|
||||
is alot nicer, it will halt but send you back to the simulator command line.
|
||||
|
||||
CPU Registers include the following:
|
||||
|
||||
name size comments
|
||||
|
||||
PC 16 The Program Counter
|
||||
AF 16 The accumulator and the flag register
|
||||
F = S Z - AC - P/V N C
|
||||
S = Sign flag.
|
||||
Z = Zero Flag.
|
||||
AC = Auxillary Carry flag.
|
||||
P/V = Parity flag on 8080
|
||||
Parity / Overflow flag on Z80
|
||||
- = not used (undefined)
|
||||
N = Internal sign flag
|
||||
C = Carry flag.
|
||||
BC 16 The BC register pair. Register B is the high 8 bits,
|
||||
C is the lower 8 bits
|
||||
DE 16 The DE register pair. Register D is the high 8 bits,
|
||||
E is the lower 8 bits.
|
||||
HL 16 The HL register pair. Register H is the high 8 bits,
|
||||
L is the lower 8 bits.
|
||||
AF1 16 The alternate AF register (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)
|
||||
|
||||
SR 16 The front panel switches (use D SR 8 for 4k Basic).
|
||||
WRU 8 The interrupt character. This starts as 5
|
||||
(ctrl-E) but some Altair software uses this
|
||||
keystroke so best to change this to something
|
||||
exotic such as 035 (which is Ctl-]).
|
||||
|
||||
|
||||
2.2 The Serial I/O Card (2SIO)
|
||||
|
||||
This simple programmed I/O device provides 2 serial ports to the
|
||||
outside world, which could be hardware jumpered to support RS-232 plugs or a
|
||||
TTY current loop interface. The standard I/O addresses assigned by MITS
|
||||
was 10-11 (hex) for the first port, and 12-13 (hex) for the second.
|
||||
We follow this standard in the Simulator.
|
||||
|
||||
The simulator directs I/O to/from the first port to the screen. The
|
||||
second port reads from an attachable "tape reader" file on input, and writes
|
||||
to an attachable "punch file" on output. These files are considered a
|
||||
simple stream of 8-bit bytes.
|
||||
|
||||
The SIO can be configured in SIMH with the following commands:
|
||||
|
||||
SET SIO TTY Bit 8 is set to zero on console output
|
||||
SET SIO ANSI Bit 8 is not touched on console output
|
||||
|
||||
SET SIO ALL Console input support lower- and upper case
|
||||
SET SIO UPPER Console input is transformed to upper case characters only
|
||||
(This feature is useful for most Altair software)
|
||||
|
||||
SET SIO BS Map the delete character to backspace
|
||||
SET SIO DEL Map the backspace character to delete
|
||||
|
||||
You can also attach the SIO to a port:
|
||||
|
||||
ATTACH SIO 23 Console IO goes via a Telnet connection on port 23
|
||||
DETACH SIO Console IO goes via the regular SIMH console
|
||||
|
||||
2.3 The 88-DISK controller.
|
||||
|
||||
The MITS 88-DISK is a simple programmed I/O interface to the MITS
|
||||
8-inch floppy drive, which was basically a Pertec FD-400 with a power
|
||||
supply and buffer board builtin. The controller supports neither interrupts
|
||||
nor DMA, so floppy access required the sustained attention of the CPU.
|
||||
The standard I/O addresses were 8, 9, and 0A (hex), and we follow the
|
||||
standard. Details on controlling this hardware are in the altair_dsk.c
|
||||
source file.
|
||||
|
||||
The only difference is that the simulated disks may be larger than the
|
||||
original ones: The original disk had 77 tracks while the simulated disks
|
||||
support up to 254 tracks (only relevant for CP/M).
|
||||
|
||||
For debugging purposes you can set the trace level of some disk I/O
|
||||
functions. To do so the following bits in TRACE (a register of the disk)
|
||||
have been defined with the following meaning:
|
||||
|
||||
1 Trace all IN and OUT instructions on the disk ports 8 and 9
|
||||
2 Trace all read and writes to full sectors on the disk
|
||||
4 Print a message whenever an unnecessary step-in or step out of the
|
||||
disk head occurs (often an indication of an infinite loop)
|
||||
8 Print a message whenever the disk head appears to be waiting for a
|
||||
sector which does not show up (often an indication of an infinite
|
||||
loop)
|
||||
|
||||
For example the command "D TRACE 10" will trace options 2+8 from above.
|
||||
|
||||
|
||||
3. Sample Software
|
||||
|
||||
Running an Altair in 1977 you would be running either MITS Disk
|
||||
Extended BASIC, or the brand new and sexy CP/M Operating System from Digital
|
||||
Research. Or possibly, you ordered Altair DOS back when it was promised in
|
||||
1975, and are still waiting for it to be delivered in early 1977.
|
||||
|
||||
We have samples of all three for you to check out. We can't go into
|
||||
the details of how they work, but we'll give you a few hints.
|
||||
|
||||
|
||||
3.1 CP/M Version 2.2
|
||||
|
||||
This version is my own port of the standard CP/M to the Altair.
|
||||
There were some "official" versions but I don't have them. None were
|
||||
endorsed or sold by MITS to my knowledge, however.
|
||||
To boot CP/M:
|
||||
|
||||
sim> attach dsk altcpm.dsk
|
||||
sim> go ff00
|
||||
62K CP/M VERSION 2.2 (ALTAIR 8800)
|
||||
A>DIR
|
||||
|
||||
CP/M feels like DOS, sort of. DIR will work. I have included all
|
||||
the standard CP/M utilities, plus a few common public-domain ones. I also
|
||||
include the sources to the customized BIOS and some other small programs.
|
||||
TYPE will print an ASCII file. DUMP will dump a binary one. LS is a better
|
||||
DIR than DIR. ASM will assemble .ASM files to Hex, LOAD will "load" them to
|
||||
binary format (.COM). ED is a simple editor, #A command will bring the
|
||||
source file to the buffer, T command will "type" lines, L will move lines,
|
||||
E exits the editor. 20L20T will move down 20 lines, and type 20. Very
|
||||
DECish. DDT is the debugger, SUBMIT is a batch-type command processor.
|
||||
A sample batch file that will assemble and write out the bootable CP/M
|
||||
image (on drive A) is "SYSGEN.SUB". To run it, type "SUBMIT SYSGEN".
|
||||
|
||||
In order to efficiently transfer files into the CP/M environment use the
|
||||
included program READ <filename.ext>. If you have a file named foo.ext in
|
||||
the current directory (i.e. the directory where SIMH is), executing
|
||||
READ FOO.EXT under CP/M will transfer the file onto the CP/M disk. READ will
|
||||
only run with Z80 CPU so remember to "SET CPU Z80".
|
||||
|
||||
The disk "altcpm.dsk" contains the following files:
|
||||
Name Ext Size Comment
|
||||
ABOOT62 ASM 1K Moves CP/M image from MOVCPM location to real location
|
||||
in memory
|
||||
ASM COM 8K Standard CP/M assembler
|
||||
CALC PRO 3K Prolog sample file "Calculator"
|
||||
CBIOS ASM 8K BIOS for the Altair (used for sysgen)
|
||||
COPY COM 1K ALTAIR diskette backup program
|
||||
CPM62 COM 9K CP/M binary (used for sysgen)
|
||||
DDT COM 5K Dynamic Debugging Tool (Standard CP/M)
|
||||
DDTZ COM 10K Dynamic Debugging Tool for Z80
|
||||
DUMP ASM 5K Assembler source for DUMP utility
|
||||
DUMP COM 1K Dumps the contents of a file in hex (Standard CP/M)
|
||||
ED COM 7K Line oriented editor (Standard CP/M)
|
||||
FAMILY PRO 2K Prolog sample file "Family relations"
|
||||
FORMAT COM 2K Formats a disk
|
||||
INTEGER PRO 1K Prolog sample file "Integer arithmetic"
|
||||
KNAKE PRO 2K Prolog sample file "Logic puzzle"
|
||||
LOAD COM 2K Loads a hex file and produces an executable
|
||||
(Standard CP/M)
|
||||
LS COM 3K Directory utility
|
||||
MOVCPM COM 12K Regenerates the CP/M system for a particular
|
||||
memory size (Standard CP/M)
|
||||
PINST COM 4K Terminal installer for PROLOGZ.COM
|
||||
PIP COM 8K Peripheral Interchange Program for copying files
|
||||
(Standard CP/M)
|
||||
PROLOGZ COM 17K Prolog development environment
|
||||
PROLOGZ TXT 40K PROLOGZ documentation in German
|
||||
PTD ASM 2K Writes Altair-format memory image to disk
|
||||
(used for sysgen)
|
||||
QUEEN PRO 2K Prolog sample file "N Queens problem"
|
||||
READ COM 2K Reads a file from the SIMH filesystem to CP/M
|
||||
README TXT 3K This file
|
||||
STAT COM 6K Provides information about drives, disks and
|
||||
files (Standard CP/M)
|
||||
SUBMIT COM 2K Submits a file of commands for batch processing
|
||||
(Standard CP/M)
|
||||
SURVEY COM 2K Provides information about memory and IO ports
|
||||
SYSCOPY COM 2K Copies the reserved tracks between disks
|
||||
SYSGEN SUB 2K Submit file for generating the CP/M system
|
||||
XSUB COM 2K Addition to SUBMIT such that all input is read
|
||||
from the submit file (Standard CP/M)
|
||||
|
||||
3.2 MITS Disk Extended BASIC Version 4.1
|
||||
|
||||
This was the commonly used software for serious users of the Altair
|
||||
computer. It is a powerful (but slow) BASIC with some extended commands to
|
||||
allow it to access and manage the disk. There was no operating system it
|
||||
ran under. To boot:
|
||||
|
||||
sim> set cpu 8080 ;Z80 will not work
|
||||
sim> attach dsk mbasic.dsk
|
||||
sim> set sio upper
|
||||
sim> go ff00
|
||||
|
||||
MEMORY SIZE? [return]
|
||||
LINEPRINTER? C [return]
|
||||
HIGHEST DISK NUMBER? 0 [return] (3 here = 4 drive system)
|
||||
NUMBER OF FILES? 3 [return]
|
||||
NUMBER OF RANDOM FILES? 2 [return]
|
||||
|
||||
44041 BYTES FREE
|
||||
ALTAIR BASIC REV. 4.1
|
||||
[DISK EXTENDED VERSION]
|
||||
COPYRIGHT 1977 BY MITS INC.
|
||||
OK
|
||||
MOUNT 0
|
||||
OK
|
||||
FILES
|
||||
|
||||
|
||||
3.3 Altair DOS Version 1.0
|
||||
|
||||
This was long promised but not delivered until it was almost
|
||||
irrelevant. A short attempted tour will reveal it to be a dog, far inferior
|
||||
to CP/M. To boot:
|
||||
|
||||
sim> attach dsk altdos.dsk
|
||||
sim> set sio upper
|
||||
sim> go ff00
|
||||
|
||||
MEMORY SIZE? [return]
|
||||
INTERRUPTS? N [return]
|
||||
HIGHEST DISK NUMBER? 0 [return] (3 here = 4 drive system)
|
||||
HOW MANY DISK FILES? 3 [return]
|
||||
HOW MANY RANDOM FILES? 2 [return]
|
||||
|
||||
056449 BYTES AVAILABLE
|
||||
DOS MONITOR VER 1.0
|
||||
COPYRIGHT 1977 BY MITS INC
|
||||
.MNT 0
|
||||
|
||||
.DIR 0
|
||||
|
||||
3.4 Altair 4k Basic
|
||||
In order to run the famous 4k Basic, use the following commands (the trick
|
||||
is to get the Switch Register right).
|
||||
|
||||
sim> set cpu 8080 ;note 4k Basic will not run on a Z80 CPU
|
||||
sim> set sio upper ;4k Basic does not like lower case letters as input
|
||||
sim> set sio ansi ;4k Basic produces 8-bit output, strip to seven bits
|
||||
sim> d sr 8 ;good setting for the Switch Register
|
||||
sim> load 4kbas.bin ;load it
|
||||
sim> go ;and go
|
||||
MEMORY SIZE? [return]
|
||||
TERMINAL WIDTH? [return]
|
||||
WANT SIN? [Y]
|
||||
|
||||
61911 BYTES FREE
|
||||
|
||||
BASIC VERSION 3.2
|
||||
[4K VERSION]
|
||||
|
||||
OK
|
||||
|
||||
3.5 Altair 8k Basic
|
||||
Running 8k Basic follows the procedure for 4k Basic.
|
||||
|
||||
sim> set cpu 8080 ;note 8k Basic will not run on a Z80 CPU
|
||||
sim> set sio upper ;8k Basic does not like lower case letters as input
|
||||
sim> set sio ansi ;8k Basic produces 8-bit output, strip to seven bits
|
||||
sim> d sr 8 ;good setting for the Switch Register
|
||||
sim> load 8kbas.bin ;load it
|
||||
sim> go ;and go
|
||||
MEMORY SIZE? [A]
|
||||
|
||||
WRITTEN FOR ROYALTIES BY MICRO-SOFT
|
||||
|
||||
MEMORY SIZE? [return]
|
||||
TERMINAL WIDTH? [return]
|
||||
WANT SIN-COS-TAN-ATN? [Y]
|
||||
|
||||
58756 BYTES FREE
|
||||
ALTAIR BASIC REV. 4.0
|
||||
[EIGHT-K VERSION]
|
||||
COPYRIGHT 1976 BY MITS INC.
|
||||
OK
|
||||
|
||||
4. Brief summary of all major changes to the original Altair simulator
|
||||
- Full support for Z80. CP/M software requiring a Z80 CPU now runs
|
||||
properly. DDTZ and PROLOGZ are included for demonstration purposes.
|
||||
- Full assembler and dis-assembler support for Z80 and 8080 mnemonics.
|
||||
Depending on the current setting of the CPU, the appropriate mnemonics
|
||||
are used.
|
||||
- The BOOT ROM was changed to fully load the software from disk. The
|
||||
original code basically loaded a copy of itself from the disk and
|
||||
executed it.
|
||||
- ROM and memory size settings are now fully honored. This means that you
|
||||
cannot write into the ROM or outside the defined RAM (e.g. when the RAM size
|
||||
was truncated with the SET CPU commands). This feature allows programs which
|
||||
check for the size of available RAM to run properly (e.g. 4k Basic).
|
||||
- The console can also be used via Telnet. This is useful when a terminal is
|
||||
needed which supports cursor control such as a VT100. PROLOGZ for example
|
||||
has a built-in screen editor which works under Telnet.
|
||||
- Simplified file exchange for CP/M. Using the READ program under CP/M one
|
||||
can easily import files into CP/M from the regular file system. Note that PIP
|
||||
does not work properly on non-text files on PTR.
|
||||
- The last character read from PTR is always Control-Z (the EOF character for
|
||||
CP/M). This makes sure that PIP (Peripheral Interchange Program on CP/M) will
|
||||
terminate properly.
|
||||
- Fixed a bug in the BIOS warm boot routine which caused CP/M to crash.
|
||||
- Modified the BIOS for CP/M to support 8 disks.
|
||||
- Changed from octal to hex which is more concise.
|
3372
AltairZ80/altairZ80_cpu.c
Normal file
3372
AltairZ80/altairZ80_cpu.c
Normal file
File diff suppressed because it is too large
Load diff
30
AltairZ80/altairZ80_defs.h
Normal file
30
AltairZ80/altairZ80_defs.h
Normal file
|
@ -0,0 +1,30 @@
|
|||
/* altairZ80_defs.h: MITS Altair simulator definitions
|
||||
Written by Peter Schorn, 2001
|
||||
Based on work by Charles E Owen ((c) 1997, Commercial use prohibited)
|
||||
*/
|
||||
|
||||
#include "sim_defs.h" /* simulator definitions */
|
||||
|
||||
/* Memory */
|
||||
#define MAXMEMSIZE 65536 /* max memory size */
|
||||
#define KB 1024 /* kilo byte */
|
||||
#define MEMSIZE (cpu_unit.capac) /* actual memory size */
|
||||
#define ADDRMASK (MAXMEMSIZE - 1) /* address mask */
|
||||
#define bootrom_size 256 /* size of boot rom */
|
||||
#define bootrom_origin 0xFF00 /* start address of boot rom */
|
||||
|
||||
#define BACKSPACE_CHAR 0x08 /* backspace character */
|
||||
#define DELETE_CHAR 0x7f /* delete character */
|
||||
#define CONTROLZ_CHAR 26 /* control Z character */
|
||||
|
||||
/* Simulator stop codes */
|
||||
#define STOP_HALT 2 /* HALT */
|
||||
#define STOP_IBKPT 3 /* breakpoint */
|
||||
#define STOP_OPCODE 4
|
||||
|
||||
#define UNIT_V_OPSTOP (UNIT_V_UF) /* Stop on Invalid OP? */
|
||||
#define UNIT_OPSTOP (1 << UNIT_V_OPSTOP)
|
||||
#define UNIT_V_CHIP (UNIT_V_UF+1) /* 8080 or Z80 */
|
||||
#define UNIT_CHIP (1 << UNIT_V_CHIP)
|
||||
#define UNIT_V_MSIZE (UNIT_V_UF+2) /* Memory Size */
|
||||
#define UNIT_MSIZE (1 << UNIT_V_MSIZE)
|
408
AltairZ80/altairZ80_dsk.c
Normal file
408
AltairZ80/altairZ80_dsk.c
Normal file
|
@ -0,0 +1,408 @@
|
|||
/* altairZ80_dsk.c: MITS Altair 88-DISK Simulator
|
||||
Written by Charles E Owen ((c) 1997, Commercial use prohibited)
|
||||
Minor modifications by Peter Schorn, 2001
|
||||
|
||||
The 88_DISK is a 8-inch floppy controller which can control up
|
||||
to 16 daisy-chained Pertec FD-400 hard-sectored floppy drives.
|
||||
Each diskette has physically 77 tracks of 32 137-byte sectors
|
||||
each.
|
||||
|
||||
The controller is interfaced to the CPU by use of 3 I/O addreses,
|
||||
standardly, these are device numbers 10, 11, and 12 (octal).
|
||||
|
||||
Address Mode Function
|
||||
------- ---- --------
|
||||
|
||||
10 Out Selects and enables Controller and Drive
|
||||
10 In Indicates status of Drive and Controller
|
||||
11 Out Controls Disk Function
|
||||
11 In Indicates current sector position of disk
|
||||
12 Out Write data
|
||||
12 In Read data
|
||||
|
||||
Drive Select Out (Device 10 OUT):
|
||||
|
||||
+---+---+---+---+---+---+---+---+
|
||||
| C | X | X | X | Device |
|
||||
+---+---+---+---+---+---+---+---+
|
||||
|
||||
C = If this bit is 1, the disk controller selected by 'device' is
|
||||
cleared. If the bit is zero, 'device' is selected as the
|
||||
device being controlled by subsequent I/O operations.
|
||||
X = not used
|
||||
Device = value zero thru 15, selects drive to be controlled.
|
||||
|
||||
Drive Status In (Device 10 IN):
|
||||
|
||||
+---+---+---+---+---+---+---+---+
|
||||
| R | Z | I | X | X | H | M | W |
|
||||
+---+---+---+---+---+---+---+---+
|
||||
|
||||
W - When 0, write circuit ready to write another byte.
|
||||
M - When 0, head movement is allowed
|
||||
H - When 0, indicates head is loaded for read/write
|
||||
X - not used (will be 0)
|
||||
I - When 0, indicates interrupts enabled (not used this simulator)
|
||||
Z - When 0, indicates head is on track 0
|
||||
R - When 0, indicates that read circuit has new byte to read
|
||||
|
||||
Drive Control (Device 11 OUT):
|
||||
|
||||
+---+---+---+---+---+---+---+---+
|
||||
| W | C | D | E | U | H | O | I |
|
||||
+---+---+---+---+---+---+---+---+
|
||||
|
||||
I - When 1, steps head IN one track
|
||||
O - When 1, steps head OUT one track
|
||||
H - When 1, loads head to drive surface
|
||||
U - When 1, unloads head
|
||||
E - Enables interrupts (ignored this simulator)
|
||||
D - Disables interrupts (ignored this simulator)
|
||||
C - When 1 lowers head current (ignored this simulator)
|
||||
W - When 1, starts Write Enable sequence: W bit on device 10
|
||||
(see above) will go 1 and data will be read from port 12
|
||||
until 137 bytes have been read by the controller from
|
||||
that port. The W bit will go off then, and the sector data
|
||||
will be written to disk. Before you do this, you must have
|
||||
stepped the track to the desired number, and waited until
|
||||
the right sector number is presented on device 11 IN, then
|
||||
set this bit.
|
||||
|
||||
Sector Position (Device 11 IN):
|
||||
|
||||
As the sectors pass by the read head, they are counted and the
|
||||
number of the current one is available in this register.
|
||||
|
||||
+---+---+---+---+---+---+---+---+
|
||||
| X | X | Sector Number | T |
|
||||
+---+---+---+---+---+---+---+---+
|
||||
|
||||
X = Not used
|
||||
Sector number = binary of the sector number currently under the
|
||||
head, 0-31.
|
||||
T = Sector True, is a 1 when the sector is positioned to read or
|
||||
write.
|
||||
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "altairZ80_defs.h"
|
||||
|
||||
#define UNIT_V_ENABLE (UNIT_V_UF + 0) /* Write Enable */
|
||||
#define UNIT_ENABLE (1 << UNIT_V_ENABLE)
|
||||
#define DSK_SECTSIZE 137 /* size of sector */
|
||||
#define DSK_SECT 32 /* sectors per track */
|
||||
#define TRACKS 254 /* number of tracks,
|
||||
original Altair has 77 tracks only */
|
||||
#define DSK_TRACSIZE (DSK_SECTSIZE * DSK_SECT)
|
||||
#define DSK_SIZE (DSK_TRACSIZE * TRACKS)
|
||||
#define TRACE_IN_OUT 1
|
||||
#define TRACE_READ_WRITE 2
|
||||
#define TRACE_SECTOR_STUCK 4
|
||||
#define TRACE_TRACK_STUCK 8
|
||||
|
||||
t_stat dsk_svc (UNIT *uptr);
|
||||
t_stat dsk_reset (DEVICE *dptr);
|
||||
void writebuf();
|
||||
|
||||
extern int32 PCX;
|
||||
extern FILE *sim_log;
|
||||
|
||||
/* Global data on status */
|
||||
|
||||
int32 cur_disk = 8; /* Currently selected drive */
|
||||
int32 cur_track[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0xff};
|
||||
int32 cur_sect[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0xff};
|
||||
int32 cur_byte[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0xff};
|
||||
int32 cur_flags[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
int32 trace_flag = 0;
|
||||
int32 in9_count = 0;
|
||||
int32 in9_message = FALSE;
|
||||
|
||||
char dskbuf[DSK_SECTSIZE]; /* Data Buffer */
|
||||
int32 dirty = 0; /* 1 when buffer has unwritten data in it */
|
||||
UNIT *dptr; /* fileref to write dirty buffer to */
|
||||
|
||||
/* 88DSK Standard I/O Data Structures */
|
||||
|
||||
UNIT dsk_unit[] = {
|
||||
{ UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, DSK_SIZE) },
|
||||
{ UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, DSK_SIZE) },
|
||||
{ UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, DSK_SIZE) },
|
||||
{ UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, DSK_SIZE) },
|
||||
{ UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, DSK_SIZE) },
|
||||
{ UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, DSK_SIZE) },
|
||||
{ UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, DSK_SIZE) },
|
||||
{ UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, DSK_SIZE) } };
|
||||
|
||||
REG dsk_reg[] = {
|
||||
{ DRDATA (DISK, cur_disk, 4) },
|
||||
{ ORDATA (TRACE, trace_flag, 8) },
|
||||
{ DRDATA (IN9, in9_count, 4), REG_RO },
|
||||
{ NULL } };
|
||||
|
||||
DEVICE dsk_dev = {
|
||||
"DSK", dsk_unit, dsk_reg, NULL,
|
||||
8, 10, 31, 1, 8, 8,
|
||||
NULL, NULL, &dsk_reset,
|
||||
NULL, NULL, NULL };
|
||||
|
||||
/* Service routines to handle simlulator functions */
|
||||
|
||||
/* service routine - actually gets char & places in buffer */
|
||||
|
||||
t_stat dsk_svc (UNIT *uptr)
|
||||
{
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Reset routine */
|
||||
|
||||
t_stat dsk_reset (DEVICE *dptr)
|
||||
{
|
||||
cur_disk = 0;
|
||||
trace_flag = 0;
|
||||
in9_count = 0;
|
||||
in9_message = FALSE;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* I/O instruction handlers, called from the CPU module when an
|
||||
IN or OUT instruction is issued.
|
||||
|
||||
Each function is passed an 'io' flag, where 0 means a read from
|
||||
the port, and 1 means a write to the port. On input, the actual
|
||||
input is passed as the return value, on output, 'data' is written
|
||||
to the device.
|
||||
*/
|
||||
|
||||
/* Disk Controller Status/Select */
|
||||
|
||||
/* IMPORTANT: The status flags read by port 8 IN instruction are
|
||||
INVERTED, that is, 0 is true and 1 is false. To handle this, the
|
||||
simulator keeps it's own status flags as 0=false, 1=true; and
|
||||
returns the COMPLEMENT of the status flags when read. This makes
|
||||
setting/testing of the flag bits more logical, yet meets the
|
||||
simulation requirement that they are reversed in hardware.
|
||||
*/
|
||||
|
||||
int32 dsk10(int32 io, int32 data)
|
||||
{
|
||||
in9_count = 0;
|
||||
if (io == 0) { /* IN: return flags */
|
||||
return ((~cur_flags[cur_disk]) & 0xFF); /* Return the COMPLEMENT! */
|
||||
}
|
||||
|
||||
/* OUT: Controller set/reset/enable/disable */
|
||||
if (dirty == 1)
|
||||
writebuf();
|
||||
if (trace_flag & TRACE_IN_OUT) {
|
||||
printf("\n[%x] OUT 08: %x", PCX, data);
|
||||
if (sim_log) {
|
||||
fprintf(sim_log, "\n[%x] OUT 08: %x", PCX, data);
|
||||
}
|
||||
}
|
||||
cur_disk = data & 0x0F;
|
||||
if ((((dsk_dev.units + cur_disk) -> flags) & UNIT_ATT) == 0) { /* nothing attached? */
|
||||
cur_disk = 8;
|
||||
}
|
||||
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 */
|
||||
}
|
||||
return (0); /* ignored since OUT */
|
||||
}
|
||||
|
||||
/* Disk Drive Status/Functions */
|
||||
|
||||
int32 dsk11(int32 io, int32 data)
|
||||
{
|
||||
if (io == 0) { /* Read sector position */
|
||||
in9_count++;
|
||||
if ((trace_flag & TRACE_SECTOR_STUCK) && (in9_count > 2*DSK_SECT) && (!in9_message)) {
|
||||
in9_message = TRUE;
|
||||
printf("\n[%x] Looping on sector find %d.\n", PCX, cur_disk);
|
||||
if (sim_log) {
|
||||
fprintf(sim_log, "\n[%x] Looping on sector find %d.\n", PCX, cur_disk);
|
||||
}
|
||||
}
|
||||
if (trace_flag & TRACE_IN_OUT) {
|
||||
printf("\n[%x] IN 09", PCX);
|
||||
if (sim_log) {
|
||||
fprintf(sim_log, "\n[%x] IN 09", PCX);
|
||||
}
|
||||
}
|
||||
if (dirty == 1)
|
||||
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;
|
||||
cur_byte[cur_disk] = 0xff;
|
||||
return (((cur_sect[cur_disk] << 1) & 0x3E) /* return 'sector true' bit = 0 (true) */
|
||||
| 0xC0); /* set on 'unused' bits */
|
||||
} else {
|
||||
return (0); /* head not loaded - return 0 */
|
||||
}
|
||||
}
|
||||
|
||||
in9_count = 0;
|
||||
/* Drive functions */
|
||||
|
||||
if (cur_disk > 7)
|
||||
return (0); /* no drive selected - can do nothing */
|
||||
|
||||
if (trace_flag & TRACE_IN_OUT) {
|
||||
printf("\n[%x] OUT 09: %x", PCX, data);
|
||||
if (sim_log) {
|
||||
fprintf(sim_log, "\n[%x] OUT 09: %x", PCX, data);
|
||||
}
|
||||
}
|
||||
if (data & 0x01) { /* Step head in */
|
||||
if (trace_flag & TRACE_TRACK_STUCK) {
|
||||
if (cur_track[cur_disk] == (TRACKS-1)) {
|
||||
printf("\n[%x] Unnecessary step in for disk %d", PCX, cur_disk);
|
||||
if (sim_log) {
|
||||
fprintf(sim_log, "\n[%x] Unnecessary step in for disk %d", PCX, cur_disk);
|
||||
}
|
||||
}
|
||||
}
|
||||
cur_track[cur_disk]++;
|
||||
if (cur_track[cur_disk] > (TRACKS-1) )
|
||||
cur_track[cur_disk] = (TRACKS-1);
|
||||
if (dirty == 1)
|
||||
writebuf();
|
||||
cur_sect[cur_disk] = 0xff;
|
||||
cur_byte[cur_disk] = 0xff;
|
||||
}
|
||||
|
||||
if (data & 0x02) { /* Step head out */
|
||||
if (trace_flag & TRACE_TRACK_STUCK) {
|
||||
if (cur_track[cur_disk] == 0) {
|
||||
printf("\n[%x] Unnecessary step out for disk %d", PCX, cur_disk);
|
||||
if (sim_log) {
|
||||
fprintf(sim_log, "\n[%x] Unnecessary step out for disk %d", PCX, cur_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 */
|
||||
}
|
||||
if (dirty == 1)
|
||||
writebuf();
|
||||
cur_sect[cur_disk] = 0xff;
|
||||
cur_byte[cur_disk] = 0xff;
|
||||
}
|
||||
|
||||
if (dirty == 1)
|
||||
writebuf();
|
||||
|
||||
if (data & 0x04) { /* Head load */
|
||||
cur_flags[cur_disk] |= 0x04; /* turn on head loaded bit */
|
||||
cur_flags[cur_disk] |= 0x80; /* turn on 'read data available */
|
||||
}
|
||||
|
||||
if (data & 0x08) { /* Head Unload */
|
||||
cur_flags[cur_disk] &= 0xFB; /* off on 'head loaded' */
|
||||
cur_flags[cur_disk] &= 0x7F; /* off on 'read data avail */
|
||||
cur_sect[cur_disk] = 0xff;
|
||||
cur_byte[cur_disk] = 0xff;
|
||||
}
|
||||
|
||||
/* Interrupts & head current are ignored */
|
||||
|
||||
if (data & 0x80) { /* write sequence start */
|
||||
cur_byte[cur_disk] = 0;
|
||||
cur_flags[cur_disk] |= 0x01; /* enter new write data on */
|
||||
}
|
||||
return (0); /* 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);
|
||||
}
|
||||
|
||||
int32 dsk12(int32 io, int32 data)
|
||||
{
|
||||
static int32 i;
|
||||
UNIT *uptr;
|
||||
|
||||
in9_count = 0;
|
||||
uptr = dsk_dev.units + cur_disk;
|
||||
if (io == 0) {
|
||||
if (cur_byte[cur_disk] >= DSK_SECTSIZE) {
|
||||
/* physically read the sector */
|
||||
if (trace_flag & TRACE_READ_WRITE) {
|
||||
printf("\n[%x] IN 0A (READ) D%d T%d S%d", PCX, cur_disk, cur_track[cur_disk], cur_sect[cur_disk]);
|
||||
if (sim_log) {
|
||||
fprintf(sim_log, "\n[%x] IN 0A (READ) D%d T%d S%d", PCX, cur_disk, cur_track[cur_disk],
|
||||
cur_sect[cur_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;
|
||||
}
|
||||
return (dskbuf[cur_byte[cur_disk]++] & 0xFF);
|
||||
}
|
||||
else {
|
||||
if (cur_byte[cur_disk] >= DSK_SECTSIZE) {
|
||||
writebuf();
|
||||
}
|
||||
else {
|
||||
dirty = 1;
|
||||
dptr = uptr;
|
||||
dskbuf[cur_byte[cur_disk]++] = data & 0xFF;
|
||||
}
|
||||
return (0); /* ignored since OUT */
|
||||
}
|
||||
}
|
||||
|
||||
void writebuf()
|
||||
{
|
||||
int32 i, rtn;
|
||||
|
||||
i = cur_byte[cur_disk]; /* null-fill rest of sector if any */
|
||||
while (i < DSK_SECTSIZE) {
|
||||
dskbuf[i++] = 0;
|
||||
}
|
||||
if (trace_flag & TRACE_READ_WRITE) {
|
||||
printf("\n[%x] OUT 0A (WRITE) D%d T%d S%d", PCX, cur_disk,
|
||||
cur_track[cur_disk], cur_sect[cur_disk]);
|
||||
if (sim_log) {
|
||||
fprintf (sim_log, "\n[%x] OUT 0A (WRITE) D%d T%d S%d", PCX, cur_disk,
|
||||
cur_track[cur_disk], cur_sect[cur_disk]);
|
||||
}
|
||||
}
|
||||
if (dskseek(dptr)) {
|
||||
printf("\n[%x] fseek failed D%d T%d S%d", PCX, cur_disk,
|
||||
cur_track[cur_disk], cur_sect[cur_disk]);
|
||||
if (sim_log) {
|
||||
fprintf(sim_log, "\n[%x] fseek failed D%d T%d S%d", PCX, cur_disk,
|
||||
cur_track[cur_disk], cur_sect[cur_disk]);
|
||||
}
|
||||
}
|
||||
rtn = fwrite(dskbuf, DSK_SECTSIZE, 1, dptr -> fileref);
|
||||
if (rtn != 1) {
|
||||
printf("\n[%x] fwrite failed T%d S%d Return=%d", PCX, cur_track[cur_disk],
|
||||
cur_sect[cur_disk], rtn);
|
||||
if (sim_log) {
|
||||
fprintf(sim_log, "\n[%x] fwrite failed T%d S%d Return=%d", PCX, cur_track[cur_disk],
|
||||
cur_sect[cur_disk], rtn);
|
||||
}
|
||||
}
|
||||
cur_flags[cur_disk] &= 0xFE; /* ENWD off */
|
||||
cur_byte[cur_disk] = 0xff;
|
||||
dirty = 0;
|
||||
}
|
434
AltairZ80/altairZ80_sio.c
Normal file
434
AltairZ80/altairZ80_sio.c
Normal file
|
@ -0,0 +1,434 @@
|
|||
/* altairZ80_sio: MITS Altair serial I/O card
|
||||
Written by Peter Schorn, 2001
|
||||
Based on work by Charles E Owen ((c) 1997, Commercial use prohibited)
|
||||
|
||||
These functions support a simulated MITS 2SIO interface card.
|
||||
The card had two physical I/O ports which could be connected
|
||||
to any serial I/O device that would connect to a current loop,
|
||||
RS232, or TTY interface. Available baud rates were jumper
|
||||
selectable for each port from 110 to 9600.
|
||||
|
||||
All I/O is via programmed I/O. Each each has a status port
|
||||
and a data port. A write to the status port can select
|
||||
some options for the device (0x03 will reset the port).
|
||||
A read of the status port gets the port status:
|
||||
|
||||
+---+---+---+---+---+---+---+---+
|
||||
| X X X X X X O I |
|
||||
+---+---+---+---+---+---+---+---+
|
||||
|
||||
I - A 1 in this bit position means a character has been received
|
||||
on the data port and is ready to be read.
|
||||
O - A 1 in this bit means the port is ready to receive a character
|
||||
on the data port and transmit it out over the serial line.
|
||||
|
||||
A read to the data port gets the buffered character, a write
|
||||
to the data port writes the character to the device.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "altairZ80_defs.h"
|
||||
#include "sim_sock.h"
|
||||
#include "sim_tmxr.h"
|
||||
|
||||
#define UNIT_V_ANSI (UNIT_V_UF + 0) /* ANSI mode, strip bit 8 on output */
|
||||
#define UNIT_ANSI (1 << UNIT_V_ANSI)
|
||||
#define UNIT_V_UPPER (UNIT_V_UF + 1) /* uppper case mode */
|
||||
#define UNIT_UPPER (1 << UNIT_V_UPPER)
|
||||
#define UNIT_V_BS (UNIT_V_UF + 2) /* map delete to backspace */
|
||||
#define UNIT_BS (1 << UNIT_V_BS)
|
||||
#define Terminals 1 /* lines per mux */
|
||||
|
||||
TMLN TerminalLines[Terminals] = { { 0 } }; /* we only need one line */
|
||||
TMXR altairTMXR = {Terminals, 0, &TerminalLines[0] }; /* mux descriptor */
|
||||
|
||||
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_svc (UNIT *uptr);
|
||||
t_stat ptr_reset (DEVICE *dptr);
|
||||
t_stat ptp_svc (UNIT *uptr);
|
||||
t_stat ptp_reset (DEVICE *dptr);
|
||||
int32 nulldev(int32 io, int32 data);
|
||||
int32 simh_dev(int32 io, int32 data);
|
||||
int32 sio0d(int32 io, int32 data);
|
||||
int32 sio0s(int32 io, int32 data);
|
||||
int32 sio1d(int32 io, int32 data);
|
||||
int32 sio1s(int32 io, int32 data);
|
||||
void attachCPM();
|
||||
|
||||
extern t_stat sim_activate (UNIT *uptr, int32 interval);
|
||||
extern t_stat sim_cancel (UNIT *uptr);
|
||||
extern t_stat sim_poll_kbd (void);
|
||||
extern t_stat sim_putchar (int32 out);
|
||||
extern t_stat attach_unit (UNIT *uptr, char *cptr);
|
||||
extern t_bool rtc_avail;
|
||||
extern FILE *sim_log;
|
||||
extern int32 sim_switches;
|
||||
extern uint32 sim_os_msec (void);
|
||||
extern uint8 M[MAXMEMSIZE];
|
||||
|
||||
/* 2SIO Standard I/O Data Structures */
|
||||
|
||||
UNIT sio_unit = { UDATA (&sio_svc, UNIT_ATTABLE, 0),
|
||||
KBD_POLL_WAIT };
|
||||
|
||||
REG sio_reg[] = {
|
||||
{ HRDATA (DATA, sio_unit.buf, 8) },
|
||||
{ HRDATA (STAT, sio_unit.u3, 8) },
|
||||
{ NULL } };
|
||||
|
||||
MTAB sio_mod[] = {
|
||||
{ UNIT_ANSI, 0, "TTY", "TTY", NULL }, /* keep bit 8 as is for output */
|
||||
{ UNIT_ANSI, UNIT_ANSI, "ANSI", "ANSI", NULL }, /* set bit 8 to 0 before output */
|
||||
{ UNIT_UPPER, 0, "ALL", "ALL", NULL }, /* do not change case of input characters */
|
||||
{ UNIT_UPPER, UNIT_UPPER, "UPPER", "UPPER", NULL }, /* change input characters to upper case */
|
||||
{ UNIT_BS, 0, "BS", "BS", NULL }, /* map delete to backspace */
|
||||
{ UNIT_BS, UNIT_BS, "DEL", "DEL", NULL }, /* map backspace to delete */
|
||||
{ 0 } };
|
||||
|
||||
DEVICE sio_dev = {
|
||||
"SIO", &sio_unit, sio_reg, sio_mod,
|
||||
1, 10, 31, 1, 8, 8,
|
||||
NULL, NULL, &sio_reset,
|
||||
NULL, &sio_attach, &sio_detach };
|
||||
|
||||
UNIT ptr_unit = { UDATA (&ptr_svc, UNIT_SEQ + UNIT_ATTABLE + UNIT_ROABLE, 0),
|
||||
KBD_POLL_WAIT };
|
||||
|
||||
REG ptr_reg[] = {
|
||||
{ HRDATA (DATA, ptr_unit.buf, 8) },
|
||||
{ HRDATA (STAT, ptr_unit.u3, 8) },
|
||||
{ DRDATA (POS, ptr_unit.pos, 31) },
|
||||
{ NULL } };
|
||||
|
||||
DEVICE ptr_dev = {
|
||||
"PTR", &ptr_unit, ptr_reg, NULL,
|
||||
1, 10, 31, 1, 8, 8,
|
||||
NULL, NULL, &ptr_reset,
|
||||
NULL, NULL, NULL };
|
||||
|
||||
UNIT ptp_unit = { UDATA (&ptp_svc, UNIT_SEQ + UNIT_ATTABLE, 0),
|
||||
KBD_POLL_WAIT };
|
||||
|
||||
REG ptp_reg[] = {
|
||||
{ HRDATA (DATA, ptp_unit.buf, 8) },
|
||||
{ HRDATA (STAT, ptp_unit.u3, 8) },
|
||||
{ DRDATA (POS, ptp_unit.pos, 31) },
|
||||
{ NULL } };
|
||||
|
||||
DEVICE ptp_dev = {
|
||||
"PTP", &ptp_unit, ptp_reg, NULL,
|
||||
1, 10, 31, 1, 8, 8,
|
||||
NULL, NULL, &ptp_reset,
|
||||
NULL, NULL, NULL };
|
||||
|
||||
t_stat sio_attach (UNIT *uptr, char *cptr)
|
||||
{
|
||||
return tmxr_attach (&altairTMXR, uptr, cptr); /* attach mux */
|
||||
}
|
||||
|
||||
/* Detach */
|
||||
|
||||
t_stat sio_detach (UNIT *uptr)
|
||||
{
|
||||
sio_unit.u3 = 0x02; /* Status */
|
||||
sio_unit.buf = 0; /* Data */
|
||||
return tmxr_detach (&altairTMXR, uptr);
|
||||
}
|
||||
|
||||
/* Service routines to handle simulator functions */
|
||||
|
||||
/* service routine - actually gets char & places in buffer */
|
||||
|
||||
t_stat sio_svc (UNIT *uptr)
|
||||
{
|
||||
int32 temp;
|
||||
|
||||
sim_activate (&sio_unit, sio_unit.wait); /* continue poll */
|
||||
|
||||
if (sio_unit.flags & UNIT_ATT) {
|
||||
if (sim_poll_kbd () == SCPE_STOP) { /* listen for ^E */
|
||||
return SCPE_STOP;
|
||||
}
|
||||
temp = tmxr_poll_conn(&altairTMXR, &sio_unit); /* poll connection */
|
||||
if (temp >= 0) {
|
||||
altairTMXR.ldsc[temp] -> rcve = 1; /* enable receive */
|
||||
}
|
||||
tmxr_poll_rx(&altairTMXR); /* poll input */
|
||||
tmxr_poll_tx(&altairTMXR); /* poll output */
|
||||
}
|
||||
else {
|
||||
if ((temp = sim_poll_kbd ()) < SCPE_KFLAG) {
|
||||
return temp; /* no char or error? */
|
||||
}
|
||||
sio_unit.buf = temp & 0xff; /* Save char */
|
||||
sio_unit.u3 |= 0x01; /* Set status */
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
t_stat ptr_svc (UNIT *uptr)
|
||||
{
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat ptp_svc (UNIT *uptr)
|
||||
{
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
/* Reset routine */
|
||||
|
||||
t_stat sio_reset (DEVICE *dptr)
|
||||
{
|
||||
if (sio_unit.flags & UNIT_ATT) {
|
||||
if (altairTMXR.ldsc[0]->conn > 0) {
|
||||
tmxr_reset_ln(altairTMXR.ldsc[0]);
|
||||
}
|
||||
sio_unit.u3 = 0; /* Status */
|
||||
}
|
||||
else {
|
||||
sio_unit.u3 = 0x02; /* Status */
|
||||
}
|
||||
sio_unit.buf = 0; /* Data */
|
||||
sim_activate (&sio_unit, sio_unit.wait); /* activate unit */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
t_stat ptr_reset (DEVICE *dptr)
|
||||
{
|
||||
ptr_unit.buf = 0;
|
||||
ptr_unit.u3 = 0;
|
||||
ptr_unit.pos = 0;
|
||||
if (ptr_unit.flags & UNIT_ATT) { /* attached? */
|
||||
rewind(ptr_dev.units -> fileref);
|
||||
}
|
||||
sim_cancel (&ptp_unit); /* deactivate unit */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat ptp_reset (DEVICE *dptr)
|
||||
{
|
||||
ptp_unit.buf = 0;
|
||||
ptp_unit.u3 = 0x02;
|
||||
sim_cancel (&ptp_unit); /* deactivate unit */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* I/O instruction handlers, called from the CPU module when an
|
||||
IN or OUT instruction is issued.
|
||||
|
||||
Each function is passed an 'io' flag, where 0 means a read from
|
||||
the port, and 1 means a write to the port. On input, the actual
|
||||
input is passed as the return value, on output, 'data' is written
|
||||
to the device.
|
||||
*/
|
||||
|
||||
int32 sio0s(int32 io, int32 data)
|
||||
{
|
||||
if (io == 0) { /* IN */
|
||||
if (sio_unit.flags & UNIT_ATT) {
|
||||
sio_unit.u3 = (((tmxr_rqln(altairTMXR.ldsc[0]) > 0 ? 0x01 : 0) | /* read possible if character available */
|
||||
(altairTMXR.ldsc[0]->conn == 0 ? 0 : 0x02))); /* write possible if connected */
|
||||
}
|
||||
return (sio_unit.u3);
|
||||
}
|
||||
else { /* OUT */
|
||||
if (sio_unit.flags & UNIT_ATT) {
|
||||
if (data == 0x03) { /* reset port! */
|
||||
sio_unit.u3 = 0;
|
||||
sio_unit.buf = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (data == 0x03) { /* reset port! */
|
||||
sio_unit.u3 = 0x02;
|
||||
sio_unit.buf = 0;
|
||||
}
|
||||
}
|
||||
return (0); /* ignored since OUT */
|
||||
}
|
||||
}
|
||||
|
||||
int32 sio0d(int32 io, int32 data)
|
||||
{
|
||||
if (io == 0) { /* IN */
|
||||
if (sio_unit.flags & UNIT_ATT) {
|
||||
sio_unit.buf = tmxr_getc_ln(altairTMXR.ldsc[0]) & 0xff;
|
||||
}
|
||||
sio_unit.u3 = sio_unit.u3 & 0xFE;
|
||||
if (sio_unit.flags & UNIT_BS) {
|
||||
if (sio_unit.buf == BACKSPACE_CHAR) {
|
||||
sio_unit.buf = DELETE_CHAR;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (sio_unit.buf == DELETE_CHAR) {
|
||||
sio_unit.buf = BACKSPACE_CHAR;
|
||||
}
|
||||
}
|
||||
return ((sio_unit.flags & UNIT_UPPER) ? toupper(sio_unit.buf) : sio_unit.buf);
|
||||
}
|
||||
else { /* OUT */
|
||||
if (sio_unit.flags & UNIT_ANSI) {
|
||||
data &= 0x7f;
|
||||
}
|
||||
if (sio_unit.flags & UNIT_ATT) {
|
||||
tmxr_putc_ln(altairTMXR.ldsc[0], data);
|
||||
}
|
||||
else {
|
||||
sim_putchar(data);
|
||||
}
|
||||
return (0); /* ignored since OUT */
|
||||
}
|
||||
}
|
||||
|
||||
/* Port 2 controls the PTR/PTP devices */
|
||||
|
||||
int32 sio1s(int32 io, 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. */
|
||||
return ((ptr_unit.flags & UNIT_ATT) == 0) || (ptr_unit.u3 != 0) ? 0x02 : 0x03;
|
||||
}
|
||||
else { /* OUT */
|
||||
if (data == 0x03) {
|
||||
ptr_unit.u3 = 0;
|
||||
ptr_unit.buf = 0;
|
||||
ptr_unit.pos = 0;
|
||||
ptp_unit.u3 = 0;
|
||||
ptp_unit.buf = 0;
|
||||
ptp_unit.pos = 0;
|
||||
}
|
||||
return (0); /* ignored since OUT */
|
||||
}
|
||||
}
|
||||
|
||||
int32 sio1d(int32 io, int32 data)
|
||||
{
|
||||
int32 temp;
|
||||
if (io == 0) { /* IN */
|
||||
if (((ptr_unit.flags & UNIT_ATT) == 0) || (ptr_unit.u3 != 0))
|
||||
return (0); /* not attached or no more data available */
|
||||
if ((temp = getc(ptr_dev.units -> fileref)) == EOF) { /* end of file? */
|
||||
ptr_unit.u3 = 0x01;
|
||||
return (CONTROLZ_CHAR); /* control Z denotes end of text file in CP/M */
|
||||
}
|
||||
ptr_unit.pos++;
|
||||
return (temp & 0xFF);
|
||||
}
|
||||
else { /* OUT */
|
||||
putc(data, ptp_dev.units -> fileref);
|
||||
ptp_unit.pos++;
|
||||
return (0); /* ignored since OUT */
|
||||
}
|
||||
}
|
||||
|
||||
int32 nulldev(int32 io, int32 data)
|
||||
{
|
||||
return (io == 0 ? 0xff : 0);
|
||||
}
|
||||
|
||||
#define splimit 10
|
||||
#define printTimeCmd 0
|
||||
#define markTimeCmd 1
|
||||
#define showTimeCmd 2
|
||||
#define resetPtrCmd 3
|
||||
#define attachCmd 4
|
||||
#define detachCmd 5
|
||||
#define resetCmd 6
|
||||
#define cpmCommandLineLength 128
|
||||
uint32 markTime[splimit];
|
||||
int32 markTimeSP = 0;
|
||||
char version[] = "SIMH001";
|
||||
int32 versionPos = 0;
|
||||
|
||||
/* The CP/M commandline is used as the name of a file and PTR is attached to it */
|
||||
void attachCPM() {
|
||||
char cpmCommandLine[cpmCommandLineLength];
|
||||
uint32 i, len = (M[0x80] & 0x7f) - 1; /* 0x80 contains length of commandline, discard first char */
|
||||
for (i = 0; i < len; i++) {
|
||||
cpmCommandLine[i] = (char)M[0x82+i]; /* the first char, typically ' ', is discarded */
|
||||
}
|
||||
cpmCommandLine[i] = 0; /* make C string */
|
||||
sim_switches = SWMASK ('R');
|
||||
attach_unit(&ptr_unit, cpmCommandLine);
|
||||
}
|
||||
|
||||
/* port 0xfe is a device for communication SIMH <--> Altair machine */
|
||||
int32 simh_dev(int32 io, int32 data) {
|
||||
uint32 delta;
|
||||
int32 result;
|
||||
if (io == 0) { /* IN */
|
||||
result = version[versionPos++];
|
||||
if (result == 0) {
|
||||
versionPos = 0;
|
||||
}
|
||||
return (result);
|
||||
}
|
||||
else { /* OUT */
|
||||
switch(data) {
|
||||
case printTimeCmd: /* print time */
|
||||
if (rtc_avail) {
|
||||
printf("Current time in milliseconds = %d.\n", sim_os_msec ());
|
||||
if (sim_log) {
|
||||
fprintf(sim_log, "Current time in milliseconds = %d.\n", sim_os_msec ());
|
||||
}
|
||||
}
|
||||
break;
|
||||
case markTimeCmd: /* mark time */
|
||||
if (rtc_avail) {
|
||||
if (markTimeSP < splimit) {
|
||||
markTime[markTimeSP++] = sim_os_msec ();
|
||||
}
|
||||
else {
|
||||
printf("Mark stack overflow.\n");
|
||||
if (sim_log) {
|
||||
fprintf(sim_log, "Mark stack overflow.\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case showTimeCmd: /* show time difference */
|
||||
if (rtc_avail) {
|
||||
if (markTimeSP > 0) {
|
||||
delta = sim_os_msec () - markTime[--markTimeSP];
|
||||
printf("Delta to mark in milliseconds = %d.\n", delta);
|
||||
if (sim_log) {
|
||||
fprintf(sim_log, "Delta to mark in milliseconds = %d.\n", delta);
|
||||
}
|
||||
}
|
||||
else {
|
||||
printf("Missing mark.\n");
|
||||
if (sim_log) {
|
||||
fprintf(sim_log, "Missing mark.\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case resetPtrCmd: /* reset ptr device */
|
||||
ptr_reset(NULL);
|
||||
break;
|
||||
case attachCmd: /* attach ptr to the file with name at beginning of CP/M command line */
|
||||
attachCPM();
|
||||
break;
|
||||
case detachCmd: /* detach ptr */
|
||||
detach_unit(&ptr_unit);
|
||||
break;
|
||||
case resetCmd:
|
||||
versionPos = 0;
|
||||
break;
|
||||
default:;
|
||||
}
|
||||
return 0; /* ignored, since OUT */
|
||||
}
|
||||
}
|
||||
|
687
AltairZ80/altairZ80_sys.c
Normal file
687
AltairZ80/altairZ80_sys.c
Normal file
|
@ -0,0 +1,687 @@
|
|||
/* altairz80_sys.c: MITS Altair system interface
|
||||
Written by Peter Schorn, 2001
|
||||
Based on work by Charles E Owen ((c) 1997 - Commercial use prohibited)
|
||||
Disassembler from Marat Fayzullin ((c) 1995, 1996, 1997 - Commercial use prohibited)
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include "altairZ80_defs.h"
|
||||
|
||||
extern DEVICE cpu_dev;
|
||||
extern DEVICE dsk_dev;
|
||||
extern UNIT cpu_unit;
|
||||
extern REG cpu_reg[];
|
||||
extern DEVICE sio_dev;
|
||||
extern DEVICE ptr_dev;
|
||||
extern DEVICE ptp_dev;
|
||||
extern uint8 M[];
|
||||
extern int32 saved_PC;
|
||||
|
||||
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, int32 *hat);
|
||||
int32 parse_X80(char *cptr, int32 addr, uint32 *val, char *Mnemonics[]);
|
||||
int32 parse_sym (char *cptr, int32 addr, UNIT *uptr, uint32 *val, int32 sw);
|
||||
int32 DAsm(char *S, uint32 *val, int32 useZ80Mnemonics);
|
||||
|
||||
/* SCP data structures
|
||||
sim_name simulator name string
|
||||
sim_PC pointer to saved PC register descriptor
|
||||
sim_emax number of words needed for examine
|
||||
sim_devices array of pointers to simulated devices
|
||||
sim_stop_messages array of pointers to stop messages
|
||||
sim_load binary loader
|
||||
*/
|
||||
|
||||
char sim_name[] = "Altair 8800 (Z80)";
|
||||
REG *sim_PC = &cpu_reg[0];
|
||||
int32 sim_emax = 4;
|
||||
DEVICE *sim_devices[] = { &cpu_dev, &sio_dev, &ptr_dev, &ptp_dev, &dsk_dev, NULL };
|
||||
|
||||
const char *sim_stop_messages[] = {
|
||||
"Unknown error",
|
||||
"Unknown I/O Instruction",
|
||||
"HALT instruction",
|
||||
"Breakpoint",
|
||||
"Invalid Opcode" };
|
||||
|
||||
static char *Mnemonics8080[] = {
|
||||
/*0/8 1/9 2/A 3/B 4/C 5/D 6/E 7/F */
|
||||
"NOP", "LXI B,#h", "STAX B", "INX B", "INR B", "DCR B", "MVI B,*h", "RLC", /* 00-07 */
|
||||
"DB 09h", "DAD B", "LDAX B", "DCX B", "INR C", "DCR C", "MVI C,*h", "RRC", /* 08-0f */
|
||||
"DB 10h", "LXI D,#h", "STAX D", "INX D", "INR D", "DCR D", "MVI D,*h", "RAL", /* 10-17 */
|
||||
"DB 18h", "DAD D", "LDAX D", "DCX D", "INR E", "DCR E", "MVI E,*h", "RAR", /* 18-1f */
|
||||
"DB 20h", "LXI H,#h", "SHLD #h", "INX H", "INR H", "DCR H", "MVI H,*h", "DAA", /* 20-27 */
|
||||
"DB 28h", "DAD H", "LHLD #h", "DCX H", "INR L", "DCR L", "MVI L,*h", "CMA", /* 28-2f */
|
||||
"DB 30h", "LXI SP,#h", "STA #h", "INX SP", "INR M", "DCR M", "MVI M,*h", "STC", /* 30-37 */
|
||||
"DB 38h", "DAD SP", "LDA #h", "DCX SP", "INR A", "DCR A", "MVI A,*h", "CMC", /* 38-3f */
|
||||
"MOV B,B", "MOV B,C", "MOV B,D", "MOV B,E", "MOV B,H", "MOV B,L", "MOV B,M", "MOV B,A", /* 40-47 */
|
||||
"MOV C,B", "MOV C,C", "MOV C,D", "MOV C,E", "MOV C,H", "MOV C,L", "MOV C,M", "MOV C,A", /* 48-4f */
|
||||
"MOV D,B", "MOV D,C", "MOV D,D", "MOV D,E", "MOV D,H", "MOV D,L", "MOV D,M", "MOV D,A", /* 50-57 */
|
||||
"MOV E,B", "MOV E,C", "MOV E,D", "MOV E,E", "MOV E,H", "MOV E,L", "MOV E,M", "MOV E,A", /* 58-5f */
|
||||
"MOV H,B", "MOV H,C", "MOV H,D", "MOV H,E", "MOV H,H", "MOV H,L", "MOV H,M", "MOV H,A", /* 60-67 */
|
||||
"MOV L,B", "MOV L,C", "MOV L,D", "MOV L,E", "MOV L,H", "MOV L,L", "MOV L,M", "MOV L,A", /* 68-6f */
|
||||
"MOV M,B", "MOV M,C", "MOV M,D", "MOV M,E", "MOV M,H", "MOV M,L", "HLT", "MOV M,A", /* 70-77 */
|
||||
"MOV A,B", "MOV A,C", "MOV A,D", "MOV A,E", "MOV A,H", "MOV A,L", "MOV A,M", "MOV A,A", /* 78-7f */
|
||||
"ADD B", "ADD C", "ADD D", "ADD E", "ADD H", "ADD L", "ADD M", "ADD A", /* 80-87 */
|
||||
"ADC B", "ADC C", "ADC D", "ADC E", "ADC H", "ADC L", "ADC M", "ADC A", /* 88-8f */
|
||||
"SUB B", "SUB C", "SUB D", "SUB E", "SUB H", "SUB L", "SUB M", "SUB A", /* 90-97 */
|
||||
"SBB B", "SBB C", "SBB D", "SBB E", "SBB H", "SBB L", "SBB M", "SBB A", /* 98-9f */
|
||||
"ANA B", "ANA C", "ANA D", "ANA E", "ANA H", "ANA L", "ANA M", "ANA A", /* a0-a7 */
|
||||
"XRA B", "XRA C", "XRA D", "XRA E", "XRA H", "XRA L", "XRA M", "XRA A", /* a8-af */
|
||||
"ORA B", "ORA C", "ORA D", "ORA E", "ORA H", "ORA L", "ORA M", "ORA A", /* b0-b7 */
|
||||
"CMP B", "CMP C", "CMP D", "CMP E", "CMP H", "CMP L", "CMP M", "CMP A", /* b8-bf */
|
||||
"RNZ", "POP B", "JNZ #h", "JMP #h", "CNZ #h", "PUSH B", "ADI *h", "RST 0", /* c0-c7 */
|
||||
"RZ", "RET", "JZ #h", "DB CBh", "CZ #h", "CALL #h", "ACI *h", "RST 1", /* c8-cf */
|
||||
"RNC", "POP D", "JNC #h", "OUT *h", "CNC #h", "PUSH D", "SUI *h", "RST 2", /* d0-d7 */
|
||||
"RC", "DB D9h", "JC #h", "IN *h", "CC #h", "DB DDh", "SBI *h", "RST 3", /* d8-df */
|
||||
"RPO", "POP H", "JPO #h", "XTHL", "CPO #h", "PUSH H", "ANI *h", "RST 4", /* e0-e7 */
|
||||
"RPE", "PCHL", "JPE #h", "XCHG", "CPE #h", "DB EDh", "XRI *h", "RST 5", /* e8-ef */
|
||||
"RP", "POP PSW", "JP #h", "DI", "CP #h", "PUSH PSW", "ORI *h", "RST 6", /* f0-f7 */
|
||||
"RM", "SPHL", "JM #h", "EI", "CM #h", "DB FDh", "CPI *h", "RST 7" /* f8-ff */
|
||||
};
|
||||
|
||||
static char *MnemonicsZ80[256] =
|
||||
{
|
||||
"NOP", "LD BC,#h", "LD (BC),A", "INC BC", "INC B", "DEC B", "LD B,*h", "RLCA",
|
||||
"EX AF,AF'", "ADD HL,BC", "LD A,(BC)", "DEC BC", "INC C", "DEC C", "LD C,*h", "RRCA",
|
||||
"DJNZ @h", "LD DE,#h", "LD (DE),A", "INC DE", "INC D", "DEC D", "LD D,*h", "RLA",
|
||||
"JR @h", "ADD HL,DE", "LD A,(DE)", "DEC DE", "INC E", "DEC E", "LD E,*h", "RRA",
|
||||
"JR NZ,@h", "LD HL,#h", "LD (#h),HL", "INC HL", "INC H", "DEC H", "LD H,*h", "DAA",
|
||||
"JR Z,@h", "ADD HL,HL", "LD HL,(#h)", "DEC HL", "INC L", "DEC L", "LD L,*h", "CPL",
|
||||
"JR NC,@h", "LD SP,#h", "LD (#h),A", "INC SP", "INC (HL)", "DEC (HL)", "LD (HL),*h", "SCF",
|
||||
"JR C,@h", "ADD HL,SP", "LD A,(#h)", "DEC SP", "INC A", "DEC A", "LD A,*h", "CCF",
|
||||
"LD B,B", "LD B,C", "LD B,D", "LD B,E", "LD B,H", "LD B,L", "LD B,(HL)", "LD B,A",
|
||||
"LD C,B", "LD C,C", "LD C,D", "LD C,E", "LD C,H", "LD C,L", "LD C,(HL)", "LD C,A",
|
||||
"LD D,B", "LD D,C", "LD D,D", "LD D,E", "LD D,H", "LD D,L", "LD D,(HL)", "LD D,A",
|
||||
"LD E,B", "LD E,C", "LD E,D", "LD E,E", "LD E,H", "LD E,L", "LD E,(HL)", "LD E,A",
|
||||
"LD H,B", "LD H,C", "LD H,D", "LD H,E", "LD H,H", "LD H,L", "LD H,(HL)", "LD H,A",
|
||||
"LD L,B", "LD L,C", "LD L,D", "LD L,E", "LD L,H", "LD L,L", "LD L,(HL)", "LD L,A",
|
||||
"LD (HL),B", "LD (HL),C", "LD (HL),D", "LD (HL),E", "LD (HL),H", "LD (HL),L", "HALT", "LD (HL),A",
|
||||
"LD A,B", "LD A,C", "LD A,D", "LD A,E", "LD A,H", "LD A,L", "LD A,(HL)", "LD A,A",
|
||||
"ADD B", "ADD C", "ADD D", "ADD E", "ADD H", "ADD L", "ADD (HL)", "ADD A",
|
||||
"ADC B", "ADC C", "ADC D", "ADC E", "ADC H", "ADC L", "ADC (HL)", "ADC A",
|
||||
"SUB B", "SUB C", "SUB D", "SUB E", "SUB H", "SUB L", "SUB (HL)", "SUB A",
|
||||
"SBC B", "SBC C", "SBC D", "SBC E", "SBC H", "SBC L", "SBC (HL)", "SBC A",
|
||||
"AND B", "AND C", "AND D", "AND E", "AND H", "AND L", "AND (HL)", "AND A",
|
||||
"XOR B", "XOR C", "XOR D", "XOR E", "XOR H", "XOR L", "XOR (HL)", "XOR A",
|
||||
"OR B", "OR C", "OR D", "OR E", "OR H", "OR L", "OR (HL)", "OR A",
|
||||
"CP B", "CP C", "CP D", "CP E", "CP H", "CP L", "CP (HL)", "CP A",
|
||||
"RET NZ", "POP BC", "JP NZ,#h", "JP #h", "CALL NZ,#h", "PUSH BC", "ADD *h", "RST 00h",
|
||||
"RET Z", "RET", "JP Z,#h", "PFX_CB", "CALL Z,#h", "CALL #h", "ADC *h", "RST 08h",
|
||||
"RET NC", "POP DE", "JP NC,#h", "OUT (*h),A", "CALL NC,#h", "PUSH DE", "SUB *h", "RST 10h",
|
||||
"RET C", "EXX", "JP C,#h", "IN A,(*h)", "CALL C,#h", "PFX_DD", "SBC *h", "RST 18h",
|
||||
"RET PO", "POP HL", "JP PO,#h", "EX HL,(SP)", "CALL PO,#h", "PUSH HL", "AND *h", "RST 20h",
|
||||
"RET PE", "LD PC,HL", "JP PE,#h", "EX DE,HL", "CALL PE,#h", "PFX_ED", "XOR *h", "RST 28h",
|
||||
"RET P", "POP AF", "JP P,#h", "DI", "CALL P,#h", "PUSH AF", "OR *h", "RST 30h",
|
||||
"RET M", "LD SP,HL", "JP M,#h", "EI", "CALL M,#h", "PFX_FD", "CP *h", "RST 38h"
|
||||
};
|
||||
|
||||
static char *MnemonicsCB[256] =
|
||||
{
|
||||
"RLC B", "RLC C", "RLC D", "RLC E", "RLC H", "RLC L", "RLC (HL)", "RLC A",
|
||||
"RRC B", "RRC C", "RRC D", "RRC E", "RRC H", "RRC L", "RRC (HL)", "RRC A",
|
||||
"RL B", "RL C", "RL D", "RL E", "RL H", "RL L", "RL (HL)", "RL A",
|
||||
"RR B", "RR C", "RR D", "RR E", "RR H", "RR L", "RR (HL)", "RR A",
|
||||
"SLA B", "SLA C", "SLA D", "SLA E", "SLA H", "SLA L", "SLA (HL)", "SLA A",
|
||||
"SRA B", "SRA C", "SRA D", "SRA E", "SRA H", "SRA L", "SRA (HL)", "SRA A",
|
||||
"SLL B", "SLL C", "SLL D", "SLL E", "SLL H", "SLL L", "SLL (HL)", "SLL A",
|
||||
"SRL B", "SRL C", "SRL D", "SRL E", "SRL H", "SRL L", "SRL (HL)", "SRL A",
|
||||
"BIT 0,B", "BIT 0,C", "BIT 0,D", "BIT 0,E", "BIT 0,H", "BIT 0,L", "BIT 0,(HL)", "BIT 0,A",
|
||||
"BIT 1,B", "BIT 1,C", "BIT 1,D", "BIT 1,E", "BIT 1,H", "BIT 1,L", "BIT 1,(HL)", "BIT 1,A",
|
||||
"BIT 2,B", "BIT 2,C", "BIT 2,D", "BIT 2,E", "BIT 2,H", "BIT 2,L", "BIT 2,(HL)", "BIT 2,A",
|
||||
"BIT 3,B", "BIT 3,C", "BIT 3,D", "BIT 3,E", "BIT 3,H", "BIT 3,L", "BIT 3,(HL)", "BIT 3,A",
|
||||
"BIT 4,B", "BIT 4,C", "BIT 4,D", "BIT 4,E", "BIT 4,H", "BIT 4,L", "BIT 4,(HL)", "BIT 4,A",
|
||||
"BIT 5,B", "BIT 5,C", "BIT 5,D", "BIT 5,E", "BIT 5,H", "BIT 5,L", "BIT 5,(HL)", "BIT 5,A",
|
||||
"BIT 6,B", "BIT 6,C", "BIT 6,D", "BIT 6,E", "BIT 6,H", "BIT 6,L", "BIT 6,(HL)", "BIT 6,A",
|
||||
"BIT 7,B", "BIT 7,C", "BIT 7,D", "BIT 7,E", "BIT 7,H", "BIT 7,L", "BIT 7,(HL)", "BIT 7,A",
|
||||
"RES 0,B", "RES 0,C", "RES 0,D", "RES 0,E", "RES 0,H", "RES 0,L", "RES 0,(HL)", "RES 0,A",
|
||||
"RES 1,B", "RES 1,C", "RES 1,D", "RES 1,E", "RES 1,H", "RES 1,L", "RES 1,(HL)", "RES 1,A",
|
||||
"RES 2,B", "RES 2,C", "RES 2,D", "RES 2,E", "RES 2,H", "RES 2,L", "RES 2,(HL)", "RES 2,A",
|
||||
"RES 3,B", "RES 3,C", "RES 3,D", "RES 3,E", "RES 3,H", "RES 3,L", "RES 3,(HL)", "RES 3,A",
|
||||
"RES 4,B", "RES 4,C", "RES 4,D", "RES 4,E", "RES 4,H", "RES 4,L", "RES 4,(HL)", "RES 4,A",
|
||||
"RES 5,B", "RES 5,C", "RES 5,D", "RES 5,E", "RES 5,H", "RES 5,L", "RES 5,(HL)", "RES 5,A",
|
||||
"RES 6,B", "RES 6,C", "RES 6,D", "RES 6,E", "RES 6,H", "RES 6,L", "RES 6,(HL)", "RES 6,A",
|
||||
"RES 7,B", "RES 7,C", "RES 7,D", "RES 7,E", "RES 7,H", "RES 7,L", "RES 7,(HL)", "RES 7,A",
|
||||
"SET 0,B", "SET 0,C", "SET 0,D", "SET 0,E", "SET 0,H", "SET 0,L", "SET 0,(HL)", "SET 0,A",
|
||||
"SET 1,B", "SET 1,C", "SET 1,D", "SET 1,E", "SET 1,H", "SET 1,L", "SET 1,(HL)", "SET 1,A",
|
||||
"SET 2,B", "SET 2,C", "SET 2,D", "SET 2,E", "SET 2,H", "SET 2,L", "SET 2,(HL)", "SET 2,A",
|
||||
"SET 3,B", "SET 3,C", "SET 3,D", "SET 3,E", "SET 3,H", "SET 3,L", "SET 3,(HL)", "SET 3,A",
|
||||
"SET 4,B", "SET 4,C", "SET 4,D", "SET 4,E", "SET 4,H", "SET 4,L", "SET 4,(HL)", "SET 4,A",
|
||||
"SET 5,B", "SET 5,C", "SET 5,D", "SET 5,E", "SET 5,H", "SET 5,L", "SET 5,(HL)", "SET 5,A",
|
||||
"SET 6,B", "SET 6,C", "SET 6,D", "SET 6,E", "SET 6,H", "SET 6,L", "SET 6,(HL)", "SET 6,A",
|
||||
"SET 7,B", "SET 7,C", "SET 7,D", "SET 7,E", "SET 7,H", "SET 7,L", "SET 7,(HL)", "SET 7,A"
|
||||
};
|
||||
|
||||
static char *MnemonicsED[256] =
|
||||
{
|
||||
"DB EDh,00h", "DB EDh,01h", "DB EDh,02h", "DB EDh,03h", "DB EDh,04h", "DB EDh,05h", "DB EDh,06h", "DB EDh,07h",
|
||||
"DB EDh,08h", "DB EDh,09h", "DB EDh,0Ah", "DB EDh,0Bh", "DB EDh,0Ch", "DB EDh,0Dh", "DB EDh,0Eh", "DB EDh,0Fh",
|
||||
"DB EDh,10h", "DB EDh,11h", "DB EDh,12h", "DB EDh,13h", "DB EDh,14h", "DB EDh,15h", "DB EDh,16h", "DB EDh,17h",
|
||||
"DB EDh,18h", "DB EDh,19h", "DB EDh,1Ah", "DB EDh,1Bh", "DB EDh,1Ch", "DB EDh,1Dh", "DB EDh,1Eh", "DB EDh,1Fh",
|
||||
"DB EDh,20h", "DB EDh,21h", "DB EDh,22h", "DB EDh,23h", "DB EDh,24h", "DB EDh,25h", "DB EDh,26h", "DB EDh,27h",
|
||||
"DB EDh,28h", "DB EDh,29h", "DB EDh,2Ah", "DB EDh,2Bh", "DB EDh,2Ch", "DB EDh,2Dh", "DB EDh,2Eh", "DB EDh,2Fh",
|
||||
"DB EDh,30h", "DB EDh,31h", "DB EDh,32h", "DB EDh,33h", "DB EDh,34h", "DB EDh,35h", "DB EDh,36h", "DB EDh,37h",
|
||||
"DB EDh,38h", "DB EDh,39h", "DB EDh,3Ah", "DB EDh,3Bh", "DB EDh,3Ch", "DB EDh,3Dh", "DB EDh,3Eh", "DB EDh,3Fh",
|
||||
"IN B,(C)", "OUT (C),B", "SBC HL,BC", "LD (#h),BC", "NEG", "RETN", "IM 0", "LD I,A",
|
||||
"IN C,(C)", "OUT (C),C", "ADC HL,BC", "LD BC,(#h)", "DB EDh,4Ch", "RETI", "DB EDh,4Eh", "LD R,A",
|
||||
"IN D,(C)", "OUT (C),D", "SBC HL,DE", "LD (#h),DE", "DB EDh,54h", "DB EDh,55h", "IM 1", "LD A,I",
|
||||
"IN E,(C)", "OUT (C),E", "ADC HL,DE", "LD DE,(#h)", "DB EDh,5Ch", "DB EDh,5Dh", "IM 2", "LD A,R",
|
||||
"IN H,(C)", "OUT (C),H", "SBC HL,HL", "LD (#h),HL", "DB EDh,64h", "DB EDh,65h", "DB EDh,66h", "RRD",
|
||||
"IN L,(C)", "OUT (C),L", "ADC HL,HL", "LD HL,(#h)", "DB EDh,6Ch", "DB EDh,6Dh", "DB EDh,6Eh", "RLD",
|
||||
"IN F,(C)", "DB EDh,71h", "SBC HL,SP", "LD (#h),SP", "DB EDh,74h", "DB EDh,75h", "DB EDh,76h", "DB EDh,77h",
|
||||
"IN A,(C)", "OUT (C),A", "ADC HL,SP", "LD SP,(#h)", "DB EDh,7Ch", "DB EDh,7Dh", "DB EDh,7Eh", "DB EDh,7Fh",
|
||||
"DB EDh,80h", "DB EDh,81h", "DB EDh,82h", "DB EDh,83h", "DB EDh,84h", "DB EDh,85h", "DB EDh,86h", "DB EDh,87h",
|
||||
"DB EDh,88h", "DB EDh,89h", "DB EDh,8Ah", "DB EDh,8Bh", "DB EDh,8Ch", "DB EDh,8Dh", "DB EDh,8Eh", "DB EDh,8Fh",
|
||||
"DB EDh,90h", "DB EDh,91h", "DB EDh,92h", "DB EDh,93h", "DB EDh,94h", "DB EDh,95h", "DB EDh,96h", "DB EDh,97h",
|
||||
"DB EDh,98h", "DB EDh,99h", "DB EDh,9Ah", "DB EDh,9Bh", "DB EDh,9Ch", "DB EDh,9Dh", "DB EDh,9Eh", "DB EDh,9Fh",
|
||||
"LDI", "CPI", "INI", "OUTI", "DB EDh,A4h", "DB EDh,A5h", "DB EDh,A6h", "DB EDh,A7h",
|
||||
"LDD", "CPD", "IND", "OUTD", "DB EDh,ACh", "DB EDh,ADh", "DB EDh,AEh", "DB EDh,AFh",
|
||||
"LDIR", "CPIR", "INIR", "OTIR", "DB EDh,B4h", "DB EDh,B5h", "DB EDh,B6h", "DB EDh,B7h",
|
||||
"LDDR", "CPDR", "INDR", "OTDR", "DB EDh,BCh", "DB EDh,BDh", "DB EDh,BEh", "DB EDh,BFh",
|
||||
"DB EDh,C0h", "DB EDh,C1h", "DB EDh,C2h", "DB EDh,C3h", "DB EDh,C4h", "DB EDh,C5h", "DB EDh,C6h", "DB EDh,C7h",
|
||||
"DB EDh,C8h", "DB EDh,C9h", "DB EDh,CAh", "DB EDh,CBh", "DB EDh,CCh", "DB EDh,CDh", "DB EDh,CEh", "DB EDh,CFh",
|
||||
"DB EDh,D0h", "DB EDh,D1h", "DB EDh,D2h", "DB EDh,D3h", "DB EDh,D4h", "DB EDh,D5h", "DB EDh,D6h", "DB EDh,D7h",
|
||||
"DB EDh,D8h", "DB EDh,D9h", "DB EDh,DAh", "DB EDh,DBh", "DB EDh,DCh", "DB EDh,DDh", "DB EDh,DEh", "DB EDh,DFh",
|
||||
"DB EDh,E0h", "DB EDh,E1h", "DB EDh,E2h", "DB EDh,E3h", "DB EDh,E4h", "DB EDh,E5h", "DB EDh,E6h", "DB EDh,E7h",
|
||||
"DB EDh,E8h", "DB EDh,E9h", "DB EDh,EAh", "DB EDh,EBh", "DB EDh,ECh", "DB EDh,EDh", "DB EDh,EEh", "DB EDh,EFh",
|
||||
"DB EDh,F0h", "DB EDh,F1h", "DB EDh,F2h", "DB EDh,F3h", "DB EDh,F4h", "DB EDh,F5h", "DB EDh,F6h", "DB EDh,F7h",
|
||||
"DB EDh,F8h", "DB EDh,F9h", "DB EDh,FAh", "DB EDh,FBh", "DB EDh,FCh", "DB EDh,FDh", "DB EDh,FEh", "DB EDh,FFh"
|
||||
};
|
||||
|
||||
static char *MnemonicsXX[256] =
|
||||
{
|
||||
"NOP", "LD BC,#h", "LD (BC),A", "INC BC", "INC B", "DEC B", "LD B,*h", "RLCA",
|
||||
"EX AF,AF'", "ADD I%,BC", "LD A,(BC)", "DEC BC", "INC C", "DEC C", "LD C,*h", "RRCA",
|
||||
"DJNZ @h", "LD DE,#h", "LD (DE),A", "INC DE", "INC D", "DEC D", "LD D,*h", "RLA",
|
||||
"JR @h", "ADD I%,DE", "LD A,(DE)", "DEC DE", "INC E", "DEC E", "LD E,*h", "RRA",
|
||||
"JR NZ,@h", "LD I%,#h", "LD (#h),I%", "INC I%", "INC I%h", "DEC I%h", "LD I%h,*h", "DAA",
|
||||
"JR Z,@h", "ADD I%,I%", "LD I%,(#h)", "DEC I%", "INC I%l", "DEC I%l", "LD I%l,*h", "CPL",
|
||||
"JR NC,@h", "LD SP,#h", "LD (#h),A", "INC SP", "INC (I%+^h)", "DEC (I%+^h)", "LD (I%+^h),*h", "SCF",
|
||||
"JR C,@h", "ADD I%,SP", "LD A,(#h)", "DEC SP", "INC A", "DEC A", "LD A,*h", "CCF",
|
||||
"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",
|
||||
"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",
|
||||
"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",
|
||||
"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",
|
||||
"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",
|
||||
"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",
|
||||
"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",
|
||||
"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",
|
||||
"ADD B", "ADD C", "ADD D", "ADD E", "ADD I%h", "ADD I%l", "ADD (I%+^h)", "ADD A",
|
||||
"ADC B", "ADC C", "ADC D", "ADC E", "ADC I%h", "ADC I%l", "ADC (I%+^h)", "ADC,A",
|
||||
"SUB B", "SUB C", "SUB D", "SUB E", "SUB I%h", "SUB I%l", "SUB (I%+^h)", "SUB A",
|
||||
"SBC B", "SBC C", "SBC D", "SBC E", "SBC I%h", "SBC I%l", "SBC (I%+^h)", "SBC A",
|
||||
"AND B", "AND C", "AND D", "AND E", "AND I%h", "AND I%l", "AND (I%+^h)", "AND A",
|
||||
"XOR B", "XOR C", "XOR D", "XOR E", "XOR I%h", "XOR I%l", "XOR (I%+^h)", "XOR A",
|
||||
"OR B", "OR C", "OR D", "OR E", "OR I%h", "OR I%l", "OR (I%+^h)", "OR A",
|
||||
"CP B", "CP C", "CP D", "CP E", "CP I%h", "CP I%l", "CP (I%+^h)", "CP A",
|
||||
"RET NZ", "POP BC", "JP NZ,#h", "JP #h", "CALL NZ,#h", "PUSH BC", "ADD *h", "RST 00h",
|
||||
"RET Z", "RET", "JP Z,#h", "PFX_CB", "CALL Z,#h", "CALL #h", "ADC *h", "RST 08h",
|
||||
"RET NC", "POP DE", "JP NC,#h", "OUT (*h),A", "CALL NC,#h", "PUSH DE", "SUB *h", "RST 10h",
|
||||
"RET C", "EXX", "JP C,#h", "IN A,(*h)", "CALL C,#h", "PFX_DD", "SBC *h", "RST 18h",
|
||||
"RET PO", "POP I%", "JP PO,#h", "EX I%,(SP)", "CALL PO,#h", "PUSH I%", "AND *h", "RST 20h",
|
||||
"RET PE", "LD PC,I%", "JP PE,#h", "EX DE,I%", "CALL PE,#h", "PFX_ED", "XOR *h", "RST 28h",
|
||||
"RET P", "POP AF", "JP P,#h", "DI", "CALL P,#h", "PUSH AF", "OR *h", "RST 30h",
|
||||
"RET M", "LD SP,I%", "JP M,#h", "EI", "CALL M,#h", "PFX_FD", "CP *h", "RST 38h"
|
||||
};
|
||||
|
||||
static char *MnemonicsXCB[256] =
|
||||
{
|
||||
"RLC B", "RLC C", "RLC D", "RLC E", "RLC H", "RLC L", "RLC (I%@h)", "RLC A",
|
||||
"RRC B", "RRC C", "RRC D", "RRC E", "RRC H", "RRC L", "RRC (I%@h)", "RRC A",
|
||||
"RL B", "RL C", "RL D", "RL E", "RL H", "RL L", "RL (I%@h)", "RL A",
|
||||
"RR B", "RR C", "RR D", "RR E", "RR H", "RR L", "RR (I%@h)", "RR A",
|
||||
"SLA B", "SLA C", "SLA D", "SLA E", "SLA H", "SLA L", "SLA (I%@h)", "SLA A",
|
||||
"SRA B", "SRA C", "SRA D", "SRA E", "SRA H", "SRA L", "SRA (I%@h)", "SRA A",
|
||||
"SLL B", "SLL C", "SLL D", "SLL E", "SLL H", "SLL L", "SLL (I%@h)", "SLL A",
|
||||
"SRL B", "SRL C", "SRL D", "SRL E", "SRL H", "SRL L", "SRL (I%@h)", "SRL A",
|
||||
"BIT 0,B", "BIT 0,C", "BIT 0,D", "BIT 0,E", "BIT 0,H", "BIT 0,L", "BIT 0,(I%@h)", "BIT 0,A",
|
||||
"BIT 1,B", "BIT 1,C", "BIT 1,D", "BIT 1,E", "BIT 1,H", "BIT 1,L", "BIT 1,(I%@h)", "BIT 1,A",
|
||||
"BIT 2,B", "BIT 2,C", "BIT 2,D", "BIT 2,E", "BIT 2,H", "BIT 2,L", "BIT 2,(I%@h)", "BIT 2,A",
|
||||
"BIT 3,B", "BIT 3,C", "BIT 3,D", "BIT 3,E", "BIT 3,H", "BIT 3,L", "BIT 3,(I%@h)", "BIT 3,A",
|
||||
"BIT 4,B", "BIT 4,C", "BIT 4,D", "BIT 4,E", "BIT 4,H", "BIT 4,L", "BIT 4,(I%@h)", "BIT 4,A",
|
||||
"BIT 5,B", "BIT 5,C", "BIT 5,D", "BIT 5,E", "BIT 5,H", "BIT 5,L", "BIT 5,(I%@h)", "BIT 5,A",
|
||||
"BIT 6,B", "BIT 6,C", "BIT 6,D", "BIT 6,E", "BIT 6,H", "BIT 6,L", "BIT 6,(I%@h)", "BIT 6,A",
|
||||
"BIT 7,B", "BIT 7,C", "BIT 7,D", "BIT 7,E", "BIT 7,H", "BIT 7,L", "BIT 7,(I%@h)", "BIT 7,A",
|
||||
"RES 0,B", "RES 0,C", "RES 0,D", "RES 0,E", "RES 0,H", "RES 0,L", "RES 0,(I%@h)", "RES 0,A",
|
||||
"RES 1,B", "RES 1,C", "RES 1,D", "RES 1,E", "RES 1,H", "RES 1,L", "RES 1,(I%@h)", "RES 1,A",
|
||||
"RES 2,B", "RES 2,C", "RES 2,D", "RES 2,E", "RES 2,H", "RES 2,L", "RES 2,(I%@h)", "RES 2,A",
|
||||
"RES 3,B", "RES 3,C", "RES 3,D", "RES 3,E", "RES 3,H", "RES 3,L", "RES 3,(I%@h)", "RES 3,A",
|
||||
"RES 4,B", "RES 4,C", "RES 4,D", "RES 4,E", "RES 4,H", "RES 4,L", "RES 4,(I%@h)", "RES 4,A",
|
||||
"RES 5,B", "RES 5,C", "RES 5,D", "RES 5,E", "RES 5,H", "RES 5,L", "RES 5,(I%@h)", "RES 5,A",
|
||||
"RES 6,B", "RES 6,C", "RES 6,D", "RES 6,E", "RES 6,H", "RES 6,L", "RES 6,(I%@h)", "RES 6,A",
|
||||
"RES 7,B", "RES 7,C", "RES 7,D", "RES 7,E", "RES 7,H", "RES 7,L", "RES 7,(I%@h)", "RES 7,A",
|
||||
"SET 0,B", "SET 0,C", "SET 0,D", "SET 0,E", "SET 0,H", "SET 0,L", "SET 0,(I%@h)", "SET 0,A",
|
||||
"SET 1,B", "SET 1,C", "SET 1,D", "SET 1,E", "SET 1,H", "SET 1,L", "SET 1,(I%@h)", "SET 1,A",
|
||||
"SET 2,B", "SET 2,C", "SET 2,D", "SET 2,E", "SET 2,H", "SET 2,L", "SET 2,(I%@h)", "SET 2,A",
|
||||
"SET 3,B", "SET 3,C", "SET 3,D", "SET 3,E", "SET 3,H", "SET 3,L", "SET 3,(I%@h)", "SET 3,A",
|
||||
"SET 4,B", "SET 4,C", "SET 4,D", "SET 4,E", "SET 4,H", "SET 4,L", "SET 4,(I%@h)", "SET 4,A",
|
||||
"SET 5,B", "SET 5,C", "SET 5,D", "SET 5,E", "SET 5,H", "SET 5,L", "SET 5,(I%@h)", "SET 5,A",
|
||||
"SET 6,B", "SET 6,C", "SET 6,D", "SET 6,E", "SET 6,H", "SET 6,L", "SET 6,(I%@h)", "SET 6,A",
|
||||
"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"
|
||||
};
|
||||
|
||||
/* Symbolic disassembler
|
||||
|
||||
Inputs:
|
||||
*val = instructions to disassemble
|
||||
useZ80Mnemonics = > 0 iff Z80 mnemonics are to be used
|
||||
Outputs:
|
||||
*S = output text
|
||||
|
||||
DAsm is Copyright (C) Marat Fayzullin 1995,1996,1997
|
||||
You are not allowed to distribute this software
|
||||
commercially.
|
||||
|
||||
*/
|
||||
|
||||
int32 DAsm(char *S, uint32 *val, int32 useZ80Mnemonics)
|
||||
{
|
||||
char R[128], H[10], C= '\0', *T, *P;
|
||||
uint8 J = 0, Offset;
|
||||
uint16 B = 0;
|
||||
|
||||
if (useZ80Mnemonics) {
|
||||
switch(val[B]) {
|
||||
case 0xCB:
|
||||
B++;
|
||||
T = MnemonicsCB[val[B++]];
|
||||
break;
|
||||
case 0xED:
|
||||
B++;
|
||||
T = MnemonicsED[val[B++]];
|
||||
break;
|
||||
case 0xDD:
|
||||
case 0xFD:
|
||||
C = (val[B] == 0xDD) ? 'X' : 'Y';
|
||||
B++;
|
||||
if (val[B] == 0xCB) {
|
||||
B++;
|
||||
Offset = val[B++];
|
||||
J = 1;
|
||||
T = MnemonicsXCB[val[B++]];
|
||||
}
|
||||
else {
|
||||
T = MnemonicsXX[val[B++]];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
T = MnemonicsZ80[val[B++]];
|
||||
}
|
||||
}
|
||||
else {
|
||||
T = Mnemonics8080[val[B++]];
|
||||
}
|
||||
|
||||
if (P = strchr(T, '^'))
|
||||
{
|
||||
strncpy(R, T, P - T);
|
||||
R[P - T] = '\0';
|
||||
sprintf(H, "%02X", val[B++]);
|
||||
strcat(R, H);
|
||||
strcat(R, P + 1);
|
||||
}
|
||||
else {
|
||||
strcpy(R, T);
|
||||
}
|
||||
if (P = strchr(R, '%')) {
|
||||
*P = C;
|
||||
if (P = strchr(P + 1, '%')) *P = C;
|
||||
}
|
||||
|
||||
if(P = strchr(R, '*')) {
|
||||
strncpy(S, R, P - R);
|
||||
S[P - R] = '\0';
|
||||
sprintf(H, "%02X", val[B++]);
|
||||
strcat(S, H);
|
||||
strcat(S, P + 1);
|
||||
}
|
||||
else if (P = strchr(R, '@')) {
|
||||
strncpy(S, R, P - R);
|
||||
S[P - R] = '\0';
|
||||
if(!J) {
|
||||
Offset = val[B++];
|
||||
}
|
||||
strcat(S, Offset & 0x80 ? "-" : "+");
|
||||
J = Offset & 0x80 ? 256 - Offset : Offset;
|
||||
sprintf(H, "%02X", J);
|
||||
strcat(S, H);
|
||||
strcat(S, P + 1);
|
||||
}
|
||||
else if (P = strchr(R, '#')) {
|
||||
strncpy(S, R, P - R);
|
||||
S[P - R] = '\0';
|
||||
sprintf(H, "%04X", val[B] + 256*val[B + 1]);
|
||||
strcat(S, H);
|
||||
strcat(S, P + 1);
|
||||
B += 2;
|
||||
}
|
||||
else {
|
||||
strcpy(S, R);
|
||||
}
|
||||
return(B);
|
||||
}
|
||||
|
||||
/* Symbolic output
|
||||
|
||||
Inputs:
|
||||
*of = output stream
|
||||
addr = current PC
|
||||
*val = pointer to values
|
||||
*uptr = pointer to unit
|
||||
sw = switches
|
||||
Outputs:
|
||||
status = error code
|
||||
*/
|
||||
|
||||
int32 fprint_sym (FILE *of, int32 addr, uint32 *val, UNIT *uptr, int32 sw)
|
||||
{
|
||||
char disasm[128];
|
||||
int32 ch = val[0] & 0x7f;
|
||||
if (sw & (SWMASK ('A') | SWMASK ('C'))) {
|
||||
fprintf(of, ((0x20 <= ch) && (ch < 0x7f)) ? "'%c'" : "%02x", ch);
|
||||
return SCPE_OK;
|
||||
}
|
||||
if (!(sw & SWMASK ('M'))) {
|
||||
return SCPE_ARG;
|
||||
}
|
||||
ch = DAsm(disasm, val, cpu_unit.flags & UNIT_CHIP);
|
||||
fprintf(of, "%s", disasm);
|
||||
return (1-ch); /* need to return additional bytes */
|
||||
}
|
||||
|
||||
/* numString checks determines the base of the number (ch, *numString)
|
||||
and returns FALSE if the number is bad */
|
||||
int32 checkbase(char ch, char *numString) {
|
||||
int32 decimal = (ch <= '9');
|
||||
if (toupper(ch) == 'H') {
|
||||
return FALSE;
|
||||
}
|
||||
while (isxdigit(ch = *numString++)) {
|
||||
if (ch > '9') {
|
||||
decimal = FALSE;
|
||||
}
|
||||
}
|
||||
return toupper(ch) == 'H' ? 16 : (decimal ? 10 : FALSE);
|
||||
}
|
||||
|
||||
int32 numok(char ch, char **numString, int32 minvalue, int32 maxvalue, int32 requireSign, int32 *result) {
|
||||
int32 sign = 1, value = 0, base;
|
||||
if (requireSign) {
|
||||
if (ch == '+') {
|
||||
ch = *(*numString)++;
|
||||
}
|
||||
else if (ch == '-') {
|
||||
sign = -1;
|
||||
ch = *(*numString)++;
|
||||
}
|
||||
else {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
if (!(base = checkbase(ch, *numString))) {
|
||||
return FALSE;
|
||||
}
|
||||
while (isxdigit(ch)) {
|
||||
value = base * value + ((ch <= '9') ? (ch - '0') : (toupper(ch) - 'A' + 10));
|
||||
ch = *(*numString)++;
|
||||
}
|
||||
if (toupper(ch) != 'H') {
|
||||
(*numString)--;
|
||||
}
|
||||
*result = value*sign;
|
||||
return (minvalue <= value) && (value <= maxvalue);
|
||||
}
|
||||
|
||||
int32 match(char *pattern, char *input, char *xy, int32 *number, int32 *star,
|
||||
int32 *at, int32 *hat) {
|
||||
char pat = *pattern++;
|
||||
char inp = *input++;
|
||||
while ((pat) && (inp)) {
|
||||
switch(pat) {
|
||||
case ',':
|
||||
if (inp == ' ') {
|
||||
inp = *input++;
|
||||
continue;
|
||||
}
|
||||
case ' ':
|
||||
if (inp != pat) {
|
||||
return FALSE;
|
||||
}
|
||||
pat = *pattern++;
|
||||
inp = *input++;
|
||||
while (inp == ' ') {
|
||||
inp = *input++;
|
||||
}
|
||||
continue;
|
||||
break;
|
||||
case '%':
|
||||
inp = toupper(inp);
|
||||
if ((inp == 'X') || (inp == 'Y')) {
|
||||
*xy = inp;
|
||||
}
|
||||
else {
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case '#':
|
||||
if (numok(inp, &input, 0, 65535, FALSE, number)) {
|
||||
pattern++; /* skip h */
|
||||
}
|
||||
else {
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case '*':
|
||||
if (numok(inp, &input, 0, 255, FALSE, star)) {
|
||||
pattern++; /* skip h */
|
||||
}
|
||||
else {
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case '@':
|
||||
if (numok(inp, &input, -128, 65535, TRUE, at)) {
|
||||
pattern++; /* skip h */
|
||||
}
|
||||
else {
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case '^':
|
||||
if (numok(inp, &input, 0, 255, FALSE, hat)) {
|
||||
pattern++; /* skip h */
|
||||
}
|
||||
else {
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (toupper(pat) != toupper(inp)) {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
pat = *pattern++;
|
||||
inp = *input++;
|
||||
}
|
||||
while (inp == ' ') {
|
||||
inp = *input++;
|
||||
}
|
||||
return (pat == 0) && (inp == 0);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
int32 parse_X80(char *cptr, int32 addr, uint32 *val, char *Mnemonics[]) {
|
||||
char xy;
|
||||
int32 op, number, star, at, hat;
|
||||
for (op = 0; op < 256; op++) {
|
||||
number = star = at = -129;
|
||||
if (match(Mnemonics[op], cptr, &xy, &number, &star, &at, &hat)) {
|
||||
val[0] = op;
|
||||
if (number >= 0) {
|
||||
val[1] = (0xff) & number;
|
||||
val[2] = (0xff) & (number >> 8);
|
||||
return (-2); /* two additional bytes returned */
|
||||
}
|
||||
else if (star >= 0) {
|
||||
val[1] = (0xff) & star;
|
||||
return (-1); /* one additional byte returned */
|
||||
}
|
||||
else if (at > -129) {
|
||||
if (at > 127) { /* assume absolute address is meant */
|
||||
at -= addr + 2; /* translate to relative address */
|
||||
}
|
||||
if ((-128 <= at) && (at < 127)) {
|
||||
val[1] = (int8)(at);
|
||||
return (-1);
|
||||
}
|
||||
else {
|
||||
return SCPE_ARG;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return SCPE_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (Mnemonics == Mnemonics8080) {
|
||||
return SCPE_ARG;
|
||||
}
|
||||
|
||||
for (op = 0; op < 256; op++) {
|
||||
if (match(MnemonicsCB[op], cptr, &xy, &number, &star, &at, &hat)) {
|
||||
val[0] = 0xCB;
|
||||
val[1] = op;
|
||||
return (-1); /* one additional byte returned */
|
||||
}
|
||||
}
|
||||
|
||||
for (op = 0; op < 256; op++) {
|
||||
number = -1;
|
||||
if (match(MnemonicsED[op], cptr, &xy, &number, &star, &at, &hat)) {
|
||||
val[0] = 0xED;
|
||||
val[1] = op;
|
||||
if (number >= 0) {
|
||||
val[2] = (0xff) & number;
|
||||
val[3] = (0xff) & (number >> 8);
|
||||
return (-3); /* three additional bytes returned */
|
||||
}
|
||||
else {
|
||||
return (-1); /* one additional byte returned */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (op = 0; op < 256; op++) {
|
||||
number = star = hat = -1;
|
||||
xy = ' ';
|
||||
if (match(MnemonicsXX[op], cptr, &xy, &number, &star, &at, &hat)) {
|
||||
if (!(val[0] = checkXY(xy))) {
|
||||
return SCPE_ARG;
|
||||
}
|
||||
val[1] = op;
|
||||
if (number >= 0) {
|
||||
val[2] = (0xff) & number;
|
||||
val[3] = (0xff) & (number >> 8);
|
||||
return (-3); /* three additional bytes returned */
|
||||
}
|
||||
else if ((star >= 0) && (hat >= 0)) {
|
||||
val[2] = (0xff) & hat;
|
||||
val[3] = (0xff) & star;
|
||||
return (-3); /* three additional bytes returned */
|
||||
}
|
||||
else if (star >= 0) {
|
||||
val[2] = (0xff) & star;
|
||||
return (-2); /* two additional bytes returned */
|
||||
}
|
||||
else if (hat >= 0) {
|
||||
val[2] = (0xff) & hat;
|
||||
return (-2); /* two additional bytes returned */
|
||||
}
|
||||
else {
|
||||
return (-1); /* one additional byte returned */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (op = 0; op < 256; op++) {
|
||||
at = -129;
|
||||
xy = ' ';
|
||||
if (match(MnemonicsXCB[op], cptr, &xy, &number, &star, &at, &hat)) {
|
||||
if (!(val[0] = checkXY(xy))) {
|
||||
return SCPE_ARG;
|
||||
}
|
||||
val[1] = 0xCB;
|
||||
if (at > -129) {
|
||||
val[2] = (int8) (at);
|
||||
}
|
||||
else {
|
||||
printf("Offset expected.\n");
|
||||
return SCPE_ARG;
|
||||
}
|
||||
val[3] = op;
|
||||
return (-3); /* three additional bytes returned */
|
||||
}
|
||||
}
|
||||
return SCPE_ARG;
|
||||
}
|
||||
|
||||
|
||||
/* Symbolic input
|
||||
|
||||
Inputs:
|
||||
*cptr = pointer to input string
|
||||
addr = current PC
|
||||
*uptr = pointer to unit
|
||||
*val = pointer to output values
|
||||
sw = switches
|
||||
Outputs:
|
||||
status = error status
|
||||
*/
|
||||
int32 parse_sym (char *cptr, int32 addr, UNIT *uptr, uint32 *val, int32 sw)
|
||||
{
|
||||
while (isspace (*cptr)) cptr++; /* absorb spaces */
|
||||
if ((sw & (SWMASK ('A') | SWMASK ('C'))) || ((*cptr == '\'') && cptr++)) { /* ASCII char? */
|
||||
if (cptr[0] == 0) {
|
||||
return SCPE_ARG; /* must have 1 char */
|
||||
}
|
||||
val[0] = (uint32) cptr[0];
|
||||
return SCPE_OK;
|
||||
}
|
||||
return (cpu_unit.flags & UNIT_CHIP) ?
|
||||
parse_X80(cptr, addr, val, MnemonicsZ80) : parse_X80(cptr, addr, val, Mnemonics8080);
|
||||
}
|
||||
|
||||
|
||||
/* This is the binary loader. The input file is considered to be
|
||||
a string of literal bytes with no format special format. The
|
||||
load starts at the current value of the PC.
|
||||
*/
|
||||
|
||||
int32 sim_load (FILE *fileref, char *cptr, char *fnam, int32 flag)
|
||||
{
|
||||
int32 i, addr = 0, cnt = 0;
|
||||
|
||||
if ((*cptr != 0) || (flag != 0)) return SCPE_ARG;
|
||||
addr = saved_PC;
|
||||
while ((i = getc (fileref)) != EOF) {
|
||||
M[addr++] = i;
|
||||
cnt++;
|
||||
} /* end while */
|
||||
printf ("%d Bytes loaded.\n", cnt);
|
||||
return (SCPE_OK);
|
||||
}
|
|
@ -23,6 +23,11 @@
|
|||
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
cpu H316/H516 CPU
|
||||
|
||||
03-Nov-01 RMS Fixed NOHSA modifier
|
||||
30-Nov-01 RMS Added extended SET/SHOW support
|
||||
|
||||
The register state for the Honeywell 316/516 CPU is:
|
||||
|
||||
AR<1:16> A register
|
||||
|
@ -184,8 +189,6 @@
|
|||
|
||||
#include "h316_defs.h"
|
||||
|
||||
#define ILL_ADR_FLAG 0100000
|
||||
#define save_ibkpt (cpu_unit.u3)
|
||||
#define UNIT_V_MSIZE (UNIT_V_UF) /* dummy mask */
|
||||
#define UNIT_MSIZE (1 << UNIT_V_MSIZE)
|
||||
#define m7 0001000 /* for generics */
|
||||
|
@ -216,21 +219,20 @@ int32 dev_enable = 0; /* dev enable */
|
|||
int32 ind_max = 8; /* iadr nest limit */
|
||||
int32 stop_inst = 1; /* stop on ill inst */
|
||||
int32 stop_dev = 2; /* stop on ill dev */
|
||||
int32 ibkpt_addr = ILL_ADR_FLAG | X_AMASK; /* breakpoint addr */
|
||||
int32 old_PC = 0; /* previous PC */
|
||||
int32 dlog = 0; /* debug log */
|
||||
int32 turnoff = 0;
|
||||
|
||||
extern int32 sim_int_char;
|
||||
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_svc (UNIT *uptr);
|
||||
t_stat cpu_set_noext (UNIT *uptr, int32 value);
|
||||
t_stat cpu_set_size (UNIT *uptr, int32 value);
|
||||
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);
|
||||
|
||||
/* CPU data structures
|
||||
|
||||
|
@ -240,7 +242,7 @@ t_stat cpu_set_size (UNIT *uptr, int32 value);
|
|||
cpu_mod CPU modifiers list
|
||||
*/
|
||||
|
||||
UNIT cpu_unit = { UDATA (&cpu_svc, UNIT_FIX + UNIT_BINK + UNIT_EXT,
|
||||
UNIT cpu_unit = { UDATA (NULL, UNIT_FIX + UNIT_BINK + UNIT_EXT,
|
||||
MAXMEMSIZE) };
|
||||
|
||||
REG cpu_reg[] = {
|
||||
|
@ -268,7 +270,6 @@ REG cpu_reg[] = {
|
|||
{ FLDATA (STOP_DEV, stop_dev, 1) },
|
||||
{ DRDATA (INDMAX, ind_max, 8), REG_NZ + PV_LEFT },
|
||||
{ ORDATA (OLDP, old_PC, 15), REG_RO },
|
||||
{ ORDATA (BREAK, ibkpt_addr, 16) },
|
||||
{ ORDATA (WRU, sim_int_char, 8) },
|
||||
{ FLDATA (DLOG, dlog, 0) },
|
||||
{ FLDATA (HEXT, cpu_unit.flags, UNIT_V_EXT), REG_HRO },
|
||||
|
@ -278,7 +279,7 @@ REG cpu_reg[] = {
|
|||
MTAB cpu_mod[] = {
|
||||
{ UNIT_EXT, 0, "no extend", "NOEXTEND", &cpu_set_noext },
|
||||
{ UNIT_EXT, UNIT_EXT, "extend", "EXTEND", NULL },
|
||||
{ UNIT_HSA, 0, "no HSA", "HSA", NULL },
|
||||
{ UNIT_HSA, 0, "no HSA", "NOHSA", NULL },
|
||||
{ UNIT_HSA, UNIT_HSA, "HSA", "HSA", NULL },
|
||||
{ UNIT_MSIZE, 4096, NULL, "4K", &cpu_set_size },
|
||||
{ UNIT_MSIZE, 8192, NULL, "8K", &cpu_set_size },
|
||||
|
@ -362,10 +363,8 @@ if ((dev_ready & (INT_PENDING | dev_enable)) > INT_PENDING) { /* int req? */
|
|||
if (dlog && sim_log) fprintf (sim_log, "Interrupt\n");
|
||||
MB = 0120000 | M_INT; } /* inst = JST* 63 */
|
||||
|
||||
else { if (PC == ibkpt_addr) { /* breakpoint? */
|
||||
save_ibkpt = ibkpt_addr; /* save address */
|
||||
ibkpt_addr = ibkpt_addr | ILL_ADR_FLAG; /* disable */
|
||||
sim_activate (&cpu_unit, 1); /* sched re-enable */
|
||||
else { if (sim_brk_summ &&
|
||||
sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */
|
||||
reason = STOP_IBKPT; /* stop simulation */
|
||||
break; }
|
||||
Y = PC; /* set mem addr */
|
||||
|
@ -986,7 +985,8 @@ dp = 0;
|
|||
ext = pme = extoff_pending = 0;
|
||||
dev_ready = dev_ready & ~INT_PENDING;
|
||||
dev_enable = 0;
|
||||
return cpu_svc (&cpu_unit);
|
||||
sim_brk_types = sim_brk_dflt = SWMASK ('E');
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Memory examine */
|
||||
|
@ -1012,35 +1012,26 @@ else M[addr] = val & DMASK;
|
|||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Breakpoint service */
|
||||
|
||||
t_stat cpu_svc (UNIT *uptr)
|
||||
{
|
||||
if ((ibkpt_addr & ~ILL_ADR_FLAG) == save_ibkpt) ibkpt_addr = save_ibkpt;
|
||||
save_ibkpt = -1;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Option processors */
|
||||
|
||||
t_stat cpu_set_noext (UNIT *uptr, int32 value)
|
||||
t_stat cpu_set_noext (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
if (MEMSIZE > (NX_AMASK + 1)) return SCPE_ARG;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat cpu_set_size (UNIT *uptr, int32 value)
|
||||
t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
int32 mc = 0;
|
||||
t_addr i;
|
||||
|
||||
if ((value <= 0) || (value > MAXMEMSIZE) || ((value & 07777) != 0) ||
|
||||
(((cpu_unit.flags & UNIT_EXT) == 0) && (value > (NX_AMASK + 1))))
|
||||
if ((val <= 0) || (val > MAXMEMSIZE) || ((val & 07777) != 0) ||
|
||||
(((cpu_unit.flags & UNIT_EXT) == 0) && (val > (NX_AMASK + 1))))
|
||||
return SCPE_ARG;
|
||||
for (i = value; i < MEMSIZE; i++) mc = mc | M[i];
|
||||
for (i = val; i < MEMSIZE; i++) mc = mc | M[i];
|
||||
if ((mc != 0) && (!get_yn ("Really truncate memory [N]?", FALSE)))
|
||||
return SCPE_OK;
|
||||
MEMSIZE = value;
|
||||
MEMSIZE = val;
|
||||
for (i = MEMSIZE; i < MAXMEMSIZE; i++) M[i] = 0;
|
||||
return SCPE_OK;
|
||||
}
|
303
H316/h316_doc.txt
Normal file
303
H316/h316_doc.txt
Normal file
|
@ -0,0 +1,303 @@
|
|||
To: Users
|
||||
From: Bob Supnik
|
||||
Subj: H316 Simulator Usage
|
||||
Date: 1-Dec-2001
|
||||
|
||||
COPYRIGHT NOTICE
|
||||
|
||||
The following copyright notice applies to both the SIMH source and binary:
|
||||
|
||||
Original code published in 1993-2001, written by Robert M Supnik
|
||||
Copyright (c) 1993-2001, Robert M Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation
|
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
and/or sell copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
Except as contained in this notice, the name of Robert M Supnik shall not
|
||||
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
This memorandum documents Honeywell 316/516 simulator.
|
||||
|
||||
|
||||
1. Simulator Files
|
||||
|
||||
The H316 requires the following files:
|
||||
|
||||
sim/ sim_defs.h
|
||||
scp.c
|
||||
scp_tty.c
|
||||
sim_rev.c
|
||||
|
||||
sim/h316/ h316_defs.h
|
||||
h316_cpu.c
|
||||
h316_lp.c
|
||||
h316_stddev.c
|
||||
h316_cpu.c
|
||||
|
||||
2. H316/H516 Features
|
||||
|
||||
The Honeywell 316/516 simulator is configured as follows:
|
||||
|
||||
device simulates
|
||||
name(s)
|
||||
|
||||
CPU H316/H516 CPU with 16/32KW memory
|
||||
PTR 316/516-50 paper tape reader
|
||||
PTP 316/516-52 paper tape punch
|
||||
TTY 316/516-33 console terminal
|
||||
CLK 316/516-12 real time clock
|
||||
LPT 316/516 line printer
|
||||
|
||||
The H316/H516 simulator implements several unique stop conditions:
|
||||
|
||||
- decode of an undefined instruction, and STOP_INST is et
|
||||
- reference to an undefined I/O device, and STOP_DEV is set
|
||||
- more than INDMAX indirect references are detected during
|
||||
memory reference address decoding
|
||||
|
||||
The H316/H516 loader is not implemented.
|
||||
|
||||
2.1 CPU
|
||||
|
||||
CPU options include choice of instruction set and memory size.
|
||||
|
||||
SET CPU HSA high speed arithmetic instructions
|
||||
SET CPU NOHSA no high speed arithmetic instructions
|
||||
SET CPU 4K set memory size = 4K
|
||||
SET CPU 8K set memory size = 8K
|
||||
SET CPU 12K set memory size = 12K
|
||||
SET CPU 16K set memory size = 16K
|
||||
SET CPU 24K set memory size = 24K
|
||||
SET CPU 32K set memory size = 32K
|
||||
|
||||
If memory size is being reduced, and the memory being truncated contains
|
||||
non-zero data, the simulator asks for confirmation. Data in the truncated
|
||||
portion of memory is lost. Initial memory size is 32K.
|
||||
|
||||
CPU registers include the visible state of the processor as well as the
|
||||
control registers for the interrupt system.
|
||||
|
||||
name size comments
|
||||
|
||||
P 15 program counter
|
||||
A 16 A register
|
||||
B 16 B register
|
||||
X 16 index register
|
||||
SC 16 shift count
|
||||
C 1 carry flag
|
||||
EXT 1 extend flag
|
||||
PME 1 previous mode extend flag
|
||||
EXT_OFF 1 extend off pending flag
|
||||
DP 1 double precision flag
|
||||
SS1..4 1 sense switches 1..4
|
||||
ION 1 interrupts enabled
|
||||
INODEF 1 interrupts not deferred
|
||||
INTREQ 16 interrupt requests
|
||||
DEVRDY 16 device ready flags (read only)
|
||||
DEVENB 16 device interrupt enable flags (read only)
|
||||
STOP_INST 1 stop on undefined instruction
|
||||
STOP_DEV 1 stop on undefined device
|
||||
INDMAX 1 indirect address limit
|
||||
OLDP 15 PC prior to last JMP, JSB, or interrupt
|
||||
WRU 8 interrupt character
|
||||
|
||||
2.2 Programmed I/O Devices
|
||||
|
||||
2.2.1 316/516-50 Paper Tape Reader (PTR)
|
||||
|
||||
The paper tape reader (PTR) reads data from a disk file. The POS
|
||||
register specifies the number of the next data item to be read.
|
||||
Thus, by changing POS, the user can backspace or advance the reader.
|
||||
|
||||
The paper tape reader supports the BOOT command. BOOT PTR copies the
|
||||
absolute binary loader into memory and starts it running.
|
||||
|
||||
The paper tape reader implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
BUF 8 last data item processed
|
||||
INTREQ 1 device interrupt request
|
||||
READY 1 device ready
|
||||
ENABLE 1 device interrupts enabled
|
||||
POS 31 position in the input or output file
|
||||
TIME 24 time from I/O initiation to interrupt
|
||||
STOP_IOE 1 stop on I/O error
|
||||
|
||||
Error handling is as follows:
|
||||
|
||||
error STOP_IOE processed as
|
||||
|
||||
not attached 1 report error and stop
|
||||
0 out of tape
|
||||
|
||||
end of file 1 report error and stop
|
||||
0 out of tape or paper
|
||||
|
||||
OS I/O error x report error and stop
|
||||
|
||||
2.2.2 316/516-52 Paper Tape Punch (PTP)
|
||||
|
||||
The paper tape punch (PTP) writes data to a disk file. The POS
|
||||
register specifies the number of the next data item to be written.
|
||||
Thus, by changing POS, the user can backspace or advance the punch.
|
||||
|
||||
The paper tape punch implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
BUF 8 last data item processed
|
||||
INTREQ 1 device interrupt request
|
||||
READY 1 device ready
|
||||
ENABLE 1 device interrupts enabled
|
||||
POWER 1 device powered up
|
||||
POS 31 position in the input or output file
|
||||
TIME 24 time from I/O initiation to interrupt
|
||||
PWRTIME 24 time from I/O request to power up
|
||||
STOP_IOE 1 stop on I/O error
|
||||
|
||||
Error handling is as follows:
|
||||
|
||||
error STOP_IOE processed as
|
||||
|
||||
not attached 1 report error and stop
|
||||
0 out of tape
|
||||
|
||||
OS I/O error x report error and stop
|
||||
|
||||
2.2.3 316/516-33 Console Teletype (TTY)
|
||||
|
||||
The terminal reads from the console keyboard and writes to the
|
||||
simulator console window. The terminal has one option, UC; when
|
||||
set, the terminal automatically converts lower case input to upper
|
||||
case. This is on by default.
|
||||
|
||||
The terminal these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
BUF 8 last data item processed
|
||||
MODE 1 read/write mode
|
||||
INTREQ 1 device interrupt request
|
||||
READY 1 device ready
|
||||
ENABLE 1 device interrupts enabled
|
||||
KPOS 31 number of characters input
|
||||
KTIME 24 keyboard polling interval
|
||||
TPOS 31 number of characters output
|
||||
TTIME 24 time from I/O initiation to interrupt
|
||||
|
||||
2.2.4 316/516-12 Real Time Clock (CLK)
|
||||
|
||||
The real time clock (CLK) implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
INTREQ 1 device interrupt request
|
||||
READY 1 device ready
|
||||
ENABLE 1 device interrupts enabled
|
||||
TIME 24 clock interval
|
||||
|
||||
2.2.5 316/5116 Line Printer (LPT)
|
||||
|
||||
The line printer (LPT) writes data to a disk file. The POS register
|
||||
specifies the number of the next data item to be written. Thus,
|
||||
by changing POS, the user can backspace or advance the printer.
|
||||
|
||||
The line printer implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
WDPOS 6 word position in current scan
|
||||
DRPOS 6 drum position
|
||||
CRPOS 1 carriage position
|
||||
XFER 1 transfer ready flag
|
||||
PRDN 1 print done flag
|
||||
INTREQ 1 device interrupt request
|
||||
ENABLE 1 device interrupt enable
|
||||
SVCST 2 service state
|
||||
SVCCH 2 service channel
|
||||
BUF 8 buffer
|
||||
POS 31 number of characters output
|
||||
XTIME 24 delay between transfers
|
||||
ETIME 24 delay at end of scan
|
||||
PTIME 24 delay for shuttle/line advance
|
||||
STOP_IOE 1 stop on I/O error
|
||||
|
||||
Error handling is as follows:
|
||||
|
||||
error STOP_IOE processed as
|
||||
|
||||
not attached 1 report error and stop
|
||||
0 out of paper
|
||||
|
||||
OS I/O error x report error and stop
|
||||
|
||||
2.3 Symbolic Display and Input
|
||||
|
||||
The H316/H516 simulator implements symbolic display and input. Display is
|
||||
controlled by command line switches:
|
||||
|
||||
-a display as ASCII character
|
||||
-c display as two character string
|
||||
-m display instruction mnemonics
|
||||
|
||||
Input parsing is controlled by the first character typed in or by command
|
||||
line switches:
|
||||
|
||||
' or -a ASCII character
|
||||
" or -c two character sixbit string
|
||||
alphabetic instruction mnemonic
|
||||
numeric octal number
|
||||
|
||||
Instruction input uses standard H316/H516 assembler syntax. There are six
|
||||
instruction classes: memory reference, I/O, control, shift, skip, and
|
||||
operate.
|
||||
|
||||
Memory reference instructions have the format
|
||||
|
||||
memref{*} {C/Z} address{,1}
|
||||
|
||||
where * signifies indirect, C a current sector reference, Z a sector zero
|
||||
reference, and 1 indexed. The address is an octal number in the range 0 -
|
||||
077777; if C or Z is specified, the address is a page offset in the range
|
||||
0 - 0777. Normally, C is not needed; the simulator figures out from the
|
||||
address what mode to use. However, when referencing memory outside the CPU
|
||||
(eg, disks), there is no valid PC, and C must be used to specify current
|
||||
sector addressing.
|
||||
|
||||
I/O instructions have the format
|
||||
|
||||
io pulse+device
|
||||
|
||||
The pulse+device is an octal number in the range 0 - 01777.
|
||||
|
||||
Control and operate instructions consist of a single opcode
|
||||
|
||||
opcode
|
||||
|
||||
Shift instructions have the format
|
||||
|
||||
shift n
|
||||
|
||||
where n is an octal number in the range 0-77.
|
||||
|
||||
Skip instructions have the format
|
||||
|
||||
sub-op sub-op sub-op...
|
||||
|
||||
The simulator checks that the combination of sub-opcodes is legal.
|
|
@ -28,6 +28,8 @@
|
|||
tty 316/516-33 teleprinter
|
||||
clk/options 316/516-12 real time clocks/internal options
|
||||
|
||||
03-Nov-01 RMS Implemented upper case for console output
|
||||
29-Nov-01 RMS Added read only unit support
|
||||
07-Sep-01 RMS Moved function prototypes
|
||||
*/
|
||||
|
||||
|
@ -66,7 +68,8 @@ t_stat clk_reset (DEVICE *dptr);
|
|||
*/
|
||||
|
||||
UNIT ptr_unit = {
|
||||
UDATA (&ptr_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_IN_WAIT };
|
||||
UDATA (&ptr_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0),
|
||||
SERIAL_IN_WAIT };
|
||||
|
||||
REG ptr_reg[] = {
|
||||
{ ORDATA (BUF, ptr_unit.buf, 8) },
|
||||
|
@ -125,7 +128,7 @@ DEVICE ptp_dev = {
|
|||
|
||||
UNIT tty_unit[] = {
|
||||
{ UDATA (&tti_svc, UNIT_UC, 0), KBD_POLL_WAIT },
|
||||
{ UDATA (&tto_svc, UNIT_UC, 0), SERIAL_OUT_WAIT } };
|
||||
{ UDATA (&tto_svc, 0, 0), SERIAL_OUT_WAIT } };
|
||||
|
||||
REG tty_reg[] = {
|
||||
{ ORDATA (BUF, tty_buf, 8) },
|
||||
|
@ -397,10 +400,13 @@ return SCPE_OK;
|
|||
|
||||
t_stat tto_svc (UNIT *uptr)
|
||||
{
|
||||
int32 temp;
|
||||
int32 ch, temp;
|
||||
|
||||
SET_READY (INT_TTY); /* set done flag */
|
||||
if ((temp = sim_putchar (tty_buf & 0177)) != SCPE_OK) return temp;
|
||||
ch = tty_buf & 0177; /* get char */
|
||||
if ((tty_unit[TTO].flags & UNIT_UC) && islower (ch)) /* force upper case? */
|
||||
ch = toupper (ch);
|
||||
if ((temp = sim_putchar (ch)) != SCPE_OK) return temp; /* output char */
|
||||
tty_unit[TTO].pos = tty_unit[TTO].pos + 1;
|
||||
return SCPE_OK;
|
||||
}
|
|
@ -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.
|
||||
|
||||
07-Dec-01 RMS Revised to use breakpoint package
|
||||
03-Dec-01 RMS Added extended SET/SHOW support
|
||||
10-Aug-01 RMS Removed register in declarations
|
||||
26-Nov-00 RMS Fixed bug in dual device number routine
|
||||
21-Nov-00 RMS Fixed bug in reset routine
|
||||
|
@ -238,8 +240,6 @@
|
|||
|
||||
#include "hp2100_defs.h"
|
||||
|
||||
#define ILL_ADR_FLAG 0100000
|
||||
#define save_ibkpt (cpu_unit.u3)
|
||||
#define UNIT_V_MSIZE (UNIT_V_UF) /* dummy mask */
|
||||
#define UNIT_MSIZE (1 << UNIT_V_MSIZE)
|
||||
#define UNIT_V_2100 (UNIT_V_UF + 1) /* 2100 vs 2116 */
|
||||
|
@ -269,10 +269,10 @@ int32 maddr = 0; /* mem prot err addr */
|
|||
int32 ind_max = 16; /* iadr nest limit */
|
||||
int32 stop_inst = 1; /* stop on ill inst */
|
||||
int32 stop_dev = 2; /* stop on ill dev */
|
||||
int32 ibkpt_addr = ILL_ADR_FLAG | AMASK; /* breakpoint addr */
|
||||
int32 old_PC = 0; /* previous PC */
|
||||
|
||||
extern int32 sim_int_char;
|
||||
extern int32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */
|
||||
|
||||
int32 shift (int32 inval, int32 flag, int32 oper);
|
||||
int32 calc_dma (void);
|
||||
int32 calc_int (void);
|
||||
|
@ -282,8 +282,7 @@ t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw);
|
|||
t_stat cpu_reset (DEVICE *dptr);
|
||||
t_stat dma0_reset (DEVICE *dptr);
|
||||
t_stat dma1_reset (DEVICE *dptr);
|
||||
t_stat cpu_svc (UNIT *uptr);
|
||||
t_stat cpu_set_size (UNIT *uptr, int32 value);
|
||||
t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
|
||||
/* CPU data structures
|
||||
|
||||
|
@ -293,7 +292,7 @@ t_stat cpu_set_size (UNIT *uptr, int32 value);
|
|||
cpu_mod CPU modifiers list
|
||||
*/
|
||||
|
||||
UNIT cpu_unit = { UDATA (&cpu_svc, UNIT_FIX + UNIT_BINK,
|
||||
UNIT cpu_unit = { UDATA (NULL, UNIT_FIX + UNIT_BINK,
|
||||
MAXMEMSIZE) };
|
||||
|
||||
REG cpu_reg[] = {
|
||||
|
@ -317,7 +316,6 @@ REG cpu_reg[] = {
|
|||
{ FLDATA (STOP_DEV, stop_dev, 1) },
|
||||
{ DRDATA (INDMAX, ind_max, 16), REG_NZ + PV_LEFT },
|
||||
{ ORDATA (OLDP, old_PC, 15), REG_RO },
|
||||
{ ORDATA (BREAK, ibkpt_addr, 16) },
|
||||
{ ORDATA (WRU, sim_int_char, 8) },
|
||||
{ FLDATA (T2100, cpu_unit.flags, UNIT_V_2100), REG_HRO },
|
||||
{ FLDATA (T21MX, cpu_unit.flags, UNIT_V_21MX), REG_HRO },
|
||||
|
@ -531,10 +529,8 @@ if (intrq && ((intrq <= PRO) || !ion_defer)) { /* interrupt request? */
|
|||
intrq = 0; /* clear request */
|
||||
clrCTL (PRO); } /* protection off */
|
||||
|
||||
else { if (PC == ibkpt_addr) { /* breakpoint? */
|
||||
save_ibkpt = ibkpt_addr; /* save address */
|
||||
ibkpt_addr = ibkpt_addr | ILL_ADR_FLAG; /* disable */
|
||||
sim_activate (&cpu_unit, 1); /* sched re-enable */
|
||||
else { if (sim_brk_summ &&
|
||||
sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */
|
||||
reason = STOP_IBKPT; /* stop simulation */
|
||||
break; }
|
||||
err_PC = PC; /* save PC for error */
|
||||
|
@ -1343,7 +1339,8 @@ clrFLG (PRO);
|
|||
clrFBF (PRO);
|
||||
mfence = 0;
|
||||
maddr = 0;
|
||||
return cpu_svc (&cpu_unit);
|
||||
sim_brk_types = sim_brk_dflt = SWMASK ('E');
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat dma0_reset (DEVICE *tptr)
|
||||
|
@ -1391,45 +1388,29 @@ else M[addr] = val & DMASK;
|
|||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Breakpoint service */
|
||||
|
||||
t_stat cpu_svc (UNIT *uptr)
|
||||
{
|
||||
if ((ibkpt_addr & ~ILL_ADR_FLAG) == save_ibkpt) ibkpt_addr = save_ibkpt;
|
||||
save_ibkpt = -1;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat cpu_set_size (UNIT *uptr, int32 value)
|
||||
t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
int32 mc = 0;
|
||||
t_addr i;
|
||||
|
||||
if ((value <= 0) || (value > MAXMEMSIZE) || ((value & 07777) != 0))
|
||||
if ((val <= 0) || (val > MAXMEMSIZE) || ((val & 07777) != 0))
|
||||
return SCPE_ARG;
|
||||
for (i = value; i < MEMSIZE; i++) mc = mc | M[i];
|
||||
for (i = val; i < MEMSIZE; i++) mc = mc | M[i];
|
||||
if ((mc != 0) && (!get_yn ("Really truncate memory [N]?", FALSE)))
|
||||
return SCPE_OK;
|
||||
MEMSIZE = value;
|
||||
MEMSIZE = val;
|
||||
for (i = MEMSIZE; i < MAXMEMSIZE; i++) M[i] = 0;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Set device number */
|
||||
/* Set/show device number */
|
||||
|
||||
extern char *read_line (char *ptr, int size, FILE *stream);
|
||||
extern t_value get_uint (char *cptr, int radix, t_value max, t_stat *status);
|
||||
|
||||
t_stat hp_setdev (UNIT *uptr, int32 ord)
|
||||
t_stat hp_setdev (UNIT *uptr, int32 ord, char *cptr, void *desc)
|
||||
{
|
||||
char cbuf[CBUFSIZE], *cptr;
|
||||
int32 i, olddev, newdev;
|
||||
int32 i, newdev;
|
||||
t_stat r;
|
||||
|
||||
olddev = infotab[ord].devno;
|
||||
printf ("Device number: %-o ", olddev);
|
||||
cptr = read_line (cbuf, CBUFSIZE, stdin);
|
||||
if ((cptr == NULL) || (*cptr == 0)) return SCPE_OK;
|
||||
if (cptr == NULL) return SCPE_ARG;
|
||||
newdev = get_uint (cptr, 8, DEVMASK, &r);
|
||||
if (r != SCPE_OK) return r;
|
||||
if (newdev < VARDEV) return SCPE_ARG;
|
||||
|
@ -1440,23 +1421,35 @@ infotab[ord].devno = newdev;
|
|||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Set device number for data/control pair */
|
||||
|
||||
t_stat hp_setdev2 (UNIT *uptr, int32 ord)
|
||||
t_stat hp_showdev (FILE *st, UNIT *uptr, int32 ord, void *desc)
|
||||
{
|
||||
int32 i, olddev;
|
||||
fprintf (st, "devno=%o", infotab[ord].devno);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Set/show device number for data/control pair */
|
||||
|
||||
t_stat hp_setdev2 (UNIT *uptr, int32 ord, char *cptr, void *desc)
|
||||
{
|
||||
int32 i, olddev, newdev;
|
||||
t_stat r;
|
||||
|
||||
olddev = infotab[ord].devno;
|
||||
if ((r = hp_setdev (uptr, ord)) != SCPE_OK) return r;
|
||||
if (infotab[ord].devno == DEVMASK) {
|
||||
if ((r = hp_setdev (uptr, ord, cptr, NULL)) != SCPE_OK) return r;
|
||||
newdev = infotab[ord].devno + 1;
|
||||
if (newdev > DEVMASK) {
|
||||
infotab[ord].devno = olddev;
|
||||
return SCPE_ARG; }
|
||||
for (i = 0; infotab[i].devno != 0; i++) {
|
||||
if ((i != (ord + 1)) &&
|
||||
((infotab[ord].devno + 1) == infotab[i].devno)) {
|
||||
if ((i != (ord + 1)) && (newdev == infotab[i].devno)) {
|
||||
infotab[ord].devno = olddev;
|
||||
return SCPE_ARG; } }
|
||||
infotab[ord + 1].devno = infotab[ord].devno + 1;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat hp_showdev2 (FILE *st, UNIT *uptr, int32 ord, void *desc)
|
||||
{
|
||||
fprintf (st, "devno=%o/%o", infotab[ord].devno, infotab[ord + 1].devno);
|
||||
return SCPE_OK;
|
||||
}
|
|
@ -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.
|
||||
|
||||
30-Nov-01 RMS Added extended SET/SHOW support
|
||||
15-Oct-00 RMS Added dynamic device numbers
|
||||
14-Apr-99 RMS Changed t_addr to unsigned
|
||||
|
||||
|
@ -178,5 +179,7 @@ struct hpdev {
|
|||
|
||||
/* Function prototypes */
|
||||
|
||||
t_bool hp_setdev (UNIT *uptr, int32 val);
|
||||
t_bool hp_setdev2 (UNIT *uptr, int32 val);
|
||||
t_stat hp_setdev (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
t_stat hp_showdev (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||
t_stat hp_setdev2 (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
t_stat hp_showdev2 (FILE *st, UNIT *uptr, int32 val, void *desc);
|
471
HP2100/hp2100_doc.txt
Normal file
471
HP2100/hp2100_doc.txt
Normal file
|
@ -0,0 +1,471 @@
|
|||
To: Users
|
||||
From: Bob Supnik
|
||||
Subj: HP2100 Simulator Usage
|
||||
Date: 1-Dec-01
|
||||
|
||||
COPYRIGHT NOTICE
|
||||
|
||||
The following copyright notice applies to both the SIMH source and binary:
|
||||
|
||||
Original code published in 1993-2001, written by Robert M Supnik
|
||||
Copyright (c) 1993-2001, Robert M Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation
|
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
and/or sell copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
Except as contained in this notice, the name of Robert M Supnik shall not
|
||||
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
This memorandum documents the HP 2100 simulator.
|
||||
|
||||
|
||||
1. Simulator Files
|
||||
|
||||
sim/ sim_defs.h
|
||||
scp.c
|
||||
scp_tty.c
|
||||
sim_rev.c
|
||||
|
||||
sim/hp2100/ hp2100_defs.h
|
||||
hp2100_cpu.c
|
||||
hp2100_dp.c
|
||||
hp2100_lp.c
|
||||
hp2100_mt.c
|
||||
hp2100_stddev.c
|
||||
hp2100_sys.c
|
||||
|
||||
2. HP2100 Features
|
||||
|
||||
The HP2100 simulator is configured as follows:
|
||||
|
||||
device simulates
|
||||
name(s)
|
||||
|
||||
CPU 2116, 2100, or 21MX CPU with 32KW memory
|
||||
DMA0, DMA1 dual channel DMA controller
|
||||
PTR,PTP 12597A paper tape reader/punch
|
||||
TTY 12631C buffered teleprinter
|
||||
LPT 12653A line printer
|
||||
CLK 12539A/B/C time base generator
|
||||
DP 12557A cartridge disk controller with four drives
|
||||
MT 12559C magnetic tape controller with one drives
|
||||
|
||||
The HP2100 simulator implements several unique stop conditions:
|
||||
|
||||
- decode of an undefined instruction, and STOP_INST is et
|
||||
- reference to an undefined I/O device, and STOP_DEV is set
|
||||
- more than INDMAX indirect references are detected during
|
||||
memory reference address decoding
|
||||
|
||||
The HP2100 loader supports standard absolute binary format. The DUMP
|
||||
command is not implemented.
|
||||
|
||||
2.1 CPU
|
||||
|
||||
CPU options include choice of instruction set and memory size.
|
||||
|
||||
SET CPU 2116 2116 instructions
|
||||
SET CPU 2100 2100 instructions
|
||||
SET CPU 21MX 21MX instructions
|
||||
SET CPU 4K set memory size = 4K
|
||||
SET CPU 8K set memory size = 8K
|
||||
SET CPU 16K set memory size = 16K
|
||||
SET CPU 24K set memory size = 24K
|
||||
SET CPU 32K set memory size = 32K
|
||||
|
||||
If memory size is being reduced, and the memory being truncated contains
|
||||
non-zero data, the simulator asks for confirmation. Data in the truncated
|
||||
portion of memory is lost. Initial memory size is 32K.
|
||||
|
||||
CPU registers include the visible state of the processor as well as the
|
||||
control registers for the interrupt system.
|
||||
|
||||
name size comments
|
||||
|
||||
P 15 program counter
|
||||
A 16 A register
|
||||
B 16 B register
|
||||
X 16 X index register (21MX)
|
||||
Y 16 Y index register (21MX)
|
||||
S 16 switch/display register
|
||||
E 1 extend flag
|
||||
O 1 overflow flag
|
||||
ION 1 interrupt enable flag
|
||||
ION_DEFER 1 interrupt defer flag
|
||||
IADDR 6 most recent interrupting device
|
||||
MPCTL 1 memory protection enable (2100, 21MX)
|
||||
MPFLG 1 memory protection flag (2100, 21MX)
|
||||
MPFBF 1 memory protection flag buffer (2100, 21MX)
|
||||
MFENCE 15 memory protection fence (2100, 21MX)
|
||||
MADDR 16 memory protection error address (2100, 21MX)
|
||||
STOP_INST 1 stop on undefined instruction
|
||||
STOP_DEV 1 stop on undefined device
|
||||
INDMAX 1 indirect address limit
|
||||
OLDP 15 PC prior to last JMP, JSB, or interrupt
|
||||
WRU 8 interrupt character
|
||||
|
||||
2.2 DMA Controllers
|
||||
|
||||
The HP2100 includes two DMA channel controllers (DMA0 and DMA1). Each
|
||||
DMA channel has the following visible state:
|
||||
|
||||
name size comments
|
||||
|
||||
CMD 1 channel enabled
|
||||
CTL 1 interrupt enabled
|
||||
FLG 1 channel ready
|
||||
FBF 1 channel ready buffer
|
||||
CW1 1 command word 1
|
||||
CW2 1 command word 2
|
||||
CW3 1 command word 3
|
||||
|
||||
2.3 Variable Device Assignments
|
||||
|
||||
On the HP2100, I/O device take their device numbers from the backplane
|
||||
slot they are plugged into. Thus, device number assignments vary
|
||||
considerably from system to system, and software package to software
|
||||
package. The HP2100 simulator supports dynamic device number assignment.
|
||||
The current device device is shown with the command SHOW <dev> DEVNO:
|
||||
|
||||
sim> SHOW PTR DEV
|
||||
device=10
|
||||
|
||||
The user can change the device number with the SET <dev> DEVNO=<num>
|
||||
command:
|
||||
|
||||
sim> SET PTR DEV=30
|
||||
sim> SHOW PTR DEV
|
||||
device=30
|
||||
|
||||
The new device number must be in the range 010..077 (octal) and must
|
||||
not be currently assigned to another device. For devices with two
|
||||
device numbers, only the lower numbered device number can be changed;
|
||||
the higher is automatically set to the lower + 1.
|
||||
|
||||
2.4 Programmed I/O Devices
|
||||
|
||||
2.4.1 12597A-002 Paper Tape Reader (PTR)
|
||||
|
||||
The paper tape reader (PTR) reads data from a disk file. The POS
|
||||
register specifies the number of the next data item to be read.
|
||||
Thus, by changing POS, the user can backspace or advance the reader.
|
||||
|
||||
The paper tape reader supports the BOOT command. BOOT PTR copies the
|
||||
absolute binary loader into memory and starts it running.
|
||||
|
||||
The paper tape reader implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
BUF 8 last data item processed
|
||||
CMD 1 reader enable
|
||||
CTL 1 device/interrupt enable
|
||||
FLG 1 device ready
|
||||
FBF 1 device ready buffer
|
||||
POS 31 position in the input file
|
||||
TIME 24 time from I/O initiation to interrupt
|
||||
STOP_IOE 1 stop on I/O error
|
||||
DEVNO 6 current device number (read only)
|
||||
|
||||
Error handling is as follows:
|
||||
|
||||
error STOP_IOE processed as
|
||||
|
||||
not attached 1 report error and stop
|
||||
0 out of tape
|
||||
|
||||
end of file 1 report error and stop
|
||||
0 out of tape or paper
|
||||
|
||||
OS I/O error x report error and stop
|
||||
|
||||
2.4.2 12597A-005 Paper Tape Punch (PTP)
|
||||
|
||||
The paper tape punch (PTP) writes data to a disk file. The POS
|
||||
register specifies the number of the next data item to be written.
|
||||
Thus, by changing POS, the user can backspace or advance the punch.
|
||||
|
||||
The paper tape punch implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
BUF 8 last data item processed
|
||||
CMD 1 punch enable
|
||||
CTL 1 device/interrupt enable
|
||||
FLG 1 device ready
|
||||
FBF 1 device ready buffer
|
||||
POS 31 position in the output file
|
||||
TIME 24 time from I/O initiation to interrupt
|
||||
STOP_IOE 1 stop on I/O error
|
||||
DEVNO 6 current device number (read only)
|
||||
|
||||
Error handling is as follows:
|
||||
|
||||
error STOP_IOE processed as
|
||||
|
||||
not attached 1 report error and stop
|
||||
0 out of tape
|
||||
|
||||
OS I/O error x report error and stop
|
||||
|
||||
2.4.3 12631C Buffered Teleprinter (TTY)
|
||||
|
||||
The console teleprinter has three units: keyboard (unit 0), printer
|
||||
(unit 1), and punch (unit 2). The keyboard reads from the console
|
||||
keyboard; the printer writes to the simulator console window. The
|
||||
punch writes to a disk file. The keyboard has one option, UC; when
|
||||
set, it automatically converts lower case input to upper case. This
|
||||
is on by default.
|
||||
|
||||
The terminal implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
BUF 8 last data item processed
|
||||
MODE 16 mode
|
||||
CTL 1 device/interrupt enable
|
||||
FLG 1 device ready
|
||||
FBF 1 device ready buffer
|
||||
KPOS 31 number of characters input
|
||||
KTIME 24 keyboard polling interval
|
||||
TPOS 31 number of characters printed
|
||||
TTIME 24 time from I/O initiation to interrupt
|
||||
PPOS 31 position in the punch output file
|
||||
STOP_IOE 1 punch stop on I/O error
|
||||
DEVNO 6 current device number (read only)
|
||||
|
||||
Error handling for the punch is as follows:
|
||||
|
||||
error STOP_IOE processed as
|
||||
|
||||
not attached 1 report error and stop
|
||||
0 out of tape
|
||||
|
||||
OS I/O error x report error and stop
|
||||
|
||||
2.4.4 12653A Line Printer (LPT)
|
||||
|
||||
The line printer (LPT) writes data to a disk file. The POS register
|
||||
specifies the number of the next data item to be written. Thus,
|
||||
by changing POS, the user can backspace or advance the printer.
|
||||
|
||||
The line printer implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
BUF 8 last data item processed
|
||||
CMD 1 printer enable
|
||||
CTL 1 device/interrupt enable
|
||||
FLG 1 device ready
|
||||
FBF 1 device ready buffer
|
||||
POS 31 position in the output file
|
||||
CTIME 24 time between characters
|
||||
PTIME 24 time for a print operation
|
||||
STOP_IOE 1 stop on I/O error
|
||||
DEVNO 6 current device number (read only)
|
||||
|
||||
Error handling is as follows:
|
||||
|
||||
error STOP_IOE processed as
|
||||
|
||||
not attached 1 report error and stop
|
||||
0 out of tape or paper
|
||||
|
||||
OS I/O error x report error and stop
|
||||
|
||||
2.4.5 12539A/B/C Time Base Generator (CLK)
|
||||
|
||||
The time base generator (CLK) implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
SEL 3 time base select
|
||||
CTL 1 device/interrupt enable
|
||||
FLG 1 device ready
|
||||
FBF 1 device ready buffer
|
||||
ERR 1 error flag
|
||||
TIME[0:7] 31 clock intervals, select = 0..7
|
||||
DEVNO 6 current device number (read only)
|
||||
|
||||
2.5 12557A Cartridge Disk (DP)
|
||||
|
||||
The 12557A cartridge disk has two separate devices, a data channel and
|
||||
a device controller. The data channel includes a 128-word (one sector)
|
||||
buffer for reads and writes. The device controller includes the four
|
||||
disk drives. Disk drives can be REMOVEd or ADDed to the configuration.
|
||||
|
||||
The data channel implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
IBUF 16 input buffer
|
||||
OBUF 16 output buffer
|
||||
BPTR 7 sector buffer pointer
|
||||
CMD 1 channel enable
|
||||
CTL 1 interrupt enable
|
||||
FLG 1 channel ready
|
||||
FBF 1 channel ready buffer
|
||||
DEVNO 6 current device number (read only)
|
||||
|
||||
The device controller implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
OBUF 16 output buffer
|
||||
BUSY 3 busy (unit #, + 1, of active unit)
|
||||
RARC 8 record address register cylinder
|
||||
RARH 2 record address register head
|
||||
RARS 4 record address register sector
|
||||
CNT 5 check record count
|
||||
CMD 1 controller enable
|
||||
CTL 1 interrupt enable
|
||||
FLG 1 controller ready
|
||||
FBF 1 controller ready buffer
|
||||
EOC 1 end of cylinder pending
|
||||
CTIME 24 command delay time
|
||||
STIME 24 seek delay time, per cylinder
|
||||
XTIME 24 interword transfer time
|
||||
STA[0:3] 16 drive status, drives 0-3
|
||||
DEVNO 6 current device number (read only)
|
||||
|
||||
Error handling is as follows:
|
||||
|
||||
error processed as
|
||||
|
||||
not attached disk not ready
|
||||
|
||||
end of file assume rest of disk is zero
|
||||
|
||||
OS I/O error report error and stop
|
||||
|
||||
2.6 12559C Magnetic Tape (MT)
|
||||
|
||||
Magnetic tape options include the ability to make the unit write enabled
|
||||
or write locked.
|
||||
|
||||
SET MT LOCKED set unit write locked
|
||||
SET MT ENABLED set unit write enabled
|
||||
|
||||
The 12559C mag tape drive has two separate devices, a data channel and
|
||||
a device controller. The data channel includes a maximum record sized
|
||||
buffer for reads and writes. The device controller includes the tape
|
||||
unit
|
||||
|
||||
The data channel implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
FLG 1 channel ready
|
||||
BPTR 16 buffer pointer (reads and writes)
|
||||
BMAX 16 buffer size (writes)
|
||||
DEVNO 6 current device number (read only)
|
||||
|
||||
The device controller implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
FNC 8 current function
|
||||
STA 9 tape status
|
||||
BUF 8 buffer
|
||||
BUSY 3 busy (unit #, + 1, of active unit)
|
||||
CTL 1 interrupt enabled
|
||||
FLG 1 controller ready
|
||||
FBF 1 controller ready buffer
|
||||
DTF 1 data transfer flop
|
||||
FSVC 1 first service flop
|
||||
POS 31 magtape position
|
||||
CTIME 24 command delay time
|
||||
XTIME 24 interword transfer delay time
|
||||
STOP_IOE 1 stop on I/O error
|
||||
DEVNO 6 current device number (read only)
|
||||
|
||||
Error handling is as follows:
|
||||
|
||||
error processed as
|
||||
|
||||
not attached tape not ready
|
||||
|
||||
end of file (read or space) end of physical tape
|
||||
(write) ignored
|
||||
|
||||
OS I/O error report error and stop
|
||||
|
||||
2.7 Symbolic Display and Input
|
||||
|
||||
The HP2100 simulator implements symbolic display and input. Display is
|
||||
controlled by command line switches:
|
||||
|
||||
-a display as ASCII character
|
||||
-c display as two character string
|
||||
-m display instruction mnemonics
|
||||
|
||||
Input parsing is controlled by the first character typed in or by command
|
||||
line switches:
|
||||
|
||||
' or -a ASCII character
|
||||
" or -c two character sixbit string
|
||||
alphabetic instruction mnemonic
|
||||
numeric octal number
|
||||
|
||||
Instruction input uses standard HP2100 assembler syntax. There are seven
|
||||
instruction classes: memory reference, I/O, shift, alter skip, extended
|
||||
shift, extended memory reference, extended two address reference.
|
||||
|
||||
Memory reference instructions have the format
|
||||
|
||||
memref {C/Z} address{,I}
|
||||
|
||||
where I signifies indirect, C a current page reference, and Z a zero page
|
||||
reference. The address is an octal number in the range 0 - 077777; if C or
|
||||
Z is specified, the address is a page offset in the range 0 - 01777. Normally,
|
||||
C is not needed; the simulator figures out from the address what mode to use.
|
||||
However, when referencing memory outside the CPU (eg, disks), there is no
|
||||
valid PC, and C must be used to specify current page addressing.
|
||||
|
||||
IOT instructions have the format
|
||||
|
||||
io device{,C}
|
||||
|
||||
where C signifies that the device flag is to be cleared. The device is an
|
||||
octal number in the range 0 - 77.
|
||||
|
||||
Shift and alter/skip instructions have the format
|
||||
|
||||
sub-op sub-op sub-op...
|
||||
|
||||
The simulator checks that the combination of sub-opcodes is legal.
|
||||
|
||||
Extended shift instructions have the format
|
||||
|
||||
extshift count
|
||||
|
||||
where count is an octal number in the range 1 - 020.
|
||||
|
||||
Extended memory reference instructions have the format
|
||||
|
||||
extmemref address{,I}
|
||||
|
||||
where I signifies indirect addressing. The address is an octal number in
|
||||
the range 0 - 077777.
|
||||
|
||||
Extended two address instructions have the format
|
||||
|
||||
ext2addr addr1{,I},addr2{,I}
|
||||
|
||||
where I signifies indirect addressing. Both address 1 and address 2 are
|
||||
octal numbers in the range 0 - 077777.
|
|
@ -25,6 +25,8 @@
|
|||
|
||||
dp 12557A cartridge disk system
|
||||
|
||||
03-Dec-01 RMS Changed DEVNO to use extended SET/SHOW
|
||||
24-Nov-01 RMS Changed STA to be an array
|
||||
07-Sep-01 RMS Moved function prototypes
|
||||
29-Nov-00 RMS Made variable names unique
|
||||
21-Nov-00 RMS Fixed flag, buffer power up state
|
||||
|
@ -182,10 +184,7 @@ REG dpc_reg[] = {
|
|||
{ DRDATA (CTIME, dpc_ctime, 24), PV_LEFT },
|
||||
{ DRDATA (STIME, dpc_stime, 24), PV_LEFT },
|
||||
{ DRDATA (XTIME, dpc_xtime, 24), REG_NZ + PV_LEFT },
|
||||
{ ORDATA (STA0, dpc_sta[0], 16) },
|
||||
{ ORDATA (STA1, dpc_sta[1], 16) },
|
||||
{ ORDATA (STA2, dpc_sta[2], 16) },
|
||||
{ ORDATA (STA3, dpc_sta[3], 16) },
|
||||
{ BRDATA (STA, dpc_sta, 8, 16, DP_NUMDRV) },
|
||||
{ GRDATA (UFLG0, dpc_unit[0].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ GRDATA (UFLG1, dpc_unit[1].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
|
@ -200,7 +199,8 @@ REG dpc_reg[] = {
|
|||
MTAB dpc_mod[] = {
|
||||
/* { UNIT_WLK, 0, "write enabled", "ENABLED", &dpc_vlock }, */
|
||||
/* { UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", &dpc_vlock }, */
|
||||
{ UNIT_DEVNO, inDPD, NULL, "DEVNO", &hp_setdev2 },
|
||||
{ MTAB_XTD | MTAB_VDV, inDPD, "DEVNO", "DEVNO",
|
||||
&hp_setdev2, &hp_showdev2, NULL },
|
||||
{ 0 } };
|
||||
|
||||
DEVICE dpc_dev = {
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
lpt 12653A line printer
|
||||
|
||||
03-Dec-01 RMS Changed DEVNO to use extended SET/SHOW
|
||||
07-Sep-01 RMS Moved function prototypes
|
||||
21-Nov-00 RMS Fixed flag, fbf power up state
|
||||
Added command flop
|
||||
|
@ -68,7 +69,8 @@ REG lpt_reg[] = {
|
|||
{ NULL } };
|
||||
|
||||
MTAB lpt_mod[] = {
|
||||
{ UNIT_DEVNO, inLPT, NULL, "DEVNO", &hp_setdev },
|
||||
{ MTAB_XTD | MTAB_VDV, inLPT, "DEVNO", "DEVNO",
|
||||
&hp_setdev, &hp_showdev, NULL },
|
||||
{ 0 } };
|
||||
|
||||
DEVICE lpt_dev = {
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
mt 12559A nine track magnetic tape
|
||||
|
||||
03-Dec-01 RMS Added read only unit, extended SET/SHOW support
|
||||
07-Sep-01 RMS Moved function prototypes
|
||||
30-Nov-00 RMS Made variable names unique
|
||||
04-Oct-98 RMS V2.4 magtape format
|
||||
|
@ -54,6 +55,7 @@
|
|||
#define DB_V_SIZE 16 /* max data buf */
|
||||
#define DBSIZE (1 << DB_V_SIZE) /* max data cmd */
|
||||
#define DBMASK (DBSIZE - 1)
|
||||
#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */
|
||||
|
||||
/* Command - mtc_fnc */
|
||||
|
||||
|
@ -97,7 +99,7 @@ static const int32 mtc_cmd[] = {
|
|||
|
||||
t_stat mtc_svc (UNIT *uptr);
|
||||
t_stat mtc_reset (DEVICE *dptr);
|
||||
t_stat mtc_vlock (UNIT *uptr, int32 val);
|
||||
t_stat mtc_vlock (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
t_stat mtc_attach (UNIT *uptr, char *cptr);
|
||||
t_stat mtc_detach (UNIT *uptr);
|
||||
t_stat mtd_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw);
|
||||
|
@ -136,7 +138,7 @@ DEVICE mtd_dev = {
|
|||
mtc_mod MTC modifier list
|
||||
*/
|
||||
|
||||
UNIT mtc_unit = { UDATA (&mtc_svc, UNIT_ATTABLE, 0) };
|
||||
UNIT mtc_unit = { UDATA (&mtc_svc, UNIT_ATTABLE + UNIT_ROABLE, 0) };
|
||||
|
||||
REG mtc_reg[] = {
|
||||
{ ORDATA (FNC, mtc_fnc, 8) },
|
||||
|
@ -159,7 +161,8 @@ REG mtc_reg[] = {
|
|||
MTAB mtc_mod[] = {
|
||||
{ UNIT_WLK, 0, "write enabled", "ENABLED", &mtc_vlock },
|
||||
{ UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", &mtc_vlock },
|
||||
{ UNIT_DEVNO, inMTD, NULL, "DEVNO", &hp_setdev2 },
|
||||
{ MTAB_XTD | MTAB_VDV, inMTD, "DEVNO", "DEVNO",
|
||||
&hp_setdev2, &hp_showdev2, NULL },
|
||||
{ 0 } };
|
||||
|
||||
DEVICE mtc_dev = {
|
||||
|
@ -236,7 +239,7 @@ case ioOTX: /* output */
|
|||
((mtc_unit.flags & UNIT_ATT) == 0) ||
|
||||
((mtc_sta & STA_BOT) &&
|
||||
((dat == FNC_BSR) || (dat == FNC_REW) || (dat == FNC_RWS))) ||
|
||||
((mtc_unit.flags & UNIT_WLK) &&
|
||||
((mtc_unit.flags & UNIT_WPRT) &&
|
||||
((dat == FNC_WC) || (dat == FNC_GAP) || (dat == FNC_WFM))))
|
||||
mtc_sta = mtc_sta | STA_REJ;
|
||||
else { sim_activate (&mtc_unit, mtc_ctime); /* start tape */
|
||||
|
@ -254,7 +257,7 @@ case ioMIX: /* merge */
|
|||
if (mtc_unit.flags & UNIT_ATT) { /* construct status */
|
||||
mtc_sta = mtc_sta & ~(STA_LOCAL | STA_WLK | STA_BUSY);
|
||||
if (sim_is_active (&mtc_unit)) mtc_sta = mtc_sta | STA_BUSY;
|
||||
if (mtc_unit.flags & UNIT_WLK) mtc_sta = mtc_sta | STA_WLK; }
|
||||
if (mtc_unit.flags & UNIT_WPRT) mtc_sta = mtc_sta | STA_WLK; }
|
||||
else mtc_sta = STA_BUSY | STA_LOCAL;
|
||||
dat = dat | mtc_sta;
|
||||
break;
|
||||
|
@ -419,7 +422,7 @@ infotab[inMTC].flg = infotab[inMTD].flg = 0; /* clear flg */
|
|||
infotab[inMTC].fbf = infotab[inMTD].fbf = 0; /* clear fbf */
|
||||
sim_cancel (&mtc_unit); /* cancel activity */
|
||||
if (mtc_unit.flags & UNIT_ATT) mtc_sta = ((mtc_unit.pos)? 0: STA_BOT) |
|
||||
((mtc_unit.flags & UNIT_WLK)? STA_WLK: 0);
|
||||
((mtc_unit.flags & UNIT_WPRT)? STA_WLK: 0);
|
||||
else mtc_sta = STA_LOCAL | STA_BUSY;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
@ -432,7 +435,7 @@ t_stat r;
|
|||
|
||||
r = attach_unit (uptr, cptr); /* attach unit */
|
||||
if (r != SCPE_OK) return r; /* update status */
|
||||
mtc_sta = STA_BOT | ((uptr -> flags & UNIT_WLK)? STA_WLK: 0);
|
||||
mtc_sta = STA_BOT | ((uptr -> flags & UNIT_WPRT)? STA_WLK: 0);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -446,9 +449,9 @@ return detach_unit (uptr); /* detach unit */
|
|||
|
||||
/* Write lock/enable routine */
|
||||
|
||||
t_stat mtc_vlock (UNIT *uptr, int32 val)
|
||||
t_stat mtc_vlock (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
if (uptr -> flags & UNIT_ATT) return SCPE_ARG;
|
||||
if (val && (uptr -> flags & UNIT_ATT)) return SCPE_ARG;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
|
@ -28,6 +28,9 @@
|
|||
tty 12531C buffered teleprinter interface
|
||||
clk 12539A/B/C time base generator
|
||||
|
||||
03-Nov-01 RMS Changed DEVNO to use extended SET/SHOW
|
||||
29-Nov-01 RMS Added read only unit support
|
||||
24-Nov-01 RMS Changed TIME to an array
|
||||
07-Sep-01 RMS Moved function prototypes
|
||||
21-Nov-00 RMS Fixed flag, buffer power up state
|
||||
Added status input for ptp, tty
|
||||
|
@ -82,7 +85,8 @@ t_stat clk_reset (DEVICE *dptr);
|
|||
*/
|
||||
|
||||
UNIT ptr_unit = {
|
||||
UDATA (&ptr_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_IN_WAIT };
|
||||
UDATA (&ptr_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0),
|
||||
SERIAL_IN_WAIT };
|
||||
|
||||
REG ptr_reg[] = {
|
||||
{ ORDATA (BUF, ptr_unit.buf, 8) },
|
||||
|
@ -97,7 +101,8 @@ REG ptr_reg[] = {
|
|||
{ NULL } };
|
||||
|
||||
MTAB ptr_mod[] = {
|
||||
{ UNIT_DEVNO, inPTR, NULL, "DEVNO", &hp_setdev },
|
||||
{ MTAB_XTD | MTAB_VDV, inPTR, "DEVNO", "DEVNO",
|
||||
&hp_setdev, &hp_showdev, NULL },
|
||||
{ 0 } };
|
||||
|
||||
DEVICE ptr_dev = {
|
||||
|
@ -130,7 +135,8 @@ REG ptp_reg[] = {
|
|||
{ NULL } };
|
||||
|
||||
MTAB ptp_mod[] = {
|
||||
{ UNIT_DEVNO, inPTP, NULL, "DEVNO", &hp_setdev },
|
||||
{ MTAB_XTD | MTAB_VDV, inPTP, "DEVNO", "DEVNO",
|
||||
&hp_setdev, &hp_showdev, NULL },
|
||||
{ 0 } };
|
||||
|
||||
DEVICE ptp_dev = {
|
||||
|
@ -153,7 +159,7 @@ DEVICE ptp_dev = {
|
|||
|
||||
UNIT tty_unit[] = {
|
||||
{ UDATA (&tti_svc, UNIT_UC, 0), KBD_POLL_WAIT },
|
||||
{ UDATA (&tto_svc, UNIT_UC, 0), SERIAL_OUT_WAIT },
|
||||
{ UDATA (&tto_svc, 0, 0), SERIAL_OUT_WAIT },
|
||||
{ UDATA (&tto_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT } };
|
||||
|
||||
REG tty_reg[] = {
|
||||
|
@ -176,7 +182,8 @@ REG tty_reg[] = {
|
|||
MTAB tty_mod[] = {
|
||||
{ UNIT_UC, 0, "lower case", "LC", NULL },
|
||||
{ UNIT_UC, UNIT_UC, "upper case", "UC", NULL },
|
||||
{ UNIT_DEVNO, inTTY, NULL, "DEVNO", &hp_setdev },
|
||||
{ MTAB_XTD | MTAB_VDV, inTTY, "DEVNO", "DEVNO",
|
||||
&hp_setdev, &hp_showdev, NULL },
|
||||
{ 0 } };
|
||||
|
||||
DEVICE tty_dev = {
|
||||
|
@ -203,19 +210,13 @@ REG clk_reg[] = {
|
|||
{ FLDATA (FLG, infotab[inCLK].flg, 0) },
|
||||
{ FLDATA (FBF, infotab[inCLK].fbf, 0) },
|
||||
{ FLDATA (ERR, clk_error, CLK_V_ERROR) },
|
||||
{ DRDATA (TIME0, clk_delay[0], 31), PV_LEFT },
|
||||
{ DRDATA (TIME1, clk_delay[1], 31), PV_LEFT },
|
||||
{ DRDATA (TIME2, clk_delay[2], 31), PV_LEFT },
|
||||
{ DRDATA (TIME3, clk_delay[3], 31), PV_LEFT },
|
||||
{ DRDATA (TIME4, clk_delay[4], 31), PV_LEFT },
|
||||
{ DRDATA (TIME5, clk_delay[5], 31), PV_LEFT },
|
||||
{ DRDATA (TIME6, clk_delay[6], 31), PV_LEFT },
|
||||
{ DRDATA (TIME7, clk_delay[7], 31), PV_LEFT },
|
||||
{ BRDATA (TIME, clk_delay, 8, 31, 8) },
|
||||
{ ORDATA (DEVNO, infotab[inCLK].devno, 6), REG_RO },
|
||||
{ NULL } };
|
||||
|
||||
MTAB clk_mod[] = {
|
||||
{ UNIT_DEVNO, inCLK, NULL, "DEVNO", &hp_setdev },
|
||||
{ MTAB_XTD | MTAB_VDV, inCLK, "DEVNO", "DEVNO",
|
||||
&hp_setdev, &hp_showdev, NULL },
|
||||
{ 0 } };
|
||||
|
||||
DEVICE clk_dev = {
|
||||
|
@ -447,6 +448,8 @@ t_stat tto_out (int32 ch)
|
|||
t_stat ret = SCPE_OK;
|
||||
|
||||
if (tty_mode & TM_PRI) { /* printing? */
|
||||
if ((tty_unit[TTI].flags & UNIT_UC) && islower (ch)) /* upper case? */
|
||||
ch = toupper (ch);
|
||||
ret = sim_putchar (ch & 0177); /* output char */
|
||||
tty_unit[TTO].pos = tty_unit[TTO].pos + 1; }
|
||||
if (tty_mode & TM_PUN) { /* punching? */
|
|
@ -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.
|
||||
|
||||
29-Nov-01 RMS Added read only unit support
|
||||
13-Apr-01 RMS Revised for register arrays
|
||||
*/
|
||||
|
||||
|
@ -60,7 +61,7 @@ t_stat cd_reset (DEVICE *dptr);
|
|||
*/
|
||||
|
||||
UNIT cdr_unit = {
|
||||
UDATA (&cdr_svc, UNIT_SEQ+UNIT_ATTABLE, 0), 100 };
|
||||
UDATA (&cdr_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0), 100 };
|
||||
|
||||
REG cdr_reg[] = {
|
||||
{ FLDATA (LAST, ind[IN_LST], 0) },
|
|
@ -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.
|
||||
|
||||
30-Nov-01 RMS Added extended SET/SHOW support
|
||||
10-Aug-01 RMS Removed register in declarations
|
||||
07-Dec-00 RMS Fixed bugs found by Charles Owen
|
||||
-- 4,7 char NOPs are legal
|
||||
|
@ -105,8 +106,6 @@
|
|||
|
||||
#include "i1401_defs.h"
|
||||
|
||||
#define ILL_ADR_FLAG 100000 /* invalid addr flag */
|
||||
#define save_ibkpt (cpu_unit.u3) /* saved bkpt addr */
|
||||
#define MM(x) x = x - 1; \
|
||||
if (x < 0) { \
|
||||
x = BA + MAXMEMSIZE - 1; \
|
||||
|
@ -135,14 +134,13 @@ int32 ind[64] = { 0 }; /* indicators */
|
|||
int32 ssa = 1; /* sense switch A */
|
||||
int32 prchk = 0; /* process check stop */
|
||||
int32 iochk = 0; /* I/O check stop */
|
||||
int32 ibkpt_addr = ILL_ADR_FLAG + MAXMEMSIZE; /* breakpoint addr */
|
||||
extern int32 sim_int_char;
|
||||
extern int32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */
|
||||
|
||||
t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw);
|
||||
t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw);
|
||||
t_stat cpu_reset (DEVICE *dptr);
|
||||
t_stat cpu_svc (UNIT *uptr);
|
||||
t_stat cpu_set_size (UNIT *uptr, int32 value);
|
||||
t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
int32 store_addr_h (int32 addr);
|
||||
int32 store_addr_t (int32 addr);
|
||||
int32 store_addr_u (int32 addr);
|
||||
|
@ -167,7 +165,7 @@ extern t_stat sim_activate (UNIT *uptr, int32 delay);
|
|||
cpu_mod CPU modifier list
|
||||
*/
|
||||
|
||||
UNIT cpu_unit = { UDATA (&cpu_svc, UNIT_FIX + UNIT_BCD + STDOPT,
|
||||
UNIT cpu_unit = { UDATA (NULL, UNIT_FIX + UNIT_BCD + STDOPT,
|
||||
MAXMEMSIZE) };
|
||||
|
||||
REG cpu_reg[] = {
|
||||
|
@ -191,7 +189,6 @@ REG cpu_reg[] = {
|
|||
{ FLDATA (IOCHK, iochk, 0) },
|
||||
{ FLDATA (PRCHK, prchk, 0) },
|
||||
{ DRDATA (OLDIS, oldIS, 14), REG_RO + PV_LEFT },
|
||||
{ DRDATA (BREAK, ibkpt_addr, 17), PV_LEFT },
|
||||
{ ORDATA (WRU, sim_int_char, 8) },
|
||||
{ NULL } };
|
||||
|
||||
|
@ -420,10 +417,7 @@ saved_IS = IS; /* commit prev instr */
|
|||
if (sim_interval <= 0) { /* check clock queue */
|
||||
if (reason = sim_process_event ()) break; }
|
||||
|
||||
if (IS == ibkpt_addr) { /* breakpoint? */
|
||||
save_ibkpt = ibkpt_addr; /* save ibkpt */
|
||||
ibkpt_addr = ibkpt_addr + ILL_ADR_FLAG; /* disable */
|
||||
sim_activate (&cpu_unit, 1); /* sched re-enable */
|
||||
if (sim_brk_summ && sim_brk_test (IS, SWMASK ('E'))) { /* breakpoint? */
|
||||
reason = STOP_IBKPT; /* stop simulation */
|
||||
break; }
|
||||
|
||||
|
@ -1061,15 +1055,7 @@ for (i = 0; i < 64; i++) ind[i] = 0;
|
|||
ind[IN_UNC] = 1;
|
||||
AS = 0; as_err = 1;
|
||||
BS = 0; bs_err = 1;
|
||||
return cpu_svc (&cpu_unit);
|
||||
}
|
||||
|
||||
/* Breakpoint service */
|
||||
|
||||
t_stat cpu_svc (UNIT *uptr)
|
||||
{
|
||||
if ((ibkpt_addr - ILL_ADR_FLAG) == save_ibkpt) ibkpt_addr = save_ibkpt;
|
||||
save_ibkpt = -1;
|
||||
sim_brk_types = sim_brk_dflt = SWMASK ('E');
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
@ -1093,17 +1079,17 @@ return SCPE_OK;
|
|||
|
||||
/* Memory size change */
|
||||
|
||||
t_stat cpu_set_size (UNIT *uptr, int32 value)
|
||||
t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
int32 mc = 0;
|
||||
t_addr i;
|
||||
|
||||
if ((value <= 0) || (value > MAXMEMSIZE) || ((value % 1000) != 0))
|
||||
if ((val <= 0) || (val > MAXMEMSIZE) || ((val % 1000) != 0))
|
||||
return SCPE_ARG;
|
||||
for (i = value; i < MEMSIZE; i++) mc = mc | M[i];
|
||||
for (i = val; i < MEMSIZE; i++) mc = mc | M[i];
|
||||
if ((mc != 0) && (!get_yn ("Really truncate memory [N]?", FALSE)))
|
||||
return SCPE_OK;
|
||||
MEMSIZE = value;
|
||||
MEMSIZE = val;
|
||||
for (i = MEMSIZE; i < MAXMEMSIZE; i++) M[i] = 0;
|
||||
if (MEMSIZE > 4000) cpu_unit.flags = cpu_unit.flags | MA;
|
||||
else cpu_unit.flags = cpu_unit.flags & ~MA;
|
428
I1401/i1401_doc.txt
Normal file
428
I1401/i1401_doc.txt
Normal file
|
@ -0,0 +1,428 @@
|
|||
To: Users
|
||||
From: Bob Supnik
|
||||
Subj: IBM 1401 Simulator Usage
|
||||
Date: 1-Dec-01
|
||||
|
||||
COPYRIGHT NOTICE
|
||||
|
||||
The following copyright notice applies to both the SIMH source and binary:
|
||||
|
||||
Original code published in 1993-2001, written by Robert M Supnik
|
||||
Copyright (c) 1993-2001, Robert M Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation
|
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
and/or sell copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
Except as contained in this notice, the name of Robert M Supnik shall not
|
||||
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
This memorandum documents the IBM 1401 simulator.
|
||||
|
||||
|
||||
1. Simulator Files
|
||||
|
||||
sim/ sim_defs.h
|
||||
scp.c
|
||||
scp_tty.c
|
||||
sim_rev.c
|
||||
|
||||
sim/i1401/ i1401_defs.h
|
||||
i1401_cpu.c
|
||||
i1401_iq.c
|
||||
i1401_lp.c
|
||||
i1401_mt.c
|
||||
i1401_sys.c
|
||||
|
||||
2. IBM 1401 Features
|
||||
|
||||
The IBM 1401 simulator is configured as follows:
|
||||
|
||||
device simulates
|
||||
name(s)
|
||||
|
||||
CPU IBM 1401 CPU with 16K of memory
|
||||
CDR,CDP IBM 1402 card reader/punch
|
||||
LPT IBM 1403 line printer
|
||||
INQ IBM 1407 inquiry terminal
|
||||
MT IBM 729 7-track magnetic tape controller with six drives
|
||||
|
||||
The IBM 1401 simulator implements many unique stop conditions. On almost
|
||||
any kind of error the simulator stops:
|
||||
|
||||
unimplemented opcode
|
||||
reference to non-existent memory
|
||||
reference to non-existent device
|
||||
no word mark under opcode
|
||||
invalid A address
|
||||
invalid B address
|
||||
invalid instruction length
|
||||
invalid modifier character
|
||||
invalid branch address
|
||||
invalid magtape unit number
|
||||
invalid magtape record length
|
||||
write to locked magtape drive
|
||||
skip to unpunched carriage control tape channel
|
||||
card reader hopper empty
|
||||
address register wrap-around
|
||||
single character A field in MCE
|
||||
single character B field in MCE
|
||||
hanging $ in MCE with EPE enabled
|
||||
I/O check with I/O stop switch set
|
||||
|
||||
The LOAD and DUMP commands are not implemented.
|
||||
|
||||
2.1 CPU
|
||||
|
||||
The CPU options include a number of special features and the size of main
|
||||
memory. Note that the Modify Address special feature is always included
|
||||
when memory size is greater than 4K.
|
||||
|
||||
SET CPU XSA enable advanced programming special feature
|
||||
SET CPU NOXSA disable advanced programming
|
||||
SET CPU HLE enable high/low/equal special feature
|
||||
SET CPU NOHLE disable high/low/equal
|
||||
SET CPU BBE enable branch on bit equal special feature
|
||||
SET CPU NOBBE disable branch on bit equal
|
||||
SET CPU MR enable move record special feature
|
||||
SET CPU NOMR disable move record
|
||||
SET CPU EPE enable extended print edit special feature
|
||||
SET CPU NOEPE disable extended print edit
|
||||
SET CPU 4K set memory size = 4K
|
||||
SET CPU 8K set memory size = 8K
|
||||
SET CPU 12K set memory size = 12K
|
||||
SET CPU 16K set memory size = 16K
|
||||
|
||||
If memory size is being reduced, and the memory being truncated contains
|
||||
non-zero data, the simulator asks for confirmation. Data in the truncated
|
||||
portion of memory is lost. Initially, memory size is 16K, and all special
|
||||
features are enabled.
|
||||
|
||||
Memory is implemented as 7 bit BCD characters, as follows:
|
||||
|
||||
6 5 4 3 2 1 0
|
||||
|
||||
word B bit A bit 8 4 2 1
|
||||
mark <-- zone --> <-------- digit -------->
|
||||
|
||||
In BCD, the decimal digits 0-9 are (octal) values 012, 001, 002, 003, 004,
|
||||
005, 006, 007, 010, 011, respectively. Signs are encoded in the zone bits,
|
||||
with 00, 01, and 11 being positive, and 10 being negative.
|
||||
|
||||
CPU registers include the visible state of the processor. The 1401 has no
|
||||
interrupt system.
|
||||
|
||||
name size comments
|
||||
|
||||
IS 14 instruction storage address register (PC)
|
||||
AS 14 A storage address register
|
||||
BS 14 B storage address register
|
||||
ASERR 1 AS invalid flag
|
||||
BSERR 1 BS invalid flag
|
||||
SSA 1 sense switch A
|
||||
SSB 1 sense switch B
|
||||
SSC 1 sense switch C
|
||||
SSD 1 sense switch D
|
||||
SSE 1 sense switch E
|
||||
SSF 1 sense switch F
|
||||
SSG 1 sense switch G
|
||||
EQU 1 equal compare indicator
|
||||
UNEQ 1 unequal compare indicator
|
||||
HIGH 1 high compare indicator
|
||||
LOW 1 low compare indicator
|
||||
OVF 1 overflow indicator
|
||||
IOCHK 1 I/O check switch
|
||||
PRCHK 1 process check switch
|
||||
OLDIS 1 IS prior to last branch
|
||||
WRU 8 interrupt character
|
||||
|
||||
2.2 1402 Card Reader/Punch (CDR, CDP, STKR)
|
||||
|
||||
The IBM 1402 card/reader punch is simulated as three independent devices:
|
||||
the card reader (CDR), the card punch (CDP), and the reader and punch
|
||||
stackers (STKR). STRK units 0, 1, 2, and 4 correspond to the reader
|
||||
normal stacker, reader stacker 1, shared stacker 2/8, and punch stacker
|
||||
4, respectively.
|
||||
|
||||
The card reader supports the BOOT command. BOOT CDR reads a card image
|
||||
into locations 1-80, sets a word mark under location 1, clears storage,
|
||||
and then transfers control to location 1.
|
||||
|
||||
The card reader reads data from disk files, while the punch and stackers
|
||||
write data to disk files. Cards are simulated as ASCII text lines with
|
||||
terminating newlines; column binary is not supported. For each unit,
|
||||
the POS register specifies the number of the next data item to be read or
|
||||
written. Thus, by changing POS, the user can backspace or advance these
|
||||
devices.
|
||||
|
||||
The reader/punch registers are:
|
||||
|
||||
device name size comments
|
||||
|
||||
CDR LAST 1 last card indicator
|
||||
ERR 1 error indicator
|
||||
S1 1 stacker 1 select flag
|
||||
S2 1 stacker 2 select flag
|
||||
POS 31 position
|
||||
TIME 24 delay window for stacker select
|
||||
BUF[0:79] 8 reader buffer
|
||||
|
||||
CDP ERR 1 error indicator
|
||||
S4 1 stacker 4 select flag
|
||||
S8 1 stacker 8 select flag
|
||||
|
||||
STKR POS0 31 position, normal reader stack
|
||||
POS1 31 position, reader stacker 1
|
||||
POS2 31 position, shared stacker 2/8
|
||||
POS4 31 position, punch stacker 4
|
||||
|
||||
Error handling is as follows:
|
||||
|
||||
device error processed as
|
||||
|
||||
reader end of file if SSA set, set LAST indicator
|
||||
on next Read, report error and stop
|
||||
|
||||
reader,punch not attached report error and stop
|
||||
OS I/O error print error message
|
||||
if IOCHK set, report error and stop
|
||||
otherwise, set ERR indicator
|
||||
|
||||
stacker not attached ignored
|
||||
OS I/O error print error message
|
||||
if IOCHK set, report error and stop
|
||||
|
||||
2.3 1403 Line Printer (LPT)
|
||||
|
||||
The IBM 1403 line printer (LPT) writes its data, converted to ASCII, to
|
||||
a disk file. The line printer supports three different print character
|
||||
sets or "chains":
|
||||
|
||||
SET LPT PCF full 64 character chain
|
||||
SET LPT PCA 48 character business chain
|
||||
SET LPT PCH 48 character FORTRAN chain
|
||||
|
||||
In addition, the line printer can be programmed with a carriage control
|
||||
tape. The LOAD command loads a new carriage control tape:
|
||||
|
||||
LOAD <file> load carriage control tape file
|
||||
|
||||
The format of a carriage control tape consists of multiple lines. Each
|
||||
line contains an optional repeat count, enclosed in parentheses, optionally
|
||||
followed by a series of column numbers separated by commas. Column numbers
|
||||
must be between 1 and 12; a column number of zero denotes top of form. The
|
||||
following are all legal carriage control specifications:
|
||||
|
||||
<blank line> no punch
|
||||
(5) 5 lines with no punches
|
||||
1,5,7,8 columns 1, 5, 7, 8 punched
|
||||
(10)2 10 lines with column 2 punched
|
||||
1,0 column 1 punched; top of form
|
||||
|
||||
The default form is 66 lines long, with column 1 and the top of form mark
|
||||
on line 1, and the rest blank.
|
||||
|
||||
The line printer registers are:
|
||||
|
||||
name size comments
|
||||
|
||||
LINES 8 number of newlines after next print
|
||||
LFLAG 1 carriage control flag (1 = skip, 0 = space)
|
||||
CCTP 8 carriage control tape pointer
|
||||
CCTL 8 carriage control tape length (read only)
|
||||
ERR 1 error indicator
|
||||
POS 31 position
|
||||
CCT[0:131] 32 carriage control tape array
|
||||
|
||||
Error handling is as follows:
|
||||
|
||||
error processed as
|
||||
|
||||
not attached report error and stop
|
||||
|
||||
OS I/O error print error message
|
||||
if IOCHK set, report error and stop
|
||||
otherwise, set ERR indicator
|
||||
|
||||
2.4 1407 Inquiry Terminal (INQ)
|
||||
|
||||
The IBM 1407 inquiry terminal (INQ) is a half-duplex console. It polls
|
||||
the console keyboard periodically for inquiry requests. The inquiry
|
||||
terminal registers are:
|
||||
|
||||
name size comments
|
||||
|
||||
INQC 7 inquiry request character (initially ESC)
|
||||
INR 1 inquiry request indicator
|
||||
INC 1 inquiry cleared indicator
|
||||
TIME 24 polling interval
|
||||
|
||||
When the 1401 CPU requests input from the keyboard, the message [Enter]
|
||||
is printed out, followed by a new line. The CPU hangs waiting for input
|
||||
until either the return/enter key is pressed, or the inquiry request
|
||||
character is typed in. The latter cancels the type-in and sets INC.
|
||||
|
||||
The inquiry terminal has no errors.
|
||||
|
||||
2.5 729 Magnetic Tape (MT)
|
||||
|
||||
The magnetic tape controller supports six drives, numbered 1 through 6.
|
||||
Magnetic tape options include the ability to make units write enabled or
|
||||
or write locked.
|
||||
|
||||
SET MTn LOCKED set unit n write locked
|
||||
SET MTn ENABLED set unit n write enabled
|
||||
|
||||
Units can also be REMOVEd or ADDed to the configuration. The magnetic
|
||||
tape simulator supports the BOOT command. BOOT MT reads the first
|
||||
record off tape, starting at location 1, and then branches to it.
|
||||
|
||||
The magnetic tape controller implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
END 1 end of file indicator
|
||||
ERR 1 error indicator
|
||||
PAR 1 parity error indicator
|
||||
POS1..6 31 position, drives 1..6
|
||||
|
||||
Error handling is as follows:
|
||||
|
||||
error processed as
|
||||
|
||||
not attached report error and stop
|
||||
|
||||
end of file (read or space) end of physical tape
|
||||
(write) ignored
|
||||
|
||||
OS I/O error print error message
|
||||
if IOCHK set, report error and stop
|
||||
otherwise, set ERR indicator
|
||||
|
||||
2.6 Symbolic Display and Input
|
||||
|
||||
The IBM 1401 simulator implements symbolic display and input. Display is
|
||||
controlled by command line switches:
|
||||
|
||||
-c display as single character
|
||||
(BCD for CPU and MT, ASCII for others)
|
||||
-s display as wordmark terminated BCD string
|
||||
(CPU only)
|
||||
-m display instruction mnemonics
|
||||
(CPU only)
|
||||
|
||||
In a CPU character display, word marks are denoted by ~.
|
||||
|
||||
Input parsing is controlled by the first character typed in or by command
|
||||
line switches:
|
||||
|
||||
' or " or -c or -s characters (BCD for CPU and MT, ASCII
|
||||
for others)
|
||||
alphabetic instruction mnemonic
|
||||
numeric octal number
|
||||
|
||||
Instruction input is free format, with spaces separating fields. There
|
||||
are six instruction formats: 1, 2, 4, 5, 7, and 8 characters:
|
||||
|
||||
1 character opcode
|
||||
2 character opcode 'modifier
|
||||
4 character opcode address
|
||||
5 character opcode address 'modifier
|
||||
7 character opcode address address
|
||||
8 character opcode address address 'modifier
|
||||
|
||||
Addresses are always decimal, except for special I/O addresses in the A
|
||||
field, which may be specified as %xy, where x denotes the device and y
|
||||
the unit number.
|
||||
|
||||
For the CPU, string input may encompass multiple characters. A word mark
|
||||
is denoted by ~ and must precede the character to be marked. All other
|
||||
devices can only accept single character input, without word marks.
|
||||
|
||||
2.7 Character Sets
|
||||
|
||||
The IBM 1401 used a 6b character code called BCD (binary coded decimal).
|
||||
Some of the characters have no equivalent in ASCII and require different
|
||||
representations:
|
||||
|
||||
BCD ASCII IBM 1401 print
|
||||
code representation character chains
|
||||
|
||||
00 space
|
||||
01 1
|
||||
02 2
|
||||
03 3
|
||||
04 4
|
||||
05 5
|
||||
06 6
|
||||
07 7
|
||||
10 8
|
||||
11 9
|
||||
12 0
|
||||
13 # = in H chain
|
||||
14 @ ' in H chain
|
||||
15 : blank in A, H chains
|
||||
16 > blank in A, H chains
|
||||
17 ( tape mark blank in A, H chains
|
||||
20 ^ alternate blank blank in A, H chains
|
||||
21 /
|
||||
22 S
|
||||
23 T
|
||||
24 U
|
||||
25 V
|
||||
26 W
|
||||
27 X
|
||||
30 Y
|
||||
31 Z
|
||||
32 ' record mark
|
||||
33 ,
|
||||
34 % ( in H chain
|
||||
35 = word mark blank in A, H chains
|
||||
36 \ blank in A, H chains
|
||||
37 + blank in A, H chains
|
||||
40 -
|
||||
41 J
|
||||
42 K
|
||||
43 L
|
||||
44 M
|
||||
45 N
|
||||
46 O
|
||||
47 P
|
||||
50 Q
|
||||
51 R
|
||||
52 !
|
||||
53 $
|
||||
54 *
|
||||
55 ] blank in A, H chains
|
||||
56 ; blank in A, H chains
|
||||
57 _ delta blank in A, H chains
|
||||
60 &
|
||||
61 A
|
||||
62 B
|
||||
63 C
|
||||
64 D
|
||||
65 E
|
||||
66 F
|
||||
67 G
|
||||
70 H
|
||||
71 I
|
||||
72 ?
|
||||
73 .
|
||||
74 ) lozenge
|
||||
75 [ blank in A, H chains
|
||||
76 < blank in A, H chains
|
||||
77 " group mark blank in A, H chains
|
|
@ -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.
|
||||
|
||||
inq 1407 inquiry terminal
|
||||
|
||||
07-Sep-01 RMS Moved function prototypes
|
||||
14-Apr-99 RMS Changed t_addr to unsigned
|
||||
*/
|
|
@ -23,7 +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.
|
||||
|
||||
lpt 1403 line printer
|
||||
lpt 1403 line printer
|
||||
|
||||
13-Apr-01 RMS Revised for register arrays
|
||||
*/
|
|
@ -1,4 +1,4 @@
|
|||
/* IBM 1401 magnetic tape simulator
|
||||
/* i1401_mt.c: IBM 1401 magnetic tape simulator
|
||||
|
||||
Copyright (c) 1993-2001, Robert M. Supnik
|
||||
|
||||
|
@ -23,6 +23,9 @@
|
|||
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
mt 7-track magtape
|
||||
|
||||
29-Nov-01 RMS Added read only unit support
|
||||
18-Apr-01 RMS Changed to rewind tape before boot
|
||||
07-Dec-00 RMS Widened display width from 6 to 8 bits to see record lnt
|
||||
CEO Added tape bootstrap
|
||||
|
@ -50,6 +53,7 @@
|
|||
#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */
|
||||
#define UNIT_WLK (1 << UNIT_V_WLK)
|
||||
#define UNIT_W_UF 2 /* #save flags */
|
||||
#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */
|
||||
|
||||
extern uint8 M[]; /* memory */
|
||||
extern int32 ind[64];
|
||||
|
@ -70,12 +74,18 @@ UNIT *get_unit (int32 unit);
|
|||
|
||||
UNIT mt_unit[] = {
|
||||
{ UDATA (NULL, UNIT_DIS, 0) }, /* doesn't exist */
|
||||
{ UDATA (NULL, UNIT_DISABLE + UNIT_ATTABLE + UNIT_BCD, 0) },
|
||||
{ UDATA (NULL, UNIT_DISABLE + UNIT_ATTABLE + UNIT_BCD, 0) },
|
||||
{ UDATA (NULL, UNIT_DISABLE + UNIT_ATTABLE + UNIT_BCD, 0) },
|
||||
{ UDATA (NULL, UNIT_DISABLE + UNIT_ATTABLE + UNIT_BCD, 0) },
|
||||
{ UDATA (NULL, UNIT_DISABLE + UNIT_ATTABLE + UNIT_BCD, 0) },
|
||||
{ UDATA (NULL, UNIT_DISABLE + UNIT_ATTABLE + UNIT_BCD, 0) } };
|
||||
{ UDATA (NULL, UNIT_DISABLE + UNIT_ATTABLE +
|
||||
UNIT_ROABLE + UNIT_BCD, 0) },
|
||||
{ UDATA (NULL, UNIT_DISABLE + UNIT_ATTABLE +
|
||||
UNIT_ROABLE + UNIT_BCD, 0) },
|
||||
{ UDATA (NULL, UNIT_DISABLE + UNIT_ATTABLE +
|
||||
UNIT_ROABLE + UNIT_BCD, 0) },
|
||||
{ UDATA (NULL, UNIT_DISABLE + UNIT_ATTABLE +
|
||||
UNIT_ROABLE + UNIT_BCD, 0) },
|
||||
{ UDATA (NULL, UNIT_DISABLE + UNIT_ATTABLE +
|
||||
UNIT_ROABLE + UNIT_BCD, 0) },
|
||||
{ UDATA (NULL, UNIT_DISABLE + UNIT_ATTABLE +
|
||||
UNIT_ROABLE + UNIT_BCD, 0) } };
|
||||
|
||||
REG mt_reg[] = {
|
||||
{ FLDATA (END, ind[IN_END], 0) },
|
||||
|
@ -145,10 +155,10 @@ case BCD_B: /* backspace */
|
|||
(2 * sizeof (t_mtrlnt));
|
||||
break; /* end case */
|
||||
case BCD_E: /* erase = nop */
|
||||
if (uptr -> flags & UNIT_WLK) return STOP_MTL;
|
||||
if (uptr -> flags & UNIT_WPRT) return STOP_MTL;
|
||||
return SCPE_OK;
|
||||
case BCD_M: /* write tapemark */
|
||||
if (uptr -> flags & UNIT_WLK) return STOP_MTL;
|
||||
if (uptr -> flags & UNIT_WPRT) return STOP_MTL;
|
||||
fseek (uptr -> fileref, uptr -> pos, SEEK_SET);
|
||||
fxwrite (&bceof, sizeof (t_mtrlnt), 1, uptr -> fileref);
|
||||
err = ferror (uptr -> fileref);
|
||||
|
@ -223,7 +233,7 @@ case BCD_R: /* read */
|
|||
break;
|
||||
|
||||
case BCD_W:
|
||||
if (uptr -> flags & UNIT_WLK) return STOP_MTL; /* locked? */
|
||||
if (uptr -> flags & UNIT_WPRT) return STOP_MTL; /* locked? */
|
||||
if (M[BS] == (BCD_GRPMRK + WM)) return STOP_MTZ; /* eor? */
|
||||
ind[IN_TAP] = ind[IN_END] = 0; /* clear error */
|
||||
for (tbc = 0; (t = M[BS++]) != (BCD_GRPMRK + WM); ) {
|
|
@ -2,9 +2,9 @@ Charles Owen's Eclipse Modules
|
|||
|
||||
1. Eclipse CPU simulator
|
||||
|
||||
The Eclipse CPU simulator can be used with the V2.5a Nova definitions and peripheral
|
||||
modules to produce an Eclipse simulator that will run Eclipse mapped RDOS V7.5. The
|
||||
compilation procedure is the same as for the Nova simulator, except:
|
||||
The Eclipse CPU simulator can be used with the Nova definitions and peripheral
|
||||
modules to produce an Eclipse simulator that will run Eclipse mapped RDOS V7.5.
|
||||
The compilation procedure is the same as for the Nova simulator, except:
|
||||
|
||||
- the symbol ECLIPSE must be defined
|
||||
- the module eclipse_cpu.c must be substituted for nova_cpu.c
|
|
@ -28,6 +28,7 @@
|
|||
|
||||
cpu Eclipse central processor
|
||||
|
||||
30-Nov-01 RMS Added extended SET/SHOW support
|
||||
01-Jun-01 RMS Added second terminal, plotter support
|
||||
26-Apr-01 RMS Added device enable/disable support
|
||||
|
||||
|
@ -313,8 +314,6 @@
|
|||
|
||||
#include "nova_defs.h"
|
||||
|
||||
#define ILL_ADR_FLAG 0100000
|
||||
#define save_ibkpt (cpu_unit.u3)
|
||||
#define UNIT_V_MICRO (UNIT_V_UF) /* Microeclipse? */
|
||||
#define UNIT_MICRO (1 << UNIT_V_MICRO)
|
||||
#define UNIT_V_MSIZE (UNIT_V_UF+1) /* dummy mask */
|
||||
|
@ -336,7 +335,6 @@ int32 pimask = 0; /* priority int mask */
|
|||
int32 pwr_low = 0; /* power fail flag */
|
||||
int32 ind_max = 15; /* iadr nest limit */
|
||||
int32 stop_dev = 0; /* stop on ill dev */
|
||||
int32 ibkpt_addr = ILL_ADR_FLAG | AMASK; /* ibreakpoint addr */
|
||||
int32 old_PC = 0; /* previous PC */
|
||||
int32 model = 130; /* Model of Eclipse */
|
||||
int32 speed = 0; /* Delay for each instruction */
|
||||
|
@ -417,15 +415,15 @@ int32 Tron = 0; /* For trace files */
|
|||
FILE *Trace;
|
||||
|
||||
t_stat reason;
|
||||
|
||||
extern int32 sim_int_char;
|
||||
extern int32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */
|
||||
|
||||
t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw);
|
||||
t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw);
|
||||
t_stat cpu_reset (DEVICE *dptr);
|
||||
t_stat cpu_svc (UNIT *uptr);
|
||||
t_stat cpu_boot (int32 unitno);
|
||||
t_stat cpu_set_size (UNIT *uptr, int32 value);
|
||||
t_stat Debug_Dump (UNIT *uptr, int32 value);
|
||||
t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
t_stat Debug_Dump (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
t_stat map_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw);
|
||||
t_stat map_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw);
|
||||
t_stat map_reset (DEVICE *dptr);
|
||||
|
@ -494,7 +492,7 @@ struct ndev dev_table[64] = {
|
|||
cpu_mod CPU modifiers list
|
||||
*/
|
||||
|
||||
UNIT cpu_unit = { UDATA (&cpu_svc, UNIT_FIX + UNIT_BINK,
|
||||
UNIT cpu_unit = { UDATA (NULL, UNIT_FIX + UNIT_BINK,
|
||||
MAXMEMSIZE) };
|
||||
|
||||
REG cpu_reg[] = {
|
||||
|
@ -517,7 +515,6 @@ REG cpu_reg[] = {
|
|||
{ FLDATA (MICRO, cpu_unit.flags, UNIT_V_MICRO), REG_HRO },
|
||||
{ DRDATA (INDMAX, ind_max, 16), REG_NZ + PV_LEFT },
|
||||
{ ORDATA (DEBUG, Debug_Flags, 16) },
|
||||
{ ORDATA (BREAK, ibkpt_addr, 16) },
|
||||
{ DRDATA (MODEL, model, 16) },
|
||||
{ DRDATA (SPEED, speed, 16) },
|
||||
{ ORDATA (WRU, sim_int_char, 8) },
|
||||
|
@ -714,10 +711,7 @@ if (Inhibit != 0) { /* Handle 1-instruction inhibit sequence */
|
|||
Inhibit = 0;
|
||||
}
|
||||
|
||||
if (PC == ibkpt_addr) { /* breakpoint? */
|
||||
save_ibkpt = ibkpt_addr; /* save address */
|
||||
ibkpt_addr = ibkpt_addr | ILL_ADR_FLAG; /* disable */
|
||||
sim_activate (&cpu_unit, 1); /* sched re-enable */
|
||||
if (sim_brk_summ && sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */
|
||||
reason = STOP_IBKPT; /* stop simulation */
|
||||
break;
|
||||
}
|
||||
|
@ -3223,7 +3217,8 @@ int_req = int_req & ~INT_ION;
|
|||
pimask = 0;
|
||||
dev_disable = 0;
|
||||
pwr_low = 0;
|
||||
return cpu_svc (&cpu_unit);
|
||||
sim_brk_types = sim_brk_dflt = SWMASK ('E');
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Memory examine */
|
||||
|
@ -3244,26 +3239,17 @@ M[addr] = val & 0177777;
|
|||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Breakpoint service */
|
||||
|
||||
t_stat cpu_svc (UNIT *uptr)
|
||||
{
|
||||
if ((ibkpt_addr & ~ILL_ADR_FLAG) == save_ibkpt) ibkpt_addr = save_ibkpt;
|
||||
save_ibkpt = -1;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat cpu_set_size (UNIT *uptr, int32 value)
|
||||
t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
int32 mc = 0;
|
||||
t_addr i;
|
||||
|
||||
if ((value <= 0) || (value > MAXMEMSIZE) || ((value & 07777) != 0))
|
||||
if ((val <= 0) || (val > MAXMEMSIZE) || ((val & 07777) != 0))
|
||||
return SCPE_ARG;
|
||||
for (i = value; i < MEMSIZE; i++) mc = mc | M[i];
|
||||
for (i = val; i < MEMSIZE; i++) mc = mc | M[i];
|
||||
if ((mc != 0) && (!get_yn ("Really truncate memory [N]?", FALSE)))
|
||||
return SCPE_OK;
|
||||
MEMSIZE = value;
|
||||
MEMSIZE = val;
|
||||
for (i = MEMSIZE; i < MAXMEMSIZE; i++) M[i] = 0;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
@ -3366,7 +3352,7 @@ int32 Debug_Entry(int32 PC, int32 inst, int32 inst2, int32 AC0, int32 AC1, int32
|
|||
return 0;
|
||||
}
|
||||
|
||||
int32 Debug_Dump(UNIT *uptr, int32 value)
|
||||
int32 Debug_Dump(UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
char debmap[4], debion[4];
|
||||
t_value simeval[20];
|
|
@ -25,6 +25,8 @@
|
|||
|
||||
cpu Nova central processor
|
||||
|
||||
07-Dec-01 RMS Revised to use breakpoint package
|
||||
30-Nov-01 RMS Added extended SET/SHOW support
|
||||
10-Aug-01 RMS Removed register in declarations
|
||||
17-Jul-01 RMS Moved function prototype
|
||||
26-Apr-01 RMS Added device enable/disable support
|
||||
|
@ -211,8 +213,6 @@
|
|||
M[x] = (M[x] - 1) & 0177777; \
|
||||
x = M[x] & AMASK
|
||||
|
||||
#define ILL_ADR_FLAG A_IND
|
||||
#define save_ibkpt (cpu_unit.u3)
|
||||
#define UNIT_V_MDV (UNIT_V_UF) /* MDV present */
|
||||
#define UNIT_MDV (1 << UNIT_V_MDV)
|
||||
#define UNIT_V_STK (UNIT_V_UF+1) /* stack instr */
|
||||
|
@ -241,15 +241,14 @@ int32 pimask = 0; /* priority int mask */
|
|||
int32 pwr_low = 0; /* power fail flag */
|
||||
int32 ind_max = 16; /* iadr nest limit */
|
||||
int32 stop_dev = 0; /* stop on ill dev */
|
||||
int32 ibkpt_addr = ILL_ADR_FLAG | AMASK; /* ibreakpoint addr */
|
||||
int32 old_PC = 0; /* previous PC */
|
||||
|
||||
extern int32 sim_int_char;
|
||||
extern int32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */
|
||||
|
||||
t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw);
|
||||
t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw);
|
||||
t_stat cpu_reset (DEVICE *dptr);
|
||||
t_stat cpu_svc (UNIT *uptr);
|
||||
t_stat cpu_set_size (UNIT *uptr, int32 value);
|
||||
t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
t_stat cpu_boot (int32 unitno);
|
||||
extern int32 ptr (int32 pulse, int32 code, int32 AC);
|
||||
extern int32 ptp (int32 pulse, int32 code, int32 AC);
|
||||
|
@ -310,7 +309,7 @@ struct ndev dev_table[64] = {
|
|||
cpu_mod CPU modifiers list
|
||||
*/
|
||||
|
||||
UNIT cpu_unit = { UDATA (&cpu_svc, UNIT_FIX + UNIT_BINK + UNIT_MDV,
|
||||
UNIT cpu_unit = { UDATA (NULL, UNIT_FIX + UNIT_BINK + UNIT_MDV,
|
||||
MAXMEMSIZE) };
|
||||
|
||||
REG cpu_reg[] = {
|
||||
|
@ -338,7 +337,6 @@ REG cpu_reg[] = {
|
|||
{ FLDATA (IBYT, cpu_unit.flags, UNIT_V_BYT), REG_HRO },
|
||||
{ DRDATA (INDMAX, ind_max, 16), REG_NZ + PV_LEFT },
|
||||
{ ORDATA (OLDPC, old_PC, 15), REG_RO },
|
||||
{ ORDATA (BREAK, ibkpt_addr, 16) },
|
||||
{ ORDATA (WRU, sim_int_char, 8) },
|
||||
{ ORDATA (IOTENB, iot_enb, 32), REG_HRO },
|
||||
{ NULL } };
|
||||
|
@ -401,10 +399,7 @@ if (int_req > INT_PENDING) { /* interrupt? */
|
|||
break; }
|
||||
PC = MA; } /* end interrupt */
|
||||
|
||||
if (PC == ibkpt_addr) { /* breakpoint? */
|
||||
save_ibkpt = ibkpt_addr; /* save address */
|
||||
ibkpt_addr = ibkpt_addr | ILL_ADR_FLAG; /* disable */
|
||||
sim_activate (&cpu_unit, 1); /* sched re-enable */
|
||||
if (sim_brk_summ && sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */
|
||||
reason = STOP_IBKPT; /* stop simulation */
|
||||
break; }
|
||||
|
||||
|
@ -828,7 +823,8 @@ int_req = int_req & ~(INT_ION | INT_STK);
|
|||
pimask = 0;
|
||||
dev_disable = 0;
|
||||
pwr_low = 0;
|
||||
return cpu_svc (&cpu_unit);
|
||||
sim_brk_types = sim_brk_dflt = SWMASK ('E');
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Memory examine */
|
||||
|
@ -849,26 +845,17 @@ M[addr] = val & DMASK;
|
|||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Breakpoint service */
|
||||
|
||||
t_stat cpu_svc (UNIT *uptr)
|
||||
{
|
||||
if ((ibkpt_addr & ~ILL_ADR_FLAG) == save_ibkpt) ibkpt_addr = save_ibkpt;
|
||||
save_ibkpt = -1;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat cpu_set_size (UNIT *uptr, int32 value)
|
||||
t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
int32 mc = 0;
|
||||
t_addr i;
|
||||
|
||||
if ((value <= 0) || (value > MAXMEMSIZE) || ((value & 07777) != 0))
|
||||
if ((val <= 0) || (val > MAXMEMSIZE) || ((val & 07777) != 0))
|
||||
return SCPE_ARG;
|
||||
for (i = value; i < MEMSIZE; i++) mc = mc | M[i];
|
||||
for (i = val; i < MEMSIZE; i++) mc = mc | M[i];
|
||||
if ((mc != 0) && (!get_yn ("Really truncate memory [N]?", FALSE)))
|
||||
return SCPE_OK;
|
||||
MEMSIZE = value;
|
||||
MEMSIZE = val;
|
||||
for (i = MEMSIZE; i < MAXMEMSIZE; i++) M[i] = 0;
|
||||
return SCPE_OK;
|
||||
}
|
|
@ -25,6 +25,8 @@
|
|||
|
||||
dkp moving head disk
|
||||
|
||||
30-Nov-01 RMS Added read only unit, extended SET/SHOW support
|
||||
24-Nov-01 RMS Changed FLG, CAPAC to arrays
|
||||
26-Apr-01 RMS Added device enable/disable support
|
||||
12-Dec-00 RMS Added Eclipse support from Charles Owen
|
||||
15-Oct-00 RMS Editorial changes
|
||||
|
@ -51,6 +53,7 @@
|
|||
#define GET_DTYPE(x) (((x) >> UNIT_V_DTYPE) & UNIT_M_DTYPE)
|
||||
#define FUNC u3 /* function */
|
||||
#define CYL u4 /* on cylinder */
|
||||
#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */
|
||||
|
||||
/* Unit, surface, sector, count register
|
||||
|
||||
|
@ -282,7 +285,7 @@ t_stat dkp_reset (DEVICE *dptr);
|
|||
t_stat dkp_boot (int32 unitno);
|
||||
t_stat dkp_attach (UNIT *uptr, char *cptr);
|
||||
t_stat dkp_go (void);
|
||||
t_stat dkp_set_size (UNIT *uptr, int32 value);
|
||||
t_stat dkp_set_size (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
#if defined (ECLIPSE)
|
||||
extern int32 MapAddr (int32 map, int32 addr);
|
||||
#else
|
||||
|
@ -299,13 +302,13 @@ extern int32 MapAddr (int32 map, int32 addr);
|
|||
|
||||
UNIT dkp_unit[] = {
|
||||
{ UDATA (&dkp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+
|
||||
(TYPE_D31 << UNIT_V_DTYPE), SIZE_D31) },
|
||||
UNIT_ROABLE+(TYPE_D31 << UNIT_V_DTYPE), SIZE_D31) },
|
||||
{ UDATA (&dkp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+
|
||||
(TYPE_D31 << UNIT_V_DTYPE), SIZE_D31) },
|
||||
UNIT_ROABLE+(TYPE_D31 << UNIT_V_DTYPE), SIZE_D31) },
|
||||
{ UDATA (&dkp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+
|
||||
(TYPE_D31 << UNIT_V_DTYPE), SIZE_D31) },
|
||||
UNIT_ROABLE+(TYPE_D31 << UNIT_V_DTYPE), SIZE_D31) },
|
||||
{ UDATA (&dkp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+
|
||||
(TYPE_D31 << UNIT_V_DTYPE), SIZE_D31) } };
|
||||
UNIT_ROABLE+(TYPE_D31 << UNIT_V_DTYPE), SIZE_D31) } };
|
||||
|
||||
REG dkp_reg[] = {
|
||||
{ ORDATA (FCCY, dkp_fccy, 16) },
|
||||
|
@ -318,18 +321,10 @@ REG dkp_reg[] = {
|
|||
{ FLDATA (DISABLE, dev_disable, INT_V_DKP) },
|
||||
{ DRDATA (STIME, dkp_swait, 24), PV_LEFT },
|
||||
{ DRDATA (RTIME, dkp_rwait, 24), PV_LEFT },
|
||||
{ GRDATA (FLG0, dkp_unit[0].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ GRDATA (FLG1, dkp_unit[1].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ GRDATA (FLG2, dkp_unit[2].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ GRDATA (FLG3, dkp_unit[3].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ DRDATA (CAPAC0, dkp_unit[0].capac, 32), PV_LEFT + REG_HRO },
|
||||
{ DRDATA (CAPAC1, dkp_unit[1].capac, 32), PV_LEFT + REG_HRO },
|
||||
{ DRDATA (CAPAC2, dkp_unit[2].capac, 32), PV_LEFT + REG_HRO },
|
||||
{ DRDATA (CAPAC3, dkp_unit[3].capac, 32), PV_LEFT + REG_HRO },
|
||||
{ URDATA (FLG, dkp_unit[0].flags, 8, UNIT_W_UF, UNIT_V_UF - 1,
|
||||
DKP_NUMDR, REG_HRO) },
|
||||
{ URDATA (CAPAC, dkp_unit[0].capac, 10, 31, 0,
|
||||
DKP_NUMDR, PV_LEFT | REG_HRO) },
|
||||
{ FLDATA (*DEVENB, iot_enb, INT_V_DKP), REG_HRO },
|
||||
{ NULL } };
|
||||
|
||||
|
@ -572,7 +567,7 @@ if (uptr -> FUNC == FCCY_SEEK) { /* seek? */
|
|||
return SCPE_OK; }
|
||||
|
||||
if (((uptr -> flags & UNIT_ATT) == 0) || /* not attached? */
|
||||
((uptr -> flags & UNIT_WLK) && (uptr -> FUNC == FCCY_WRITE)))
|
||||
((uptr -> flags & UNIT_WPRT) && (uptr -> FUNC == FCCY_WRITE)))
|
||||
dkp_sta = dkp_sta | STA_DONE | STA_ERR; /* error */
|
||||
|
||||
else if ((uptr -> CYL >= drv_tab[dtype].cyl) || /* bad cylinder */
|
||||
|
@ -673,10 +668,10 @@ return SCPE_OK;
|
|||
|
||||
/* Set size command validation routine */
|
||||
|
||||
t_stat dkp_set_size (UNIT *uptr, int32 value)
|
||||
t_stat dkp_set_size (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
if (uptr -> flags & UNIT_ATT) return SCPE_ALATT;
|
||||
uptr -> capac = drv_tab[GET_DTYPE (value)].size;
|
||||
uptr -> capac = drv_tab[GET_DTYPE (val)].size;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
565
NOVA/nova_doc.txt
Normal file
565
NOVA/nova_doc.txt
Normal file
|
@ -0,0 +1,565 @@
|
|||
To: Users
|
||||
From: Bob Supnik
|
||||
Subj: Nova Simulator Usage
|
||||
Date: 1-Dec-01
|
||||
|
||||
COPYRIGHT NOTICE
|
||||
|
||||
The following copyright notice applies to both the SIMH source and binary:
|
||||
|
||||
Original code published in 1993-2001, written by Robert M Supnik
|
||||
Copyright (c) 1993-2001, Robert M Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation
|
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
and/or sell copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
Except as contained in this notice, the name of Robert M Supnik shall not
|
||||
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
This memorandum documents the Nova simulator.
|
||||
|
||||
|
||||
1. Simulator Files
|
||||
|
||||
sim/ sim_defs.h
|
||||
sim_sock.h
|
||||
sim_tmxr.h
|
||||
scp.c
|
||||
scp_tty.c
|
||||
sim_rev.c
|
||||
sim_sock.c
|
||||
sim_tmxr.c
|
||||
|
||||
sim/nova/ nova_defs.h
|
||||
nova_cpu.c
|
||||
nova_clk.c
|
||||
nova_dkp.c
|
||||
nova_dsk.c
|
||||
nova_lp.c
|
||||
nova_mta.c
|
||||
nova_plt.c
|
||||
nova_sys.c
|
||||
nova_tt.c
|
||||
nova_tt1.c
|
||||
|
||||
2. Nova Features
|
||||
|
||||
The Nova simulator is configured as follows:
|
||||
|
||||
device simulates
|
||||
name(s)
|
||||
|
||||
CPU Nova CPU with 32KW of memory
|
||||
- hardware multiply/divide
|
||||
PTR,PTP paper tape reader/punch
|
||||
TTI,TTO console terminal
|
||||
TTI1,TTO1 second terminal
|
||||
LPT line printer
|
||||
PLT plotter
|
||||
CLK real-time clock
|
||||
DK head-per-track disk controller
|
||||
DP moving head disk controller with four drives
|
||||
MT magnetic tape controller with eight drives
|
||||
|
||||
The TTI1/TTO1, PLT, DK, DP, and MT devices can be DISABLEd.
|
||||
|
||||
The Nova simulator implements these unique stop conditions:
|
||||
|
||||
- reference to undefined I/O device, and STOP_DEV is set
|
||||
- more than INDMAX indirect addresses are detected during
|
||||
an interrupt
|
||||
- more than INDMAX indirect addresses are detected during
|
||||
memory reference address decoding
|
||||
|
||||
The Nova loader supports standard binary format tapes. The DUMP command
|
||||
is not implemented.
|
||||
|
||||
2.1 CPU
|
||||
|
||||
The only CPU options are the presence of the optional instructions
|
||||
and the size of main memory.
|
||||
|
||||
SET CPU NOVA4 enable Nova4 instructions
|
||||
SET CPU NOVA3 enable Nova3 instructions
|
||||
SET CPU MDV enable multiply/divide
|
||||
SET CPU NONE disable all optional instructions
|
||||
SET CPU 4K set memory size = 4K
|
||||
SET CPU 8K set memory size = 8K
|
||||
SET CPU 12K set memory size = 12K
|
||||
SET CPU 16K set memory size = 16K
|
||||
SET CPU 20K set memory size = 20K
|
||||
SET CPU 24K set memory size = 24K
|
||||
SET CPU 28K set memory size = 28K
|
||||
SET CPU 32K set memory size = 32K
|
||||
|
||||
(MDV = unsigned multiply/divide instructions)
|
||||
(Nova 3 = unsigned multiply/divide, stack, trap instructions)
|
||||
(Nova 4 = unsigned and signed multiply/divide, stack, byte, trap instructions)
|
||||
|
||||
If memory size is being reduced, and the memory being truncated contains
|
||||
non-zero data, the simulator asks for confirmation. Data in the truncated
|
||||
portion of memory is lost. Initial memory size is 32K.
|
||||
|
||||
CPU registers include the visible state of the processor as well as the
|
||||
control registers for the interrupt system.
|
||||
|
||||
name size comments
|
||||
|
||||
PC 15 program counter
|
||||
AC0..AC3 16 accumulators 0..3
|
||||
C 1 carry
|
||||
SR 16 front panel switches
|
||||
PI 16 priority interrupt mask
|
||||
ION 1 interrupt enable
|
||||
ION_DELAY 1 interrupt enable delay for ION
|
||||
PWR 1 power fail interrupt
|
||||
INT 15 interrupt pending flags
|
||||
BUSY 15 device busy flags
|
||||
DONE 15 device done flags
|
||||
DISABLE 15 device interrupt disable flags
|
||||
STOP_DEV 1 stop on undefined IOT
|
||||
INDMAX 15 maximum number of nested indirects
|
||||
OLDPC 15 PC prior to last JMP, JMS, or interrupt
|
||||
WRU 8 interrupt character
|
||||
|
||||
2.2 Programmed I/O Devices
|
||||
|
||||
2.2.1 Paper Tape Reader (PTR)
|
||||
|
||||
The paper tape reader (PTR) reads data from a disk file. The POS
|
||||
register specifies the number of the next data item to be read. Thus,
|
||||
by changing POS, the user can backspace or advance the reader.
|
||||
|
||||
The paper tape reader implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
BUF 8 last data item processed
|
||||
BUSY 1 device busy flag
|
||||
DONE 1 device done flag
|
||||
DISABLE 1 interrupt disable flag
|
||||
INT 1 interrupt pending flag
|
||||
POS 31 position in the input file
|
||||
TIME 24 time from I/O initiation to interrupt
|
||||
STOP_IOE 1 stop on I/O error
|
||||
|
||||
Error handling is as follows:
|
||||
|
||||
error STOP_IOE processed as
|
||||
|
||||
not attached 1 report error and stop
|
||||
0 out of tape or paper
|
||||
|
||||
end of file 1 report error and stop
|
||||
0 out of tape or paper
|
||||
|
||||
OS I/O error x report error and stop
|
||||
|
||||
2.2.2 Paper Tape Punch (PTP)
|
||||
|
||||
The paper tape punch (PTP) writes data to a disk file. The POS
|
||||
register specifies the number of the next data item to be written.
|
||||
Thus, by changing POS, the user can backspace or advance the punch.
|
||||
|
||||
The paper tape punch implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
BUF 8 last data item processed
|
||||
BUSY 1 device busy flag
|
||||
DONE 1 device done flag
|
||||
DISABLE 1 interrupt disable flag
|
||||
INT 1 interrupt pending flag
|
||||
POS 31 position in the output file
|
||||
TIME 24 time from I/O initiation to interrupt
|
||||
STOP_IOE 1 stop on I/O error
|
||||
|
||||
Error handling is as follows:
|
||||
|
||||
error STOP_IOE processed as
|
||||
|
||||
not attached 1 report error and stop
|
||||
0 out of tape or paper
|
||||
|
||||
OS I/O error x report error and stop
|
||||
|
||||
2.2.3 Terminal Input (TTI)
|
||||
|
||||
The terminal input polls the console keyboard for input. Terminal
|
||||
input options include the ability to set ANSI mode or limited Dasher
|
||||
compatibility mode:
|
||||
|
||||
SET TTI ANSI normal mode
|
||||
SET TTI DASHER Dasher mode
|
||||
|
||||
Setting either TTI or TTO changes both devices. In Dasher mode, carriage
|
||||
return is changed to newline on input, and ^X is changed to backspace.
|
||||
|
||||
The terminal input implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
BUF 8 last data item processed
|
||||
BUSY 1 device busy flag
|
||||
DONE 1 device done flag
|
||||
DISABLE 1 interrupt disable flag
|
||||
INT 1 interrupt pending flag
|
||||
POS 31 number of characters input
|
||||
TIME 24 keyboard polling interval
|
||||
|
||||
2.2.4 Terminal Output (TTO)
|
||||
|
||||
The terminal output writes to the simulator console window. Terminal
|
||||
output options include the the ability to set ANSI mode or limited
|
||||
Dasher compatibility mode:
|
||||
|
||||
SET TTO ANSI normal mode
|
||||
SET TTO DASHER Dasher mode
|
||||
|
||||
Setting either TTI or TTO changes both devices. In Dasher mode, carriage
|
||||
return is changed to newline on input, and ^X is changed to backspace.
|
||||
|
||||
The terminal output implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
BUF 8 last data item processed
|
||||
BUSY 1 device busy flag
|
||||
DONE 1 device done flag
|
||||
DISABLE 1 interrupt disable flag
|
||||
INT 1 interrupt pending flag
|
||||
POS 31 number of characters output
|
||||
TIME 24 time from I/O initiation to interrupt
|
||||
|
||||
2.2.5 Line Printer (LPT)
|
||||
|
||||
The line printer (LPT) writes data to a disk file. The POS register
|
||||
specifies the number of the next data item to be written. Thus,
|
||||
by changing POS, the user can backspace or advance the printer.
|
||||
|
||||
The line printer implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
BUF 8 last data item processed
|
||||
BUSY 1 device busy flag
|
||||
DONE 1 device done flag
|
||||
DISABLE 1 interrupt disable flag
|
||||
INT 1 interrupt pending flag
|
||||
POS 31 position in the output file
|
||||
TIME 24 time from I/O initiation to interrupt
|
||||
STOP_IOE 1 stop on I/O error
|
||||
|
||||
Error handling is as follows:
|
||||
|
||||
error STOP_IOE processed as
|
||||
|
||||
not attached 1 report error and stop
|
||||
0 out of paper
|
||||
|
||||
OS I/O error x report error and stop
|
||||
|
||||
2.2.6 Real-Time Clock (CLK)
|
||||
|
||||
The real-time clock (CLK) implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
SELECT 2 selected clock interval
|
||||
BUSY 1 device busy flag
|
||||
DONE 1 device done flag
|
||||
DISABLE 1 interrupt disable flag
|
||||
INT 1 interrupt pending flag
|
||||
TIME0 24 clock frequency, select = 0
|
||||
TIME1 24 clock frequency, select = 1
|
||||
TIME2 24 clock frequency, select = 2
|
||||
TIME3 24 clock frequency, select = 3
|
||||
|
||||
The real-time clock autocalibrates; the clock interval is adjusted up or
|
||||
down so that the clock tracks actual elapsed time.
|
||||
|
||||
2.2.7 Plotter (PTP)
|
||||
|
||||
The plotter (PLT) writes data to a disk file. The POS register
|
||||
specifies the number of the next data item to be written. Thus,
|
||||
by changing POS, the user can backspace or advance the plotter.
|
||||
|
||||
The plotter implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
BUF 8 last data item processed
|
||||
BUSY 1 device busy flag
|
||||
DONE 1 device done flag
|
||||
DISABLE 1 interrupt disable flag
|
||||
INT 1 interrupt pending flag
|
||||
POS 31 position in the output file
|
||||
TIME 24 time from I/O initiation to interrupt
|
||||
STOP_IOE 1 stop on I/O error
|
||||
|
||||
Error handling is as follows:
|
||||
|
||||
error STOP_IOE processed as
|
||||
|
||||
not attached 1 report error and stop
|
||||
0 out of tape or paper
|
||||
|
||||
OS I/O error x report error and stop
|
||||
|
||||
2.2.8 Second Terminal (TTI1, TTO1)
|
||||
|
||||
The second terminal consists of two independent devices, TTI1 and TTO1.
|
||||
The additional terminal performs input and output through a Telnet session
|
||||
connecting into a user-specified port. The ATTACH command specifies the
|
||||
port to be used:
|
||||
|
||||
ATTACH TTI1 <port>(cr) -- set up listening port
|
||||
|
||||
where port is a decimal number between 1 and 65535 that is not being used
|
||||
for other TCP/IP activities.
|
||||
|
||||
Once TTI1 is attached and the simulator is running, the terminal listens
|
||||
for a connection on the specified port. It assumes that the incoming
|
||||
connection is a Telnet connection. The connection remain opens until
|
||||
disconnected by the Telnet client, or by a DETACH TTI1 command.
|
||||
|
||||
The second terminal has two options, recognized on both devices, for
|
||||
setting limited Dasher-compatibility mode or ANSI mode:
|
||||
|
||||
SET TTI1 ANSI normal mode
|
||||
SET TTI1 DASHER Dasher mode
|
||||
SET TTO1 ANSI normal mode
|
||||
SET TTO1 DASHER Dasher mode
|
||||
|
||||
Setting either TTI1 or TTO1 changes both devices. In Dasher mode, carriage
|
||||
return is changed to newline on input, and ^X is changed to backspace.
|
||||
|
||||
The SHOW TTI1 LINESTATUS command displays the current connection to the
|
||||
second terminal.
|
||||
|
||||
The second terminal input implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
BUF 8 last data item processed
|
||||
BUSY 1 device busy flag
|
||||
DONE 1 device done flag
|
||||
DISABLE 1 interrupt disable flag
|
||||
INT 1 interrupt pending flag
|
||||
POS 31 number of characters input
|
||||
TIME 24 keyboard polling interval
|
||||
|
||||
The second terminal output implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
BUF 8 last data item processed
|
||||
BUSY 1 device busy flag
|
||||
DONE 1 device done flag
|
||||
DISABLE 1 interrupt disable flag
|
||||
INT 1 interrupt pending flag
|
||||
POS 31 number of characters output
|
||||
TIME 24 time from I/O initiation to interrupt
|
||||
|
||||
2.3 Fixed Head Disk (DK)
|
||||
|
||||
The fixed head disk controller implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
STAT 16 status
|
||||
DA 16 disk address
|
||||
MA 16 memory address
|
||||
BUSY 1 device busy flag
|
||||
DONE 1 device done flag
|
||||
DISABLE 1 device disable flag
|
||||
INT 1 interrupt pending flag
|
||||
WLK 8 write lock switches
|
||||
TIME 24 rotational delay, per sector
|
||||
STOP_IOE 1 stop on I/O error
|
||||
|
||||
The fixed head disk controller supports the BOOT command.
|
||||
|
||||
Error handling is as follows:
|
||||
|
||||
error STOP_IOE processed as
|
||||
|
||||
not attached 1 report error and stop
|
||||
0 disk not ready
|
||||
|
||||
Fixed head disk data files are buffered in memory; therefore, end of file
|
||||
and OS I/O errors cannot occur.
|
||||
|
||||
2.4 Moving Head Disk (DP)
|
||||
|
||||
Moving head disk options include the ability to make units write enabled or
|
||||
write locked, and to select the type of drive:
|
||||
|
||||
SET DPn LOCKED set unit n write locked
|
||||
SET DPn ENABLED set unit n write enabled
|
||||
SET DPn FLOPPY set unit n to floppy disk
|
||||
SET DPn D31 set unit n to Diablo 31
|
||||
SET DPn D44 set unit n to Diablo 44
|
||||
SET DPn C111 set unit n to Century 111
|
||||
SET DPn C114 set unit n to Century 114
|
||||
SET DPn 6225 set unit n to 6225
|
||||
SET DPn 6099 set unit n to 6099
|
||||
SET DPn 6227 set unit n to 6227
|
||||
SET DPn 6070 set unit n to 6070
|
||||
SET DPn 6103 set unit n to 6103
|
||||
SET DPn 4231 set unit n to 4231
|
||||
|
||||
Units can also be REMOVEd or ADDed to the configuration. The moving head
|
||||
disk controller supports the BOOT command.
|
||||
|
||||
All drives have 256 16b words per sector. The other disk parameters are:
|
||||
|
||||
drive cylinders surfaces sectors size (MW) DG models
|
||||
|
||||
floppy 77 1 8 .158 6038
|
||||
D31 203 2 12 1.247 4047, 4237, 4238
|
||||
D44 408 4 12 5.014 4234, 6045
|
||||
C111 203 10 6 3.118 4048
|
||||
C114 203 20 12 12.472 4057, 2314
|
||||
6225 20 2 245 2.508
|
||||
6099 32 4 192 6.291
|
||||
6227 20 6 245 7.526
|
||||
6070 24 4 408 10.027
|
||||
6103 32 8 192 12.583
|
||||
4231 23 19 411 45.979
|
||||
|
||||
The moving head disk controller implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
FCCY 16 flags, command, cylinder
|
||||
USSC 16 unit, surface, sector, count
|
||||
STAT 16 status
|
||||
MA 16 memory address
|
||||
BUSY 1 device busy flag
|
||||
DONE 1 device done flag
|
||||
DISABLE 1 interrupt disable flag
|
||||
INT 1 interrupt pending flag
|
||||
STIME 24 seek time, per cylinder
|
||||
RTIME 24 rotational delay
|
||||
|
||||
Error handling is as follows:
|
||||
|
||||
error processed as
|
||||
|
||||
not attached disk not ready
|
||||
|
||||
end of file assume rest of disk is zero
|
||||
|
||||
OS I/O error report error and stop
|
||||
|
||||
2.5 Magnetic Tape (MT)
|
||||
|
||||
Magnetic tape options include the ability to make units write enabled or
|
||||
or write locked.
|
||||
|
||||
SET MTn LOCKED set unit n write locked
|
||||
SET MTn ENABLED set unit n write enabled
|
||||
|
||||
Units can also be REMOVEd or ADDed to the configuration. The magnetic
|
||||
tape controller supports the BOOT command.
|
||||
|
||||
The magnetic tape controller implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
CU 16 command, unit
|
||||
MA 16 memory address
|
||||
WC 16 word count
|
||||
STA1 16 status word 1
|
||||
STA2 16 status word 2
|
||||
EP 1 extended polling mode (not supported)
|
||||
BUSY 1 device busy flag
|
||||
DONE 1 device done flag
|
||||
DISABLE 1 interrupt disable flag
|
||||
INT 1 interrupt pending flag
|
||||
STOP_IOE 1 stop on I/O error
|
||||
CTIME 24 controller delay
|
||||
RTIME 24 record delay
|
||||
UST[0:7] 32 unit status, units 0-7
|
||||
POS[0:7] 31 position, units 0-7
|
||||
|
||||
Error handling is as follows:
|
||||
|
||||
error processed as
|
||||
|
||||
not attached tape not ready
|
||||
|
||||
end of file (read or space) end of physical tape
|
||||
(write) ignored
|
||||
|
||||
OS I/O error report error and stop
|
||||
|
||||
2.6 Symbolic Display and Input
|
||||
|
||||
The Nova simulator implements symbolic display and input. Display is
|
||||
controlled by command line switches:
|
||||
|
||||
-a display as ASCII character
|
||||
-c display as two character ASCII string
|
||||
-m display instruction mnemonics
|
||||
|
||||
Input parsing is controlled by the first character typed in or by command
|
||||
line switches:
|
||||
|
||||
' or -a ASCII character
|
||||
" or -c two character ASCII string
|
||||
alphabetic instruction mnemonic
|
||||
numeric octal number
|
||||
|
||||
Instruction input uses standard Nova assembler syntax. There are three
|
||||
instruction classes: memory reference, IOT, and operate.
|
||||
|
||||
Memory reference instructions have the format
|
||||
|
||||
memref {ac,}{@}address{,index}
|
||||
|
||||
LDA and STA require an initial register; ISZ, DSZ, JSR, and JMP do not.
|
||||
The syntax for addresses and indices is as follows:
|
||||
|
||||
syntax mode displacement comments
|
||||
|
||||
0 <= n < 0400 0 n
|
||||
{+/-}n >= 0400 1 {+/-}n - PC must be in range [-200, 177]
|
||||
invalid on disk
|
||||
.+/-n 1 {+/-}n must be in range [-200, 177]
|
||||
{+/-}n,2 2 {+/-}n must be in range [-200, 177]
|
||||
{+/-}n,3 3 {+/-}n must be in range [-200, 177]
|
||||
|
||||
IOT instructions have one of four formats
|
||||
|
||||
syntax example
|
||||
|
||||
iot HALT
|
||||
iot reg INTA
|
||||
iot device SKPDN
|
||||
iot reg,device DOAS
|
||||
|
||||
Devices may be specified as mnemonics or as numbers in the range 0 - 077.
|
||||
|
||||
Operate instructions have the format
|
||||
|
||||
opcode{#} reg,reg{,skip}
|
||||
|
||||
In all Nova instructions, blanks may be substituted for commas as field
|
||||
delimiters.
|
|
@ -25,6 +25,8 @@
|
|||
|
||||
mta magnetic tape
|
||||
|
||||
30-Nov-01 RMS Added read only unit, extended SET/SHOW support
|
||||
24-Nov-01 RMS Changed POS, USTAT, FLG to an array
|
||||
26-Apr-01 RMS Added device enable/disable support
|
||||
18-Apr-01 RMS Changed to rewind tape before boot
|
||||
10-Dec-00 RMS Added Eclipse support from Charles Owen
|
||||
|
@ -54,12 +56,13 @@
|
|||
|
||||
#define MTA_NUMDR 8 /* #drives */
|
||||
#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */
|
||||
#define UNIT_WLK (1 << UNIT_V_WLK)
|
||||
#define UNIT_W_UF 2 /* saved flags width */
|
||||
#define UNIT_WLK 1 << UNIT_V_WLK
|
||||
#define USTAT u3 /* unit status */
|
||||
#define UNUM u4 /* unit number */
|
||||
#define DTSIZE (1 << 14) /* max data xfer */
|
||||
#define DTMASK (DTSIZE - 1)
|
||||
#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */
|
||||
|
||||
/* Command/unit */
|
||||
|
||||
|
@ -149,7 +152,7 @@ t_stat mta_attach (UNIT *uptr, char *cptr);
|
|||
t_stat mta_detach (UNIT *uptr);
|
||||
int32 mta_updcsta (UNIT *uptr);
|
||||
void mta_upddsta (UNIT *uptr, int32 newsta);
|
||||
t_stat mta_vlock (UNIT *uptr, int32 val);
|
||||
t_stat mta_vlock (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
#if defined (ECLIPSE)
|
||||
extern int32 MapAddr (int32 map, int32 addr);
|
||||
#else
|
||||
|
@ -169,14 +172,14 @@ static const int ctype[32] = { /* c vs r timing */
|
|||
*/
|
||||
|
||||
UNIT mta_unit[] = {
|
||||
{ UDATA (&mta_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mta_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mta_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mta_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mta_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mta_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mta_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mta_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) } };
|
||||
{ UDATA (&mta_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) },
|
||||
{ UDATA (&mta_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) },
|
||||
{ UDATA (&mta_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) },
|
||||
{ UDATA (&mta_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) },
|
||||
{ UDATA (&mta_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) },
|
||||
{ UDATA (&mta_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) },
|
||||
{ UDATA (&mta_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) },
|
||||
{ UDATA (&mta_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) } };
|
||||
|
||||
REG mta_reg[] = {
|
||||
{ ORDATA (CU, mta_cu, 16) },
|
||||
|
@ -191,38 +194,11 @@ REG mta_reg[] = {
|
|||
{ FLDATA (INT, int_req, INT_V_MTA) },
|
||||
{ DRDATA (CTIME, mta_cwait, 24), PV_LEFT },
|
||||
{ DRDATA (RTIME, mta_rwait, 24), PV_LEFT },
|
||||
{ ORDATA (UST0, mta_unit[0].USTAT, 32) },
|
||||
{ ORDATA (UST1, mta_unit[1].USTAT, 32) },
|
||||
{ ORDATA (UST2, mta_unit[2].USTAT, 32) },
|
||||
{ ORDATA (UST3, mta_unit[3].USTAT, 32) },
|
||||
{ ORDATA (UST4, mta_unit[4].USTAT, 32) },
|
||||
{ ORDATA (UST5, mta_unit[5].USTAT, 32) },
|
||||
{ ORDATA (UST6, mta_unit[6].USTAT, 32) },
|
||||
{ ORDATA (UST7, mta_unit[7].USTAT, 32) },
|
||||
{ DRDATA (POS0, mta_unit[0].pos, 31), REG_RO + PV_LEFT },
|
||||
{ DRDATA (POS1, mta_unit[1].pos, 31), REG_RO + PV_LEFT },
|
||||
{ DRDATA (POS2, mta_unit[2].pos, 31), REG_RO + PV_LEFT },
|
||||
{ DRDATA (POS3, mta_unit[3].pos, 31), REG_RO + PV_LEFT },
|
||||
{ DRDATA (POS4, mta_unit[4].pos, 31), REG_RO + PV_LEFT },
|
||||
{ DRDATA (POS5, mta_unit[5].pos, 31), REG_RO + PV_LEFT },
|
||||
{ DRDATA (POS6, mta_unit[6].pos, 31), REG_RO + PV_LEFT },
|
||||
{ DRDATA (POS7, mta_unit[7].pos, 31), REG_RO + PV_LEFT },
|
||||
{ GRDATA (FLG0, mta_unit[0].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ GRDATA (FLG1, mta_unit[1].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ GRDATA (FLG2, mta_unit[2].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ GRDATA (FLG3, mta_unit[3].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ GRDATA (FLG4, mta_unit[4].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ GRDATA (FLG5, mta_unit[5].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ GRDATA (FLG6, mta_unit[6].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ GRDATA (FLG7, mta_unit[7].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ URDATA (UST, mta_unit[0].USTAT, 8, 32, 0, MTA_NUMDR, 0) },
|
||||
{ URDATA (POS, mta_unit[0].pos, 8, 31, 0,
|
||||
MTA_NUMDR, REG_RO | PV_LEFT) },
|
||||
{ URDATA (FLG, mta_unit[0].flags, 8, UNIT_W_UF, UNIT_V_UF - 1,
|
||||
MTA_NUMDR, REG_HRO) },
|
||||
{ FLDATA (*DEVENB, iot_enb, INT_V_MTA), REG_HRO },
|
||||
{ NULL } };
|
||||
|
||||
|
@ -341,7 +317,7 @@ if ((uptr -> flags & UNIT_ATT) == 0) { /* not attached? */
|
|||
mta_upddsta (uptr, 0); /* unit off line */
|
||||
mta_sta = mta_sta | STA_ILL; } /* illegal operation */
|
||||
|
||||
else if ((uptr -> flags & UNIT_WLK) && /* write locked? */
|
||||
else if ((uptr -> flags & UNIT_WPRT) && /* write locked? */
|
||||
((c == CU_WRITE) || (c == CU_WREOF) || (c == CU_ERASE))) {
|
||||
mta_upddsta (uptr, uptr -> USTAT | STA_WLK | STA_RDY);
|
||||
mta_sta = mta_sta | STA_ILL; } /* illegal operation */
|
||||
|
@ -526,7 +502,7 @@ for (u = 0; u < MTA_NUMDR; u++) { /* loop thru units */
|
|||
uptr -> UNUM = u;
|
||||
if (uptr -> flags & UNIT_ATT) uptr -> USTAT = STA_RDY |
|
||||
(uptr -> USTAT & STA_PEM) |
|
||||
((uptr -> flags & UNIT_WLK)? STA_WLK: 0) |
|
||||
((uptr -> flags & UNIT_WPRT)? STA_WLK: 0) |
|
||||
((uptr -> pos)? 0: STA_BOT);
|
||||
else uptr -> USTAT = 0; }
|
||||
mta_updcsta (&mta_unit[0]); /* update status */
|
||||
|
@ -542,7 +518,7 @@ t_stat r;
|
|||
r = attach_unit (uptr, cptr);
|
||||
if (r != SCPE_OK) return r;
|
||||
if (!sim_is_active (uptr)) mta_upddsta (uptr, STA_RDY | STA_BOT | STA_PEM |
|
||||
((uptr -> flags & UNIT_WLK)? STA_WLK: 0));
|
||||
((uptr -> flags & UNIT_WPRT)? STA_WLK: 0));
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -556,7 +532,7 @@ return detach_unit (uptr);
|
|||
|
||||
/* Write lock/unlock validate routine */
|
||||
|
||||
t_stat mta_vlock (UNIT *uptr, int32 val)
|
||||
t_stat mta_vlock (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
if ((uptr -> flags & UNIT_ATT) && val)
|
||||
mta_upddsta (uptr, uptr -> USTAT | STA_WLK);
|
|
@ -25,6 +25,8 @@
|
|||
|
||||
ptr paper tape reader
|
||||
ptp paper tape punch
|
||||
|
||||
29-Nov-01 RMS Added read only unit support
|
||||
*/
|
||||
|
||||
#include "nova_defs.h"
|
||||
|
@ -44,7 +46,8 @@ t_stat ptp_reset (DEVICE *dptr);
|
|||
*/
|
||||
|
||||
UNIT ptr_unit = {
|
||||
UDATA (&ptr_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_IN_WAIT };
|
||||
UDATA (&ptr_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0),
|
||||
SERIAL_IN_WAIT };
|
||||
|
||||
REG ptr_reg[] = {
|
||||
{ ORDATA (BUF, ptr_unit.buf, 8) },
|
|
@ -26,6 +26,7 @@
|
|||
tti terminal input
|
||||
tto terminal output
|
||||
|
||||
30-Nov-01 RMS Added extended SET/SHOW support
|
||||
17-Sep-01 RMS Removed multiconsole support
|
||||
07-Sep-01 RMS Moved function prototypes
|
||||
31-May-01 RMS Added multiconsole support
|
||||
|
@ -40,7 +41,7 @@ t_stat tti_svc (UNIT *uptr);
|
|||
t_stat tto_svc (UNIT *uptr);
|
||||
t_stat tti_reset (DEVICE *dptr);
|
||||
t_stat tto_reset (DEVICE *dptr);
|
||||
t_stat ttx_setmod (UNIT *uptr, int32 value);
|
||||
t_stat ttx_setmod (UNIT *uptr, int32 val, char *cptr);
|
||||
|
||||
/* TTI data structures
|
||||
|
||||
|
@ -200,9 +201,9 @@ sim_cancel (&tto_unit); /* deactivate unit */
|
|||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat ttx_setmod (UNIT *uptr, int32 value)
|
||||
t_stat ttx_setmod (UNIT *uptr, int32 val, char *cptr)
|
||||
{
|
||||
tti_unit.flags = (tti_unit.flags & ~UNIT_DASHER) | value;
|
||||
tto_unit.flags = (tto_unit.flags & ~UNIT_DASHER) | value;
|
||||
tti_unit.flags = (tti_unit.flags & ~UNIT_DASHER) | val;
|
||||
tto_unit.flags = (tto_unit.flags & ~UNIT_DASHER) | val;
|
||||
return SCPE_OK;
|
||||
}
|
|
@ -27,6 +27,7 @@
|
|||
tti1 second terminal input
|
||||
tto1 second terminal output
|
||||
|
||||
30-Nov-01 RMS Added extended SET/SHOW support
|
||||
17-Sep-01 RMS Changed to use terminal multiplexor library
|
||||
07-Sep-01 RMS Moved function prototypes
|
||||
31-May-01 RMS Added multiconsole support
|
||||
|
@ -49,10 +50,10 @@ t_stat tti1_svc (UNIT *uptr);
|
|||
t_stat tto1_svc (UNIT *uptr);
|
||||
t_stat tti1_reset (DEVICE *dptr);
|
||||
t_stat tto1_reset (DEVICE *dptr);
|
||||
t_stat ttx1_setmod (UNIT *uptr, int32 value);
|
||||
t_stat ttx1_setmod (UNIT *uptr, int32 val, char *cptr);
|
||||
t_stat tti1_attach (UNIT *uptr, char *cptr);
|
||||
t_stat tti1_detach (UNIT *uptr);
|
||||
t_stat tti1_status (UNIT *uptr, FILE *st);
|
||||
t_stat tti1_status (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||
|
||||
/* TTI1 data structures
|
||||
|
||||
|
@ -77,9 +78,11 @@ REG tti1_reg[] = {
|
|||
{ NULL } };
|
||||
|
||||
MTAB ttx1_mod[] = {
|
||||
{ UNIT_ATT, UNIT_ATT, "line status:", NULL, &tti1_status },
|
||||
{ UNIT_DASHER, 0, "ANSI", "ANSI", &ttx1_setmod },
|
||||
{ UNIT_DASHER, UNIT_DASHER, "Dasher", "DASHER", &ttx1_setmod },
|
||||
{ UNIT_ATT, UNIT_ATT, "line status", NULL, NULL, &tti1_status },
|
||||
{ MTAB_XTD | MTAB_VDV | MTAB_VUN | MTAB_NMO, 0, "LINE", NULL,
|
||||
NULL, &tti1_status, NULL },
|
||||
{ 0 } };
|
||||
|
||||
DEVICE tti1_dev = {
|
||||
|
@ -233,10 +236,10 @@ sim_cancel (&tto1_unit); /* deactivate unit */
|
|||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat ttx1_setmod (UNIT *uptr, int32 value)
|
||||
t_stat ttx1_setmod (UNIT *uptr, int32 val, char *cptr)
|
||||
{
|
||||
tti1_unit.flags = (tti1_unit.flags & ~UNIT_DASHER) | value;
|
||||
tto1_unit.flags = (tto1_unit.flags & ~UNIT_DASHER) | value;
|
||||
tti1_unit.flags = (tti1_unit.flags & ~UNIT_DASHER) | val;
|
||||
tto1_unit.flags = (tto1_unit.flags & ~UNIT_DASHER) | val;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
@ -266,7 +269,7 @@ return r;
|
|||
|
||||
/* Status routine */
|
||||
|
||||
t_stat tti1_status (UNIT *uptr, FILE *st)
|
||||
t_stat tti1_status (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||
{
|
||||
tmxr_fstatus (st, &tt1_ldsc, -1);
|
||||
return SCPE_OK;
|
|
@ -25,6 +25,8 @@
|
|||
|
||||
cpu PDP-1 central processor
|
||||
|
||||
07-Dec-01 RMS Revised to use breakpoint package
|
||||
30-Nov-01 RMS Added extended SET/SHOW support
|
||||
16-Dec-00 RMS Fixed bug in XCT address calculation
|
||||
14-Apr-99 RMS Changed t_addr to unsigned
|
||||
|
||||
|
@ -212,8 +214,6 @@
|
|||
|
||||
#include "pdp1_defs.h"
|
||||
|
||||
#define ILL_ADR_FLAG (1 << ASIZE)
|
||||
#define save_ibkpt (cpu_unit.u3)
|
||||
#define UNIT_V_MDV (UNIT_V_UF) /* mul/div */
|
||||
#define UNIT_MDV (1 << UNIT_V_MDV)
|
||||
#define UNIT_V_MSIZE (UNIT_V_UF+1) /* dummy mask */
|
||||
|
@ -238,15 +238,14 @@ int32 stop_inst = 0; /* stop on rsrv inst */
|
|||
int32 xct_max = 16; /* nested XCT limit */
|
||||
int32 ind_max = 16; /* nested ind limit */
|
||||
int32 old_PC = 0; /* old PC */
|
||||
int32 ibkpt_addr = ILL_ADR_FLAG | AMASK; /* breakpoint addr */
|
||||
extern UNIT *sim_clock_queue;
|
||||
extern int32 sim_int_char;
|
||||
extern int32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */
|
||||
|
||||
t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw);
|
||||
t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw);
|
||||
t_stat cpu_reset (DEVICE *dptr);
|
||||
t_stat cpu_svc (UNIT *uptr);
|
||||
t_stat cpu_set_size (UNIT *uptr, int32 value);
|
||||
extern int32 sim_int_char;
|
||||
extern UNIT *sim_clock_queue;
|
||||
t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
extern int32 ptr (int32 inst, int32 dev, int32 IO);
|
||||
extern int32 ptp (int32 inst, int32 dev, int32 IO);
|
||||
extern int32 tti (int32 inst, int32 dev, int32 IO);
|
||||
|
@ -297,7 +296,7 @@ int32 sc_map[512] = {
|
|||
cpu_mod CPU modifier list
|
||||
*/
|
||||
|
||||
UNIT cpu_unit = { UDATA (&cpu_svc, UNIT_FIX + UNIT_BINK, MAXMEMSIZE) };
|
||||
UNIT cpu_unit = { UDATA (NULL, UNIT_FIX + UNIT_BINK, MAXMEMSIZE) };
|
||||
|
||||
REG cpu_reg[] = {
|
||||
{ ORDATA (PC, PC, ASIZE) },
|
||||
|
@ -321,7 +320,6 @@ REG cpu_reg[] = {
|
|||
{ FLDATA (MDV, cpu_unit.flags, UNIT_V_MDV), REG_HRO },
|
||||
{ DRDATA (XCT_MAX, xct_max, 8), PV_LEFT + REG_NZ },
|
||||
{ DRDATA (IND_MAX, ind_max, 8), PV_LEFT + REG_NZ },
|
||||
{ ORDATA (BREAK, ibkpt_addr, ASIZE + 1) },
|
||||
{ ORDATA (WRU, sim_int_char, 8) },
|
||||
{ NULL } };
|
||||
|
||||
|
@ -379,10 +377,7 @@ if (sbs == (SB_ON | SB_RQ)) { /* interrupt? */
|
|||
extm = 0; /* extend off */
|
||||
OV = 0; } /* clear overflow */
|
||||
|
||||
if (PC == ibkpt_addr) { /* breakpoint? */
|
||||
save_ibkpt = ibkpt_addr; /* save ibkpt */
|
||||
ibkpt_addr = ibkpt_addr | ILL_ADR_FLAG; /* disable */
|
||||
sim_activate (&cpu_unit, 1); /* sched re-enable */
|
||||
if (sim_brk_summ && sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */
|
||||
reason = STOP_IBKPT; /* stop simulation */
|
||||
break; }
|
||||
|
||||
|
@ -741,7 +736,8 @@ extm = extm_init;
|
|||
ioh = ioc = 0;
|
||||
OV = 0;
|
||||
PF = 0;
|
||||
return cpu_svc (&cpu_unit);
|
||||
sim_brk_types = sim_brk_dflt = SWMASK ('E');
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Memory examine */
|
||||
|
@ -762,28 +758,19 @@ M[addr] = val & 0777777;
|
|||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Service breakpoint */
|
||||
|
||||
t_stat cpu_svc (UNIT *uptr)
|
||||
{
|
||||
if ((ibkpt_addr & ~ILL_ADR_FLAG) == save_ibkpt) ibkpt_addr = save_ibkpt;
|
||||
save_ibkpt = -1;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Change memory size */
|
||||
|
||||
t_stat cpu_set_size (UNIT *uptr, int32 value)
|
||||
t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
int32 mc = 0;
|
||||
t_addr i;
|
||||
|
||||
if ((value <= 0) || (value > MAXMEMSIZE) || ((value & 07777) != 0))
|
||||
if ((val <= 0) || (val > MAXMEMSIZE) || ((val & 07777) != 0))
|
||||
return SCPE_ARG;
|
||||
for (i = value; i < MEMSIZE; i++) mc = mc | M[i];
|
||||
for (i = val; i < MEMSIZE; i++) mc = mc | M[i];
|
||||
if ((mc != 0) && (!get_yn ("Really truncate memory [N]?", FALSE)))
|
||||
return SCPE_OK;
|
||||
MEMSIZE = value;
|
||||
MEMSIZE = val;
|
||||
for (i = MEMSIZE; i < MAXMEMSIZE; i++) M[i] = 0;
|
||||
return SCPE_OK;
|
||||
}
|
409
PDP1/pdp1_doc.txt
Normal file
409
PDP1/pdp1_doc.txt
Normal file
|
@ -0,0 +1,409 @@
|
|||
To: Users
|
||||
From: Bob Supnik
|
||||
Subj: PDP-1 Simulator Usage
|
||||
Date: 1-Dec-01
|
||||
|
||||
COPYRIGHT NOTICE
|
||||
|
||||
The following copyright notice applies to both the SIMH source and binary:
|
||||
|
||||
Original code published in 1993-2001, written by Robert M Supnik
|
||||
Copyright (c) 1993-2001, Robert M Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation
|
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
and/or sell copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
Except as contained in this notice, the name of Robert M Supnik shall not
|
||||
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
This memorandum documents the PDP-1 simulator.
|
||||
|
||||
|
||||
1. Simulator Files
|
||||
|
||||
sim/ sim_defs.h
|
||||
scp.c
|
||||
scp_tty.c
|
||||
sim_rev.c
|
||||
|
||||
sim/pdp1/ pdp1_defs.h
|
||||
pdp1_cpu.c
|
||||
pdp1_lp.c
|
||||
pdp1_stddev.c
|
||||
pdp1_sys.c
|
||||
|
||||
2. PDP-1 Features
|
||||
|
||||
The PDP-1 is configured as follows:
|
||||
|
||||
device simulates
|
||||
name(s)
|
||||
|
||||
CPU PDP-1 CPU with up to 64KW of memory
|
||||
PTR,PTP integral paper tape reader/punch
|
||||
TTI,TTO Flexowriter typewriter input/output
|
||||
LPT Type 62 line printer
|
||||
|
||||
The PDP-1 simulator implements the following unique stop conditions:
|
||||
|
||||
- an unimplemented instruction is decoded, and register
|
||||
STOP_INST is set
|
||||
- more than INDMAX indirect addresses are detected during
|
||||
memory reference address decoding
|
||||
- more than XCTMAX nested executes are detected during
|
||||
instruction execution
|
||||
- wait state entered, and no I/O operations outstanding
|
||||
(ie, no interrupt can ever occur)
|
||||
|
||||
The PDP-1 loader supports RIM format tapes. The DUMP command is not
|
||||
implemented.
|
||||
|
||||
2.1 CPU
|
||||
|
||||
The only CPU options are the presence of hardware multiply/divide and the
|
||||
size of main memory.
|
||||
|
||||
SET CPU MDV enable multiply/divide
|
||||
SET CPU NOMDV disable multiply/divide
|
||||
SET CPU 4K set memory size = 4K
|
||||
SET CPU 8K set memory size = 8K
|
||||
SET CPU 12K set memory size = 12K
|
||||
SET CPU 16K set memory size = 16K
|
||||
SET CPU 20K set memory size = 20K
|
||||
SET CPU 24K set memory size = 24K
|
||||
SET CPU 28K set memory size = 28K
|
||||
SET CPU 32K set memory size = 32K
|
||||
SET CPU 48K set memory size = 48K
|
||||
SET CPU 64K set memory size = 64K
|
||||
|
||||
If memory size is being reduced, and the memory being truncated contains
|
||||
non-zero data, the simulator asks for confirmation. Data in the truncated
|
||||
portion of memory is lost. Initial memory size is 64K.
|
||||
|
||||
CPU registers include the visible state of the processor as well as the
|
||||
control registers for the interrupt system.
|
||||
|
||||
name size comments
|
||||
|
||||
PC 16 program counter
|
||||
AC 18 accumulator
|
||||
IO 18 IO register
|
||||
OV 1 overflow flag
|
||||
PF 6 program flags<1:6>
|
||||
SS 6 sense switches<1:6>
|
||||
TW 18 test word (front panel switches)
|
||||
EXTM 1 extend mode
|
||||
IOSTA 18 IO status register
|
||||
SBON 1 sequence break enable
|
||||
SBRQ 1 sequence break request
|
||||
SBIP 1 sequence break in progress
|
||||
IOH 1 I/O halt in progress
|
||||
IOC 1 I/O continue
|
||||
OLDPC 16 PC prior to last transfer
|
||||
STOP_INST 1 stop on undefined instruction
|
||||
SBS_INIT 1 initial state of sequence break enable
|
||||
EXTM_INIT 1 initial state of extend mode
|
||||
WRU 8 interrupt character
|
||||
|
||||
2.2 Programmed I/O Devices
|
||||
|
||||
2.2.1 Paper Tape Reader (PTR)
|
||||
|
||||
The paper tape reader (PTR) reads data from or a disk file. The POS
|
||||
register specifies the number of the next data item to be read. Thus,
|
||||
by changing POS, the user can backspace or advance the reader.
|
||||
|
||||
The paper tape reader supports the BOOT command. BOOT PTR copies the
|
||||
RIM loader into memory and starts it running.
|
||||
|
||||
The paper tape reader implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
BUF 8 last data item processed
|
||||
DONE 1 device done flag
|
||||
RPLS 1 return restart pulse flag
|
||||
POS 31 position in the input file
|
||||
TIME 24 time from I/O initiation to interrupt
|
||||
STOP_IOE 1 stop on I/O error
|
||||
|
||||
Error handling is as follows:
|
||||
|
||||
error STOP_IOE processed as
|
||||
|
||||
not attached 1 report error and stop
|
||||
0 out of tape
|
||||
|
||||
end of file 1 report error and stop
|
||||
0 out of tape
|
||||
|
||||
OS I/O error x report error and stop
|
||||
|
||||
2.2.2 Paper Tape Punch (PTP)
|
||||
|
||||
The paper tape punch (PTP) writes data to a disk file. The POS
|
||||
register specifies the number of the next data item to be written.
|
||||
Thus, by changing POS, the user can backspace or advance the punch.
|
||||
|
||||
The paper tape punch implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
BUF 8 last data item processed
|
||||
DONE 1 device done flag
|
||||
RPLS 1 return restart pulse flag
|
||||
POS 31 position in the output file
|
||||
TIME 24 time from I/O initiation to interrupt
|
||||
STOP_IOE 1 stop on I/O error
|
||||
|
||||
Error handling is as follows:
|
||||
|
||||
error STOP_IOE processed as
|
||||
|
||||
not attached 1 report error and stop
|
||||
0 out of tape
|
||||
|
||||
OS I/O error x report error and stop
|
||||
|
||||
2.2.3 Terminal Input (TTI)
|
||||
|
||||
The terminal input (TTI) polls the console keyboard for input. It
|
||||
implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
BUF 8 last data item processed
|
||||
DONE 1 device done flag
|
||||
POS 31 number of characters input
|
||||
TIME 24 keyboard polling interval
|
||||
|
||||
2.2.4 Terminal Output (TTO)
|
||||
|
||||
The terminal output (TTO) writes to the simulator console window.
|
||||
It implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
BUF 8 last data item processed
|
||||
DONE 1 device done flag
|
||||
RPLS 1 return restart pulse flag
|
||||
POS 31 number of characters output
|
||||
TIME 24 time from I/O initiation to interrupt
|
||||
|
||||
2.2.5 Type 62 Line Printer (LPT)
|
||||
|
||||
The paper line printer (LPT) writes data to a disk file. The POS
|
||||
register specifies the number of the next data item to be written.
|
||||
Thus, by changing POS, the user can backspace or advance the printer.
|
||||
|
||||
The line printer implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
BUF 8 last data item processed
|
||||
PNT 1 printing done flag
|
||||
SPC 1 spacing done flag
|
||||
RPLS 1 return restart pulse flag
|
||||
BPTR 6 print buffer pointer
|
||||
POS 31 position in the output file
|
||||
TIME 24 time from I/O initiation to interrupt
|
||||
STOP_IOE 1 stop on I/O error
|
||||
LBUF[0:119] 8 line buffer
|
||||
|
||||
Error handling is as follows:
|
||||
|
||||
error STOP_IOE processed as
|
||||
|
||||
not attached 1 report error and stop
|
||||
0 out of tape or paper
|
||||
|
||||
OS I/O error x report error and stop
|
||||
|
||||
2.3 Symbolic Display and Input
|
||||
|
||||
The PDP-1 simulator implements symbolic display and input. Display is
|
||||
controlled by command line switches:
|
||||
|
||||
-a display as ASCII character
|
||||
-c display as FIODEC character string
|
||||
-m display instruction mnemonics
|
||||
|
||||
Input parsing is controlled by the first character typed in or by command
|
||||
line switches:
|
||||
|
||||
' or -a ASCII character
|
||||
" or -c three character FIODEC string
|
||||
alphabetic instruction mnemonic
|
||||
numeric octal number
|
||||
|
||||
Instruction input uses modified PDP-1 assembler syntax. There are six
|
||||
instruction classes: memory reference, shift, skip, operate, IOT, and
|
||||
LAW.
|
||||
|
||||
Memory reference instructions have the format
|
||||
|
||||
memref {I} address
|
||||
|
||||
where I signifies indirect reference. The address is an octal number in
|
||||
the range 0 - 0177777.
|
||||
|
||||
Shift instructions have the format
|
||||
|
||||
shift shift_count
|
||||
|
||||
The shift count is an octal number in the range 0-9.
|
||||
|
||||
Skip instructions consist of single mnemonics, eg, SZA, SZS4. Skip
|
||||
instructions may be or'd together
|
||||
|
||||
skip skip skip...
|
||||
|
||||
The sense of a skip can be inverted by including the mnemonic I.
|
||||
|
||||
Operate instructions consist of single mnemonics, eg, CLA, CLI. Operate
|
||||
instructions may be or'd together
|
||||
|
||||
opr opr opr...
|
||||
|
||||
IOT instructions consist of single mnemonics, eg, TYI, TYO. IOT
|
||||
instructions may include an octal numeric modifier or the modifier I:
|
||||
|
||||
iot modifier
|
||||
|
||||
The simulator does not check the legality of skip, operate, or IOT
|
||||
combinations.
|
||||
|
||||
Finally, the LAW instruction has the format
|
||||
|
||||
LAW {I} immediate
|
||||
|
||||
where immediate is in the range 0 to 07777.
|
||||
|
||||
2.4 Character Sets
|
||||
|
||||
The PDP-1's console was a Frieden Flexowriter; its character encoding
|
||||
was known as FIODEC. The PDP-1's line printer used a modified Hollerith
|
||||
character set. The following table provides equivalences between ASCII
|
||||
characters and the PDP-1's I/O devices. In the console table, UC stands
|
||||
for upper case.
|
||||
|
||||
PDP-1 PDP-1
|
||||
ASCII console line printer
|
||||
|
||||
000 - 007 none none
|
||||
bs 075 none
|
||||
tab 036 none
|
||||
012 - 014 none none
|
||||
cr 077 none
|
||||
016 - 037 none none
|
||||
space 000 000
|
||||
! {OR} UC+005 none
|
||||
" UC+001 none
|
||||
# {IMPLIES} UC+004 none
|
||||
$ none none
|
||||
% none none
|
||||
& {AND} UC+006 none
|
||||
' UC+002 none
|
||||
( 057 057
|
||||
) 055 055
|
||||
* {TIMES} UC+073 072
|
||||
+ UC+054 074
|
||||
, 033 033
|
||||
- 054 054
|
||||
. 073 073
|
||||
/ 021 021
|
||||
0 020 020
|
||||
1 001 001
|
||||
2 002 002
|
||||
3 003 003
|
||||
4 004 004
|
||||
5 005 005
|
||||
6 006 006
|
||||
7 007 007
|
||||
8 010 010
|
||||
9 011 011
|
||||
: none none
|
||||
; none none
|
||||
< UC+007 034
|
||||
= UC+033 053
|
||||
> UC+010 034
|
||||
? UC+021 037
|
||||
@ {MID DOT} 040 {MID DOT} 040
|
||||
A UC+061 061
|
||||
B UC+062 062
|
||||
C UC+063 063
|
||||
D UC+064 064
|
||||
E UC+065 065
|
||||
F UC+066 066
|
||||
G UC+067 067
|
||||
H UC+070 070
|
||||
I UC+071 071
|
||||
J UC+041 041
|
||||
K UC+042 042
|
||||
L UC+043 043
|
||||
M UC+044 044
|
||||
N UC+045 045
|
||||
O UC+046 046
|
||||
P UC+047 047
|
||||
Q UC+050 050
|
||||
R UC+051 051
|
||||
S UC+022 022
|
||||
T UC+023 023
|
||||
U UC+024 024
|
||||
V UC+025 025
|
||||
W UC+026 026
|
||||
X UC+027 027
|
||||
Y UC+030 030
|
||||
Z UC+031 031
|
||||
[ UC+057 none
|
||||
\ {OVERLINE} 056 {OVERLINE} 056
|
||||
] UC+055 none
|
||||
^ {UP ARROW} UC+011 {UP ARROW} 035
|
||||
_ UC+040 UC+040
|
||||
` {RT ARROW} UC+020 036
|
||||
a 061 none
|
||||
b 062 none
|
||||
c 063 none
|
||||
d 064 none
|
||||
e 065 none
|
||||
f 066 none
|
||||
g 067 none
|
||||
h 070 none
|
||||
i 071 none
|
||||
j 041 none
|
||||
k 042 none
|
||||
l 043 none
|
||||
m 044 none
|
||||
n 045 none
|
||||
o 046 none
|
||||
p 047 none
|
||||
q 050 none
|
||||
r 051 none
|
||||
s 022 none
|
||||
t 023 none
|
||||
u 024 none
|
||||
v 025 none
|
||||
w 026 none
|
||||
x 027 none
|
||||
y 030 none
|
||||
z 031 none
|
||||
{ none none
|
||||
| UC+056 076
|
||||
} none none
|
||||
~ UC+003 013
|
||||
del 075 none
|
|
@ -28,6 +28,7 @@
|
|||
tti keyboard
|
||||
tto teleprinter
|
||||
|
||||
29-Nov-01 RMS Added read only unit support
|
||||
07-Sep-01 RMS Moved function prototypes
|
||||
10-Jun-01 RMS Fixed comment
|
||||
30-Oct-00 RMS Standardized device naming
|
||||
|
@ -103,7 +104,8 @@ int32 ascii_to_fiodec[128] = {
|
|||
*/
|
||||
|
||||
UNIT ptr_unit = {
|
||||
UDATA (&ptr_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_IN_WAIT };
|
||||
UDATA (&ptr_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0),
|
||||
SERIAL_IN_WAIT };
|
||||
|
||||
REG ptr_reg[] = {
|
||||
{ ORDATA (BUF, ptr_unit.buf, 18) },
|
|
@ -25,6 +25,9 @@
|
|||
|
||||
cpu KS10 central processor
|
||||
|
||||
25-Dec-01 RMS Cleaned up sim_inst declarations
|
||||
07-Dec-01 RMS Revised to use new breakpoint package
|
||||
21-Nov-01 RMS Implemented ITS 1-proceed hack
|
||||
31-Aug-01 RMS Changed int64 to t_int64 for Windoze
|
||||
10-Aug-01 RMS Removed register in declarations
|
||||
17-Jul-01 RMS Moved function prototype
|
||||
|
@ -112,13 +115,19 @@
|
|||
pdp10_defs.h add interrupt request definition
|
||||
pdp10_ksio.c add I/O page linkages
|
||||
pdp10_sys.c add pointer to data structures to sim_devices
|
||||
|
||||
A note on ITS 1-proceed. The simulator follows the implementation
|
||||
on the KS10, keeping 1-proceed as a side flag (its_1pr) rather than
|
||||
as flags<8>. This simplifies the flag saving instructions, which
|
||||
don't have to clear flags<8> before saving it. Instead, the page
|
||||
fail and interrupt code must restore flags<8> from its_1pr. Unlike
|
||||
the KS10, the simulator will not lose the 1-proceed trap if the
|
||||
1-proceeded instructions clears 1-proceed.
|
||||
*/
|
||||
|
||||
#include "pdp10_defs.h"
|
||||
#include <setjmp.h>
|
||||
|
||||
#define ILL_ADR_FLAG (1 << VASIZE)
|
||||
#define save_ibkpt (cpu_unit.u3)
|
||||
#define UNIT_V_MSIZE (UNIT_V_T20V41 + 1) /* dummy mask */
|
||||
#define UNIT_MSIZE (1 << UNIT_V_MSIZE)
|
||||
|
||||
|
@ -126,9 +135,12 @@ d10 *M = NULL; /* memory */
|
|||
d10 acs[AC_NBLK * AC_NUM] = { 0 }; /* AC blocks */
|
||||
d10 *ac_cur, *ac_prv; /* AC cur, prv (dyn) */
|
||||
a10 epta, upta; /* proc tbl addr (dyn) */
|
||||
d10 last_inst = 0; /* most recent inst */
|
||||
a10 saved_PC = 0; /* scp: saved PC */
|
||||
d10 pager_word = 0; /* pager: error word */
|
||||
a10 pager_PC = 0; /* pager: saved PC */
|
||||
int32 pager_flags = 0; /* pager: trap flags */
|
||||
t_bool pager_pi = FALSE; /* pager: in pi seq */
|
||||
t_bool pager_tc = FALSE; /* pager: trap cycle */
|
||||
d10 ebr = 0; /* exec base reg */
|
||||
d10 ubr = 0; /* user base reg */
|
||||
d10 hsb = 0; /* halt status block */
|
||||
|
@ -152,22 +164,60 @@ int32 apr_flg = 0; /* apr flags */
|
|||
int32 apr_lvl = 0; /* apr level */
|
||||
int32 qintr = 0; /* interrupt pending */
|
||||
int32 flags = 0; /* flags */
|
||||
int32 its_1pr = 0; /* ITS 1-proceed */
|
||||
int32 stop_op0 = 0; /* stop on 0 */
|
||||
d10 pager_word = 0; /* pager error word */
|
||||
int32 rlog = 0; /* extend fixup log */
|
||||
int32 ind_max = 32; /* nested ind limit */
|
||||
int32 xct_max = 32; /* nested XCT limit */
|
||||
int32 astop_cpu = 0; /* address stop */
|
||||
a10 old_PC = 0; /* old PC */
|
||||
a10 ibkpt_addr = ILL_ADR_FLAG | AMASK; /* breakpoint addr */
|
||||
jmp_buf save_env;
|
||||
|
||||
extern int32 sim_int_char;
|
||||
extern int32 sim_interval;
|
||||
extern int32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */
|
||||
extern UNIT tim_unit;
|
||||
|
||||
/* Forward and external declarations */
|
||||
|
||||
t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw);
|
||||
t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw);
|
||||
t_stat cpu_reset (DEVICE *dptr);
|
||||
t_stat cpu_svc (UNIT *uptr);
|
||||
extern int32 sim_int_char;
|
||||
extern int32 sim_interval;
|
||||
d10 adjsp (d10 val, a10 ea);
|
||||
void ibp (a10 ea, int32 pflgs);
|
||||
d10 ldb (a10 ea, int32 pflgs);
|
||||
void dpb (d10 val, a10 ea, int32 pflgs);
|
||||
void adjbp (int32 ac, a10 ea, int32 pflgs);
|
||||
d10 add (d10 val, d10 mb);
|
||||
d10 sub (d10 val, d10 mb);
|
||||
void dadd (int32 ac, d10 *rs);
|
||||
void dsub (int32 ac, d10 *rs);
|
||||
int32 jffo (d10 val);
|
||||
d10 lsh (d10 val, a10 ea);
|
||||
d10 rot (d10 val, a10 ea);
|
||||
d10 ash (d10 val, a10 ea);
|
||||
void lshc (int32 ac, a10 ea);
|
||||
void rotc (int32 ac, a10 ea);
|
||||
void ashc (int32 ac, a10 ea);
|
||||
void circ (int32 ac, a10 ea);
|
||||
void blt (int32 ac, a10 ea, int32 pflgs);
|
||||
void bltu (int32 ac, a10 ea, int32 pflgs, int dir);
|
||||
a10 calc_ea (d10 inst, int32 prv);
|
||||
a10 calc_ioea (d10 inst, int32 prv);
|
||||
d10 calc_jrstfea (d10 inst, int32 pflgs);
|
||||
void pi_dismiss (void);
|
||||
void set_newflags (d10 fl, t_bool jrst);
|
||||
extern t_bool aprid (a10 ea, int32 prv);
|
||||
t_bool wrpi (a10 ea, int32 prv);
|
||||
t_bool rdpi (a10 ea, int32 prv);
|
||||
t_bool czpi (a10 ea, int32 prv);
|
||||
t_bool copi (a10 ea, int32 prv);
|
||||
t_bool wrapr (a10 ea, int32 prv);
|
||||
t_bool rdapr (a10 ea, int32 prv);
|
||||
t_bool czapr (a10 ea, int32 prv);
|
||||
t_bool coapr (a10 ea, int32 prv);
|
||||
int32 pi_eval (void);
|
||||
int32 test_int (void);
|
||||
void set_ac_display (d10 *acbase);
|
||||
|
||||
extern d10 Read (a10 ea, int32 prv); /* read, read check */
|
||||
extern d10 ReadM (a10 ea, int32 prv); /* read, write check */
|
||||
|
@ -180,9 +230,69 @@ extern t_bool AccViol (a10 ea, int32 prv, int32 mode); /* access check */
|
|||
extern void set_dyn_ptrs (void);
|
||||
extern a10 conmap (a10 ea, int32 mode, int32 sw);
|
||||
extern void fe_intr ();
|
||||
int32 pi_eval (void);
|
||||
int32 test_int (void);
|
||||
void set_ac_display (d10 *acbase);
|
||||
extern void dfad (int32 ac, d10 *rs, int32 inv);
|
||||
extern void dfmp (int32 ac, d10 *rs);
|
||||
extern void dfdv (int32 ac, d10 *rs);
|
||||
extern void dmul (int32 ac, d10 *rs);
|
||||
extern void ddiv (int32 ac, d10 *rs);
|
||||
extern void fix (int32 ac, d10 mb, t_bool rnd);
|
||||
extern d10 fad (d10 val, d10 mb, t_bool rnd, int32 inv);
|
||||
extern d10 fmp (d10 val, d10 mb, t_bool rnd);
|
||||
extern t_bool fdv (d10 val, d10 mb, d10 *rs, t_bool rnd);
|
||||
extern d10 fsc (d10 val, a10 ea);
|
||||
extern d10 fltr (d10 mb);
|
||||
extern int xtend (int32 ac, a10 ea, int32 pflgs);
|
||||
extern void xtcln (int32 rlog);
|
||||
extern d10 map (a10 ea, int32 prv);
|
||||
extern d10 imul (d10 val, d10 mb);
|
||||
extern t_bool idiv (d10 val, d10 mb, d10 *rs);
|
||||
extern void mul (d10 val, d10 mb, d10 *rs);
|
||||
extern t_bool divi (int32 ac, d10 mb, d10 *rs);
|
||||
extern t_bool io710 (int32 ac, a10 ea);
|
||||
extern t_bool io711 (int32 ac, a10 ea);
|
||||
extern d10 io712 (a10 ea);
|
||||
extern void io713 (d10 val, a10 ea);
|
||||
extern void io714 (d10 val, a10 ea);
|
||||
extern void io715 (d10 val, a10 ea);
|
||||
extern t_bool io720 (int32 ac, a10 ea);
|
||||
extern t_bool io721 (int32 ac, a10 ea);
|
||||
extern d10 io722 (a10 ea);
|
||||
extern void io723 (d10 val, a10 ea);
|
||||
extern void io724 (d10 val, a10 ea);
|
||||
extern void io725 (d10 val, a10 ea);
|
||||
extern t_bool clrcsh (a10 ea, int32 prv);
|
||||
extern t_bool clrpt (a10 ea, int32 prv);
|
||||
extern t_bool wrubr (a10 ea, int32 prv);
|
||||
extern t_bool wrebr (a10 ea, int32 prv);
|
||||
extern t_bool wrhsb (a10 ea, int32 prv);
|
||||
extern t_bool wrspb (a10 ea, int32 prv);
|
||||
extern t_bool wrcsb (a10 ea, int32 prv);
|
||||
extern t_bool wrpur (a10 ea, int32 prv);
|
||||
extern t_bool wrcstm (a10 ea, int32 prv);
|
||||
extern t_bool ldbr1 (a10 ea, int32 prv);
|
||||
extern t_bool ldbr2 (a10 ea, int32 prv);
|
||||
extern t_bool ldbr3 (a10 ea, int32 prv);
|
||||
extern t_bool ldbr4 (a10 ea, int32 prv);
|
||||
extern t_bool rdubr (a10 ea, int32 prv);
|
||||
extern t_bool rdebr (a10 ea, int32 prv);
|
||||
extern t_bool rdhsb (a10 ea, int32 prv);
|
||||
extern t_bool rdspb (a10 ea, int32 prv);
|
||||
extern t_bool rdcsb (a10 ea, int32 prv);
|
||||
extern t_bool rdpur (a10 ea, int32 prv);
|
||||
extern t_bool rdcstm (a10 ea, int32 prv);
|
||||
extern t_bool sdbr1 (a10 ea, int32 prv);
|
||||
extern t_bool sdbr2 (a10 ea, int32 prv);
|
||||
extern t_bool sdbr3 (a10 ea, int32 prv);
|
||||
extern t_bool sdbr4 (a10 ea, int32 prv);
|
||||
extern t_bool rdtim (a10 ea, int32 prv);
|
||||
extern t_bool rdint (a10 ea, int32 prv);
|
||||
extern t_bool wrtim (a10 ea, int32 prv);
|
||||
extern t_bool wrint (a10 ea, int32 prv);
|
||||
extern t_bool rdpcst (a10 ea, int32 prv);
|
||||
extern t_bool wrpcst (a10 ea, int32 prv);
|
||||
extern t_bool spm (a10 ea, int32 prv);
|
||||
extern t_bool lpmr (a10 ea, int32 prv);
|
||||
extern int32 pi_ub_vec (int32 lvl, int32 *uba);
|
||||
|
||||
/* CPU data structures
|
||||
|
||||
|
@ -192,7 +302,7 @@ void set_ac_display (d10 *acbase);
|
|||
cpu_mod CPU modifier list
|
||||
*/
|
||||
|
||||
UNIT cpu_unit = { UDATA (&cpu_svc, UNIT_FIX, MAXMEMSIZE) };
|
||||
UNIT cpu_unit = { UDATA (NULL, UNIT_FIX, MAXMEMSIZE) };
|
||||
|
||||
REG cpu_reg[] = {
|
||||
{ ORDATA (PC, saved_PC, VASIZE) },
|
||||
|
@ -213,7 +323,6 @@ REG cpu_reg[] = {
|
|||
{ ORDATA (AC15, acs[15], 36) },
|
||||
{ ORDATA (AC16, acs[16], 36) },
|
||||
{ ORDATA (AC17, acs[17], 36) },
|
||||
{ ORDATA (IR, last_inst, 36), REG_RO },
|
||||
{ ORDATA (PFW, pager_word, 36) },
|
||||
{ ORDATA (EBR, ebr, EBR_N_EBR) },
|
||||
{ FLDATA (PGON, ebr, EBR_V_PGON) },
|
||||
|
@ -241,12 +350,12 @@ REG cpu_reg[] = {
|
|||
{ ORDATA (APRFLG, apr_flg, 8) },
|
||||
{ ORDATA (APRLVL, apr_lvl, 3) },
|
||||
{ ORDATA (RLOG, rlog, 10) },
|
||||
{ FLDATA (F1PR, its_1pr, 0) },
|
||||
{ ORDATA (OLDPC, old_PC, VASIZE), REG_RO },
|
||||
{ DRDATA (INDMAX, ind_max, 8), PV_LEFT + REG_NZ },
|
||||
{ DRDATA (XCTMAX, xct_max, 8), PV_LEFT + REG_NZ },
|
||||
{ FLDATA (ITS, cpu_unit.flags, UNIT_V_ITS), REG_HRO },
|
||||
{ FLDATA (T20V41, cpu_unit.flags, UNIT_V_T20V41), REG_HRO },
|
||||
{ ORDATA (BREAK, ibkpt_addr, VASIZE + 1) },
|
||||
{ ORDATA (WRU, sim_int_char, 8) },
|
||||
{ FLDATA (STOP_ILL, stop_op0, 0) },
|
||||
{ BRDATA (REG, acs, 8, 36, AC_NUM * AC_NBLK) },
|
||||
|
@ -294,12 +403,32 @@ const d10 bytemask[64] = { 0,
|
|||
ONES, ONES, ONES, ONES, ONES, ONES, ONES, ONES, ONES,
|
||||
ONES, ONES, ONES, ONES, ONES, ONES, ONES, ONES, ONES };
|
||||
|
||||
/* JRST classes */
|
||||
static t_bool (*io700d[16])() = {
|
||||
&aprid, NULL, NULL, NULL, &wrapr, &rdapr, &czapr, &coapr,
|
||||
NULL, NULL, NULL, NULL, &wrpi, &rdpi, &czpi, &copi };
|
||||
static t_bool (*io701d[16])() = {
|
||||
NULL, &rdubr, &clrpt, &wrubr, &wrebr, &rdebr, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
|
||||
static t_bool (*io702d[16])() = {
|
||||
&rdspb, &rdcsb, &rdpur, &rdcstm, &rdtim, &rdint, &rdhsb, NULL,
|
||||
&wrspb, &wrcsb, &wrpur, &wrcstm, &wrtim, &wrint, &wrhsb, NULL };
|
||||
#define io700i io700d
|
||||
static t_bool (*io701i[16])() = {
|
||||
&clrcsh, &rdubr, &clrpt, &wrubr, &wrebr, &rdebr, NULL, NULL,
|
||||
NULL, &rdpcst, NULL, &wrpcst, NULL, NULL, NULL, NULL };
|
||||
static t_bool (*io702i[16])() = {
|
||||
&sdbr1, &sdbr2, &sdbr3, &sdbr4, &rdtim, &rdint, &rdhsb, &spm,
|
||||
&ldbr1, &ldbr2, &ldbr3, &ldbr4, &wrtim, &wrint, &wrhsb, &lpmr };
|
||||
|
||||
/* JRST classes and validation table */
|
||||
|
||||
#define JRST_U 1 /* ok anywhere */
|
||||
#define JRST_E 2 /* ok exec mode */
|
||||
#define JRST_UIO 3 /* ok user I/O mode */
|
||||
|
||||
|
||||
static t_stat jrst_tab[16] = {
|
||||
JRST_U, JRST_U, JRST_U, 0, JRST_E, JRST_U, JRST_E, JRST_E,
|
||||
JRST_UIO, 0, JRST_UIO, 0, JRST_E, JRST_U, 0, 0 };
|
||||
|
||||
/* Address operations */
|
||||
|
||||
|
@ -443,148 +572,19 @@ const d10 bytemask[64] = { 0,
|
|||
|
||||
t_stat sim_instr (void)
|
||||
{
|
||||
|
||||
/* External and forward declarations */
|
||||
|
||||
extern void dfad (int32 ac, d10 *rs, int32 inv);
|
||||
extern void dfmp (int32 ac, d10 *rs);
|
||||
extern void dfdv (int32 ac, d10 *rs);
|
||||
extern void dmul (int32 ac, d10 *rs);
|
||||
extern void ddiv (int32 ac, d10 *rs);
|
||||
extern void fix (int32 ac, d10 mb, t_bool rnd);
|
||||
extern d10 fad (d10 val, d10 mb, t_bool rnd, int32 inv);
|
||||
extern d10 fmp (d10 val, d10 mb, t_bool rnd);
|
||||
extern t_bool fdv (d10 val, d10 mb, d10 *rs, t_bool rnd);
|
||||
extern d10 fsc (d10 val, a10 ea);
|
||||
extern d10 fltr (d10 mb);
|
||||
extern int xtend (int32 ac, a10 ea, int32 pflgs);
|
||||
extern void xtcln (int32 rlog);
|
||||
extern d10 map (a10 ea, int32 prv);
|
||||
extern d10 imul (d10 val, d10 mb);
|
||||
extern t_bool idiv (d10 val, d10 mb, d10 *rs);
|
||||
extern void mul (d10 val, d10 mb, d10 *rs);
|
||||
extern t_bool divi (int32 ac, d10 mb, d10 *rs);
|
||||
extern t_bool io710 (int32 ac, a10 ea);
|
||||
extern t_bool io711 (int32 ac, a10 ea);
|
||||
extern d10 io712 (a10 ea);
|
||||
extern void io713 (d10 val, a10 ea);
|
||||
extern void io714 (d10 val, a10 ea);
|
||||
extern void io715 (d10 val, a10 ea);
|
||||
extern t_bool io720 (int32 ac, a10 ea);
|
||||
extern t_bool io721 (int32 ac, a10 ea);
|
||||
extern d10 io722 (a10 ea);
|
||||
extern void io723 (d10 val, a10 ea);
|
||||
extern void io724 (d10 val, a10 ea);
|
||||
extern void io725 (d10 val, a10 ea);
|
||||
|
||||
extern t_bool clrcsh (a10 ea, int32 prv);
|
||||
extern t_bool clrpt (a10 ea, int32 prv);
|
||||
extern t_bool wrubr (a10 ea, int32 prv);
|
||||
extern t_bool wrebr (a10 ea, int32 prv);
|
||||
extern t_bool wrhsb (a10 ea, int32 prv);
|
||||
extern t_bool wrspb (a10 ea, int32 prv);
|
||||
extern t_bool wrcsb (a10 ea, int32 prv);
|
||||
extern t_bool wrpur (a10 ea, int32 prv);
|
||||
extern t_bool wrcstm (a10 ea, int32 prv);
|
||||
extern t_bool ldbr1 (a10 ea, int32 prv);
|
||||
extern t_bool ldbr2 (a10 ea, int32 prv);
|
||||
extern t_bool ldbr3 (a10 ea, int32 prv);
|
||||
extern t_bool ldbr4 (a10 ea, int32 prv);
|
||||
extern t_bool rdubr (a10 ea, int32 prv);
|
||||
extern t_bool rdebr (a10 ea, int32 prv);
|
||||
extern t_bool rdhsb (a10 ea, int32 prv);
|
||||
extern t_bool rdspb (a10 ea, int32 prv);
|
||||
extern t_bool rdcsb (a10 ea, int32 prv);
|
||||
extern t_bool rdpur (a10 ea, int32 prv);
|
||||
extern t_bool rdcstm (a10 ea, int32 prv);
|
||||
extern t_bool sdbr1 (a10 ea, int32 prv);
|
||||
extern t_bool sdbr2 (a10 ea, int32 prv);
|
||||
extern t_bool sdbr3 (a10 ea, int32 prv);
|
||||
extern t_bool sdbr4 (a10 ea, int32 prv);
|
||||
extern t_bool rdtim (a10 ea, int32 prv);
|
||||
extern t_bool rdint (a10 ea, int32 prv);
|
||||
extern t_bool wrtim (a10 ea, int32 prv);
|
||||
extern t_bool wrint (a10 ea, int32 prv);
|
||||
extern t_bool rdpcst (a10 ea, int32 prv);
|
||||
extern t_bool wrpcst (a10 ea, int32 prv);
|
||||
extern t_bool spm (a10 ea, int32 prv);
|
||||
extern t_bool lpmr (a10 ea, int32 prv);
|
||||
|
||||
extern int32 pi_ub_vec (int32 lvl, int32 *uba);
|
||||
extern UNIT tim_unit;
|
||||
|
||||
d10 adjsp (d10 val, a10 ea);
|
||||
void ibp (a10 ea, int32 pflgs);
|
||||
d10 ldb (a10 ea, int32 pflgs);
|
||||
void dpb (d10 val, a10 ea, int32 pflgs);
|
||||
void adjbp (int32 ac, a10 ea, int32 pflgs);
|
||||
d10 add (d10 val, d10 mb);
|
||||
d10 sub (d10 val, d10 mb);
|
||||
void dadd (int32 ac, d10 *rs);
|
||||
void dsub (int32 ac, d10 *rs);
|
||||
int32 jffo (d10 val);
|
||||
d10 lsh (d10 val, a10 ea);
|
||||
d10 rot (d10 val, a10 ea);
|
||||
d10 ash (d10 val, a10 ea);
|
||||
void lshc (int32 ac, a10 ea);
|
||||
void rotc (int32 ac, a10 ea);
|
||||
void ashc (int32 ac, a10 ea);
|
||||
void circ (int32 ac, a10 ea);
|
||||
void blt (int32 ac, a10 ea, int32 pflgs);
|
||||
void bltu (int32 ac, a10 ea, int32 pflgs, int dir);
|
||||
a10 calc_ea (d10 inst, int32 prv);
|
||||
a10 calc_ioea (d10 inst, int32 prv);
|
||||
d10 calc_jrstfea (d10 inst, int32 pflgs);
|
||||
void pi_dismiss (void);
|
||||
void set_newflags (d10 fl, t_bool jrst);
|
||||
extern t_bool aprid (a10 ea, int32 prv);
|
||||
t_bool wrpi (a10 ea, int32 prv);
|
||||
t_bool rdpi (a10 ea, int32 prv);
|
||||
t_bool czpi (a10 ea, int32 prv);
|
||||
t_bool copi (a10 ea, int32 prv);
|
||||
t_bool wrapr (a10 ea, int32 prv);
|
||||
t_bool rdapr (a10 ea, int32 prv);
|
||||
t_bool czapr (a10 ea, int32 prv);
|
||||
t_bool coapr (a10 ea, int32 prv);
|
||||
|
||||
static t_bool (*io700d[16])() = {
|
||||
&aprid, NULL, NULL, NULL, &wrapr, &rdapr, &czapr, &coapr,
|
||||
NULL, NULL, NULL, NULL, &wrpi, &rdpi, &czpi, &copi };
|
||||
static t_bool (*io701d[16])() = {
|
||||
NULL, &rdubr, &clrpt, &wrubr, &wrebr, &rdebr, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
|
||||
static t_bool (*io702d[16])() = {
|
||||
&rdspb, &rdcsb, &rdpur, &rdcstm, &rdtim, &rdint, &rdhsb, NULL,
|
||||
&wrspb, &wrcsb, &wrpur, &wrcstm, &wrtim, &wrint, &wrhsb, NULL };
|
||||
#define io700i io700d
|
||||
static t_bool (*io701i[16])() = {
|
||||
&clrcsh, &rdubr, &clrpt, &wrubr, &wrebr, &rdebr, NULL, NULL,
|
||||
NULL, &rdpcst, NULL, &wrpcst, NULL, NULL, NULL, NULL };
|
||||
static t_bool (*io702i[16])() = {
|
||||
&sdbr1, &sdbr2, &sdbr3, &sdbr4, &rdtim, &rdint, &rdhsb, &spm,
|
||||
&ldbr1, &ldbr2, &ldbr3, &ldbr4, &wrtim, &wrint, &wrhsb, &lpmr };
|
||||
static t_stat jrst_tab[16] = {
|
||||
JRST_U, JRST_U, JRST_U, 0, JRST_E, JRST_U, JRST_E, JRST_E,
|
||||
JRST_UIO, 0, JRST_UIO, 0, JRST_E, JRST_U, 0, 0 };
|
||||
|
||||
d10 inst;
|
||||
a10 PC;
|
||||
int32 pflgs;
|
||||
int32 pager_flags = 0; /* pager: trap flags */
|
||||
t_bool pager_pi = FALSE; /* pager: in pi seq */
|
||||
int abortval = 0; /* abort value */
|
||||
t_bool (*fptr)();
|
||||
|
||||
/* Restore register state */
|
||||
|
||||
pager_PC = PC = saved_PC & AMASK; /* load local PC */
|
||||
set_dyn_ptrs (); /* set up local ptrs */
|
||||
pflgs = 0; /* not trap or PXCT */
|
||||
pager_tc = FALSE; /* not in trap cycle */
|
||||
pager_pi = FALSE; /* not in pi sequence */
|
||||
rlog = 0; /* not in extend */
|
||||
pi_eval (); /* eval pi system */
|
||||
astop_cpu = 0; /* no addr stop */
|
||||
sim_rtc_init (tim_unit.wait); /* init calibration */
|
||||
if (!ITS) its_1pr = 0; /* ~ITS, clr 1-proc */
|
||||
|
||||
/* Abort handling
|
||||
|
||||
|
@ -597,28 +597,32 @@ if ((abortval > 0) || pager_pi) { /* stop or pi err? */
|
|||
if (pager_pi && (abortval == PAGE_FAIL))
|
||||
abortval = STOP_PAGINT; /* stop for pi err */
|
||||
saved_PC = pager_PC & AMASK; /* failing instr PC */
|
||||
last_inst = inst; /* last instr decoded */
|
||||
set_ac_display (ac_cur); /* set up AC display */
|
||||
return abortval; } /* return to SCP */
|
||||
|
||||
/* Page fail - checked against KS10 ucode */
|
||||
/* Page fail - checked against KS10 ucode
|
||||
All state variables MUST be declared global for GCC optimization to work
|
||||
*/
|
||||
|
||||
else if (abortval == PAGE_FAIL) { /* page fail */
|
||||
d10 mb;
|
||||
if (rlog) xtcln (rlog); /* clean up extend */
|
||||
rlog = 0; /* clear log */
|
||||
if (pflgs & TRAP_CYCLE) flags = pager_flags; /* trap? get flags */
|
||||
if (!T20 || ITS) { /* TOPS-10 or ITS */
|
||||
a10 ea;
|
||||
if (ITS) ea = epta + EPT_ITS_PAG + (pi_m2lvl[pi_act] * 3);
|
||||
if (pager_tc) flags = pager_flags; /* trap? get flags */
|
||||
if (T20) { /* TOPS-20 */
|
||||
WriteP (upta + UPT_T20_PFL, pager_word);/* write page fail wd */
|
||||
WriteP (upta + UPT_T20_OFL, XWD (flags, 0));
|
||||
WriteP (upta + UPT_T20_OPC, pager_PC);
|
||||
mb = ReadP (upta + UPT_T20_NPC); }
|
||||
else { a10 ea; /* TOPS-10 or ITS */
|
||||
if (ITS) { /* ITS? */
|
||||
ea = epta + EPT_ITS_PAG + (pi_m2lvl[pi_act] * 3);
|
||||
if (its_1pr) flags = flags | F_1PR; /* store 1-proc */
|
||||
its_1pr = 0; } /* clear 1-proc */
|
||||
else ea = upta + UPT_T10_PAG;
|
||||
WriteP (ea, pager_word); /* write page fail wd */
|
||||
WriteP (ADDA (ea, 1), XWD (flags, pager_PC));
|
||||
mb = ReadP (ADDA (ea, 2)); }
|
||||
else { WriteP (upta + UPT_T20_PFL, pager_word);/* write page fail wd */
|
||||
WriteP (upta + UPT_T20_OFL, XWD (flags, 0));
|
||||
WriteP (upta + UPT_T20_OPC, pager_PC);
|
||||
mb = ReadP (upta + UPT_T20_NPC); }
|
||||
JUMP (mb); /* set new PC */
|
||||
set_newflags (mb, FALSE); /* set new flags */
|
||||
pi_eval (); } /* eval pi system */
|
||||
|
@ -627,14 +631,15 @@ else PC = pager_PC; /* intr, restore PC */
|
|||
/* Main instruction fetch/decode loop: check clock queue, intr, trap, bkpt */
|
||||
|
||||
for ( ;; ) { /* loop until ABORT */
|
||||
int32 op, ac, i, st, xr, xct_cnt;
|
||||
int32 op, ac, i, st, xr, xct_cnt, its_2pr, pflgs;
|
||||
a10 ea;
|
||||
d10 mb, indrct, rs[2];
|
||||
d10 inst, mb, indrct, rs[2];
|
||||
t_bool (*fptr)();
|
||||
|
||||
pager_PC = PC; /* update pager PC */
|
||||
pflgs = 0; /* not in PXCT or trap */
|
||||
pager_tc = FALSE; /* not in trap cycle */
|
||||
pflgs = 0; /* not in PXCT */
|
||||
xct_cnt = 0; /* count XCT's */
|
||||
if (astop_cpu) ABORT (STOP_ASTOP); /* address stop? */
|
||||
if (sim_interval <= 0) { /* check clock queue */
|
||||
if (i = sim_process_event ()) ABORT (i); /* error? stop sim */
|
||||
pi_eval (); } /* eval pi system */
|
||||
|
@ -657,6 +662,9 @@ if (qintr) {
|
|||
else inst = ReadP (epta + EPT_PIIT + (2 * qintr));
|
||||
op = GET_OP (inst); /* get opcode */
|
||||
ac = GET_AC (inst); /* get ac */
|
||||
if (its_1pr && ITS) { /* 1-proc set? */
|
||||
flags = flags | F_1PR; /* store 1-proc */
|
||||
its_1pr = 0; } /* clear 1-proc */
|
||||
if (op == OP_JSR) { /* JSR? */
|
||||
ea = calc_ea (inst, MM_CUR); /* calc ea, cur mode */
|
||||
WriteE (ea, FLPC); /* save flags+PC, exec */
|
||||
|
@ -688,7 +696,7 @@ if (qintr) {
|
|||
|
||||
if (TSTF (F_T1 | F_T2) && PAGING) {
|
||||
Read (pager_PC = PC, MM_CUR); /* test fetch */
|
||||
pflgs = TRAP_CYCLE; /* in a trap sequence */
|
||||
pager_tc = TRUE; /* in a trap sequence */
|
||||
pager_flags = flags; /* save flags */
|
||||
ea = (TSTF (F_USR)? upta + UPT_TRBASE: epta + EPT_TRBASE)
|
||||
+ GET_TRAPS (flags);
|
||||
|
@ -697,10 +705,8 @@ if (TSTF (F_T1 | F_T2) && PAGING) {
|
|||
|
||||
/* Test for instruction breakpoint */
|
||||
|
||||
else { if (PC == ibkpt_addr) { /* breakpoint? */
|
||||
save_ibkpt = ibkpt_addr; /* save bkpt */
|
||||
ibkpt_addr = ibkpt_addr | ILL_ADR_FLAG; /* disable */
|
||||
sim_activate (&cpu_unit, 1); /* sched re-enable */
|
||||
else { if (sim_brk_summ &&
|
||||
sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */
|
||||
ABORT (STOP_IBKPT); } /* stop simulation */
|
||||
|
||||
/* Ready (at last) to get an instruction */
|
||||
|
@ -709,6 +715,8 @@ else { if (PC == ibkpt_addr) { /* breakpoint? */
|
|||
INCPC;
|
||||
sim_interval = sim_interval - 1; }
|
||||
|
||||
its_2pr = its_1pr; /* save 1-proc flag */
|
||||
|
||||
/* Execute instruction. XCT and PXCT also return here. */
|
||||
|
||||
XCT:
|
||||
|
@ -1240,7 +1248,8 @@ case 0725: IOA; io725 (AC(ac), ea); break; /* BCIOB, IOWRBQ */
|
|||
*/
|
||||
|
||||
default:
|
||||
MUUO: if (T20) { /* TOPS20? */
|
||||
MUUO: its_2pr = 0; /* clear trap */
|
||||
if (T20) { /* TOPS20? */
|
||||
int32 tf = (op << (INST_V_OP - 18)) | (ac << (INST_V_AC - 18));
|
||||
WriteP (upta + UPT_MUUO, XWD ( /* store flags,,op+ac */
|
||||
flags & ~(F_T2 | F_T1), tf)); /* traps clear */
|
||||
|
@ -1252,7 +1261,7 @@ MUUO: if (T20) { /* TOPS20? */
|
|||
flags & ~(F_T2 | F_T1), PC)); /* traps clear */
|
||||
WriteP (upta + UPT_T10_CTX, UBRWORD); } /* store context */
|
||||
ea = upta + (TSTF (F_USR)? UPT_UNPC: UPT_ENPC) +
|
||||
(pflgs & TRAP_CYCLE? UPT_NPCT: 0); /* calculate vector */
|
||||
(pager_tc? UPT_NPCT: 0); /* calculate vector */
|
||||
mb = ReadP (ea); /* new flags, PC */
|
||||
JUMP (mb); /* set new PC */
|
||||
if (TSTF (F_USR)) mb = mb | XWD (F_UIO, 0); /* set PCU */
|
||||
|
@ -1325,6 +1334,15 @@ case 0254: /* JRST */
|
|||
JUMP (Read (ea, MM_OPND)); /* jump to M[ea] */
|
||||
break; } /* end case subop */
|
||||
break; } /* end case op */
|
||||
|
||||
if (its_2pr) { /* 1-proc trap? */
|
||||
its_1pr = its_2pr = 0; /* clear trap */
|
||||
if (ITS) { /* better be ITS */
|
||||
WriteP (upta + UPT_1PO, FLPC); /* wr old flgs, PC */
|
||||
mb = ReadP (upta + UPT_1PN); /* rd new flgs, PC */
|
||||
JUMP (mb); /* set PC */
|
||||
set_newflags (mb, TRUE); } /* set new flags */
|
||||
} /* end if 2-proc */
|
||||
} /* end for */
|
||||
|
||||
/* Should never get here */
|
||||
|
@ -1905,6 +1923,9 @@ int32 fl = (int32) LRZ (newf);
|
|||
if (jrst && TSTF (F_USR)) { /* if in user now */
|
||||
fl = fl | F_USR; /* can't clear user */
|
||||
if (!TSTF (F_UIO)) fl = fl & ~F_UIO; } /* if !UIO, can't set */
|
||||
if (ITS && (fl & F_1PR)) { /* ITS 1-proceed? */
|
||||
its_1pr = 1; /* set flag */
|
||||
fl = fl & ~F_1PR; } /* vanish bit */
|
||||
flags = fl & F_MASK; /* set new flags */
|
||||
set_dyn_ptrs (); /* set new ptrs */
|
||||
return;
|
||||
|
@ -2002,6 +2023,7 @@ return;
|
|||
t_stat cpu_reset (DEVICE *dptr)
|
||||
{
|
||||
flags = 0; /* clear flags */
|
||||
its_1pr = 0; /* clear 1-proceed */
|
||||
ebr = ubr = 0; /* clear paging */
|
||||
pi_enb = pi_act = pi_prq = 0; /* clear PI */
|
||||
apr_enb = apr_flg = apr_lvl = 0; /* clear APR */
|
||||
|
@ -2013,7 +2035,8 @@ set_ac_display (ac_cur);
|
|||
pi_eval ();
|
||||
if (M == NULL) M = calloc (MAXMEMSIZE, sizeof (d10));
|
||||
if (M == NULL) return SCPE_MEM;
|
||||
return cpu_svc (&cpu_unit);
|
||||
sim_brk_types = sim_brk_dflt = SWMASK ('E');
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Memory examine */
|
||||
|
@ -2043,15 +2066,6 @@ else { if (sw & SWMASK ('V')) {
|
|||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Service breakpoint */
|
||||
|
||||
t_stat cpu_svc (UNIT *uptr)
|
||||
{
|
||||
if ((ibkpt_addr & ~ILL_ADR_FLAG) == save_ibkpt) ibkpt_addr = save_ibkpt;
|
||||
save_ibkpt = -1;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Set current AC pointers for SCP */
|
||||
|
||||
void set_ac_display (d10 *acbase)
|
|
@ -379,11 +379,10 @@ typedef t_int64 d10; /* PDP-10 data (36b) */
|
|||
There are only two real contexts for selecting the AC block and
|
||||
the memory map: current and previous. However, PXCT allows the
|
||||
choice of current versus previous to be made selectively for
|
||||
various parts of an instruction. The PXCT flags (and the trap
|
||||
in progress flag) are kept in a dynamic CPU variable.
|
||||
various parts of an instruction. The PXCT flags are kept in a
|
||||
dynamic CPU variable.
|
||||
*/
|
||||
|
||||
#define TRAP_CYCLE 040 /* trap in progress */
|
||||
#define EA_PXCT 010 /* eff addr calc */
|
||||
#define OPND_PXCT 004 /* operand, bdst */
|
||||
#define EABP_PXCT 002 /* bp eff addr calc */
|
||||
|
@ -420,6 +419,8 @@ typedef t_int64 d10; /* PDP-10 data (36b) */
|
|||
#define UPT_T20_UEA 0426 /* T20: address */
|
||||
#define UPT_T20_CTX 0427 /* T20: context */
|
||||
#define UPT_ENPC 0430 /* MUUO new PC, exec */
|
||||
#define UPT_1PO 0432 /* ITS 1-proc: old PC */
|
||||
#define UPT_1PN 0433 /* ITS 1-proc: new PC */
|
||||
#define UPT_UNPC 0434 /* MUUO new PC, user */
|
||||
#define UPT_NPCT 1 /* PC offset if trap */
|
||||
#define UPT_T10_PAG 0500 /* T10: page fail blk */
|
526
PDP10/pdp10_doc.txt
Normal file
526
PDP10/pdp10_doc.txt
Normal file
|
@ -0,0 +1,526 @@
|
|||
To: Users
|
||||
From: Bob Supnik
|
||||
Subj: PDP-10 Simulator Usage
|
||||
Date: 1-Dec-01
|
||||
|
||||
COPYRIGHT NOTICE
|
||||
|
||||
The following copyright notice applies to both the SIMH source and binary:
|
||||
|
||||
Original code published in 1993-2001, written by Robert M Supnik
|
||||
Copyright (c) 1993-2001, Robert M Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation
|
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
and/or sell copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
Except as contained in this notice, the name of Robert M Supnik shall not
|
||||
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
This memorandum documents the PDP-10 simulator.
|
||||
|
||||
|
||||
1. Simulator Files
|
||||
|
||||
To compile the PDP-10, you must define USE_INT64 as part of the compilation
|
||||
command line.
|
||||
|
||||
sim/ sim_defs.h
|
||||
sim_sock.h
|
||||
sim_tmxr.h
|
||||
dec_dz.h
|
||||
scp.c
|
||||
scp_tty.c
|
||||
sim_rev.c
|
||||
sim_sock.c
|
||||
sim_tmxr.c
|
||||
|
||||
sim/pdp10/ pdp10_defs.h
|
||||
pdp10_cpu.c
|
||||
pdp10_dz.c
|
||||
pdp10_fe.c
|
||||
pdp10_ksio.c
|
||||
pdp10_lp20.c
|
||||
pdp10_mdfp.c
|
||||
pdp10_pag.c
|
||||
pdp10_pt.c
|
||||
pdp10_rp.c
|
||||
pdp10_sys.c
|
||||
pdp10_tu.c
|
||||
pdp10_xtnd.c
|
||||
|
||||
2. PDP-10 Features
|
||||
|
||||
The PDP-10 simulator is configured as follows:
|
||||
|
||||
device simulates
|
||||
name(s)
|
||||
|
||||
CPU KS10 CPU with 1MW of memory
|
||||
PAG paging unit (translation maps)
|
||||
UBA Unibus adapters (translation maps)
|
||||
FE console
|
||||
TIM timer
|
||||
PTR,PTP PC11 paper tape reader/punch
|
||||
DZ DZ11 8-line terminal multiplexor
|
||||
LP20 LP20 line printer
|
||||
RP RH11/RP04/RP05/RP06/RP07/RM03/RM05/RM80 controller with
|
||||
eight drives
|
||||
TU RH11/TM02/TU45 controller with eight drives
|
||||
|
||||
The PTR/PTP are initially DISABLEd. The DZ11 can also be DISABLEd.
|
||||
|
||||
The PDP-10 simulator implements several unique stop condition:
|
||||
|
||||
- illegal instruction (000) in kernel mode
|
||||
- indirect addressing nesting exceeds limit
|
||||
- execute chaining exceeds limit
|
||||
- page fail or other error in interrupt sequence
|
||||
- illegal instruction in interrupt sequence
|
||||
- invalid vector pointer in interrupt sequence
|
||||
- invalid Unibus adapter number
|
||||
- non-existent exec or user page table address
|
||||
|
||||
The PDP-10 loader supports RIM10B format paper tapes, SAV binary files, and
|
||||
EXE binary files. LOAD switches -r, -s, -e specify RIM10, SAV, EXE format,
|
||||
respectively. If no switch is specified, the LOAD command checks the file
|
||||
extension; .RIM, .SAV, .EXE specify RIM10, SAV, EXE format, respectively.
|
||||
If no switch specified, and no extension matches, the LOAD command checks
|
||||
the file format to try to determine the file type.
|
||||
|
||||
2.1 CPU
|
||||
|
||||
The CPU options allow the user to specify standard microcode, standard
|
||||
microcode with a bug fix for a boostrap problem in TOPS-20 V4.1, or ITS
|
||||
microcode
|
||||
|
||||
SET CPU STANDARD Standard microcode
|
||||
SET CPU TOPS20V41 Standard microcode with TOPS-20 V4.1 bug fix
|
||||
SET CPU ITS ITS compatible microcode
|
||||
|
||||
CPU registers include the visible state of the processor as well as the
|
||||
control registers for the interrupt system.
|
||||
|
||||
name size comments
|
||||
|
||||
PC 18 program counter
|
||||
FLAGS 18 processor flags (<13:17> unused)
|
||||
AC0..AC17 36 accumulators
|
||||
IR 36 instruction register
|
||||
EBR 18 executive base register
|
||||
PGON 1 paging enabled flag
|
||||
T20P 1 TOPS-20 paging
|
||||
UBR 18 user base register
|
||||
CURAC 3 current AC block
|
||||
PRVAC 3 previous AC block
|
||||
SPT 36 shared pointer table
|
||||
CST 36 core status table
|
||||
PUR 36 process update register
|
||||
CSTM 36 CST mask
|
||||
HSB 18 halt status block address
|
||||
DBR1 18 descriptor base register 1 (ITS)
|
||||
DBR2 18 descriptor base register 2 (ITS)
|
||||
DBR3 18 descriptor base register 3 (ITS)
|
||||
DBR4 18 descriptor base register 4 (ITS)
|
||||
PIENB 7 PI levels enabled
|
||||
PIACT 7 PI levels active
|
||||
PIPRQ 7 PI levels with program requests
|
||||
PIIOQ 7 PI levels with IO requests
|
||||
PIAPR 7 PI levels with APR requests
|
||||
APRENB 8 APR flags enabled
|
||||
APRFLG 8 APR flags active
|
||||
APRLVL 3 PI level for APR interrupt
|
||||
IND_MAX 8 indirect address nesting limit
|
||||
XCT_MAX 8 execute chaining limit
|
||||
OLDPC 18 PC prior to last transfer instruction
|
||||
WRU 8 interrupt character
|
||||
REG[0:127] 36 fast memory blocks
|
||||
|
||||
2.2 Pager
|
||||
|
||||
The pager contains the page maps for executive and user mode. The
|
||||
executive page map is the memory space for unit 0, the user page map the
|
||||
memory space for unit 1. A page map entry is 32 bits wide and has the
|
||||
following format:
|
||||
|
||||
bit content
|
||||
--- -------
|
||||
31 page is writeable
|
||||
30 entry is valid
|
||||
29:19 mbz
|
||||
18:9 physical page base address
|
||||
8:0 mbz
|
||||
|
||||
The pager has no registers.
|
||||
|
||||
2.3 Unibus Adapters
|
||||
|
||||
The Unibus adapters link the system I/O devices to the CPU. Unibus
|
||||
adapter 1 (UBA1) is unit 0, and Unibus adapter 3 is unit 1. The
|
||||
adapter's Unibus map is the memory space of the corresponding unit.
|
||||
|
||||
The Unibus Adapter has the following registers:
|
||||
|
||||
name size comments
|
||||
|
||||
INTREQ 32 interrupt requests
|
||||
UB1CS 16 Unibus adapter 1 control/status
|
||||
UB3CS 16 Unibus adapter 3 control/status
|
||||
|
||||
2.4 Front End (FE)
|
||||
|
||||
The front end is the system console. The keyboard input is unit 0,
|
||||
the console output is unit 1. It supports two options:
|
||||
|
||||
SET FE STOP halts the PDP-10 operating system
|
||||
SET FE CTLC simulates typing ^C (for Windoze)
|
||||
|
||||
The front end has the following registers:
|
||||
|
||||
name size comments
|
||||
|
||||
IBUF 8 input buffer
|
||||
ICOUNT 31 count of input characters
|
||||
ITIME 24 keyboard polling interval
|
||||
OBUF 8 output buffer
|
||||
OCOUNT 31 count of output characters
|
||||
OTIME 24 console output response time
|
||||
|
||||
2.5 Timer (TIM)
|
||||
|
||||
The timer (TIM) implements the system timer, the interval timer, and
|
||||
the time of day clock used to get the date and time at system startup.
|
||||
Because most PDP-10 software is not Y2K compliant, the timer implements
|
||||
one option
|
||||
|
||||
SET TIM NOY2K software not Y2K compliant, limit time
|
||||
of day clock to 1999 (default)
|
||||
SET TIM Y2K software is Y2K compliant
|
||||
|
||||
The timer has the following registers:
|
||||
|
||||
name size comments
|
||||
|
||||
TIMBASE 59 time base (double precision)
|
||||
TTG 36 time to go (remaining time) for interval
|
||||
PERIOD 36 reset value for interval
|
||||
QUANT 36 quantum timer (ITS only)
|
||||
TIME 24 tick delay
|
||||
DIAG 1 use fixed tick delay instead of autocalibration
|
||||
|
||||
Unless the DIAG flag is set, the timer autocalibrates; the tick delay
|
||||
is adjusted up or down so that the time base tracks actual elapsed time.
|
||||
This may cause time-dependent diagnostics to report errors.
|
||||
|
||||
2.6 PC11 Paper Tape Reader (PTR)
|
||||
|
||||
The paper tape reader (PTR) reads data from a disk file. The POS
|
||||
register specifies the number of the next data item to be read. Thus,
|
||||
by changing POS, the user can backspace or advance the reader.
|
||||
|
||||
The paper tape reader implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
BUF 8 last data item processed
|
||||
CSR 16 control/status register
|
||||
INT 1 interrupt pending flag
|
||||
ERR 1 error flag (CSR<15>)
|
||||
BUSY 1 busy flag (CSR<11>)
|
||||
DONE 1 device done flag (CSR<7>)
|
||||
IE 1 interrupt enable flag (CSR<6>)
|
||||
POS 31 position in the input file
|
||||
TIME 24 time from I/O initiation to interrupt
|
||||
STOP_IOE 1 stop on I/O error
|
||||
|
||||
Error handling is as follows:
|
||||
|
||||
error STOP_IOE processed as
|
||||
|
||||
not attached 1 report error and stop
|
||||
0 out of tape
|
||||
|
||||
end of file 1 report error and stop
|
||||
0 out of tape
|
||||
|
||||
OS I/O error x report error and stop
|
||||
|
||||
|
||||
2.7 PC11 Paper Tape Punch (PTP)
|
||||
|
||||
The paper tape punch (PTP) writes data to a disk file. The POS
|
||||
register specifies the number of the next data item to be written.
|
||||
Thus, by by changing POS, the user can backspace or advance the punch.
|
||||
|
||||
The paper tape punch implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
BUF 8 last data item processed
|
||||
CSR 16 control/status register
|
||||
INT 1 interrupt pending flag
|
||||
ERR 1 error flag (CSR<15>)
|
||||
DONE 1 device done flag (CSR<7>)
|
||||
IE 1 interrupt enable flag (CSR<6>)
|
||||
POS 31 position in the input or output file
|
||||
TIME 24 time from I/O initiation to interrupt
|
||||
STOP_IOE 1 stop on I/O error
|
||||
|
||||
Error handling is as follows:
|
||||
|
||||
error STOP_IOE processed as
|
||||
|
||||
not attached 1 report error and stop
|
||||
0 out of tape
|
||||
|
||||
OS I/O error x report error and stop
|
||||
|
||||
2.8 DZ11 Terminal Multiplexor (DZ)
|
||||
|
||||
The DZ11 is an 8-line terminal multiplexor. The terminal lines perform
|
||||
input and output through Telnet sessions connected to a user-specified
|
||||
port. The ATTACH command specifies the port to be used:
|
||||
|
||||
ATTACH {-am} DZ <port>(cr) -- set up listening port
|
||||
|
||||
where port is a decimal number between 1 and 65535 that is not being used
|
||||
for other TCP/IP activities. The optional switch -m turns on the DZ11's
|
||||
modem controls; the optional switch -a turns on active disconnects
|
||||
(disconnect session if computer clears Data Terminal Ready).
|
||||
|
||||
Once the DZ is attached and the simulator is running, the DZ will listen
|
||||
for connections on the specified port. It assumes that the incoming
|
||||
connections are Telnet connections. The connection remains open until
|
||||
disconnected either by the simulated program or by the Telnet client.
|
||||
|
||||
The SHOW DZ LINESTATUS command displays the current connections to the DZ.
|
||||
|
||||
The DZ11 implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
CSR 16 control/status register
|
||||
RBUF 16 receive buffer
|
||||
LPR 16 line parameter register
|
||||
TCR 16 transmission control register
|
||||
MSR 16 modem status register
|
||||
TDR 16 transmit data register
|
||||
SAENB 1 silo alarm enabled
|
||||
MDMTCL 1 modem control enabled
|
||||
AUTODS 1 autodisconnect enabled
|
||||
RPOS0..7 32 count of characters received
|
||||
TPOS0..7 32 count of characters transmitted
|
||||
|
||||
The DZ11 does not support save and restore. All open connections are
|
||||
lost when the simulator shuts down or the DZ is detached.
|
||||
|
||||
2.9 RH11 Adapter, RM02/03/05/80, RP04/05/06/07 drives (RP)
|
||||
|
||||
The RP controller implements the Massbus 18b (RH11) direct interface for
|
||||
large disk drives. It is more abstract than other device simulators, with
|
||||
just enough detail to run operating system drivers. In addition, the RP
|
||||
controller conflates the details of the RM series controllers with the RP
|
||||
series controllers, although there were detailed differences.
|
||||
|
||||
RP options include the ability to set units write enabled or write locked,
|
||||
to set the drive type to one of six disk types, or autosize:
|
||||
|
||||
SET RPn LOCKED set unit n write locked
|
||||
SET RPn ENABLED set unit n write enabled
|
||||
SET RPn RM03 set type to RM03
|
||||
SET RPn RM05 set type to RM05
|
||||
SET RPn RM80 set type to RM80
|
||||
SET RPn RP04 set type to RP04
|
||||
SET RPn RP06 set type to RP06
|
||||
SET RPn RP07 set type to RP07
|
||||
SET RPn AUTOSIZE set type based on file size at attach
|
||||
|
||||
The type options can be used only when a unit is not attached to a file.
|
||||
Note that TOPS-10 V7.03 only supported the RP06 and RM03; V7.04 added
|
||||
support for the RP07. Units can be REMOVEd or ADDed to the configuration.
|
||||
|
||||
The RP controller implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
RPCS1 16 control/status 1
|
||||
RPWC 16 word count
|
||||
RPBA 16 bus address
|
||||
RPDA 16 desired surface, sector
|
||||
RPCS2 16 control/status 2
|
||||
RPDS[0:7] 16 drive status, drives 0-7
|
||||
RPER1[0:7] 16 drive errors, drives 0-7
|
||||
RPOF 16 offset
|
||||
RPDC 8 desired cylinder
|
||||
RPER2 16 error status 2
|
||||
RPER3 16 error status 3
|
||||
RPEC1 16 ECC syndrome 1
|
||||
RPEC2 16 ECC syndrome 2
|
||||
RPMR 16 maintenance register
|
||||
RPDB 16 data buffer
|
||||
IFF 1 transfer complete interrupt request flop
|
||||
INT 1 interrupt pending flag
|
||||
SC 1 special condition (CSR1<15>)
|
||||
DONE 1 device done flag (CSR1<7>)
|
||||
IE 1 interrupt enable flag (CSR1<6>)
|
||||
STIME 24 seek time, per cylinder
|
||||
RTIME 24 rotational delay
|
||||
STOP_IOE 1 stop on I/O error
|
||||
|
||||
Error handling is as follows:
|
||||
|
||||
error STOP_IOE processed as
|
||||
|
||||
not attached 1 report error and stop
|
||||
0 disk not ready
|
||||
|
||||
end of file x assume rest of disk is zero
|
||||
|
||||
OS I/O error x report error and stop
|
||||
|
||||
2.10 RH11 Adapter, TM02 Formatter, TU45 Magnetic Tape (TU)
|
||||
|
||||
The magnetic tape simulator simulates an RH11 Massbus adapter with one
|
||||
TM02 formatter and up to eight TU45 drives. Magnetic tape options include
|
||||
the ability to make units write enabled or locked.
|
||||
|
||||
SET TUn LOCKED set unit n write locked
|
||||
SET TUn ENABLED set unit n write enabled
|
||||
|
||||
Units can also be REMOVEd or ADDed to the configuration.
|
||||
|
||||
The magnetic tape controller implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
MTCS1 16 control/status 1
|
||||
MTBA 16 memory address
|
||||
MTWC 16 word count
|
||||
MTFC 16 frame count
|
||||
MTCS2 16 control/status 2
|
||||
MTFS 16 formatter status
|
||||
MTER 16 error status
|
||||
MTCC 16 check character
|
||||
MTDB 16 data buffer
|
||||
MTMR 16 maintenance register
|
||||
MTTC 16 tape control register
|
||||
INT 1 interrupt pending flag
|
||||
DONE 1 device done flag
|
||||
IE 1 interrupt enable flag
|
||||
STOP_IOE 1 stop on I/O error
|
||||
TIME 24 delay
|
||||
UST[0:7] 16 unit status, units 0-7
|
||||
POS[0:7] 31 position, units 0-7
|
||||
|
||||
Error handling is as follows:
|
||||
|
||||
error processed as
|
||||
|
||||
not attached tape not ready
|
||||
|
||||
end of file (read or space) end of physical tape
|
||||
(write) ignored
|
||||
|
||||
OS I/O error report error and stop
|
||||
|
||||
2.11 LP20 DMA Line Printer (LP20)
|
||||
|
||||
The LP20 is a DMA-based line printer controller. There is one
|
||||
line printer option to clear the vertical forms unit (VFU).
|
||||
|
||||
SET LP20 VFUCLEAR clear the vertical forms unit
|
||||
|
||||
The LP20 implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
LPCSA 16 control/status register A
|
||||
LPCSB 16 control/status register B
|
||||
LPBA 16 bus address register
|
||||
LPBC 12 byte count register
|
||||
LPPAGC 12 page count register
|
||||
LPRDAT 12 RAM data register
|
||||
LPCBUF 8 character buffer register
|
||||
LPCOLC 8 column counter register
|
||||
LPPDAT 8 printer data register
|
||||
LPCSUM 8 checksum register
|
||||
DVPTR 7 vertical forms unit pointer
|
||||
DVLNT 7 vertical forms unit length
|
||||
INT 1 interrupt request
|
||||
ERR 1 error flag
|
||||
DONE 1 done flag
|
||||
IE 1 interrupt enable flag
|
||||
POS 31 position in output file
|
||||
TIME 24 response time
|
||||
STOP_IOE 1 stop on I/O error
|
||||
TXRAM[0:255] 12 translation RAM
|
||||
DAVFU[0:142] 12 vertical forms unit array
|
||||
|
||||
Error handling is as follows:
|
||||
|
||||
error STOP_IOE processed as
|
||||
|
||||
not attached 1 report error and stop
|
||||
0 out of paper
|
||||
|
||||
OS I/O error x report error and stop
|
||||
|
||||
2.12 Symbolic Display and Input
|
||||
|
||||
The PDP-10 simulator implements symbolic display and input. Display is
|
||||
controlled by command line switches:
|
||||
|
||||
-a display as ASCII character
|
||||
-c display as (sixbit) character string
|
||||
-p display as packed (seven bit) string
|
||||
-m display instruction mnemonics
|
||||
-v interpret address as virtual
|
||||
-e force executive mode
|
||||
-u force user mode
|
||||
|
||||
Input parsing is controlled by the first character typed in or by command
|
||||
line switches:
|
||||
|
||||
' or -a ASCII character
|
||||
" or -c sixbit string
|
||||
# or -p packed seven bit string
|
||||
alphabetic instruction mnemonic
|
||||
numeric octal number
|
||||
|
||||
Instruction input uses standard PDP-10 assembler syntax. There are three
|
||||
instruction classes: memory reference, memory reference with AC, and I/O.
|
||||
|
||||
Memory reference instructions have the format
|
||||
|
||||
memref {@}address{(index)}
|
||||
|
||||
memory reference with AC instructions have the format
|
||||
|
||||
memac ac,{@}address{(index)}
|
||||
|
||||
and I/O instructions have the format
|
||||
|
||||
io device,{@}address{(index)}
|
||||
|
||||
where @ signifies indirect. The address is a signed octal number in the
|
||||
range 0 - 0777777. The ac and index are unsigned octal numbers in the
|
||||
range 0-17. The device is either a recognized device mnemonic (APR, PI,
|
||||
TIM) or an octal number in the range 0 - 0177.
|
||||
|
||||
The simulator recognizes the standard MACRO alternate mnemonics (CLEAR
|
||||
for SETZ, OR for IORI), the individual definitions for JRST and JFCL
|
||||
variants, and the extended instruction mnemonics.
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
fe KS10 console front end
|
||||
|
||||
30-Nov-01 RMS Added extended SET/SHOW support
|
||||
23-Oct-01 RMS New IO page address constants
|
||||
07-Sep-01 RMS Moved function prototypes
|
||||
*/
|
||||
|
@ -37,8 +38,8 @@ extern int32 apr_flg;
|
|||
t_stat fei_svc (UNIT *uptr);
|
||||
t_stat feo_svc (UNIT *uptr);
|
||||
t_stat fe_reset (DEVICE *dptr);
|
||||
t_stat fe_stop_os (UNIT *uptr, int32 val);
|
||||
t_stat fe_ctrl_c (UNIT *uptr, int32 val);
|
||||
t_stat fe_stop_os (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
t_stat fe_ctrl_c (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
|
||||
/* FE data structures
|
||||
|
||||
|
@ -146,7 +147,7 @@ return SCPE_OK;
|
|||
|
||||
/* Stop operating system */
|
||||
|
||||
t_stat fe_stop_os (UNIT *uptr, int32 val)
|
||||
t_stat fe_stop_os (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
M[FE_SWITCH] = IOBA_RP; /* tell OS to stop */
|
||||
return SCPE_OK;
|
||||
|
@ -154,7 +155,7 @@ return SCPE_OK;
|
|||
|
||||
/* Enter control-C for Windoze */
|
||||
|
||||
t_stat fe_ctrl_c (UNIT *uptr, int32 val)
|
||||
t_stat fe_ctrl_c (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
fei_unit.buf = 003; /* control-C */
|
||||
M[FE_CTYIN] = fei_unit.buf | FE_CVALID; /* put char in mem */
|
|
@ -24,6 +24,8 @@
|
|||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
lp20 line printer
|
||||
|
||||
30-Nov-01 RMS Added extended SET/SHOW support
|
||||
*/
|
||||
|
||||
#include "pdp10_defs.h"
|
||||
|
@ -152,7 +154,7 @@ t_stat lp20_svc (UNIT *uptr);
|
|||
t_stat lp20_reset (DEVICE *dptr);
|
||||
t_stat lp20_attach (UNIT *uptr, char *ptr);
|
||||
t_stat lp20_detach (UNIT *uptr);
|
||||
t_stat lp20_clear_vfu (UNIT *uptr, int32 arg);
|
||||
t_stat lp20_clear_vfu (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
t_bool lp20_print (int32 c);
|
||||
t_bool lp20_adv (int32 c, t_bool advdvu);
|
||||
t_bool lp20_davfu (int32 c);
|
||||
|
@ -570,7 +572,7 @@ update_lpcs (CSA_MBZ);
|
|||
return reason;
|
||||
}
|
||||
|
||||
t_stat lp20_clear_vfu (UNIT *uptr, int32 arg)
|
||||
t_stat lp20_clear_vfu (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
int i;
|
||||
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
pag KS10 pager
|
||||
|
||||
02-Dec-01 RMS Fixed bug in ITS LPMR (found by Dave Conroy)
|
||||
21-Aug-01 RMS Fixed bug in ITS paging (found by Miriam Lennox)
|
||||
Removed register from declarations
|
||||
19-May-01 RMS Added workaround for TOPS-20 V4.1 boot bug
|
||||
|
@ -754,6 +755,7 @@ val = Read (ADDA (ea, 2), prv);
|
|||
dbr1 = (a10) (Read (ea, prv) & AMASK);
|
||||
dbr2 = (a10) (Read (ADDA (ea, 1), prv) & AMASK);
|
||||
quant = val;
|
||||
pag_reset (&pag_dev);
|
||||
return FALSE;
|
||||
}
|
||||
|
|
@ -26,6 +26,7 @@
|
|||
ptr paper tape reader
|
||||
ptp paper tape punch
|
||||
|
||||
29-Nov-01 RMS Added read only unit support
|
||||
07-Sep-01 RMS Revised disable mechanism
|
||||
*/
|
||||
|
||||
|
@ -59,7 +60,8 @@ t_stat ptp_detach (UNIT *uptr);
|
|||
*/
|
||||
|
||||
UNIT ptr_unit = {
|
||||
UDATA (&ptr_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_IN_WAIT };
|
||||
UDATA (&ptr_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0),
|
||||
SERIAL_IN_WAIT };
|
||||
|
||||
REG ptr_reg[] = {
|
||||
{ ORDATA (CSR, ptr_csr, 16) },
|
|
@ -25,6 +25,8 @@
|
|||
|
||||
rp RH/RP/RM moving head disks
|
||||
|
||||
30-Nov-01 RMS Added read only unit, extended SET/SHOW support support
|
||||
24-Nov-01 RMS Changed RPER, RPDS, FNC, FLG to arrays
|
||||
23-Oct-01 RMS Fixed bug in error interrupts
|
||||
New IO page address constants
|
||||
05-Oct-01 RMS Rewrote interrupt handling from schematics
|
||||
|
@ -75,9 +77,10 @@
|
|||
#define UNIT_DTYPE (UNIT_M_DTYPE << UNIT_V_DTYPE)
|
||||
#define UNIT_AUTO (1 << UNIT_V_AUTO)
|
||||
#define UNIT_W_UF 6 /* user flags width */
|
||||
#define UNIT_V_DUMMY (UNIT_V_UF + UNIT_W_UF) /* dummy flag */
|
||||
#define UNIT_V_DUMMY (UNIT_V_UF + UNIT_W_UF) /* dummy flag */
|
||||
#define UNIT_DUMMY (1 << UNIT_V_DUMMY)
|
||||
#define GET_DTYPE(x) (((x) >> UNIT_V_DTYPE) & UNIT_M_DTYPE)
|
||||
#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */
|
||||
|
||||
/* Parameters in the unit descriptor */
|
||||
|
||||
|
@ -338,7 +341,7 @@ int reg_in_drive[32] = {
|
|||
|
||||
void update_rpcs (int32 flags, int32 drv);
|
||||
void rp_go (int32 drv, int32 fnc);
|
||||
t_stat rp_set_size (UNIT *uptr, int32 value);
|
||||
t_stat rp_set_size (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
t_stat rp_svc (UNIT *uptr);
|
||||
t_stat rp_reset (DEVICE *dptr);
|
||||
t_stat rp_boot (int32 unitno);
|
||||
|
@ -355,21 +358,21 @@ t_stat rp_detach (UNIT *uptr);
|
|||
|
||||
UNIT rp_unit[] = {
|
||||
{ UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
(RP06_DTYPE << UNIT_V_DTYPE), RP06_SIZE) },
|
||||
UNIT_ROABLE+(RP06_DTYPE << UNIT_V_DTYPE), RP06_SIZE) },
|
||||
{ UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
(RP06_DTYPE << UNIT_V_DTYPE), RP06_SIZE) },
|
||||
UNIT_ROABLE+(RP06_DTYPE << UNIT_V_DTYPE), RP06_SIZE) },
|
||||
{ UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
(RP06_DTYPE << UNIT_V_DTYPE), RP06_SIZE) },
|
||||
UNIT_ROABLE+(RP06_DTYPE << UNIT_V_DTYPE), RP06_SIZE) },
|
||||
{ UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
(RP06_DTYPE << UNIT_V_DTYPE), RP06_SIZE) },
|
||||
UNIT_ROABLE+(RP06_DTYPE << UNIT_V_DTYPE), RP06_SIZE) },
|
||||
{ UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
(RP06_DTYPE << UNIT_V_DTYPE), RP06_SIZE) },
|
||||
UNIT_ROABLE+(RP06_DTYPE << UNIT_V_DTYPE), RP06_SIZE) },
|
||||
{ UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
(RP06_DTYPE << UNIT_V_DTYPE), RP06_SIZE) },
|
||||
UNIT_ROABLE+(RP06_DTYPE << UNIT_V_DTYPE), RP06_SIZE) },
|
||||
{ UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
(RP06_DTYPE << UNIT_V_DTYPE), RP06_SIZE) },
|
||||
UNIT_ROABLE+(RP06_DTYPE << UNIT_V_DTYPE), RP06_SIZE) },
|
||||
{ UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
(RP06_DTYPE << UNIT_V_DTYPE), RP06_SIZE) } };
|
||||
UNIT_ROABLE+(RP06_DTYPE << UNIT_V_DTYPE), RP06_SIZE) } };
|
||||
|
||||
REG rp_reg[] = {
|
||||
{ ORDATA (RPCS1, rpcs1, 16) },
|
||||
|
@ -377,6 +380,8 @@ REG rp_reg[] = {
|
|||
{ ORDATA (RPBA, rpba, 16) },
|
||||
{ ORDATA (RPDA, rpda, 16) },
|
||||
{ ORDATA (RPCS2, rpcs2, 16) },
|
||||
{ BRDATA (RPDS, rpds, 8, 16, RP_NUMDR) },
|
||||
{ BRDATA (RPER1, rper1, 8, 16, RP_NUMDR) },
|
||||
{ ORDATA (RPOF, rpof, 16) },
|
||||
{ ORDATA (RPDC, rpdc, 16) },
|
||||
{ ORDATA (RPER2, rper2, 16) },
|
||||
|
@ -392,46 +397,11 @@ REG rp_reg[] = {
|
|||
{ FLDATA (IE, rpcs1, CSR_V_IE) },
|
||||
{ DRDATA (STIME, rp_swait, 24), REG_NZ + PV_LEFT },
|
||||
{ DRDATA (RTIME, rp_rwait, 24), REG_NZ + PV_LEFT },
|
||||
{ ORDATA (RPDS0, rpds[0], 16) },
|
||||
{ ORDATA (RPDS1, rpds[1], 16) },
|
||||
{ ORDATA (RPDS2, rpds[2], 16) },
|
||||
{ ORDATA (RPDS3, rpds[3], 16) },
|
||||
{ ORDATA (RPDS4, rpds[4], 16) },
|
||||
{ ORDATA (RPDS5, rpds[5], 16) },
|
||||
{ ORDATA (RPDS6, rpds[6], 16) },
|
||||
{ ORDATA (RPDS7, rpds[7], 16) },
|
||||
{ ORDATA (RPDE0, rper1[0], 16) },
|
||||
{ ORDATA (RPDE1, rper1[1], 16) },
|
||||
{ ORDATA (RPDE2, rper1[2], 16) },
|
||||
{ ORDATA (RPDE3, rper1[3], 16) },
|
||||
{ ORDATA (RPDE4, rper1[4], 16) },
|
||||
{ ORDATA (RPDE5, rper1[5], 16) },
|
||||
{ ORDATA (RPDE6, rper1[6], 16) },
|
||||
{ ORDATA (RPDE7, rper1[7], 16) },
|
||||
{ ORDATA (RPFN0, rp_unit[0].FUNC, 5), REG_HRO },
|
||||
{ ORDATA (RPFN1, rp_unit[1].FUNC, 5), REG_HRO },
|
||||
{ ORDATA (RPFN2, rp_unit[2].FUNC, 5), REG_HRO },
|
||||
{ ORDATA (RPFN3, rp_unit[3].FUNC, 5), REG_HRO },
|
||||
{ ORDATA (RPFN4, rp_unit[4].FUNC, 5), REG_HRO },
|
||||
{ ORDATA (RPFN5, rp_unit[5].FUNC, 5), REG_HRO },
|
||||
{ ORDATA (RPFN6, rp_unit[6].FUNC, 5), REG_HRO },
|
||||
{ ORDATA (RPFN7, rp_unit[7].FUNC, 5), REG_HRO },
|
||||
{ GRDATA (FLG0, rp_unit[0].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ GRDATA (FLG1, rp_unit[1].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ GRDATA (FLG2, rp_unit[2].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ GRDATA (FLG3, rp_unit[3].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ GRDATA (FLG4, rp_unit[4].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ GRDATA (FLG5, rp_unit[5].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ GRDATA (FLG6, rp_unit[6].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ GRDATA (FLG7, rp_unit[7].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ URDATA (FNC, rp_unit[0].FUNC, 8, 5, 0, RP_NUMDR, REG_HRO) },
|
||||
{ URDATA (FLG, rp_unit[0].flags, 8, UNIT_W_UF, UNIT_V_UF - 1,
|
||||
RP_NUMDR, REG_HRO) },
|
||||
{ URDATA (CAPAC, rp_unit[0].capac, 10, 31, 0,
|
||||
RP_NUMDR, PV_LEFT | REG_HRO) },
|
||||
{ FLDATA (STOP_IOE, rp_stopioe, 0) },
|
||||
{ NULL } };
|
||||
|
||||
|
@ -828,7 +798,7 @@ case FNC_SEEK: /* seek */
|
|||
#define XBA_MBZ 0000003 /* addr<1:0> must be 0 */
|
||||
|
||||
case FNC_WRITE: /* write */
|
||||
if (uptr -> flags & UNIT_WLK) { /* write locked? */
|
||||
if (uptr -> flags & UNIT_WPRT) { /* write locked? */
|
||||
rper1[drv] = rper1[drv] | ER1_WLE; /* set drive error */
|
||||
update_rpcs (CS1_DONE | CS1_TRE, drv); /* set done, err */
|
||||
break; }
|
||||
|
@ -978,7 +948,7 @@ for (i = 0; i < RP_NUMDR; i++) {
|
|||
sim_cancel (uptr);
|
||||
uptr -> CYL = uptr -> FUNC = 0;
|
||||
if (uptr -> flags & UNIT_ATT) rpds[i] = (rpds[i] & DS_VV) |
|
||||
DS_DPR | DS_RDY | DS_MOL | ((uptr -> flags & UNIT_WLK)? DS_WRL: 0);
|
||||
DS_DPR | DS_RDY | DS_MOL | ((uptr -> flags & UNIT_WPRT)? DS_WRL: 0);
|
||||
else if (uptr -> flags & UNIT_DIS) rpds[i] = 0;
|
||||
else rpds[i] = DS_DPR;
|
||||
rper1[i] = 0; }
|
||||
|
@ -997,7 +967,7 @@ r = attach_unit (uptr, cptr);
|
|||
if (r != SCPE_OK) return r;
|
||||
drv = uptr - rp_dev.units; /* get drv number */
|
||||
rpds[drv] = DS_ATA | DS_MOL | DS_RDY | DS_DPR |
|
||||
((uptr -> flags & UNIT_WLK)? DS_WRL: 0);
|
||||
((uptr -> flags & UNIT_WPRT)? DS_WRL: 0);
|
||||
rper1[drv] = 0;
|
||||
update_rpcs (CS1_SC, drv);
|
||||
|
||||
|
@ -1032,10 +1002,10 @@ return detach_unit (uptr);
|
|||
|
||||
/* Set size command validation routine */
|
||||
|
||||
t_stat rp_set_size (UNIT *uptr, int32 value)
|
||||
t_stat rp_set_size (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
if (uptr -> flags & UNIT_ATT) return SCPE_ALATT;
|
||||
uptr -> capac = drv_tab[GET_DTYPE (value)].size;
|
||||
uptr -> capac = drv_tab[GET_DTYPE (val)].size;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
tim timer subsystem
|
||||
|
||||
02-Dec-01 RMS Fixed bug in ITS PC sampling (found by Dave Conroy)
|
||||
31-Aug-01 RMS Changed int64 to t_int64 for Windoze
|
||||
17-Jul-01 RMS Moved function prototype
|
||||
04-Jul-01 RMS Added DZ11 support
|
||||
|
@ -142,8 +143,8 @@ if (ttg <= 0) { /* timeout? */
|
|||
if (ITS) { /* ITS? */
|
||||
if (pi_act == 0) quant = (quant + TIM_HWRE) & DMASK;
|
||||
if (TSTS (pcst)) { /* PC sampling? */
|
||||
pcst = AOB (pcst); /* add 1,,1 */
|
||||
WriteP ((a10) pcst & AMASK, pager_PC); }
|
||||
WriteP ((a10) pcst & AMASK, pager_PC); /* store sample */
|
||||
pcst = AOB (pcst); } /* add 1,,1 */
|
||||
} /* end ITS */
|
||||
return SCPE_OK;
|
||||
}
|
|
@ -25,6 +25,8 @@
|
|||
|
||||
tu RH11/TM03/TU45 magtape
|
||||
|
||||
30-Nov-01 RMS Added read only unit, extended SET/SHOW support
|
||||
24-Nov-01 RMS Changed POS, FLG, UST to arrays
|
||||
23-Oct-01 RMS Fixed bug in error interrupts
|
||||
New IO page address constants
|
||||
05-Oct-01 RMS Rewrote interrupt handling from schematics
|
||||
|
@ -74,6 +76,7 @@
|
|||
#define UDENS u4 /* unit density */
|
||||
#define UD_UNK 0 /* unknown */
|
||||
#define XBUFLNT (1 << 16) /* max data buf */
|
||||
#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */
|
||||
|
||||
/* MTCS1 - 172440 - control/status 1 */
|
||||
|
||||
|
@ -300,7 +303,7 @@ t_stat tu_detach (UNIT *uptr);
|
|||
t_stat tu_boot (int32 unitno);
|
||||
void tu_go (int32 drv);
|
||||
void update_tucs (int32 flag, int32 drv);
|
||||
t_stat tu_vlock (UNIT *uptr, int32 val);
|
||||
t_stat tu_vlock (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
|
||||
/* TU data structures
|
||||
|
||||
|
@ -311,14 +314,14 @@ t_stat tu_vlock (UNIT *uptr, int32 val);
|
|||
*/
|
||||
|
||||
UNIT tu_unit[] = {
|
||||
{ UDATA (&tu_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) },
|
||||
{ UDATA (&tu_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) },
|
||||
{ UDATA (&tu_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) },
|
||||
{ UDATA (&tu_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) },
|
||||
{ UDATA (&tu_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) },
|
||||
{ UDATA (&tu_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) },
|
||||
{ UDATA (&tu_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) },
|
||||
{ UDATA (&tu_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) } };
|
||||
{ UDATA (&tu_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) },
|
||||
{ UDATA (&tu_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) },
|
||||
{ UDATA (&tu_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) },
|
||||
{ UDATA (&tu_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) },
|
||||
{ UDATA (&tu_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) },
|
||||
{ UDATA (&tu_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) },
|
||||
{ UDATA (&tu_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) },
|
||||
{ UDATA (&tu_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) } };
|
||||
|
||||
REG tu_reg[] = {
|
||||
{ ORDATA (MTCS1, tucs1, 16) },
|
||||
|
@ -338,38 +341,11 @@ REG tu_reg[] = {
|
|||
{ FLDATA (IE, tucs1, CSR_V_IE) },
|
||||
{ FLDATA (STOP_IOE, tu_stopioe, 0) },
|
||||
{ DRDATA (TIME, tu_time, 24), PV_LEFT },
|
||||
{ ORDATA (UST0, tu_unit[0].USTAT, 17) },
|
||||
{ ORDATA (UST1, tu_unit[1].USTAT, 17) },
|
||||
{ ORDATA (UST2, tu_unit[2].USTAT, 17) },
|
||||
{ ORDATA (UST3, tu_unit[3].USTAT, 17) },
|
||||
{ ORDATA (UST4, tu_unit[4].USTAT, 17) },
|
||||
{ ORDATA (UST5, tu_unit[5].USTAT, 17) },
|
||||
{ ORDATA (UST6, tu_unit[6].USTAT, 17) },
|
||||
{ ORDATA (UST7, tu_unit[7].USTAT, 17) },
|
||||
{ DRDATA (POS0, tu_unit[0].pos, 31), PV_LEFT + REG_RO },
|
||||
{ DRDATA (POS1, tu_unit[1].pos, 31), PV_LEFT + REG_RO },
|
||||
{ DRDATA (POS2, tu_unit[2].pos, 31), PV_LEFT + REG_RO },
|
||||
{ DRDATA (POS3, tu_unit[3].pos, 31), PV_LEFT + REG_RO },
|
||||
{ DRDATA (POS4, tu_unit[4].pos, 31), PV_LEFT + REG_RO },
|
||||
{ DRDATA (POS5, tu_unit[5].pos, 31), PV_LEFT + REG_RO },
|
||||
{ DRDATA (POS6, tu_unit[6].pos, 31), PV_LEFT + REG_RO },
|
||||
{ DRDATA (POS7, tu_unit[7].pos, 31), PV_LEFT + REG_RO },
|
||||
{ GRDATA (FLG0, tu_unit[0].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ GRDATA (FLG1, tu_unit[1].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ GRDATA (FLG2, tu_unit[2].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ GRDATA (FLG3, tu_unit[3].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ GRDATA (FLG4, tu_unit[4].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ GRDATA (FLG5, tu_unit[5].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ GRDATA (FLG6, tu_unit[6].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ GRDATA (FLG7, tu_unit[7].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ URDATA (UST, tu_unit[0].USTAT, 8, 17, 0, TU_NUMDR, 0) },
|
||||
{ URDATA (POS, tu_unit[0].pos, 8, 31, 0,
|
||||
TU_NUMDR, PV_LEFT | REG_RO) },
|
||||
{ URDATA (FLG, tu_unit[0].flags, 8, UNIT_W_UF, UNIT_V_UF - 1,
|
||||
TU_NUMDR, REG_HRO) },
|
||||
{ ORDATA (LOG, tu_log, 8), REG_HIDDEN },
|
||||
{ NULL } };
|
||||
|
||||
|
@ -630,7 +606,7 @@ case FNC_WRITE: /* write */
|
|||
break; }
|
||||
case FNC_WREOF: /* write tape mark */
|
||||
case FNC_ERASE: /* erase */
|
||||
if (uptr -> flags & UNIT_WLK) { /* write locked? */
|
||||
if (uptr -> flags & UNIT_WPRT) { /* write locked? */
|
||||
tuer = tuer | ER_NXF;
|
||||
break; }
|
||||
case FNC_WCHKF: /* wchk = read */
|
||||
|
@ -902,7 +878,7 @@ if (GET_FMTR (tucs2) == 0) { /* formatter present? */
|
|||
if (tu_unit[drv].flags & UNIT_ATT) {
|
||||
tufs = tufs | FS_MOL | tu_unit[drv].USTAT;
|
||||
if (tu_unit[drv].UDENS == TC_1600) tufs = tufs | FS_PE;
|
||||
if (tu_unit[drv].flags & UNIT_WLK) tufs = tufs | FS_WRL;
|
||||
if (tu_unit[drv].flags & UNIT_WPRT) tufs = tufs | FS_WRL;
|
||||
if ((tu_unit[drv].pos == 0) && !act) tufs = tufs | FS_BOT; }
|
||||
if (tuer) tufs = tufs | FS_ERR; }
|
||||
else tufs = 0;
|
||||
|
@ -984,7 +960,7 @@ return detach_unit (uptr);
|
|||
|
||||
/* Write lock/enable routine */
|
||||
|
||||
t_stat tu_vlock (UNIT *uptr, int32 val)
|
||||
t_stat tu_vlock (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
if (sim_is_active (uptr)) return SCPE_ARG;
|
||||
return SCPE_OK;
|
|
@ -25,6 +25,11 @@
|
|||
|
||||
cpu PDP-11 CPU (J-11 microprocessor)
|
||||
|
||||
25-Dec-01 RMS Cleaned up sim_inst declarations
|
||||
11-Dec-01 RMS Moved interrupt debug code
|
||||
07-Dec-01 RMS Revised to use new breakpoint package
|
||||
08-Nov-01 RMS Moved I/O to external module
|
||||
26-Oct-01 RMS Revised to use symbolic definitions for IO page
|
||||
15-Oct-01 RMS Added debug logging
|
||||
08-Oct-01 RMS Fixed bug in revised interrupt logic
|
||||
07-Sep-01 RMS Revised device disable and interrupt mechanisms
|
||||
|
@ -168,39 +173,41 @@
|
|||
4. Adding I/O devices. This requires modifications to three modules:
|
||||
|
||||
pdp11_defs.h add interrupt request definitions
|
||||
pdp11_cpu.c add I/O page linkages
|
||||
pdp11_io.c add I/O page linkages
|
||||
pdp11_sys.c add to sim_devices
|
||||
*/
|
||||
|
||||
/* Definitions */
|
||||
|
||||
#include "pdp11_defs.h"
|
||||
#include <setjmp.h>
|
||||
|
||||
#define calc_is(md) ((md) << VA_V_MODE)
|
||||
#define calc_ds(md) (calc_is((md)) | ((MMR3 & dsmask[(md)])? VA_DS: 0))
|
||||
#define calc_MMR1(val) (MMR1 = MMR1? ((val) << 8) | MMR1: (val))
|
||||
#define GET_SIGN_W(v) ((v) >> 15)
|
||||
#define GET_SIGN_B(v) ((v) >> 7)
|
||||
#define GET_Z(v) ((v) == 0)
|
||||
#define JMP_PC(x) old_PC = PC; PC = (x)
|
||||
#define BRANCH_F(x) old_PC = PC; PC = (PC + (((x) + (x)) & 0377)) & 0177777
|
||||
#define BRANCH_B(x) old_PC = PC; PC = (PC + (((x) + (x)) | 0177400)) & 0177777
|
||||
#define ILL_ADR_FLAG 0200000
|
||||
#define save_ibkpt (cpu_unit.u3) /* will be SAVEd */
|
||||
#define last_pa (cpu_unit.u4) /* and RESTOREd */
|
||||
#define calc_is(md) ((md) << VA_V_MODE)
|
||||
#define calc_ds(md) (calc_is((md)) | ((MMR3 & dsmask[(md)])? VA_DS: 0))
|
||||
#define calc_MMR1(val) (MMR1 = MMR1? ((val) << 8) | MMR1: (val))
|
||||
#define GET_SIGN_W(v) ((v) >> 15)
|
||||
#define GET_SIGN_B(v) ((v) >> 7)
|
||||
#define GET_Z(v) ((v) == 0)
|
||||
#define JMP_PC(x) old_PC = PC; PC = (x)
|
||||
#define BRANCH_F(x) old_PC = PC; PC = (PC + (((x) + (x)) & 0377)) & 0177777
|
||||
#define BRANCH_B(x) old_PC = PC; PC = (PC + (((x) + (x)) | 0177400)) & 0177777
|
||||
#define last_pa (cpu_unit.u4) /* auto save/rest */
|
||||
#define UNIT_V_18B (UNIT_V_UF) /* force 18b addr */
|
||||
#define UNIT_V_UBM (UNIT_V_UF + 1) /* bus map present */
|
||||
#define UNIT_V_RH11 (UNIT_V_UF + 2) /* RH11 Massbus */
|
||||
#define UNIT_V_CIS (UNIT_V_UF + 3) /* CIS present */
|
||||
#define UNIT_V_MSIZE (UNIT_V_UF + 4) /* dummy */
|
||||
#define UNIT_18B (1u << UNIT_V_18B)
|
||||
#define UNIT_V_CIS (UNIT_V_UF + 1) /* CIS present */
|
||||
#define UNIT_UBM (1u << UNIT_V_UBM)
|
||||
#define UNIT_RH11 (1u << UNIT_V_RH11)
|
||||
#define UNIT_CIS (1u << UNIT_V_CIS)
|
||||
#define UNIT_V_MSIZE (UNIT_V_UF + 2) /* dummy */
|
||||
#define UNIT_MSIZE (1u << UNIT_V_MSIZE)
|
||||
#define UNIT_MAP (UNIT_18B | UNIT_UBM | UNIT_RH11)
|
||||
|
||||
/* Global state */
|
||||
|
||||
extern FILE *sim_log;
|
||||
|
||||
uint16 *M = NULL; /* address of memory */
|
||||
uint16 *M = NULL; /* memory */
|
||||
int32 REGFILE[6][2] = { 0 }; /* R0-R5, two sets */
|
||||
int32 STACKFILE[4] = { 0 }; /* SP, four modes */
|
||||
int32 saved_PC = 0; /* program counter */
|
||||
|
@ -227,34 +234,36 @@ int32 MMR0 = 0; /* MMR0 - status */
|
|||
int32 MMR1 = 0; /* MMR1 - R+/-R */
|
||||
int32 MMR2 = 0; /* MMR2 - saved PC */
|
||||
int32 MMR3 = 0; /* MMR3 - 22b status */
|
||||
int32 ub_map[UBM_LNT_LW] = { 0 }; /* Unibus map array */
|
||||
int32 cpu_bme = 0; /* bus map enable */
|
||||
int32 cpu_18b = 0; /* 18b CPU config'd */
|
||||
int32 cpu_ubm = 0; /* bus map config'd */
|
||||
int32 cpu_rh11 = 0; /* RH11 config'd */
|
||||
int32 isenable = 0, dsenable = 0; /* i, d space flags */
|
||||
int32 CPUERR = 0; /* CPU error reg */
|
||||
int32 MEMERR = 0; /* memory error reg */
|
||||
int32 CCR = 0; /* cache control reg */
|
||||
int32 HITMISS = 0; /* hit/miss reg */
|
||||
int32 MAINT = (0 << 9) + (0 << 8) + (4 << 4); /* maint bit<9> = Q/U */
|
||||
/* <8> = hwre FP */
|
||||
/* <6:4> = sys type */
|
||||
int32 MAINT = MAINT_Q | MAINT_NOFPA | MAINT_KDJ; /* maint reg */
|
||||
int32 stop_trap = 1; /* stop on trap */
|
||||
int32 stop_vecabort = 1; /* stop on vec abort */
|
||||
int32 stop_spabort = 1; /* stop on SP abort */
|
||||
int32 wait_enable = 0; /* wait state enable */
|
||||
int32 pdp11_log = 0; /* logging */
|
||||
int32 ibkpt_addr = ILL_ADR_FLAG | VAMASK; /* breakpoint addr */
|
||||
int32 cpu_log = 0; /* logging */
|
||||
int32 old_PC = 0; /* previous PC */
|
||||
int32 dev_enb = (-1) & ~INT_TS; /* dev enables */
|
||||
jmp_buf save_env; /* abort handler */
|
||||
int32 dsmask[4] = { MMR3_KDS, MMR3_SDS, 0, MMR3_UDS }; /* dspace enables */
|
||||
|
||||
extern int32 sim_int_char;
|
||||
extern int32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */
|
||||
|
||||
/* Function declarations */
|
||||
|
||||
t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw);
|
||||
t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw);
|
||||
t_stat cpu_reset (DEVICE *dptr);
|
||||
t_stat cpu_svc (UNIT *uptr);
|
||||
t_stat cpu_set_size (UNIT *uptr, int32 value);
|
||||
t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
int32 GeteaB (int32 spec);
|
||||
int32 GeteaW (int32 spec);
|
||||
int32 relocR (int32 addr);
|
||||
|
@ -267,103 +276,14 @@ void WriteW (int32 data, int32 addr);
|
|||
void WriteB (int32 data, int32 addr);
|
||||
void PWriteW (int32 data, int32 addr);
|
||||
void PWriteB (int32 data, int32 addr);
|
||||
t_stat iopageR (int32 *data, int32 addr, int32 access);
|
||||
t_stat iopageW (int32 data, int32 addr, int32 access);
|
||||
int32 calc_ints (int32 nipl, int32 trq);
|
||||
|
||||
t_stat CPU_rd (int32 *data, int32 addr, int32 access);
|
||||
t_stat CPU_wr (int32 data, int32 addr, int32 access);
|
||||
t_stat APR_rd (int32 *data, int32 addr, int32 access);
|
||||
t_stat APR_wr (int32 data, int32 addr, int32 access);
|
||||
t_stat SR_MMR012_rd (int32 *data, int32 addr, int32 access);
|
||||
t_stat SR_MMR012_wr (int32 data, int32 addr, int32 access);
|
||||
t_stat MMR3_rd (int32 *data, int32 addr, int32 access);
|
||||
t_stat MMR3_wr (int32 data, int32 addr, int32 access);
|
||||
extern t_stat std_rd (int32 *data, int32 addr, int32 access);
|
||||
extern t_stat std_wr (int32 data, int32 addr, int32 access);
|
||||
extern t_stat lpt_rd (int32 *data, int32 addr, int32 access);
|
||||
extern t_stat lpt_wr (int32 data, int32 addr, int32 access);
|
||||
extern t_stat dz_rd (int32 *data, int32 addr, int32 access);
|
||||
extern t_stat dz_wr (int32 data, int32 addr, int32 access);
|
||||
extern t_stat rk_rd (int32 *data, int32 addr, int32 access);
|
||||
extern t_stat rk_wr (int32 data, int32 addr, int32 access);
|
||||
extern int32 rk_inta (void);
|
||||
extern int32 rk_enb;
|
||||
/* extern t_stat hk_rd (int32 *data, int32 addr, int32 access);
|
||||
extern t_stat hk_wr (int32 data, int32 addr, int32 access);
|
||||
extern int32 hk_inta (void);
|
||||
extern int32 hk_enb; */
|
||||
extern t_stat rl_rd (int32 *data, int32 addr, int32 access);
|
||||
extern t_stat rl_wr (int32 data, int32 addr, int32 access);
|
||||
extern int32 rl_enb;
|
||||
extern t_stat rp_rd (int32 *data, int32 addr, int32 access);
|
||||
extern t_stat rp_wr (int32 data, int32 addr, int32 access);
|
||||
extern int32 rp_inta (void);
|
||||
extern int32 rp_enb;
|
||||
extern t_stat rx_rd (int32 *data, int32 addr, int32 access);
|
||||
extern t_stat rx_wr (int32 data, int32 addr, int32 access);
|
||||
extern int32 rx_enb;
|
||||
extern t_stat dt_rd (int32 *data, int32 addr, int32 access);
|
||||
extern t_stat dt_wr (int32 data, int32 addr, int32 access);
|
||||
extern int32 dt_enb;
|
||||
extern t_stat tm_rd (int32 *data, int32 addr, int32 access);
|
||||
extern t_stat tm_wr (int32 data, int32 addr, int32 access);
|
||||
extern int32 tm_enb;
|
||||
extern t_stat ts_rd (int32 *data, int32 addr, int32 access);
|
||||
extern t_stat ts_wr (int32 data, int32 addr, int32 access);
|
||||
extern int32 ts_enb;
|
||||
|
||||
/* Auxiliary data structures */
|
||||
|
||||
struct iolink { /* I/O page linkage */
|
||||
int32 low; /* low I/O addr */
|
||||
int32 high; /* high I/O addr */
|
||||
int32 *enb; /* enable flag */
|
||||
t_stat (*read)(); /* read routine */
|
||||
t_stat (*write)(); }; /* write routine */
|
||||
extern t_stat iopageR (int32 *data, int32 addr, int32 access);
|
||||
extern t_stat iopageW (int32 data, int32 addr, int32 access);
|
||||
extern int32 calc_ints (int32 nipl, int32 trq);
|
||||
extern int32 get_vector (int32 nipl);
|
||||
|
||||
struct iolink iotable[] = {
|
||||
{ 017777740, 017777777, NULL, &CPU_rd, &CPU_wr },
|
||||
{ 017777546, 017777567, NULL, &std_rd, &std_wr },
|
||||
{ 017777514, 017777517, NULL, &lpt_rd, &lpt_wr },
|
||||
{ 017760100, 017760107, NULL, &dz_rd, &dz_wr },
|
||||
{ 017777400, 017777417, &rk_enb, &rk_rd, &rk_wr },
|
||||
/* { 017777440, 017777477, &hk_enb, &hk_rd, &hk_wr }, */
|
||||
{ 017774400, 017774411, &rl_enb, &rl_rd, &rl_wr },
|
||||
{ 017776700, 017776753, &rp_enb, &rp_rd, &rp_wr },
|
||||
{ 017777170, 017777173, &rx_enb, &rx_rd, &rx_wr },
|
||||
{ 017777340, 017777351, &dt_enb, &dt_rd, &dt_wr },
|
||||
{ 017772520, 017772533, &tm_enb, &tm_rd, &tm_wr },
|
||||
{ 017772520, 017772523, &ts_enb, &ts_rd, &ts_wr },
|
||||
{ 017777600, 017777677, NULL, &APR_rd, &APR_wr },
|
||||
{ 017772200, 017772377, NULL, &APR_rd, &APR_wr },
|
||||
{ 017777570, 017777577, NULL, &SR_MMR012_rd, &SR_MMR012_wr },
|
||||
{ 017772516, 017772517, NULL, &MMR3_rd, &MMR3_wr },
|
||||
{ 0, 0, NULL, NULL, NULL } };
|
||||
|
||||
int32 int_vec[IPL_HLVL][32] = { /* int req to vector */
|
||||
{ 0 }, /* IPL 0 */
|
||||
{ VEC_PIRQ }, /* IPL 1 */
|
||||
{ VEC_PIRQ }, /* IPL 2 */
|
||||
{ VEC_PIRQ }, /* IPL 3 */
|
||||
{ VEC_TTI, VEC_TTO, VEC_PTR, VEC_PTP, /* IPL 4 */
|
||||
VEC_LPT, VEC_PIRQ },
|
||||
{ VEC_RK, VEC_RL, VEC_RX, VEC_TM, /* IPL 5 */
|
||||
VEC_RP, VEC_TS, VEC_HK, VEC_DZRX,
|
||||
VEC_DZTX, VEC_PIRQ },
|
||||
{ VEC_CLK, VEC_DTA, VEC_PIRQ }, /* IPL 6 */
|
||||
{ VEC_PIRQ } }; /* IPL 7 */
|
||||
|
||||
int32 (*int_ack[IPL_HLVL][32])() = { /* int ack routines */
|
||||
{ NULL }, /* IPL 0 */
|
||||
{ NULL }, /* IPL 1 */
|
||||
{ NULL }, /* IPL 2 */
|
||||
{ NULL }, /* IPL 3 */
|
||||
{ NULL }, /* IPL 4 */
|
||||
{ &rk_inta, NULL, NULL, NULL, /* IPL 5 */
|
||||
&rp_inta, NULL, NULL, NULL },
|
||||
{ NULL }, /* IPL 6 */
|
||||
{ NULL } }; /* IPL 7 */
|
||||
/* Trap data structures */
|
||||
|
||||
int32 trap_vec[TRAP_V_MAX] = { /* trap req to vector */
|
||||
VEC_RED, VEC_ODD, VEC_MME, VEC_NXM,
|
||||
|
@ -390,7 +310,7 @@ int32 trap_clear[TRAP_V_MAX] = { /* trap clears */
|
|||
cpu_mod CPU modifier list
|
||||
*/
|
||||
|
||||
UNIT cpu_unit = { UDATA (&cpu_svc, UNIT_FIX + UNIT_BINK, INIMEMSIZE) };
|
||||
UNIT cpu_unit = { UDATA (NULL, UNIT_FIX + UNIT_BINK, INIMEMSIZE) };
|
||||
|
||||
REG cpu_reg[] = {
|
||||
{ ORDATA (PC, saved_PC, 16) },
|
||||
|
@ -434,7 +354,7 @@ REG cpu_reg[] = {
|
|||
{ ORDATA (STOP_TRAPS, stop_trap, TRAP_V_MAX) },
|
||||
{ FLDATA (STOP_VECA, stop_vecabort, 0) },
|
||||
{ FLDATA (STOP_SPA, stop_spabort, 0) },
|
||||
{ ORDATA (DBGLOG, pdp11_log, 16), REG_HIDDEN },
|
||||
{ ORDATA (DBGLOG, cpu_log, 16), REG_HIDDEN },
|
||||
{ ORDATA (FAC0H, FR[0].h, 32) },
|
||||
{ ORDATA (FAC0L, FR[0].l, 32) },
|
||||
{ ORDATA (FAC1H, FR[1].h, 32) },
|
||||
|
@ -550,19 +470,23 @@ REG cpu_reg[] = {
|
|||
{ GRDATA (UDPDR6, APRFILE[076], 8, 16, 0) },
|
||||
{ GRDATA (UDPAR7, APRFILE[077], 8, 16, 16) },
|
||||
{ GRDATA (UDPDR7, APRFILE[077], 8, 16, 0) },
|
||||
{ BRDATA (UBMAP, ub_map, 8, 22, UBM_LNT_LW) },
|
||||
{ FLDATA (18B_ADDR, cpu_unit.flags, UNIT_V_18B), REG_HRO },
|
||||
{ FLDATA (UB_MAP, cpu_unit.flags, UNIT_V_UBM), REG_HRO },
|
||||
{ FLDATA (RH11, cpu_unit.flags, UNIT_V_RH11), REG_HRO },
|
||||
{ FLDATA (CIS, cpu_unit.flags, UNIT_V_CIS), REG_HRO },
|
||||
{ ORDATA (OLDPC, old_PC, 16), REG_RO },
|
||||
{ ORDATA (BREAK, ibkpt_addr, 17) },
|
||||
{ ORDATA (WRU, sim_int_char, 8) },
|
||||
{ ORDATA (DEVENB, dev_enb, 32), REG_HRO },
|
||||
{ NULL} };
|
||||
|
||||
MTAB cpu_mod[] = {
|
||||
{ UNIT_18B, UNIT_18B, "18b addressing", "18B", NULL },
|
||||
{ UNIT_18B, 0, NULL, "22B", NULL },
|
||||
{ UNIT_MAP, UNIT_18B, "18b addressing", "18B", NULL },
|
||||
{ UNIT_MAP, UNIT_UBM, "22b Unibus + RH70", "URH70", NULL },
|
||||
{ UNIT_MAP, UNIT_UBM + UNIT_RH11, "22b Unibus + RH11", "URH11", NULL },
|
||||
{ UNIT_MAP, 0, "22b addressing", "22B", NULL },
|
||||
{ UNIT_CIS, UNIT_CIS, "CIS", "CIS", NULL },
|
||||
{ UNIT_CIS, 0, "No CIS", "NOCIS", NULL },
|
||||
{ UNIT_CIS, 0, "no CIS", "NOCIS", NULL },
|
||||
{ UNIT_MSIZE, 16384, NULL, "16K", &cpu_set_size},
|
||||
{ UNIT_MSIZE, 32768, NULL, "32K", &cpu_set_size},
|
||||
{ UNIT_MSIZE, 49152, NULL, "48K", &cpu_set_size},
|
||||
|
@ -595,11 +519,8 @@ t_stat sim_instr (void)
|
|||
extern int32 sim_interval;
|
||||
extern UNIT *sim_clock_queue;
|
||||
extern UNIT clk_unit;
|
||||
int32 IR, srcspec, srcreg, dstspec, dstreg;
|
||||
int32 src, src2, dst;
|
||||
int32 i, j, t, sign, oldrs, trapnum;
|
||||
int32 abortval;
|
||||
volatile int32 trapea;
|
||||
int abortval, i;
|
||||
volatile int32 trapea; /* needed at longjmp */
|
||||
t_stat reason;
|
||||
void fp11 (int32 IR);
|
||||
void cis11 (int32 IR);
|
||||
|
@ -631,7 +552,11 @@ isenable = calc_is (cm);
|
|||
dsenable = calc_ds (cm);
|
||||
|
||||
CPU_wr (PIRQ, 017777772, WRITE); /* rewrite PIRQ */
|
||||
trap_req = calc_ints (ipl, trap_req);
|
||||
cpu_bme = (MMR3 & MMR3_BME) && (cpu_unit.flags & UNIT_UBM);
|
||||
cpu_18b = cpu_unit.flags & UNIT_18B; /* export cnf flgs */
|
||||
cpu_ubm = cpu_unit.flags & UNIT_UBM;
|
||||
cpu_rh11 = cpu_unit.flags & UNIT_RH11;
|
||||
trap_req = calc_ints (ipl, trap_req); /* upd int req */
|
||||
trapea = 0;
|
||||
reason = 0;
|
||||
sim_rtc_init (clk_unit.wait); /* init clock */
|
||||
|
@ -668,41 +593,37 @@ if (abortval != 0) {
|
|||
*/
|
||||
|
||||
while (reason == 0) {
|
||||
if (sim_interval <= 0) { /* check clock queue */
|
||||
reason = sim_process_event ();
|
||||
trap_req = calc_ints (ipl, trap_req);
|
||||
continue; }
|
||||
|
||||
int32 IR, srcspec, srcreg, dstspec, dstreg;
|
||||
int32 src, src2, dst;
|
||||
int32 i, t, sign, oldrs, trapnum;
|
||||
|
||||
if (sim_interval <= 0) { /* intv cnt expired? */
|
||||
reason = sim_process_event (); /* process events */
|
||||
trap_req = calc_ints (ipl, trap_req); /* recalc int req */
|
||||
continue;
|
||||
} /* end if sim_interval */
|
||||
|
||||
if (trap_req) { /* check traps, ints */
|
||||
trapea = 0; /* assume srch fails */
|
||||
if (t = trap_req & TRAP_ALL) { /* if a trap */
|
||||
for (trapnum = 0; trapnum < TRAP_V_MAX; trapnum++) {
|
||||
if ((t >> trapnum) & 1) {
|
||||
trapea = trap_vec[trapnum];
|
||||
for (trapnum = 0; trapnum < TRAP_V_MAX; trapnum++) {
|
||||
if ((t >> trapnum) & 1) { /* trap set? */
|
||||
trapea = trap_vec[trapnum]; /* get vec, clr */
|
||||
trap_req = trap_req & ~trap_clear[trapnum];
|
||||
if ((stop_trap >> trapnum) & 1)
|
||||
reason = trapnum + 1;
|
||||
break; } /* end if t & 1 */
|
||||
} /* end for */
|
||||
} /* end if */
|
||||
else {
|
||||
for (i = IPL_HLVL - 1; (trapea == 0) && (i > ipl); i--) {
|
||||
t = int_req[i]; /* get level */
|
||||
for (j = 0; t && (j < 32); j++) { /* srch level */
|
||||
if ((t >> j) & 1) { /* irq found? */
|
||||
int_req[i] = int_req[i] & ~(1u << j);
|
||||
if (int_ack[i][j]) trapea = int_ack[i][j]();
|
||||
else trapea = int_vec[i][j];
|
||||
trapnum = TRAP_V_MAX;
|
||||
if (DBG_LOG (LOG_CPU_I)) fprintf (sim_log,
|
||||
">>CPU, lvl=%d, flag=%d, vec=%o\n",
|
||||
i, j, trapea);
|
||||
break; } /* end if t & 1 */
|
||||
} /* end for j */
|
||||
} /* end for i */
|
||||
} /* end else */
|
||||
if ((stop_trap >> trapnum) & 1) /* stop on trap? */
|
||||
reason = trapnum + 1;
|
||||
break;
|
||||
} /* end if t & 1 */
|
||||
} /* end for */
|
||||
} /* end if t */
|
||||
else { trapea = get_vector (ipl); /* get int vector */
|
||||
trapnum = TRAP_V_MAX; /* defang stk trap */
|
||||
} /* end else t*/
|
||||
if (trapea == 0) { /* nothing to do? */
|
||||
trap_req = calc_ints (ipl, 0); /* recalculate */
|
||||
continue; } /* back to fetch */
|
||||
continue; /* back to fetch */
|
||||
} /* end if trapea */
|
||||
|
||||
/* Process a trap or interrupt
|
||||
|
||||
|
@ -761,10 +682,7 @@ if (wait_state) { /* wait state? */
|
|||
else reason = STOP_WAIT;
|
||||
continue; }
|
||||
|
||||
if (PC == ibkpt_addr) { /* breakpoint? */
|
||||
save_ibkpt = ibkpt_addr; /* save bkpt */
|
||||
ibkpt_addr = ibkpt_addr | ILL_ADR_FLAG; /* disable */
|
||||
sim_activate (&cpu_unit, 1); /* sched re-enable */
|
||||
if (sim_brk_summ && sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */
|
||||
reason = STOP_IBKPT; /* stop simulation */
|
||||
continue; }
|
||||
|
||||
|
@ -2090,56 +2008,6 @@ else { pa = va & 0177777; /* mmgt off */
|
|||
return pa;
|
||||
}
|
||||
|
||||
/* I/O page lookup and linkage routines
|
||||
|
||||
Inputs:
|
||||
*data = pointer to data to read, if READ
|
||||
data = data to store, if WRITE or WRITEB
|
||||
pa = address
|
||||
access = READ, WRITE, or WRITEB
|
||||
Outputs:
|
||||
status = SCPE_OK or SCPE_NXM
|
||||
*/
|
||||
|
||||
t_stat iopageR (int32 *data, int32 pa, int32 access)
|
||||
{
|
||||
t_stat stat;
|
||||
struct iolink *p;
|
||||
|
||||
for (p = &iotable[0]; p -> low != 0; p++ ) {
|
||||
if ((pa >= p -> low) && (pa <= p -> high) &&
|
||||
((p -> enb == NULL) || *p -> enb)) {
|
||||
stat = p -> read (data, pa, access);
|
||||
trap_req = calc_ints (ipl, trap_req);
|
||||
return stat; } }
|
||||
return SCPE_NXM;
|
||||
}
|
||||
|
||||
t_stat iopageW (int32 data, int32 pa, int32 access)
|
||||
{
|
||||
t_stat stat;
|
||||
struct iolink *p;
|
||||
|
||||
for (p = &iotable[0]; p -> low != 0; p++ ) {
|
||||
if ((pa >= p -> low) && (pa <= p -> high) &&
|
||||
((p -> enb == NULL) || *p -> enb)) {
|
||||
stat = p -> write (data, pa, access);
|
||||
trap_req = calc_ints (ipl, trap_req);
|
||||
return stat; } }
|
||||
return SCPE_NXM;
|
||||
}
|
||||
|
||||
/* Calculate interrupt outstanding */
|
||||
|
||||
int32 calc_ints (int32 nipl, int32 trq)
|
||||
{
|
||||
int32 i;
|
||||
|
||||
for (i = IPL_HLVL - 1; i > nipl; i--) {
|
||||
if (int_req[i]) return (trq | TRAP_INT); }
|
||||
return (trq & ~TRAP_INT);
|
||||
}
|
||||
|
||||
/* I/O page routines for CPU registers
|
||||
|
||||
Switch register and memory management registers
|
||||
|
@ -2196,6 +2064,7 @@ if (pa & 1) return SCPE_OK;
|
|||
MMR3 = data & MMR3_RW;
|
||||
if (cpu_unit.flags & UNIT_18B)
|
||||
MMR3 = MMR3 & ~(MMR3_BME + MMR3_M22E); /* for UNIX V6 */
|
||||
cpu_bme = (MMR3 & MMR3_BME) && (cpu_unit.flags & UNIT_UBM);
|
||||
dsenable = calc_ds (cm);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
@ -2269,8 +2138,9 @@ case 2: /* MEMERR */
|
|||
case 3: /* CCR */
|
||||
*data = CCR;
|
||||
return SCPE_OK;
|
||||
case 4: /* MAint */
|
||||
*data = MAINT;
|
||||
case 4: /* MAINT */
|
||||
if (cpu_ubm) *data = MAINT | MAINT_U;
|
||||
else *data = MAINT | MAINT_Q;
|
||||
return SCPE_OK;
|
||||
case 5: /* Hit/miss */
|
||||
*data = HITMISS;
|
||||
|
@ -2378,14 +2248,19 @@ return SCPE_NXM; /* unimplemented */
|
|||
|
||||
t_stat cpu_reset (DEVICE *dptr)
|
||||
{
|
||||
int32 i;
|
||||
|
||||
PIRQ = MMR0 = MMR1 = MMR2 = MMR3 = 0;
|
||||
cpu_bme = 0;
|
||||
DR = CPUERR = MEMERR = CCR = HITMISS = 0;
|
||||
PSW = 000340;
|
||||
trap_req = 0;
|
||||
wait_state = 0;
|
||||
if (M == NULL) M = calloc (MEMSIZE >> 1, sizeof (unsigned int16));
|
||||
if (M == NULL) return SCPE_MEM;
|
||||
return cpu_svc (&cpu_unit);
|
||||
for (i = 0; i < UBM_LNT_LW; i++) ub_map[i] = 0;
|
||||
sim_brk_types = sim_brk_dflt = SWMASK ('E');
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Memory examine */
|
||||
|
@ -2423,34 +2298,25 @@ if (addr < MEMSIZE) {
|
|||
if (addr < IOPAGEBASE) return SCPE_NXM;
|
||||
return iopageW ((int32) val, addr, WRITEC);
|
||||
}
|
||||
|
||||
/* Breakpoint service */
|
||||
|
||||
t_stat cpu_svc (UNIT *uptr)
|
||||
{
|
||||
if ((ibkpt_addr & ~ILL_ADR_FLAG) == save_ibkpt) ibkpt_addr = save_ibkpt;
|
||||
save_ibkpt = -1;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Memory allocation */
|
||||
|
||||
t_stat cpu_set_size (UNIT *uptr, int32 value)
|
||||
t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
int32 mc = 0;
|
||||
t_addr i, clim;
|
||||
unsigned int16 *nM = NULL;
|
||||
|
||||
if ((value <= 0) || (value > MAXMEMSIZE) || ((value & 07777) != 0))
|
||||
if ((val <= 0) || (val > MAXMEMSIZE) || ((val & 07777) != 0))
|
||||
return SCPE_ARG;
|
||||
for (i = value; i < MEMSIZE; i = i + 2) mc = mc | M[i >> 1];
|
||||
for (i = val; i < MEMSIZE; i = i + 2) mc = mc | M[i >> 1];
|
||||
if ((mc != 0) && !get_yn ("Really truncate memory [N]?", FALSE))
|
||||
return SCPE_OK;
|
||||
nM = calloc (value >> 1, sizeof (unsigned int16));
|
||||
nM = calloc (val >> 1, sizeof (unsigned int16));
|
||||
if (nM == NULL) return SCPE_MEM;
|
||||
clim = (((t_addr) value) < MEMSIZE)? value: MEMSIZE;
|
||||
clim = (((t_addr) val) < MEMSIZE)? val: MEMSIZE;
|
||||
for (i = 0; i < clim; i = i + 2) nM[i >> 1] = M[i >> 1];
|
||||
free (M);
|
||||
M = nM;
|
||||
MEMSIZE = value;
|
||||
MEMSIZE = val;
|
||||
return SCPE_OK; }
|
|
@ -26,6 +26,9 @@
|
|||
The author gratefully acknowledges the help of Max Burnet, Megan Gentry,
|
||||
and John Wilson in resolving questions about the PDP-11
|
||||
|
||||
09-Nov-01 RMS Added bus map support
|
||||
07-Nov-01 RMS Added RQDX3 support
|
||||
26-Oct-01 RMS Added symbolic definitions for IO page
|
||||
19-Oct-01 RMS Added DZ definitions
|
||||
15-Oct-01 RMS Added logging capabilities
|
||||
07-Sep-01 RMS Revised for multilevel interrupts
|
||||
|
@ -46,6 +49,7 @@
|
|||
#define INIMEMSIZE 001000000 /* 2**18 */
|
||||
#define IOPAGEBASE 017760000 /* 2**22 - 2**13 */
|
||||
#define MAXMEMSIZE 020000000 /* 2**22 */
|
||||
#define PAMASK (MAXMEMSIZE - 1) /* 2**22 - 1 */
|
||||
#define MEMSIZE (cpu_unit.capac)
|
||||
#define ADDR_IS_MEM(x) (((t_addr) (x)) < MEMSIZE)
|
||||
#define DMASK 0177777
|
||||
|
@ -146,6 +150,16 @@
|
|||
#define VA_V_MODE 17 /* offset to mode */
|
||||
#define VA_DS (1u << VA_V_DS) /* data space flag */
|
||||
|
||||
/* Unibus map (if present) */
|
||||
|
||||
#define UBM_LNT_LW 32 /* size in LW */
|
||||
#define UBM_V_PN 13 /* page number */
|
||||
#define UBM_M_PN 037
|
||||
#define UBM_V_OFF 0 /* offset */
|
||||
#define UBM_M_OFF 017777
|
||||
#define UBM_GETPN(x) (((x) >> UBM_V_PN) & UBM_M_PN)
|
||||
#define UBM_GETOFF(x) ((x) & UBM_M_OFF)
|
||||
|
||||
/* CPUERR */
|
||||
|
||||
#define CPUE_RED 0004 /* red stack */
|
||||
|
@ -156,6 +170,17 @@
|
|||
#define CPUE_HALT 0200 /* HALT not kernel */
|
||||
#define CPUE_IMP 0374 /* implemented bits */
|
||||
|
||||
/* Maintenance register */
|
||||
|
||||
#define MAINT_V_UQ 9 /* Q/U flag */
|
||||
#define MAINT_Q (0 << MAINT_V_UQ) /* Qbus */
|
||||
#define MAINT_U (1 << MAINT_V_UQ)
|
||||
#define MAINT_V_FPA 8 /* FPA flag */
|
||||
#define MAINT_NOFPA (0 << MAINT_V_FPA)
|
||||
#define MAINT_FPA (1 << MAINT_V_FPA)
|
||||
#define MAINT_V_TYP 4 /* system type */
|
||||
#define MAINT_KDJ (4 << MAINT_V_TYP)
|
||||
|
||||
/* Floating point accumulators */
|
||||
|
||||
struct fpac {
|
||||
|
@ -233,11 +258,12 @@ typedef struct fpac fpac_t;
|
|||
|
||||
/* Simulator stop codes; codes 1:TRAP_V_MAX correspond to traps 0:TRAPMAX-1 */
|
||||
|
||||
#define STOP_HALT TRAP_V_MAX + 1 /* HALT instruction */
|
||||
#define STOP_IBKPT TRAP_V_MAX + 2 /* instruction bkpt */
|
||||
#define STOP_WAIT TRAP_V_MAX + 3 /* wait, no events */
|
||||
#define STOP_VECABORT TRAP_V_MAX + 4 /* abort vector read */
|
||||
#define STOP_SPABORT TRAP_V_MAX + 5 /* abort trap push */
|
||||
#define STOP_HALT (TRAP_V_MAX + 1) /* HALT instruction */
|
||||
#define STOP_IBKPT (TRAP_V_MAX + 2) /* instruction bkpt */
|
||||
#define STOP_WAIT (TRAP_V_MAX + 3) /* wait, no events */
|
||||
#define STOP_VECABORT (TRAP_V_MAX + 4) /* abort vector read */
|
||||
#define STOP_SPABORT (TRAP_V_MAX + 5) /* abort trap push */
|
||||
#define STOP_RQ (TRAP_V_MAX + 6) /* RQDX3 panic */
|
||||
#define IORETURN(f,v) ((f)? (v): SCPE_OK) /* cond error return */
|
||||
|
||||
/* DZ11 parameters */
|
||||
|
@ -245,6 +271,45 @@ typedef struct fpac fpac_t;
|
|||
#define DZ_MUXES 1 /* # of muxes */
|
||||
#define DZ_LINES 8 /* lines per mux */
|
||||
|
||||
/* I/O page layout */
|
||||
|
||||
#define IOBA_DZ (IOPAGEBASE + 000100) /* DZ11 */
|
||||
#define IOLN_DZ (010 * DZ_MUXES)
|
||||
#define IOBA_UBM (IOPAGEBASE + 010200) /* Unibus map */
|
||||
#define IOLN_UBM (UBM_LNT_LW * sizeof (int32))
|
||||
#define IOBA_RQ (IOPAGEBASE + 012150) /* RQDX3 */
|
||||
#define IOLN_RQ 004
|
||||
#define IOBA_APR (IOPAGEBASE + 012200) /* APRs */
|
||||
#define IOLN_APR 0200
|
||||
#define IOBA_MMR3 (IOPAGEBASE + 012516) /* MMR3 */
|
||||
#define IOLN_MMR3 002
|
||||
#define IOBA_TM (IOPAGEBASE + 012520) /* TM11 */
|
||||
#define IOLN_TM 014
|
||||
#define IOBA_TS (IOPAGEBASE + 012520) /* TS11 */
|
||||
#define IOLN_TS 004
|
||||
#define IOBA_RL (IOPAGEBASE + 014400) /* RL11 */
|
||||
#define IOLN_RL 012
|
||||
#define IOBA_RP (IOPAGEBASE + 016700) /* RP/RM */
|
||||
#define IOLN_RP 054
|
||||
#define IOBA_RX (IOPAGEBASE + 017170) /* RX11 */
|
||||
#define IOLN_RX 004
|
||||
#define IOBA_TC (IOPAGEBASE + 017340) /* TC11 */
|
||||
#define IOLN_TC 012
|
||||
#define IOBA_RK (IOPAGEBASE + 017400) /* RK11 */
|
||||
#define IOLN_RK 020
|
||||
#define IOBA_RK6 (IOPAGEBASE + 017440) /* RK611 */
|
||||
#define IOLN_RK6 040
|
||||
#define IOBA_LPT (IOPAGEBASE + 017514) /* LP11 */
|
||||
#define IOLN_LPT 004
|
||||
#define IOBA_STD (IOPAGEBASE + 017546) /* KW11L, DL11, PC11 */
|
||||
#define IOLN_STD 022
|
||||
#define IOBA_SRMM (IOPAGEBASE + 017570) /* SR, MMR0-2 */
|
||||
#define IOLN_SRMM 010
|
||||
#define IOBA_APR1 (IOPAGEBASE + 017600) /* APRs */
|
||||
#define IOLN_APR1 0100
|
||||
#define IOBA_CPU (IOPAGEBASE + 017740) /* CPU reg */
|
||||
#define IOLN_CPU 040
|
||||
|
||||
/* Interrupt assignments; within each level, priority is right to left */
|
||||
|
||||
#define IPL_HLVL 8 /* # int levels */
|
||||
|
@ -262,9 +327,10 @@ typedef struct fpac fpac_t;
|
|||
#define INT_V_RP 4
|
||||
#define INT_V_TS 5
|
||||
#define INT_V_HK 6
|
||||
#define INT_V_DZRX 7
|
||||
#define INT_V_DZTX 8
|
||||
#define INT_V_PIR5 9
|
||||
#define INT_V_RQ 7
|
||||
#define INT_V_DZRX 8
|
||||
#define INT_V_DZTX 9
|
||||
#define INT_V_PIR5 10
|
||||
|
||||
#define INT_V_TTI 0 /* BR4 */
|
||||
#define INT_V_TTO 1
|
||||
|
@ -287,7 +353,8 @@ typedef struct fpac fpac_t;
|
|||
#define INT_TM (1u << INT_V_TM)
|
||||
#define INT_RP (1u << INT_V_RP)
|
||||
#define INT_TS (1u << INT_V_TS)
|
||||
#define INT_HK (1u << INT_V_HK)
|
||||
#define INT_RK6 (1u << INT_V_HK)
|
||||
#define INT_RQ (1u << INT_V_RQ)
|
||||
#define INT_DZRX (1u << INT_V_DZRX)
|
||||
#define INT_DZTX (1u << INT_V_DZTX)
|
||||
#define INT_PIR5 (1u << INT_V_PIR5)
|
||||
|
@ -309,7 +376,8 @@ typedef struct fpac fpac_t;
|
|||
#define IPL_TM 5
|
||||
#define IPL_RP 5
|
||||
#define IPL_TS 5
|
||||
#define IPL_HK 5
|
||||
#define IPL_RK6 5
|
||||
#define IPL_RQ 5
|
||||
#define IPL_DZRX 5
|
||||
#define IPL_DZTX 5
|
||||
#define IPL_PTR 4
|
||||
|
@ -326,16 +394,18 @@ typedef struct fpac fpac_t;
|
|||
#define IPL_PIR2 2
|
||||
#define IPL_PIR1 1
|
||||
|
||||
#define VEC_PIRQ 0240 /* interrupt vectors */
|
||||
#define VEC_Q 0000 /* vector base */
|
||||
#define VEC_PIRQ 0240
|
||||
#define VEC_TTI 0060
|
||||
#define VEC_TTO 0064
|
||||
#define VEC_PTR 0070
|
||||
#define VEC_PTP 0074
|
||||
#define VEC_CLK 0100
|
||||
#define VEC_LPT 0200
|
||||
#define VEC_HK 0210
|
||||
#define VEC_RK 0220
|
||||
#define VEC_RQ 0154
|
||||
#define VEC_RL 0160
|
||||
#define VEC_LPT 0200
|
||||
#define VEC_RK6 0210
|
||||
#define VEC_RK 0220
|
||||
#define VEC_DTA 0214
|
||||
#define VEC_TM 0224
|
||||
#define VEC_TS 0224
|
||||
|
@ -347,15 +417,15 @@ typedef struct fpac fpac_t;
|
|||
/* Interrupt macros */
|
||||
|
||||
#define IREQ(dv) int_req[IPL_##dv]
|
||||
#define SET_INT(dv) IREQ(dv) = IREQ(dv) | (INT_##dv)
|
||||
#define CLR_INT(dv) IREQ(dv) = IREQ(dv) & ~(INT_##dv)
|
||||
#define SET_INT(dv) int_req[IPL_##dv] = int_req[IPL_##dv] | (INT_##dv)
|
||||
#define CLR_INT(dv) int_req[IPL_##dv] = int_req[IPL_##dv] & ~(INT_##dv)
|
||||
|
||||
/* CPU and FPU macros */
|
||||
|
||||
#define update_MM ((MMR0 & (MMR0_FREEZE + MMR0_MME)) == MMR0_MME)
|
||||
#define setTRAP(name) trap_req = trap_req | (name)
|
||||
#define setCPUERR(name) CPUERR = CPUERR | (name)
|
||||
#define ABORT(val) longjmp (save_env, (val))
|
||||
#define update_MM ((MMR0 & (MMR0_FREEZE + MMR0_MME)) == MMR0_MME)
|
||||
#define setTRAP(name) trap_req = trap_req | (name)
|
||||
#define setCPUERR(name) CPUERR = CPUERR | (name)
|
||||
#define ABORT(val) longjmp (save_env, (val))
|
||||
#define SP R[6]
|
||||
#define PC R[7]
|
||||
|
||||
|
@ -364,9 +434,21 @@ typedef struct fpac fpac_t;
|
|||
#define LOG_CPU_I 00000001
|
||||
#define LOG_RP 00000010
|
||||
#define LOG_TS 00000020
|
||||
#define LOG_RQ 00000040
|
||||
#define LOG_TC_MS 00000100
|
||||
#define LOG_TC_RW 00000200
|
||||
#define LOG_TC_RA 00000400
|
||||
#define LOG_TC_BL 00001000
|
||||
|
||||
#define DBG_LOG(x) (sim_log && (pdp11_log & (x)))
|
||||
#define DBG_LOG(x) (sim_log && (cpu_log & (x)))
|
||||
|
||||
/* Function prototypes */
|
||||
|
||||
#define QB 0 /* Q22 native */
|
||||
#define UB 1 /* Unibus */
|
||||
|
||||
t_bool Map_Addr (t_addr qa, t_addr *ma);
|
||||
int32 Map_ReadB (t_addr ba, int32 bc, uint8 *buf, t_bool ub);
|
||||
int32 Map_ReadW (t_addr ba, int32 bc, uint16 *buf, t_bool ub);
|
||||
int32 Map_WriteB (t_addr ba, int32 bc, uint8 *buf, t_bool ub);
|
||||
int32 Map_WriteW (t_addr ba, int32 bc, uint16 *buf, t_bool ub);
|
868
PDP11/pdp11_doc.txt
Normal file
868
PDP11/pdp11_doc.txt
Normal file
|
@ -0,0 +1,868 @@
|
|||
To: Users
|
||||
From: Bob Supnik
|
||||
Subj: PDP-11 Simulator Usage
|
||||
Date: 1-Dec-01
|
||||
|
||||
COPYRIGHT NOTICE
|
||||
|
||||
The following copyright notice applies to both the SIMH source and binary:
|
||||
|
||||
Original code published in 1993-2001, written by Robert M Supnik
|
||||
Copyright (c) 1993-2001, Robert M Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation
|
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
and/or sell copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
Except as contained in this notice, the name of Robert M Supnik shall not
|
||||
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
This memorandum documents the PDP-11 simulator.
|
||||
|
||||
|
||||
1. Simulator Files
|
||||
|
||||
sim/ sim_defs.h
|
||||
sim_sock.h
|
||||
sim_tmxr.h
|
||||
dec_dz.h
|
||||
dec_mscp.h
|
||||
dec_uqssp.h
|
||||
scp.c
|
||||
scp_tty.c
|
||||
sim_rev.c
|
||||
sim_sock.c
|
||||
sim_tmxr.c
|
||||
|
||||
sim/pdp11/ pdp11_defs.h
|
||||
pdp11_cpu.c
|
||||
pdp11_dz.c
|
||||
pdp11_fp.c
|
||||
pdp11_io.c
|
||||
pdp11_lp.c
|
||||
pdp11_rk.c
|
||||
pdp11_rl.c
|
||||
pdp11_rp.c
|
||||
pdp11_rq.c
|
||||
pdp11_rx.c
|
||||
pdp11_stddev.c
|
||||
pdp11_sys.c
|
||||
pdp11_tc.c
|
||||
pdp11_tm.c
|
||||
pdp11_ts.c
|
||||
|
||||
2. PDP-11 Features
|
||||
|
||||
The PDP-11 simulator is configured as follows:
|
||||
|
||||
device simulates
|
||||
name(s)
|
||||
|
||||
CPU J-11 CPU with 256KB of memory
|
||||
- FP11 floating point unit (FPA)
|
||||
- CIS11 commercial instruction set (CIS, off by default)
|
||||
PTR,PTP PC11 paper tape reader/punch
|
||||
TTI,TTO DL11 console terminal
|
||||
LPT LP11 line printer
|
||||
CLK line frequency clock
|
||||
DZ DZ11 8-line terminal multiplexor
|
||||
RK RK11/RK05 cartridge disk controller with eight drives
|
||||
RL RLV12/RL01(2) cartridge disk controller with four drives
|
||||
RP RM02/03/05/80, RP04/05/06/07 Massbus style controller
|
||||
with eight drives
|
||||
RQ RQDX3 MSCP controller with four drives
|
||||
RX RX11/RX01 floppy disk controller with two drives
|
||||
TC TC11/TU56 DECtape controller with eight drives
|
||||
TM TM11/TU10 magnetic tape controller with eight drives
|
||||
TS TS11/TSV05 magnetic tape controller with one drive
|
||||
|
||||
The DZ, RK, RL, RP, RQ, RX, TC, TM, and TS devices can be DISABLEd. The
|
||||
PDP-11 can support either a TM11 or a TS11, but not both, since they use
|
||||
the same I/O addresses. The simulator defaults to the TM11. To change
|
||||
the magtape,
|
||||
|
||||
ENABLE TM11 enable TM11 and disable TS11
|
||||
ENABLE TS11 enable TS11 and disable TM11
|
||||
|
||||
The PDP-11 simulator implements several unique stop conditions:
|
||||
|
||||
- abort during exception vector fetch, and register STOP_VEC is set
|
||||
- abort during exception stack push, and register STOP_SPA is set
|
||||
- trap condition 'n' occurs, and register STOP_TRAP<n> is set
|
||||
- wait state entered, and no I/O operations outstanding
|
||||
(ie, no interrupt can ever occur)
|
||||
|
||||
The PDP-11 loader supports standard binary format tapes. The DUMP command
|
||||
is not implemented.
|
||||
|
||||
2.1 CPU
|
||||
|
||||
The CPU options include CPU mapping configuration (18b Unibus, 22b Unibus
|
||||
with RH70-style controllers, 22b Unibus with RH11 style controllers, and
|
||||
22b Qbus), the CIS instruction set, and the size of main memory.
|
||||
|
||||
SET CPU 18B 18b addressing, no I/O map
|
||||
SET CPU URH11 22b addresssing, Unibus I/O map,
|
||||
18b mapped RH11 controller
|
||||
SET CPU URH70 22b addressing, Unibus I/O map,
|
||||
22b unmapped RH70 controller
|
||||
SET CPU 22B 22b addressing, no I/O map (Qbus)
|
||||
SET CPU NOCIS disable CIS instructions (default)
|
||||
SET CPU CIS enable CIS instructions
|
||||
SET CPU 16K set memory size = 16KB
|
||||
SET CPU 32K set memory size = 32KB
|
||||
SET CPU 48K set memory size = 48KB
|
||||
SET CPU 64K set memory size = 64KB
|
||||
SET CPU 96K set memory size = 96KB
|
||||
SET CPU 128K set memory size = 128KB
|
||||
SET CPU 192K set memory size = 192KB
|
||||
SET CPU 256K set memory size = 256KB
|
||||
SET CPU 384K set memory size = 384KB
|
||||
SET CPU 512K set memory size = 512KB
|
||||
SET CPU 768K set memory size = 768KB
|
||||
SET CPU 1024K (or 1M) set memory size = 1024KB
|
||||
SET CPU 2048K (or 2M) set memory size = 2048KB
|
||||
SET CPU 3072K (or 3M) set memory size = 3072KB
|
||||
SET CPU 4096K (or 4M) set memory size = 4096KB
|
||||
|
||||
If memory size is being reduced, and the memory being truncated contains
|
||||
non-zero data, the simulator asks for confirmation. Data in the truncated
|
||||
portion of memory is lost. Initial memory size is 256KB.
|
||||
|
||||
These switches are recognized when examining or depositing in CPU memory:
|
||||
|
||||
-v interpret address as virtual
|
||||
-d if mem mgt enabled, force data space
|
||||
-k if mem mgt enabled, force kernel mode
|
||||
-s if mem mgt enabled, force supervisor mode
|
||||
-u if mem mgt enabled, force user mode
|
||||
-p if mem mgt enabled, force previous mode
|
||||
|
||||
CPU registers include the visible state of the processor as well as the
|
||||
control registers for the interrupt system.
|
||||
|
||||
name size comments
|
||||
|
||||
PC 16 program counter
|
||||
R0..R5 16 R0..R5, first register set
|
||||
R10..R15 16 R0..R5, second register set
|
||||
KSP 16 kernel stack pointer
|
||||
SSP 16 supervisor stack pointer
|
||||
USP 16 user stack pointer
|
||||
PSW 16 processor status word
|
||||
CM 2 current mode, PSW<15:14>
|
||||
PM 2 previous mode, PSW<13:12>
|
||||
RS 2 register set, PSW<11>
|
||||
IPL 3 interrupt priority level, PSW<7:5>
|
||||
T 1 trace bit, PSW<4>
|
||||
N 1 negative flag, PSW<3>
|
||||
Z 1 zero flag, PSW<2>
|
||||
V 1 overflow flag, PSW<1>
|
||||
C 1 carry flag, PSW<0>
|
||||
SR 16 front panel switches
|
||||
DR 16 front panel display
|
||||
MEMERR 16 memory error register
|
||||
CCR 16 cache control register
|
||||
MAINT 16 maintenance register
|
||||
HITMISS 16 hit/miss register
|
||||
CPUERR 16 CPU error register
|
||||
PIRQ 16 programmed interrupt requests
|
||||
FAC0H..FAC5H 32 FAC0..FAC5, high 32 bits
|
||||
FAC0L..FAC5L 32 FAC0..FAC5, low 32 bits
|
||||
FPS 16 floating point status
|
||||
FEA 16 floating exception address
|
||||
FEC 4 floating exception code
|
||||
MMR0..3 16 memory management registers 0..3
|
||||
{K/S/U}{I/D}{PAR/PDR}{0..7}
|
||||
16 memory management registers
|
||||
UBMAP[0:63] 16 Unibus map registers
|
||||
INT 32 interrupt pending flags
|
||||
TRAP 18 trap pending flags
|
||||
WAIT 0 wait state flag
|
||||
WAIT_ENABLE 0 wait state enable flag
|
||||
STOP_TRAPS 18 stop on trap flags
|
||||
STOP_VECA 1 stop on read abort in trap or interrupt
|
||||
STOP_SPA 1 stop on stack push abort in trap or interrupt
|
||||
OLDPC 16 PC prior to last JMP, JMS, or interrupt
|
||||
WRU 8 interrupt character
|
||||
|
||||
2.2 Programmed I/O Devices
|
||||
|
||||
2.2.1 PC11 Paper Tape Reader (PTR)
|
||||
|
||||
The paper tape reader (PTR) reads data from a disk file. The POS
|
||||
register specifies the number of the next data item to be read. Thus,
|
||||
by changing POS, the user can backspace or advance the reader.
|
||||
|
||||
The paper tape reader implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
BUF 8 last data item processed
|
||||
CSR 16 control/status register
|
||||
INT 1 interrupt pending flag
|
||||
ERR 1 error flag (CSR<15>)
|
||||
BUSY 1 busy flag (CSR<11>)
|
||||
DONE 1 device done flag (CSR<7>)
|
||||
IE 1 interrupt enable flag (CSR<6>)
|
||||
POS 31 position in the input file
|
||||
TIME 24 time from I/O initiation to interrupt
|
||||
STOP_IOE 1 stop on I/O error
|
||||
|
||||
Error handling is as follows:
|
||||
|
||||
error STOP_IOE processed as
|
||||
|
||||
not attached 1 report error and stop
|
||||
0 out of tape
|
||||
|
||||
end of file 1 report error and stop
|
||||
0 out of tape
|
||||
|
||||
OS I/O error x report error and stop
|
||||
|
||||
2.2.2 PC11 Paper Tape Punch (PTP)
|
||||
|
||||
The paper tape punch (PTP) writes data to a disk file. The POS
|
||||
register specifies the number of the next data item to be written.
|
||||
Thus, by by changing POS, the user can backspace or advance the punch.
|
||||
|
||||
The paper tape punch implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
BUF 8 last data item processed
|
||||
CSR 16 control/status register
|
||||
INT 1 interrupt pending flag
|
||||
ERR 1 error flag (CSR<15>)
|
||||
DONE 1 device done flag (CSR<7>)
|
||||
IE 1 interrupt enable flag (CSR<6>)
|
||||
POS 31 position in the output file
|
||||
TIME 24 time from I/O initiation to interrupt
|
||||
STOP_IOE 1 stop on I/O error
|
||||
|
||||
Error handling is as follows:
|
||||
|
||||
error STOP_IOE processed as
|
||||
|
||||
not attached 1 report error and stop
|
||||
0 out of tape
|
||||
|
||||
OS I/O error x report error and stop
|
||||
|
||||
2.2.3 DL11 Terminal Input (TTI)
|
||||
|
||||
The terminal input (TTI) polls the console keyboard for input. It
|
||||
implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
BUF 8 last data item processed
|
||||
CSR 16 control/status register
|
||||
INT 1 interrupt pending flag
|
||||
ERR 1 error flag (CSR<15>)
|
||||
DONE 1 device done flag (CSR<7>)
|
||||
IE 1 interrupt enable flag (CSR<6>)
|
||||
POS 31 number of characters input
|
||||
TIME 24 keyboard polling interval
|
||||
|
||||
2.2.4 DL11 Terminal Output (TTO)
|
||||
|
||||
The terminal output (TTO) writes to the simulator console window. It
|
||||
implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
BUF 8 last data item processed
|
||||
CSR 16 control/status register
|
||||
INT 1 interrupt pending flag
|
||||
ERR 1 error flag (CSR<15>)
|
||||
DONE 1 device done flag (CSR<7>)
|
||||
IE 1 interrupt enable flag (CSR<6>)
|
||||
POS 31 number of characters input
|
||||
TIME 24 time from I/O initiation to interrupt
|
||||
|
||||
2.2.5 LP11 Line Printer (LPT)
|
||||
|
||||
The line printer (LPT) writes data to a disk file. The POS register
|
||||
specifies the number of the next data item to be written. Thus,
|
||||
by changing POS, the user can backspace or advance the printer.
|
||||
|
||||
The line printer implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
BUF 8 last data item processed
|
||||
CSR 16 control/status register
|
||||
INT 1 interrupt pending flag
|
||||
ERR 1 error flag (CSR<15>)
|
||||
DONE 1 device done flag (CSR<7>)
|
||||
IE 1 interrupt enable flag (CSR<6>)
|
||||
POS 31 position in the output file
|
||||
TIME 24 time from I/O initiation to interrupt
|
||||
STOP_IOE 1 stop on I/O error
|
||||
|
||||
Error handling is as follows:
|
||||
|
||||
error STOP_IOE processed as
|
||||
|
||||
not attached 1 report error and stop
|
||||
0 out of paper
|
||||
|
||||
OS I/O error x report error and stop
|
||||
|
||||
2.2.6 Line-Time Clock (CLK)
|
||||
|
||||
The clock (CLK) implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
CSR 16 control/status register
|
||||
INT 1 interrupt pending flag
|
||||
DONE 1 device done flag (CSR<7>)
|
||||
IE 1 interrupt enable flag (CSR<6>)
|
||||
TIME 24 clock frequency
|
||||
TPS 8 ticks per second (60 or 50)
|
||||
|
||||
The real-time clock autocalibrates; the clock interval is adjusted up or
|
||||
down so that the clock tracks actual elapsed time.
|
||||
|
||||
2.2.7 DZ11 Terminal Multiplexor (DZ)
|
||||
|
||||
The DZ11 is an 8-line terminal multiplexor. The terminal lines perform
|
||||
input and output through Telnet sessions connected to a user-specified
|
||||
port. The ATTACH command specifies the port to be used:
|
||||
|
||||
ATTACH {-am} DZ <port>(cr) -- set up listening port
|
||||
|
||||
where port is a decimal number between 1 and 65535 that is not being used
|
||||
for other TCP/IP activities. The optional switch -m turns on the DZ11's
|
||||
modem controls; the optional switch -a turns on active disconnects
|
||||
(disconnect session if computer clears Data Terminal Ready).
|
||||
|
||||
Once the DZ is attached and the simulator is running, the DZ will listen
|
||||
for connections on the specified port. It assumes that the incoming
|
||||
connections are Telnet connections. The connection remains open until
|
||||
disconnected either by the simulated program or by the Telnet client.
|
||||
|
||||
The SHOW DZ LINESTATUS command displays the current connections to the DZ.
|
||||
|
||||
The DZ11 implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
CSR 16 control/status register
|
||||
RBUF 16 receive buffer
|
||||
LPR 16 line parameter register
|
||||
TCR 16 transmission control register
|
||||
MSR 16 modem status register
|
||||
TDR 16 transmit data register
|
||||
SAENB 1 silo alarm enabled
|
||||
MDMTCL 1 modem control enabled
|
||||
AUTODS 1 autodisconnect enabled
|
||||
RPOS0..7 32 count of characters received
|
||||
TPOS0..7 32 count of characters transmitted
|
||||
|
||||
The DZ11 does not support save and restore. All open connections are
|
||||
lost when the simulator shuts down or the DZ is detached.
|
||||
|
||||
2.3 RK11/RK05 Cartridge Disk (RK)
|
||||
|
||||
RK11 options include the ability to make units write enabled or write locked:
|
||||
|
||||
SET RKn LOCKED set unit n write locked
|
||||
SET RKn ENABLED set unit n write enabled
|
||||
|
||||
Units can also be REMOVEd or ADDed to the configuration. The RK11 supports
|
||||
the BOOT command.
|
||||
|
||||
The RK11 implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
RKCS 16 control/status
|
||||
RKDA 16 disk address
|
||||
RKBA 16 memory address
|
||||
RKWC 16 word count
|
||||
RKDS 16 drive status
|
||||
RKER 16 error status
|
||||
INTQ 9 interrupt queue
|
||||
DRVN 3 number of last selected drive
|
||||
INT 1 interrupt pending flag
|
||||
ERR 1 error flag (CSR<15>)
|
||||
DONE 1 device done flag (CSR<7>)
|
||||
IE 1 interrupt enable flag (CSR<6>)
|
||||
INT 1 interrupt pending flag
|
||||
STIME 24 seek time, per cylinder
|
||||
RTIME 24 rotational delay
|
||||
STOP_IOE 1 stop on I/O error
|
||||
|
||||
Error handling is as follows:
|
||||
|
||||
error STOP_IOE processed as
|
||||
|
||||
not attached 1 report error and stop
|
||||
0 disk not ready
|
||||
|
||||
end of file x assume rest of disk is zero
|
||||
|
||||
OS I/O error x report error and stop
|
||||
|
||||
2.4 RX11/RX01 Floppy Disk (RX)
|
||||
|
||||
RX11 options include the ability to make units write enabled or write locked:
|
||||
|
||||
SET RXn LOCKED set unit n write locked
|
||||
SET RXn ENABLED set unit n write enabled
|
||||
|
||||
The RX11 supports the BOOT command.
|
||||
|
||||
The RX11 implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
RXCS 12 status
|
||||
RXDB 8 data buffer
|
||||
RXES 8 error status
|
||||
RXERR 8 error code
|
||||
RXTA 8 current track
|
||||
RXSA 8 current sector
|
||||
STAPTR 3 controller state
|
||||
BUFPTR 3 buffer pointer
|
||||
INT 1 interrupt pending flag
|
||||
ERR 1 error flag (CSR<15>)
|
||||
TR 1 transfer ready flag (CSR<7>)
|
||||
IE 1 interrupt enable flag (CSR<6>)
|
||||
DONE 1 device done flag (CSR<5>)
|
||||
CTIME 24 command completion time
|
||||
STIME 24 seek time, per track
|
||||
XTIME 24 transfer ready delay
|
||||
STOP_IOE 1 stop on I/O error
|
||||
SBUF[0:127] 8 sector buffer array
|
||||
|
||||
Error handling is as follows:
|
||||
|
||||
error STOP_IOE processed as
|
||||
|
||||
not attached 1 report error and stop
|
||||
0 disk not ready
|
||||
|
||||
RX01 data files are buffered in memory; therefore, end of file and OS
|
||||
I/O errors cannot occur.
|
||||
|
||||
2.5 RL11(V12)/RL01,RL02 Cartridge Disk (RL)
|
||||
|
||||
RL11 options include the ability to set units write enabled or write locked,
|
||||
to set the drive size to RL01, RL02, or autosize, and to write a DEC standard
|
||||
044 compliant bad block table on the last track:
|
||||
|
||||
SET RLn LOCKED set unit n write locked
|
||||
SET RLn ENABLED set unit n write enabled
|
||||
SET RLn RL01 set size to RL01
|
||||
SET RLn RL02 set size to RL02
|
||||
SET RLn AUTOSIZE set size based on file size at attach
|
||||
SET RLn BADBLOCK write bad block table on last track
|
||||
|
||||
The size options can be used only when a unit is not attached to a file. The
|
||||
bad block option can be used only when a unit is attached to a file. Units
|
||||
can also be REMOVEd or ADDed to the configuration. The RL11 supports the
|
||||
BOOT command.
|
||||
|
||||
The RL11 implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
RLCS 16 control/status
|
||||
RLDA 16 disk address
|
||||
RLBA 16 memory address
|
||||
RLBAE 6 memory address extension (RLV12)
|
||||
RLMP..RLMP2 16 multipurpose register queue
|
||||
INT 1 interrupt pending flag
|
||||
ERR 1 error flag (CSR<15>)
|
||||
DONE 1 device done flag (CSR<7>)
|
||||
IE 1 interrupt enable flag (CSR<6>)
|
||||
STIME 24 seek time, per cylinder
|
||||
RTIME 24 rotational delay
|
||||
STOP_IOE 1 stop on I/O error
|
||||
|
||||
Error handling is as follows:
|
||||
|
||||
error STOP_IOE processed as
|
||||
|
||||
not attached 1 report error and stop
|
||||
0 disk not ready
|
||||
|
||||
end of file x assume rest of disk is zero
|
||||
|
||||
OS I/O error x report error and stop
|
||||
|
||||
2.6 RM02/03/05/80, RP04/05/06/07 Disk Pack Drives (RP)
|
||||
|
||||
The RP controller implements a "Massbus style" 22b direct interface for
|
||||
large disk drives. It is more abstract than other device simulators, with
|
||||
just enough detail to run operating system drivers. In addition, the RP
|
||||
controller conflates the details of the RM series controllers with the RP
|
||||
series controllers, although there were detailed differences.
|
||||
|
||||
RP options include the ability to set units write enabled or write locked,
|
||||
to set the drive type to one of six disk types, or autosize, and to write
|
||||
a DEC standard 044 compliant bad block table on the last track:
|
||||
|
||||
SET RPn LOCKED set unit n write locked
|
||||
SET RPn ENABLED set unit n write enabled
|
||||
SET RPn RM03 set type to RM03
|
||||
SET RPn RM05 set type to RM05
|
||||
SET RPn RM80 set type to RM80
|
||||
SET RPn RP04 set type to RP04
|
||||
SET RPn RP06 set type to RP06
|
||||
SET RPn RP07 set type to RP07
|
||||
SET RPn AUTOSIZE set type based on file size at attach
|
||||
SET RPn BADBLOCK write bad block table on last track
|
||||
|
||||
The type options can be used only when a unit is not attached to a file. The
|
||||
bad block option can be used only when a unit is attached to a file. Units
|
||||
can also be REMOVEd or ADDed to the configuration. The RP controller supports
|
||||
the BOOT command.
|
||||
|
||||
The RP controller implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
RPCS1 16 control/status 1
|
||||
RPWC 16 word count
|
||||
RPBA 16 bus address
|
||||
RPDA 16 desired surface, sector
|
||||
RPCS2 16 control/status 2
|
||||
RPDS[0:7] 16 drive status, drives 0-7
|
||||
RPER1[0:7] 16 drive errors, drives 0-7
|
||||
RPOF 16 offset
|
||||
RPDC 8 desired cylinder
|
||||
RPER2 16 error status 2
|
||||
RPER3 16 error status 3
|
||||
RPEC1 16 ECC syndrome 1
|
||||
RPEC2 16 ECC syndrome 2
|
||||
RPMR 16 maintenance register
|
||||
RPDB 16 data buffer
|
||||
RPBAE 6 bus address extension
|
||||
RPCS3 16 control/status 3
|
||||
IFF 1 transfer complete interrupt request flop
|
||||
INT 1 interrupt pending flag
|
||||
SC 1 special condition (CSR1<15>)
|
||||
DONE 1 device done flag (CSR1<7>)
|
||||
IE 1 interrupt enable flag (CSR1<6>)
|
||||
STIME 24 seek time, per cylinder
|
||||
RTIME 24 rotational delay
|
||||
STOP_IOE 1 stop on I/O error
|
||||
|
||||
Error handling is as follows:
|
||||
|
||||
error STOP_IOE processed as
|
||||
|
||||
not attached 1 report error and stop
|
||||
0 disk not ready
|
||||
|
||||
end of file x assume rest of disk is zero
|
||||
|
||||
OS I/O error x report error and stop
|
||||
|
||||
2.7 RQDX3 MSCP Disk Controller (RQ)
|
||||
|
||||
The RQ controller simulates the RQDX3 MSCP disk controller. RQ options
|
||||
include the ability to set units write enabled or write locked, and to
|
||||
set the drive type to one of eleven disk types:
|
||||
|
||||
SET RQn LOCKED set unit n write locked
|
||||
SET RQn ENABLED set unit n write enabled
|
||||
SET RQn RX50 set type to RX50
|
||||
SET RQn RX33 set type to RX33
|
||||
SET RQn RD51 set type to RD51
|
||||
SET RQn RD52 set type to RD52
|
||||
SET RQn RD53 set type to RD53
|
||||
SET RQn RD54 set type to RD54
|
||||
SET RQn RD31 set type to RD31
|
||||
SET RQn RA82 set type to RA82
|
||||
SET RQn RA72 set type to RA72
|
||||
SET RQn RA90 set type to RA90
|
||||
SET RQn RA92 set type to RA92
|
||||
|
||||
The type options can be used only when a unit is not attached to a file.
|
||||
Units can also be REMOVEd or ADDed to the configuration. The RQ controller
|
||||
supports the BOOT command.
|
||||
|
||||
The RQ controller implements the following special SHOW commands:
|
||||
|
||||
SHOW RQ RINGS show command and response rings
|
||||
SHOW RQ FREEQ show packet free queue
|
||||
SHOW RQ RESPQ show packet response queue
|
||||
SHOW RQ UNITQ show unit queues
|
||||
SHOW RQ ALL show all ring and queue state
|
||||
SHOW RQn UNITQ show unit queues for unit n
|
||||
|
||||
The RQ controller implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
SA 16 status/address register
|
||||
S1DAT 16 step 1 init host data
|
||||
CQBA 22 command queue base address
|
||||
CQLNT 8 command queue length
|
||||
CQIDX 8 command queue index
|
||||
RQBA 22 request queue base address
|
||||
RQLNT 8 request queue length
|
||||
RQIDX 8 request queue index
|
||||
FREE 5 head of free packet list
|
||||
RESP 5 head of response packet list
|
||||
PBSY 5 number of busy packets
|
||||
CFLGS 16 controller flags
|
||||
CSTA 4 controller state
|
||||
PERR 9 port error number
|
||||
CRED 5 host credits
|
||||
HAT 16 host available timer
|
||||
HTMO 17 host timeout value
|
||||
CPKT[0:3] 5 current packet, units 0-3
|
||||
PKTQ[0:3] 5 packet queue, units 0-3
|
||||
UFLG[0:3] 16 unit flags, units 0-3
|
||||
INT 1 interrupt request
|
||||
QTIME 24 response time for 'immediate' packets
|
||||
XTIME 24 response time for data transfers
|
||||
PKTS[33*32] 16 packet buffers, 33W each,
|
||||
32 entries
|
||||
|
||||
Error handling is as follows:
|
||||
|
||||
error processed as
|
||||
|
||||
not attached disk not ready
|
||||
|
||||
end of file assume rest of disk is zero
|
||||
|
||||
OS I/O error report error and stop
|
||||
|
||||
2.8 TC11/TU56 DECtape (DT)
|
||||
|
||||
DECtapes drives are numbered 1-8; in the simulator, drive 8 is unit 0.
|
||||
DECtape options include the ability to make units write enabled or write
|
||||
locked.
|
||||
|
||||
SET DTn LOCKED set unit n write locked
|
||||
SET DTn ENABLED set unit n write enabled
|
||||
|
||||
Units can also be REMOVEd or ADDed to the configuration. The TC11 supports
|
||||
the BOOT command.
|
||||
|
||||
The TC11 supports both PDP-8 format and PDP-9/11/15 format DECtape images.
|
||||
ATTACH tries to determine the tape format from the DECtape image; the user
|
||||
can force a particular format with switches:
|
||||
|
||||
-f foreign (PDP-8) format
|
||||
-n native (PDP-9/11/15) format
|
||||
|
||||
The DECtape controller is a data-only simulator; the timing and mark
|
||||
track, and block header and trailer, are not stored. Thus, the WRITE
|
||||
TIMING AND MARK TRACK function is not supported; the READ ALL function
|
||||
always returns the hardware standard block header and trailer; and the
|
||||
WRITE ALL function dumps non-data words into the bit bucket.
|
||||
|
||||
The DECtape controller implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
TCST 16 status register
|
||||
TCCM 16 command register
|
||||
TCWC 16 word count register
|
||||
TCBA 16 bus address register
|
||||
TCDT 16 data register
|
||||
INT 1 interrupt pending flag
|
||||
ERR 1 error flag
|
||||
DONE 1 done flag
|
||||
IE 1 interrupt enable flag
|
||||
CTIME 31 time to complete transport stop
|
||||
LTIME 31 time between lines
|
||||
ACTIME 31 time to accelerate to full speed
|
||||
DCTIME 31 time to decelerate to a full stop
|
||||
SUBSTATE 2 read/write command substate
|
||||
POS[0:7] 31 position, in lines, units 0-7
|
||||
STATT[0-7] 31 unit state, units 0-7
|
||||
|
||||
It is critically important to maintain certain timing relationships
|
||||
among the DECtape parameters, or the DECtape simulator will fail to
|
||||
operate correctly.
|
||||
|
||||
- LTIME must be at least 6
|
||||
- ACTIME must be less than DCTIME, and both need to be at
|
||||
least 100 times LTIME
|
||||
|
||||
2.9 TM11 Magnetic Tape (TM)
|
||||
|
||||
TM options include the ability to make units write enabled or write locked.
|
||||
|
||||
SET TMn LOCKED set unit n write locked
|
||||
SET TMn ENABLED set unit n write enabled
|
||||
|
||||
Units can also be REMOVEd or ADDed to the configuration.
|
||||
|
||||
The TM11 supports the BOOT command. The bootstrap supports both original
|
||||
and DEC standard boot formats. Originally, a tape bootstrap read and
|
||||
executed the first record on tape. To allow for ANSI labels, the DEC
|
||||
standard bootstrap skipped the first record and read and executed the second.
|
||||
The DEC standard is the default; to bootstrap an original format tape, use
|
||||
the -o switch.
|
||||
|
||||
The magnetic tape controller implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
MTS 16 status
|
||||
MTC 16 command
|
||||
MTCMA 16 memory address
|
||||
MTBRC 16 byte/record count
|
||||
INT 1 interrupt pending flag
|
||||
ERR 1 error flag
|
||||
DONE 1 device done flag
|
||||
IE 1 interrupt enable flag
|
||||
STOP_IOE 1 stop on I/O error
|
||||
TIME 24 delay
|
||||
UST[0:7] 16 unit status, units 0-7
|
||||
POS[0:7] 31 position, units 0-7
|
||||
|
||||
Error handling is as follows:
|
||||
|
||||
error processed as
|
||||
|
||||
not attached tape not ready
|
||||
|
||||
end of file (read or space) end of physical tape
|
||||
(write) ignored
|
||||
|
||||
OS I/O error report error and stop
|
||||
|
||||
2.10 TS11/TSV05 Magnetic Tape (TS)
|
||||
|
||||
The TS actually implements the TSV05, with 22-bit addressing, but will
|
||||
work with TS11 drivers. TS options include the ability to make the unit
|
||||
write enabled or write locked.
|
||||
|
||||
SET TS LOCKED set unit write locked
|
||||
SET TS ENABLED set unit write enabled
|
||||
|
||||
The TS11 supports the BOOT command. The bootstrap supports only DEC
|
||||
standard boot formats. To allow for ANSI labels, the DEC standard bootstrap
|
||||
skipped the first record and read and executed the second.
|
||||
|
||||
The magnetic tape controller implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
TSSR 16 status register
|
||||
TSBA 16 bus address register
|
||||
TSDBX 16 data buffer extension register
|
||||
CHDR 16 command packet header
|
||||
CADL 16 command packet low address or count
|
||||
CADH 16 command packet high address
|
||||
CLNT 16 command packet length
|
||||
MHDR 16 message packet header
|
||||
MRFC 16 message packet residual frame count
|
||||
MXS0 16 message packet extended status 0
|
||||
MXS1 16 message packet extended status 1
|
||||
MXS2 16 message packet extended status 2
|
||||
MXS3 16 message packet extended status 3
|
||||
MXS4 16 message packet extended status 4
|
||||
WADL 16 write char packet low address
|
||||
WADH 16 write char packet high address
|
||||
WLNT 16 write char packet length
|
||||
WOPT 16 write char packet options
|
||||
WXOPT 16 write char packet extended options
|
||||
ATTN 1 attention message pending
|
||||
BOOT 1 boot request pending
|
||||
OWNC 1 if set, tape owns command buffer
|
||||
OWNM 1 if set, tape owns message buffer
|
||||
TIME 24 delay
|
||||
POS 31 position
|
||||
|
||||
Error handling is as follows:
|
||||
|
||||
error processed as
|
||||
|
||||
not attached tape not ready
|
||||
|
||||
end of file (read or space) end of physical tape
|
||||
(write) ignored
|
||||
|
||||
OS I/O error fatal tape error
|
||||
|
||||
2.11 Symbolic Display and Input
|
||||
|
||||
The PDP-11 simulator implements symbolic display and input. Display is
|
||||
controlled by command line switches:
|
||||
|
||||
-a display as ASCII character
|
||||
-c display as two character ASCII string
|
||||
-m display instruction mnemonics
|
||||
|
||||
Input parsing is controlled by the first character typed in or by command
|
||||
line switches:
|
||||
|
||||
' or -a ASCII character
|
||||
" or -c two character ASCII string
|
||||
alphabetic instruction mnemonic
|
||||
numeric octal number
|
||||
|
||||
Instruction input uses standard PDP-11 assembler syntax. There are sixteen
|
||||
instruction classes:
|
||||
|
||||
class operands examples comments
|
||||
|
||||
no operands none HALT, RESET
|
||||
3b literal literal, 0 - 7 SPL
|
||||
6b literal literal, 0 - 077 MARK
|
||||
8b literal literal, 0 - 0377 EMT, TRAP
|
||||
register register RTS
|
||||
sop specifier SWAB, CLR, ASL
|
||||
reg-sop register, specifier JSR, XOR, MUL
|
||||
fop flt specifier ABSf, NEGf
|
||||
ac-fop flt reg, flt specifier LDf, MULf
|
||||
ac-sop flt reg, specifier LDEXP, STEXP
|
||||
ac-moded sop flt reg, specifier LDCif, STCfi
|
||||
dop specifier, specifier MOV, ADD, BIC
|
||||
cond branch address BR, BCC, BNE
|
||||
sob register, address SOB
|
||||
cc clear cc clear instructions CLC, CLV, CLZ, CLN combinable
|
||||
cc set cc set instructions SEC, SEV, SEZ, SEN combinable
|
||||
|
||||
For floating point opcodes, F and D variants, and I and L variants, may be
|
||||
specified regardless of the state of FPS.
|
||||
|
||||
The syntax for specifiers is as follows:
|
||||
|
||||
syntax specifier displacement comments
|
||||
|
||||
Rn 0n -
|
||||
Fn 0n - only in flt reg classes
|
||||
(Rn) 1n -
|
||||
@(Rn) 7n 0 equivalent to @0(Rn)
|
||||
(Rn)+ 2n -
|
||||
@(Rn)+ 3n -
|
||||
-(Rn) 4n -
|
||||
@-(Rn) 5n -
|
||||
{+/-}d(Rn) 6n {+/-}d
|
||||
@{+/-}d(Rn) 7n {+/-}d
|
||||
#n 27 n
|
||||
@#n 37 n
|
||||
.+/-n 67 +/-n - 4
|
||||
@.+/-n 77 +/-n - 4
|
||||
{+/-}n 67 {+/-}n - PC - 4 if on disk, 37 and n
|
||||
@{+/-}n 77 {+/-}n - PC - 4 if on disk, invalid
|
|
@ -24,7 +24,19 @@
|
|||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
dz DZ11 terminal multiplexor
|
||||
|
||||
09-Nov-01 RMS Added VAX support
|
||||
*/
|
||||
|
||||
#if defined (USE_INT64)
|
||||
#define VM_VAX 1
|
||||
#include "vax_defs.h"
|
||||
#define DZ_RDX 16
|
||||
|
||||
#else
|
||||
#define VM_PDP11 1
|
||||
#include "pdp11_defs.h"
|
||||
#define DZ_RDX 8
|
||||
#endif
|
||||
|
||||
#include "dec_dz.h"
|
361
PDP11/pdp11_io.c
Normal file
361
PDP11/pdp11_io.c
Normal file
|
@ -0,0 +1,361 @@
|
|||
/* pdp11_io.c: PDP-11 I/O simulator
|
||||
|
||||
Copyright (c) 1993-2001, Robert M Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation
|
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
and/or sell copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
Except as contained in this notice, the name of Robert M Supnik shall not
|
||||
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
11-Dec-01 RMS Moved interrupt debug code
|
||||
08-Nov-01 RMS Cloned from cpu sources
|
||||
*/
|
||||
|
||||
#include "pdp11_defs.h"
|
||||
|
||||
extern uint16 *M;
|
||||
extern int32 int_req[IPL_HLVL];
|
||||
extern int32 ub_map[UBM_LNT_LW];
|
||||
extern UNIT cpu_unit;
|
||||
extern int32 cpu_bme, cpu_ubm;
|
||||
extern int32 trap_req, ipl;
|
||||
extern int32 cpu_log;
|
||||
extern FILE *sim_log;
|
||||
int32 calc_ints (int32 nipl, int32 trq);
|
||||
|
||||
extern t_stat CPU_rd (int32 *data, int32 addr, int32 access);
|
||||
extern t_stat CPU_wr (int32 data, int32 addr, int32 access);
|
||||
extern t_stat APR_rd (int32 *data, int32 addr, int32 access);
|
||||
extern t_stat APR_wr (int32 data, int32 addr, int32 access);
|
||||
extern t_stat SR_MMR012_rd (int32 *data, int32 addr, int32 access);
|
||||
extern t_stat SR_MMR012_wr (int32 data, int32 addr, int32 access);
|
||||
extern t_stat MMR3_rd (int32 *data, int32 addr, int32 access);
|
||||
extern t_stat MMR3_wr (int32 data, int32 addr, int32 access);
|
||||
extern t_stat ubm_rd (int32 *data, int32 addr, int32 access);
|
||||
extern t_stat ubm_wr (int32 data, int32 addr, int32 access);
|
||||
extern t_stat std_rd (int32 *data, int32 addr, int32 access);
|
||||
extern t_stat std_wr (int32 data, int32 addr, int32 access);
|
||||
extern t_stat lpt_rd (int32 *data, int32 addr, int32 access);
|
||||
extern t_stat lpt_wr (int32 data, int32 addr, int32 access);
|
||||
extern t_stat dz_rd (int32 *data, int32 addr, int32 access);
|
||||
extern t_stat dz_wr (int32 data, int32 addr, int32 access);
|
||||
extern t_stat rk_rd (int32 *data, int32 addr, int32 access);
|
||||
extern t_stat rk_wr (int32 data, int32 addr, int32 access);
|
||||
extern int32 rk_inta (void);
|
||||
extern int32 rk_enb;
|
||||
/* extern t_stat rk6_rd (int32 *data, int32 addr, int32 access);
|
||||
extern t_stat rk6_wr (int32 data, int32 addr, int32 access);
|
||||
extern int32 rk6_inta (void);
|
||||
extern int32 rk6_enb; */
|
||||
extern t_stat rl_rd (int32 *data, int32 addr, int32 access);
|
||||
extern t_stat rl_wr (int32 data, int32 addr, int32 access);
|
||||
extern int32 rl_enb;
|
||||
extern t_stat rp_rd (int32 *data, int32 addr, int32 access);
|
||||
extern t_stat rp_wr (int32 data, int32 addr, int32 access);
|
||||
extern int32 rp_inta (void);
|
||||
extern int32 rp_enb;
|
||||
extern t_stat rq_rd (int32 *data, int32 addr, int32 access);
|
||||
extern t_stat rq_wr (int32 data, int32 addr, int32 access);
|
||||
extern int32 rq_inta (void);
|
||||
extern int32 rq_enb;
|
||||
extern t_stat rx_rd (int32 *data, int32 addr, int32 access);
|
||||
extern t_stat rx_wr (int32 data, int32 addr, int32 access);
|
||||
extern int32 rx_enb;
|
||||
extern t_stat dt_rd (int32 *data, int32 addr, int32 access);
|
||||
extern t_stat dt_wr (int32 data, int32 addr, int32 access);
|
||||
extern int32 dt_enb;
|
||||
extern t_stat tm_rd (int32 *data, int32 addr, int32 access);
|
||||
extern t_stat tm_wr (int32 data, int32 addr, int32 access);
|
||||
extern int32 tm_enb;
|
||||
extern t_stat ts_rd (int32 *data, int32 addr, int32 access);
|
||||
extern t_stat ts_wr (int32 data, int32 addr, int32 access);
|
||||
extern int32 ts_enb;
|
||||
|
||||
/* I/O data structures */
|
||||
|
||||
struct iolink { /* I/O page linkage */
|
||||
int32 low; /* low I/O addr */
|
||||
int32 high; /* high I/O addr */
|
||||
int32 *enb; /* enable flag */
|
||||
t_stat (*read)(); /* read routine */
|
||||
t_stat (*write)(); }; /* write routine */
|
||||
|
||||
struct iolink iotable[] = {
|
||||
{ IOBA_CPU, IOBA_CPU+IOLN_CPU, NULL, &CPU_rd, &CPU_wr },
|
||||
{ IOBA_STD, IOBA_STD+IOLN_STD, NULL, &std_rd, &std_wr },
|
||||
{ IOBA_LPT, IOBA_LPT+IOLN_LPT, NULL, &lpt_rd, &lpt_wr },
|
||||
{ IOBA_DZ, IOBA_DZ +IOLN_DZ, NULL, &dz_rd, &dz_wr },
|
||||
{ IOBA_RK, IOBA_RK +IOLN_RK, &rk_enb, &rk_rd, &rk_wr },
|
||||
{ IOBA_RL, IOBA_RL +IOLN_RL, &rl_enb, &rl_rd, &rl_wr },
|
||||
{ IOBA_RP, IOBA_RP +IOLN_RP, &rp_enb, &rp_rd, &rp_wr },
|
||||
{ IOBA_RQ, IOBA_RQ +IOLN_RQ, &rq_enb, &rq_rd, &rq_wr },
|
||||
{ IOBA_RX, IOBA_RX +IOLN_RX, &rx_enb, &rx_rd, &rx_wr },
|
||||
{ IOBA_TC, IOBA_TC +IOLN_TC, &dt_enb, &dt_rd, &dt_wr },
|
||||
{ IOBA_TM, IOBA_TM +IOLN_TM, &tm_enb, &tm_rd, &tm_wr },
|
||||
{ IOBA_TS, IOBA_TS +IOLN_TS, &ts_enb, &ts_rd, &ts_wr },
|
||||
/* { IOBA_RK6, IOBA_RK6+IOLN_RK6, &rk6_enb, &rk6_rd, &rk6_wr }, */
|
||||
{ IOBA_APR, IOBA_APR+IOLN_APR, NULL, &APR_rd, &APR_wr },
|
||||
{ IOBA_APR1, IOBA_APR1+IOLN_APR1, NULL, &APR_rd, &APR_wr },
|
||||
{ IOBA_SRMM, IOBA_SRMM+IOLN_SRMM, NULL, &SR_MMR012_rd, &SR_MMR012_wr },
|
||||
{ IOBA_MMR3, IOBA_MMR3+IOLN_MMR3, NULL, &MMR3_rd, &MMR3_wr },
|
||||
{ IOBA_UBM, IOBA_UBM+IOLN_UBM, NULL, &ubm_rd, &ubm_wr },
|
||||
{ 0, 0, NULL, NULL, NULL } };
|
||||
|
||||
int32 int_vec[IPL_HLVL][32] = { /* int req to vector */
|
||||
{ 0 }, /* IPL 0 */
|
||||
{ VEC_PIRQ }, /* IPL 1 */
|
||||
{ VEC_PIRQ }, /* IPL 2 */
|
||||
{ VEC_PIRQ }, /* IPL 3 */
|
||||
{ VEC_TTI, VEC_TTO, VEC_PTR, VEC_PTP, /* IPL 4 */
|
||||
VEC_LPT, VEC_PIRQ },
|
||||
{ VEC_RK, VEC_RL, VEC_RX, VEC_TM, /* IPL 5 */
|
||||
VEC_RP, VEC_TS, VEC_RK6, VEC_RQ,
|
||||
VEC_DZRX, VEC_DZTX, VEC_PIRQ },
|
||||
{ VEC_CLK, VEC_DTA, VEC_PIRQ }, /* IPL 6 */
|
||||
{ VEC_PIRQ } }; /* IPL 7 */
|
||||
|
||||
int32 (*int_ack[IPL_HLVL][32])() = { /* int ack routines */
|
||||
{ NULL }, /* IPL 0 */
|
||||
{ NULL }, /* IPL 1 */
|
||||
{ NULL }, /* IPL 2 */
|
||||
{ NULL }, /* IPL 3 */
|
||||
{ NULL }, /* IPL 4 */
|
||||
{ &rk_inta, NULL, NULL, NULL, /* IPL 5 */
|
||||
&rp_inta, NULL, NULL, &rq_inta },
|
||||
{ NULL }, /* IPL 6 */
|
||||
{ NULL } }; /* IPL 7 */
|
||||
|
||||
/* I/O page lookup and linkage routines
|
||||
|
||||
Inputs:
|
||||
*data = pointer to data to read, if READ
|
||||
data = data to store, if WRITE or WRITEB
|
||||
pa = address
|
||||
access = READ, WRITE, or WRITEB
|
||||
Outputs:
|
||||
status = SCPE_OK or SCPE_NXM
|
||||
*/
|
||||
|
||||
t_stat iopageR (int32 *data, int32 pa, int32 access)
|
||||
{
|
||||
t_stat stat;
|
||||
struct iolink *p;
|
||||
|
||||
for (p = &iotable[0]; p -> low != 0; p++ ) {
|
||||
if ((pa >= p -> low) && (pa < p -> high) &&
|
||||
((p -> enb == NULL) || *p -> enb)) {
|
||||
stat = p -> read (data, pa, access);
|
||||
trap_req = calc_ints (ipl, trap_req);
|
||||
return stat; } }
|
||||
return SCPE_NXM;
|
||||
}
|
||||
|
||||
t_stat iopageW (int32 data, int32 pa, int32 access)
|
||||
{
|
||||
t_stat stat;
|
||||
struct iolink *p;
|
||||
|
||||
for (p = &iotable[0]; p -> low != 0; p++ ) {
|
||||
if ((pa >= p -> low) && (pa < p -> high) &&
|
||||
((p -> enb == NULL) || *p -> enb)) {
|
||||
stat = p -> write (data, pa, access);
|
||||
trap_req = calc_ints (ipl, trap_req);
|
||||
return stat; } }
|
||||
return SCPE_NXM;
|
||||
}
|
||||
|
||||
/* Calculate interrupt outstanding */
|
||||
|
||||
int32 calc_ints (int32 nipl, int32 trq)
|
||||
{
|
||||
int32 i;
|
||||
|
||||
for (i = IPL_HLVL - 1; i > nipl; i--) {
|
||||
if (int_req[i]) return (trq | TRAP_INT); }
|
||||
return (trq & ~TRAP_INT);
|
||||
}
|
||||
|
||||
/* Find vector for highest priority interrupt */
|
||||
|
||||
int32 get_vector (int32 nipl)
|
||||
{
|
||||
int32 i, j, t, vec;
|
||||
|
||||
for (i = IPL_HLVL - 1; i > nipl; i--) { /* loop thru lvls */
|
||||
t = int_req[i]; /* get level */
|
||||
for (j = 0; t && (j < 32); j++) { /* srch level */
|
||||
if ((t >> j) & 1) { /* irq found? */
|
||||
int_req[i] = int_req[i] & ~(1u << j); /* clr irq */
|
||||
if (int_ack[i][j]) vec = int_ack[i][j]();
|
||||
else vec = int_vec[i][j];
|
||||
if (DBG_LOG (LOG_CPU_I)) fprintf (sim_log,
|
||||
">>INT: lvl=%d, flag=%d, vec=%o\n", i, j, vec);
|
||||
return vec; /* return vector */
|
||||
} /* end if t */
|
||||
} /* end for j */
|
||||
} /* end for i */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Read and write Unibus map registers
|
||||
|
||||
In any even/odd pair
|
||||
even = low 16b, bit <0> clear
|
||||
odd = high 6b
|
||||
|
||||
The Unibus map is stored as an array of longwords
|
||||
*/
|
||||
|
||||
t_stat ubm_rd (int32 *data, int32 addr, int32 access)
|
||||
{
|
||||
if (cpu_ubm) {
|
||||
int32 pg = (addr >> 2) & UBM_M_PN;
|
||||
*data = (addr & 2)? ((ub_map[pg] >> 16) & 077):
|
||||
(ub_map[pg] & 0177776);
|
||||
return SCPE_OK; }
|
||||
return SCPE_NXM;
|
||||
}
|
||||
|
||||
t_stat ubm_wr (int32 data, int32 addr, int32 access)
|
||||
{
|
||||
if (cpu_ubm) {
|
||||
int32 sc, pg = (addr >> 2) & UBM_M_PN;
|
||||
if (access == WRITEB) {
|
||||
sc = (addr & 3) << 3;
|
||||
ub_map[pg] = (ub_map[pg] & ~(0377 << sc)) |
|
||||
((data & 0377) << sc); }
|
||||
else { sc = (addr & 2) << 3;
|
||||
ub_map[pg] = (ub_map[pg] & ~(0177777 << sc)) |
|
||||
((data & 0177777) << sc); }
|
||||
ub_map[pg] = ub_map[pg] & 017777776;
|
||||
return SCPE_OK; }
|
||||
return SCPE_NXM;
|
||||
}
|
||||
|
||||
/* Mapped memory access routines for DMA devices */
|
||||
|
||||
/* Map I/O address to memory address */
|
||||
|
||||
t_bool Map_Addr (t_addr ba, t_addr *ma)
|
||||
{
|
||||
if (cpu_bme) { /* bus map on? */
|
||||
int32 pg = UBM_GETPN (ba); /* map entry */
|
||||
int32 off = UBM_GETOFF (ba); /* offset */
|
||||
if (pg != UBM_M_PN) /* last page? */
|
||||
*ma = (ub_map[pg] + off) & PAMASK; /* no, use map */
|
||||
else *ma = (IOPAGEBASE + off) & PAMASK; } /* yes, use fixed */
|
||||
else *ma = ba; /* else physical */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* I/O buffer routines, aligned access
|
||||
|
||||
Map_ReadB - fetch byte buffer from memory
|
||||
Map_ReadW - fetch word buffer from memory
|
||||
Map_WriteB - store byte buffer into memory
|
||||
Map_WriteW - store word buffer into memory
|
||||
*/
|
||||
|
||||
int32 Map_ReadB (t_addr ba, int32 bc, uint8 *buf, t_bool ub)
|
||||
{
|
||||
t_addr alim, lim, ma;
|
||||
|
||||
lim = ba + bc;
|
||||
if (ub && cpu_bme) { /* UB, map on? */
|
||||
for ( ; ba < lim; ba++) { /* by bytes */
|
||||
Map_Addr (ba, &ma); /* map addr */
|
||||
if (!ADDR_IS_MEM (ma)) return (lim - ba); /* NXM? err */
|
||||
if (ma & 1) *buf++ = (M[ma >> 1] >> 8) & 0377; /* get byte */
|
||||
else *buf++ = M[ma >> 1] & 0377; }
|
||||
return 0; }
|
||||
else { /* physical */
|
||||
if (ADDR_IS_MEM (lim)) alim = lim; /* end ok? */
|
||||
else if (ADDR_IS_MEM (ba)) alim = MEMSIZE; /* no, strt ok? */
|
||||
else return bc; /* no, err */
|
||||
for ( ; ba < alim; ba++) { /* by bytes */
|
||||
if (ba & 1) *buf++ = (M[ba >> 1] >> 8) & 0377; /* get byte */
|
||||
else *buf++ = M[ba >> 1] & 0377; }
|
||||
return (lim - alim); }
|
||||
}
|
||||
|
||||
int32 Map_ReadW (t_addr ba, int32 bc, uint16 *buf, t_bool ub)
|
||||
{
|
||||
t_addr alim, lim, ma;
|
||||
|
||||
ba = ba & ~01; /* align start */
|
||||
lim = ba + (bc & ~01);
|
||||
if (ub && cpu_bme) { /* UB, map on? */
|
||||
for (; ba < lim; ba = ba + 2) { /* by words */
|
||||
Map_Addr (ba, &ma); /* map addr */
|
||||
if (!ADDR_IS_MEM (ma)) return (lim - ba); /* NXM? err */
|
||||
*buf++ = M[ma >> 1]; }
|
||||
return 0; }
|
||||
else { /* physical */
|
||||
if (ADDR_IS_MEM (lim)) alim = lim; /* end ok? */
|
||||
else if (ADDR_IS_MEM (ba)) alim = MEMSIZE; /* no, strt ok? */
|
||||
else return bc; /* no, err */
|
||||
for ( ; ba < alim; ba = ba + 2) { /* by words */
|
||||
*buf++ = M[ba >> 1]; }
|
||||
return (lim - alim); }
|
||||
}
|
||||
|
||||
int32 Map_WriteB (t_addr ba, int32 bc, uint8 *buf, t_bool ub)
|
||||
{
|
||||
t_addr alim, lim, ma;
|
||||
|
||||
lim = ba + bc;
|
||||
if (ub && cpu_bme) { /* UB, map on? */
|
||||
for ( ; ba < lim; ba++) { /* by bytes */
|
||||
Map_Addr (ba, &ma); /* map addr */
|
||||
if (!ADDR_IS_MEM (ma)) return (lim - ba); /* NXM? err */
|
||||
if (ma & 1) M[ma >> 1] = (M[ma >> 1] & 0377) |
|
||||
((uint16) *buf++ << 8);
|
||||
else M[ma >> 1] = (M[ma >> 1] & ~0377) | *buf++; }
|
||||
return 0; }
|
||||
else { /* physical */
|
||||
if (ADDR_IS_MEM (lim)) alim = lim; /* end ok? */
|
||||
else if (ADDR_IS_MEM (ba)) alim = MEMSIZE; /* no, strt ok? */
|
||||
else return bc; /* no, err */
|
||||
for ( ; ba < alim; ba++) { /* by bytes */
|
||||
if (ba & 1) M[ba >> 1] = (M[ba >> 1] & 0377) |
|
||||
((uint16) *buf++ << 8);
|
||||
else M[ba >> 1] = (M[ba >> 1] & ~0377) | *buf++; }
|
||||
return (lim - alim); }
|
||||
}
|
||||
|
||||
int32 Map_WriteW (t_addr ba, int32 bc, uint16 *buf, t_bool ub)
|
||||
{
|
||||
t_addr alim, lim, ma;
|
||||
|
||||
ba = ba & ~01; /* align start */
|
||||
lim = ba + (bc & ~01);
|
||||
if (ub && cpu_bme) { /* UB, map on? */
|
||||
for (; ba < lim; ba = ba + 2) { /* by words */
|
||||
Map_Addr (ba, &ma); /* map addr */
|
||||
if (!ADDR_IS_MEM (ma)) return (lim - ba); /* NXM? err */
|
||||
M[ma >> 1] = *buf++; } /* store word */
|
||||
return 0; }
|
||||
else { /* physical */
|
||||
if (ADDR_IS_MEM (lim)) alim = lim; /* end ok? */
|
||||
else if (ADDR_IS_MEM (ba)) alim = MEMSIZE; /* no, strt ok? */
|
||||
else return bc; /* no, err */
|
||||
for ( ; ba < alim; ba = ba + 2) { /* by words */
|
||||
M[ba >> 1] = *buf++; }
|
||||
return (lim - alim); }
|
||||
}
|
|
@ -25,11 +25,21 @@
|
|||
|
||||
lpt LP11 line printer
|
||||
|
||||
09-Nov-01 RMS Added VAX support
|
||||
07-Sep-01 RMS Revised interrupt mechanism
|
||||
30-Oct-00 RMS Standardized register naming
|
||||
*/
|
||||
|
||||
#if defined (USE_INT64)
|
||||
#define VM_VAX 1
|
||||
#include "vax_defs.h"
|
||||
#define LPT_DRDX 16
|
||||
|
||||
#else
|
||||
#define VM_PDP11 1
|
||||
#include "pdp11_defs.h"
|
||||
#define LPT_DRDX 8
|
||||
#endif
|
||||
|
||||
#define LPTCSR_IMP (CSR_ERR + CSR_DONE + CSR_IE) /* implemented */
|
||||
#define LPTCSR_RW (CSR_IE) /* read/write */
|
||||
|
@ -53,8 +63,8 @@ UNIT lpt_unit = {
|
|||
UDATA (&lpt_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT };
|
||||
|
||||
REG lpt_reg[] = {
|
||||
{ ORDATA (BUF, lpt_unit.buf, 8) },
|
||||
{ ORDATA (CSR, lpt_csr, 16) },
|
||||
{ GRDATA (BUF, lpt_unit.buf, LPT_DRDX, 8, 0) },
|
||||
{ GRDATA (CSR, lpt_csr, LPT_DRDX, 16, 0) },
|
||||
{ FLDATA (INT, IREQ (LPT), INT_V_LPT) },
|
||||
{ FLDATA (ERR, lpt_csr, CSR_V_ERR) },
|
||||
{ FLDATA (DONE, lpt_csr, CSR_V_DONE) },
|
||||
|
@ -66,7 +76,7 @@ REG lpt_reg[] = {
|
|||
|
||||
DEVICE lpt_dev = {
|
||||
"LPT", &lpt_unit, lpt_reg, NULL,
|
||||
1, 10, 31, 1, 8, 8,
|
||||
1, 10, 31, 1, LPT_DRDX, 8,
|
||||
NULL, NULL, &lpt_reset,
|
||||
NULL, &lpt_attach, &lpt_detach };
|
||||
|
|
@ -25,6 +25,9 @@
|
|||
|
||||
rk RK11/RK05 cartridge disk
|
||||
|
||||
30-Nov-01 RMS Added read only unit, extended SET/SHOW support
|
||||
24-Nov-01 RMS Converted FLG to array
|
||||
09-Nov-01 RMS Added bus map support
|
||||
07-Sep-01 RMS Revised device disable and interrupt mechanisms
|
||||
26-Apr-01 RMS Added device enable/disable support
|
||||
25-Mar-01 RMS Fixed block fill calculation
|
||||
|
@ -62,9 +65,9 @@
|
|||
#define RK_NUMDR 8 /* drives/controller */
|
||||
#define RK_M_NUMDR 07
|
||||
#define RK_SIZE (RK_NUMCY * RK_NUMSF * RK_NUMSC * RK_NUMWD) /* words/drive */
|
||||
#define RK_MAXMEM ((int32) (MEMSIZE / sizeof (int16))) /* words/memory */
|
||||
#define RK_CTLI 1 /* controller int */
|
||||
#define RK_SCPI(x) (2u << (x)) /* drive int */
|
||||
#define RK_MAXFR (1 << 16) /* max transfer */
|
||||
|
||||
/* Flags in the unit flags word */
|
||||
|
||||
|
@ -73,6 +76,7 @@
|
|||
#define UNIT_W_UF 3 /* user flags width */
|
||||
#define UNIT_HWLK (1u << UNIT_V_HWLK)
|
||||
#define UNIT_SWLK (1u << UNIT_V_SWLK)
|
||||
#define UNIT_WPRT (UNIT_HWLK|UNIT_SWLK|UNIT_RO) /* write prot */
|
||||
|
||||
/* Parameters in the unit descriptor */
|
||||
|
||||
|
@ -163,7 +167,7 @@
|
|||
|
||||
extern uint16 *M; /* memory */
|
||||
extern int32 int_req[IPL_HLVL];
|
||||
extern UNIT cpu_unit;
|
||||
uint16 *rkxb = NULL; /* xfer buffer */
|
||||
int32 rkcs = 0; /* control/status */
|
||||
int32 rkds = 0; /* drive status */
|
||||
int32 rkba = 0; /* memory address */
|
||||
|
@ -192,14 +196,22 @@ t_stat rk_boot (int32 unitno);
|
|||
*/
|
||||
|
||||
UNIT rk_unit[] = {
|
||||
{ UDATA (&rk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, RK_SIZE) },
|
||||
{ UDATA (&rk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, RK_SIZE) },
|
||||
{ UDATA (&rk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, RK_SIZE) },
|
||||
{ UDATA (&rk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, RK_SIZE) },
|
||||
{ UDATA (&rk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, RK_SIZE) },
|
||||
{ UDATA (&rk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, RK_SIZE) },
|
||||
{ UDATA (&rk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, RK_SIZE) },
|
||||
{ UDATA (&rk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, RK_SIZE) } };
|
||||
{ UDATA (&rk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE, RK_SIZE) },
|
||||
{ UDATA (&rk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE, RK_SIZE) },
|
||||
{ UDATA (&rk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE, RK_SIZE) },
|
||||
{ UDATA (&rk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE, RK_SIZE) },
|
||||
{ UDATA (&rk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE, RK_SIZE) },
|
||||
{ UDATA (&rk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE, RK_SIZE) },
|
||||
{ UDATA (&rk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE, RK_SIZE) },
|
||||
{ UDATA (&rk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE, RK_SIZE) } };
|
||||
|
||||
REG rk_reg[] = {
|
||||
{ ORDATA (RKCS, rkcs, 16) },
|
||||
|
@ -216,32 +228,15 @@ REG rk_reg[] = {
|
|||
{ FLDATA (IE, rkcs, CSR_V_IE) },
|
||||
{ DRDATA (STIME, rk_swait, 24), PV_LEFT },
|
||||
{ DRDATA (RTIME, rk_rwait, 24), PV_LEFT },
|
||||
{ GRDATA (FLG0, rk_unit[0].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ GRDATA (FLG1, rk_unit[1].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ GRDATA (FLG2, rk_unit[2].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ GRDATA (FLG3, rk_unit[3].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ GRDATA (FLG4, rk_unit[4].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ GRDATA (FLG5, rk_unit[5].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ GRDATA (FLG6, rk_unit[6].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ GRDATA (FLG7, rk_unit[7].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ URDATA (FLG, rk_unit[0].flags, 8, UNIT_W_UF, UNIT_V_UF - 1,
|
||||
RK_NUMDR, REG_HRO) },
|
||||
{ FLDATA (STOP_IOE, rk_stopioe, 0) },
|
||||
{ FLDATA (*DEVENB, rk_enb, 0), REG_HRO },
|
||||
{ NULL } };
|
||||
|
||||
MTAB rk_mod[] = {
|
||||
{ (UNIT_HWLK+UNIT_SWLK), 0, "write enabled", "ENABLED", NULL },
|
||||
{ (UNIT_HWLK+UNIT_SWLK), UNIT_HWLK, "write locked", "LOCKED", NULL },
|
||||
{ (UNIT_HWLK+UNIT_SWLK), UNIT_SWLK, "write locked", NULL, NULL },
|
||||
{ (UNIT_HWLK+UNIT_SWLK), (UNIT_HWLK+UNIT_SWLK), "write locked",
|
||||
NULL, NULL },
|
||||
{ UNIT_HWLK, 0, "write enabled", "ENABLED", NULL },
|
||||
{ UNIT_HWLK, UNIT_HWLK, "write locked", "LOCKED", NULL },
|
||||
{ 0 } };
|
||||
|
||||
DEVICE rk_dev = {
|
||||
|
@ -275,7 +270,7 @@ case 0: /* RKDS: read only */
|
|||
uptr = rk_dev.units + GET_DRIVE (rkda); /* selected unit */
|
||||
if (uptr -> flags & UNIT_ATT) rkds = rkds | RKDS_RDY; /* attached? */
|
||||
if (!sim_is_active (uptr)) rkds = rkds | RKDS_RWS; /* idle? */
|
||||
if (uptr -> flags & (UNIT_HWLK + UNIT_SWLK)) rkds = rkds | RKDS_WLK;
|
||||
if (uptr -> flags & UNIT_WPRT) rkds = rkds | RKDS_WLK;
|
||||
if (GET_SECT (rkda) == (rkds & RKDS_SC)) rkds = rkds | RKDS_ON_SC;
|
||||
*data = rkds;
|
||||
return SCPE_OK;
|
||||
|
@ -373,7 +368,7 @@ if (((uptr -> flags & UNIT_ATT) == 0) || sim_is_active (uptr)) {
|
|||
if (rkcs & (RKCS_INH + RKCS_FMT)) { /* format? */
|
||||
rk_set_done (RKER_PGE);
|
||||
return; }
|
||||
if ((func == RKCS_WRITE) && (uptr -> flags & (UNIT_HWLK + UNIT_SWLK))) {
|
||||
if ((func == RKCS_WRITE) && (uptr -> flags & UNIT_WPRT)) {
|
||||
rk_set_done (RKER_WLK); /* write and locked? */
|
||||
return; }
|
||||
if (func == RKCS_WLK) { /* write lock? */
|
||||
|
@ -413,9 +408,10 @@ return;
|
|||
|
||||
t_stat rk_svc (UNIT *uptr)
|
||||
{
|
||||
int32 comp, drv, err, awc, twc, wc;
|
||||
int32 pa, da, remc, track, sect;
|
||||
static uint16 fill[RK_NUMWD] = { 0 };
|
||||
int32 i, drv, err, awc, wc, t;
|
||||
int32 da, track, sect;
|
||||
t_addr ma;
|
||||
uint16 comp;
|
||||
|
||||
drv = uptr - rk_dev.units; /* get drv number */
|
||||
if (uptr -> FUNC == RKCS_SEEK) { /* seek */
|
||||
|
@ -424,54 +420,56 @@ if (uptr -> FUNC == RKCS_SEEK) { /* seek */
|
|||
rkintq = rkintq | RK_SCPI (drv); /* queue request */
|
||||
if (rkcs & CSR_DONE) SET_INT (RK); }
|
||||
else { rkintq = 0; /* clear queue */
|
||||
CLR_INT (RK); } /* clear interrupt */
|
||||
CLR_INT (RK); } /* clear interrupt */
|
||||
return SCPE_OK; }
|
||||
|
||||
if ((uptr -> flags & UNIT_ATT) == 0) { /* attached? */
|
||||
rk_set_done (RKER_DRE);
|
||||
return IORETURN (rk_stopioe, SCPE_UNATT); }
|
||||
pa = (((rkcs & RKCS_MEX) << (16 - RKCS_V_MEX)) | rkba) >> 1;
|
||||
ma = ((rkcs & RKCS_MEX) << (16 - RKCS_V_MEX)) | rkba; /* get mem addr */
|
||||
da = GET_DA (rkda) * RK_NUMWD; /* get disk addr */
|
||||
twc = 0200000 - rkwc; /* get true wc */
|
||||
if ((pa + twc) > RK_MAXMEM) { /* mem overrun? */
|
||||
rker = rker | RKER_NXM;
|
||||
wc = (RK_MAXMEM - pa); }
|
||||
else wc = twc;
|
||||
if (wc < 0) { /* abort transfer? */
|
||||
rk_set_done (0);
|
||||
return SCPE_OK; }
|
||||
if ((da + twc) > RK_SIZE) { /* disk overrun? */
|
||||
rker = rker | RKER_OVR;
|
||||
if (wc > (RK_SIZE - da)) wc = RK_SIZE - da; }
|
||||
wc = 0200000 - rkwc; /* get wd cnt */
|
||||
|
||||
err = fseek (uptr -> fileref, da * sizeof (int16), SEEK_SET);
|
||||
|
||||
if ((uptr -> FUNC == RKCS_READ) && (err == 0)) { /* read? */
|
||||
awc = fxread (&M[pa], sizeof (int16), wc, uptr -> fileref);
|
||||
for ( ; awc < wc; awc++) M[pa + awc] = 0;
|
||||
err = ferror (uptr -> fileref); }
|
||||
i = fxread (rkxb, sizeof (int16), wc, uptr -> fileref);
|
||||
err = ferror (uptr -> fileref);
|
||||
for ( ; i < wc; i++) rkxb[i] = 0; /* fill buf */
|
||||
if (t = Map_WriteW (ma, wc << 1, rkxb, UB)) { /* store buf */
|
||||
rker = rker | RKER_NXM; /* NXM? set flg */
|
||||
wc = wc - t; } /* adj wd cnt */
|
||||
} /* end read */
|
||||
|
||||
if ((uptr -> FUNC == RKCS_WRITE) && (err == 0)) { /* write? */
|
||||
fxwrite (&M[pa], sizeof (int16), wc, uptr -> fileref);
|
||||
err = ferror (uptr -> fileref);
|
||||
if ((err == 0) && (remc = (wc & (RK_NUMWD - 1)))) {
|
||||
fxwrite (fill, sizeof (int16), RK_NUMWD - remc, uptr -> fileref);
|
||||
err = ferror (uptr -> fileref); } }
|
||||
if (t = Map_ReadW (ma, wc << 1, rkxb, UB)) { /* get buf */
|
||||
rker = rker | RKER_NXM; /* NXM? set flg */
|
||||
wc = wc - t; } /* adj wd cnt */
|
||||
if (wc) { /* any xfer? */
|
||||
awc = (wc + (RK_NUMWD - 1)) & ~(RK_NUMWD - 1); /* clr to */
|
||||
for (i = wc; i < awc; i++) rkxb[i] = 0; /* end of blk */
|
||||
fxwrite (rkxb, sizeof (int16), awc, uptr -> fileref);
|
||||
err = ferror (uptr -> fileref); }
|
||||
} /* end write */
|
||||
|
||||
if ((uptr -> FUNC == RKCS_WCHK) && (err == 0)) { /* write check? */
|
||||
twc = wc; /* xfer length */
|
||||
for (wc = 0; (err == 0) && (wc < twc); wc++) {
|
||||
awc = fxread (&comp, sizeof (int16), 1, uptr -> fileref);
|
||||
if (awc == 0) comp = 0;
|
||||
if (comp != M[pa + wc]) {
|
||||
rker = rker | RKER_WCE;
|
||||
i = fxread (rkxb, sizeof (int16), wc, uptr -> fileref);
|
||||
err = ferror (uptr -> fileref);
|
||||
for ( ; i < wc; i++) rkxb[i] = 0; /* fill buf */
|
||||
awc = wc; /* save wc */
|
||||
for (wc = 0; (err == 0) && (wc < awc); wc++) { /* loop thru buf */
|
||||
if (Map_ReadW (ma + (wc << 1), 2, &comp, UB)) { /* mem wd */
|
||||
rker = rker | RKER_NXM; /* NXM? set flg */
|
||||
break; }
|
||||
if (comp != rkxb[wc]) { /* match to disk? */
|
||||
rker = rker | RKER_WCE; /* no, err */
|
||||
if (rkcs & RKCS_SSE) break; } }
|
||||
err = ferror (uptr -> fileref); }
|
||||
} /* end wcheck */
|
||||
|
||||
rkwc = (rkwc + wc) & 0177777; /* final word count */
|
||||
pa = (pa + wc) << 1; /* final byte addr */
|
||||
rkba = pa & RKBA_IMP; /* lower 16b */
|
||||
rkcs = (rkcs & ~RKCS_MEX) | ((pa >> (16 - RKCS_V_MEX)) & RKCS_MEX);
|
||||
ma = ma + (wc << 1); /* final byte addr */
|
||||
rkba = ma & RKBA_IMP; /* lower 16b */
|
||||
rkcs = (rkcs & ~RKCS_MEX) | ((ma >> (16 - RKCS_V_MEX)) & RKCS_MEX);
|
||||
da = da + wc + (RK_NUMWD - 1);
|
||||
track = (da / RK_NUMWD) / RK_NUMSC;
|
||||
sect = (da / RK_NUMWD) % RK_NUMSC;
|
||||
|
@ -546,6 +544,8 @@ for (i = 0; i < RK_NUMDR; i++) {
|
|||
sim_cancel (uptr);
|
||||
uptr -> CYL = uptr -> FUNC = 0;
|
||||
uptr -> flags = uptr -> flags & ~UNIT_SWLK; }
|
||||
if (rkxb == NULL) rkxb = calloc (RK_MAXFR, sizeof (unsigned int16));
|
||||
if (rkxb == NULL) return SCPE_MEM;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
/* pdp11_rl.c: RL11 (RLV12) cartridge disk simulator
|
||||
/* pdp11_rl.c: RL11 (RLV12) cartridge disk simulator
|
||||
|
||||
Copyright (c) 1993-2001, Robert M Supnik
|
||||
|
||||
|
@ -25,6 +25,11 @@
|
|||
|
||||
rl RL11(RLV12)/RL01/RL02 cartridge disk
|
||||
|
||||
30-Nov-01 MRS Added read only, extended SET/SHOW support
|
||||
26-Nov-01 RMS Fixed per-drive error handling
|
||||
24-Nov-01 RMS Converted FLG, CAPAC to arrays
|
||||
19-Nov-01 RMS Fixed signed/unsigned mismatch in write check
|
||||
09-Nov-01 RMS Added bus map, VAX support
|
||||
07-Sep-01 RMS Revised device disable and interrupt mechanisms
|
||||
20-Aug-01 RMS Added bad block option in attach
|
||||
17-Jul-01 RMS Fixed warning from VC++ 6.0
|
||||
|
@ -42,11 +47,31 @@
|
|||
|
||||
The most complicated part of the RL11 controller is the way it does
|
||||
seeks. Seeking is relative to the current disk address; this requires
|
||||
keeping accurate track of the current cylinder. The RL01 will not
|
||||
keeping accurate track of the current cylinder. The RL11 will not
|
||||
switch heads or cross cylinders during transfers.
|
||||
|
||||
The RL11 functions in three environments:
|
||||
|
||||
- PDP-11 Q22 systems - the I/O map is one for one, so it's safe to
|
||||
go through the I/O map
|
||||
- PDP-11 Unibus 22b systems - the RL11 behaves as an 18b Unibus
|
||||
peripheral and must go through the I/O map
|
||||
- VAX Q22 systems - the RL11 must go through the I/O map
|
||||
*/
|
||||
|
||||
#if defined (USE_INT64) /* VAX version */
|
||||
#include "vax_defs.h"
|
||||
#define VM_VAX 1
|
||||
#define RL_RDX 16
|
||||
#define RL_18B FALSE /* always 22b */
|
||||
|
||||
#else /* PDP11 version */
|
||||
#include "pdp11_defs.h"
|
||||
#define VM_PDP11 1
|
||||
#define RL_RDX 8
|
||||
#define RL_18B (cpu_18b || cpu_ubm)
|
||||
extern int32 cpu_18b, cpu_ubm;
|
||||
#endif
|
||||
|
||||
/* Constants */
|
||||
|
||||
|
@ -55,46 +80,47 @@
|
|||
#define RL_NUMSF 2 /* surfaces/cylinder */
|
||||
#define RL_NUMCY 256 /* cylinders/drive */
|
||||
#define RL_NUMDR 4 /* drives/controller */
|
||||
#define RL_MAXFR (1 << 16) /* max transfer */
|
||||
#define RL01_SIZE (RL_NUMCY * RL_NUMSF * RL_NUMSC * RL_NUMWD) /* words/drive */
|
||||
#define RL02_SIZE (RL01_SIZE * 2) /* words/drive */
|
||||
#define RL_MAXMEM ((int) (MEMSIZE / sizeof (int16))) /* words/memory */
|
||||
|
||||
/* Flags in the unit flags word */
|
||||
|
||||
#define UNIT_V_HWLK (UNIT_V_UF) /* hwre write lock */
|
||||
#define UNIT_V_WLK (UNIT_V_UF) /* hwre write lock */
|
||||
#define UNIT_V_RL02 (UNIT_V_UF+1) /* RL01 vs RL02 */
|
||||
#define UNIT_V_AUTO (UNIT_V_UF+2) /* autosize enable */
|
||||
#define UNIT_W_UF 4 /* saved flags width */
|
||||
#define UNIT_V_DUMMY (UNIT_V_UF + UNIT_W_UF) /* dummy flag */
|
||||
#define UNIT_DUMMY (1 << UNIT_V_DUMMY)
|
||||
#define UNIT_HWLK (1u << UNIT_V_HWLK)
|
||||
#define UNIT_WLK (1u << UNIT_V_WLK)
|
||||
#define UNIT_RL02 (1u << UNIT_V_RL02)
|
||||
#define UNIT_AUTO (1u << UNIT_V_AUTO)
|
||||
#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protected */
|
||||
|
||||
/* Parameters in the unit descriptor */
|
||||
|
||||
#define TRK u3 /* current track */
|
||||
#define STAT u4 /* status */
|
||||
|
||||
/* RLDS */
|
||||
/* RLDS, NI = not implemented, * = kept in STAT, ^ = kept in TRK */
|
||||
|
||||
#define RLDS_LOAD 0 /* no cartridge */
|
||||
#define RLDS_LOCK 5 /* lock on */
|
||||
#define RLDS_BHO 0000010 /* brushes home */
|
||||
#define RLDS_HDO 0000020 /* heads out */
|
||||
#define RLDS_CVO 0000040 /* cover open */
|
||||
#define RLDS_HD 0000100 /* head select */
|
||||
#define RLDS_DSE 0000400 /* drive select err */
|
||||
#define RLDS_BHO 0000010 /* brushes home NI */
|
||||
#define RLDS_HDO 0000020 /* heads out NI */
|
||||
#define RLDS_CVO 0000040 /* cover open NI */
|
||||
#define RLDS_HD 0000100 /* head select ^ */
|
||||
#define RLDS_RL02 0000200 /* RL02 */
|
||||
#define RLDS_VCK 0001000 /* volume check */
|
||||
#define RLDS_WGE 0002000 /* write gate err */
|
||||
#define RLDS_SPE 0004000 /* spin err */
|
||||
#define RLDS_STO 0010000 /* seek time out */
|
||||
#define RLDS_WLK 0020000 /* write locked */
|
||||
#define RLDS_HCE 0040000 /* head current err */
|
||||
#define RLDS_WDE 0100000 /* write data err */
|
||||
#define RLDS_ATT (RLDS_HDO+RLDS_BHO+RLDS_LOCK) /* attached status */
|
||||
#define RLDS_UNATT (RLDS_CVO+RLDS_LOAD) /* unattached status */
|
||||
#define RLDS_DSE 0000400 /* drv sel err NI */
|
||||
#define RLDS_VCK 0001000 /* vol check * */
|
||||
#define RLDS_WGE 0002000 /* wr gate err * */
|
||||
#define RLDS_SPE 0004000 /* spin err * */
|
||||
#define RLDS_STO 0010000 /* seek time out NI */
|
||||
#define RLDS_WLK 0020000 /* wr locked */
|
||||
#define RLDS_HCE 0040000 /* hd curr err NI */
|
||||
#define RLDS_WDE 0100000 /* wr data err NI */
|
||||
#define RLDS_ATT (RLDS_HDO+RLDS_BHO+RLDS_LOCK) /* att status */
|
||||
#define RLDS_UNATT (RLDS_CVO+RLDS_LOAD) /* unatt status */
|
||||
#define RLDS_ERR (RLDS_WDE+RLDS_HCE+RLDS_STO+RLDS_SPE+RLDS_WGE+ \
|
||||
RLDS_VCK+RLDS_DSE) /* errors bits */
|
||||
|
||||
|
@ -156,9 +182,8 @@
|
|||
|
||||
#define RLBAE_IMP 0000077 /* implemented */
|
||||
|
||||
extern uint16 *M; /* memory */
|
||||
extern int32 int_req[IPL_HLVL];
|
||||
extern UNIT cpu_unit;
|
||||
uint16 *rlxb = NULL; /* xfer buffer */
|
||||
int32 rlcs = 0; /* control/status */
|
||||
int32 rlba = 0; /* memory address */
|
||||
int32 rlbae = 0; /* mem addr extension */
|
||||
|
@ -173,8 +198,8 @@ t_stat rl_reset (DEVICE *dptr);
|
|||
void rl_set_done (int32 error);
|
||||
t_stat rl_boot (int32 unitno);
|
||||
t_stat rl_attach (UNIT *uptr, char *cptr);
|
||||
t_stat rl_set_size (UNIT *uptr, int32 value);
|
||||
t_stat rl_set_bad (UNIT *uptr, int32 value);
|
||||
t_stat rl_set_size (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
t_stat rl_set_bad (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
extern t_stat pdp11_bad_block (UNIT *uptr, int32 sec, int32 wds);
|
||||
|
||||
/* RL11 data structures
|
||||
|
@ -186,48 +211,40 @@ extern t_stat pdp11_bad_block (UNIT *uptr, int32 sec, int32 wds);
|
|||
*/
|
||||
|
||||
UNIT rl_unit[] = {
|
||||
{ UDATA (&rl_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO,
|
||||
RL01_SIZE) },
|
||||
{ UDATA (&rl_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO,
|
||||
RL01_SIZE) },
|
||||
{ UDATA (&rl_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO,
|
||||
RL01_SIZE) },
|
||||
{ UDATA (&rl_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO,
|
||||
RL01_SIZE) } };
|
||||
{ UDATA (&rl_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE+UNIT_AUTO, RL01_SIZE) },
|
||||
{ UDATA (&rl_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE+UNIT_AUTO, RL01_SIZE) },
|
||||
{ UDATA (&rl_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE+UNIT_AUTO, RL01_SIZE) },
|
||||
{ UDATA (&rl_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE+UNIT_AUTO, RL01_SIZE) } };
|
||||
|
||||
REG rl_reg[] = {
|
||||
{ ORDATA (RLCS, rlcs, 16) },
|
||||
{ ORDATA (RLDA, rlda, 16) },
|
||||
{ ORDATA (RLBA, rlba, 16) },
|
||||
{ ORDATA (RLBAE, rlbae, 6) },
|
||||
{ ORDATA (RLMP, rlmp, 16) },
|
||||
{ ORDATA (RLMP1, rlmp1, 16) },
|
||||
{ ORDATA (RLMP2, rlmp2, 16) },
|
||||
{ GRDATA (RLCS, rlcs, RL_RDX, 16, 0) },
|
||||
{ GRDATA (RLDA, rlda, RL_RDX, 16, 0) },
|
||||
{ GRDATA (RLBA, rlba, RL_RDX, 16, 0) },
|
||||
{ GRDATA (RLBAE, rlbae, RL_RDX, 6, 0) },
|
||||
{ GRDATA (RLMP, rlmp, RL_RDX, 16, 0) },
|
||||
{ GRDATA (RLMP1, rlmp1, RL_RDX, 16, 0) },
|
||||
{ GRDATA (RLMP2, rlmp2, RL_RDX, 16, 0) },
|
||||
{ FLDATA (INT, IREQ (RL), INT_V_RL) },
|
||||
{ FLDATA (ERR, rlcs, CSR_V_ERR) },
|
||||
{ FLDATA (DONE, rlcs, CSR_V_DONE) },
|
||||
{ FLDATA (IE, rlcs, CSR_V_IE) },
|
||||
{ DRDATA (STIME, rl_swait, 24), PV_LEFT },
|
||||
{ DRDATA (RTIME, rl_rwait, 24), PV_LEFT },
|
||||
{ GRDATA (FLG0, rl_unit[0].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ GRDATA (FLG1, rl_unit[1].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ GRDATA (FLG2, rl_unit[2].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ GRDATA (FLG3, rl_unit[3].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ DRDATA (CAPAC0, rl_unit[0].capac, 32), PV_LEFT + REG_HRO },
|
||||
{ DRDATA (CAPAC1, rl_unit[1].capac, 32), PV_LEFT + REG_HRO },
|
||||
{ DRDATA (CAPAC2, rl_unit[2].capac, 32), PV_LEFT + REG_HRO },
|
||||
{ DRDATA (CAPAC3, rl_unit[3].capac, 32), PV_LEFT + REG_HRO },
|
||||
{ URDATA (FLG, rl_unit[0].flags, 8, UNIT_W_UF, UNIT_V_UF - 1,
|
||||
RL_NUMDR, REG_HRO) },
|
||||
{ URDATA (CAPAC, rl_unit[0].capac, 10, 31, 0,
|
||||
RL_NUMDR, PV_LEFT + REG_HRO) },
|
||||
{ FLDATA (STOP_IOE, rl_stopioe, 0) },
|
||||
{ FLDATA (*DEVENB, rl_enb, 0), REG_HRO },
|
||||
{ NULL } };
|
||||
|
||||
MTAB rl_mod[] = {
|
||||
{ UNIT_HWLK, 0, "write enabled", "ENABLED", NULL },
|
||||
{ UNIT_HWLK, UNIT_HWLK, "write locked", "LOCKED", NULL },
|
||||
{ UNIT_WLK, 0, "write enabled", "ENABLED", NULL },
|
||||
{ UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL },
|
||||
{ UNIT_DUMMY, 0, NULL, "BADBLOCK", &rl_set_bad },
|
||||
{ (UNIT_RL02+UNIT_ATT), UNIT_ATT, "RL01", NULL, NULL },
|
||||
{ (UNIT_RL02+UNIT_ATT), (UNIT_RL02+UNIT_ATT), "RL02", NULL, NULL },
|
||||
|
@ -241,7 +258,7 @@ MTAB rl_mod[] = {
|
|||
|
||||
DEVICE rl_dev = {
|
||||
"RL", rl_unit, rl_reg, rl_mod,
|
||||
RL_NUMDR, 8, 24, 1, 8, 16,
|
||||
RL_NUMDR, RL_RDX, 24, 1, RL_RDX, 16,
|
||||
NULL, NULL, &rl_reset,
|
||||
&rl_boot, &rl_attach, NULL };
|
||||
|
||||
|
@ -279,6 +296,7 @@ case 3: /* RLMP */
|
|||
rlmp1 = rlmp2;
|
||||
break;
|
||||
case 4: /* RLBAE */
|
||||
if (RL_18B) return SCPE_NXM; /* not in RL11 */
|
||||
*data = rlbae & RLBAE_IMP;
|
||||
break; } /* end switch */
|
||||
return SCPE_OK;
|
||||
|
@ -348,6 +366,7 @@ case 3: /* RLMP */
|
|||
rlmp = rlmp1 = rlmp2 = data;
|
||||
break;
|
||||
case 4: /* RLBAE */
|
||||
if (RL_18B) return SCPE_NXM; /* not in RL11 */
|
||||
if (PA & 1) return SCPE_OK;
|
||||
rlbae = data & RLBAE_IMP;
|
||||
rlcs = (rlcs & ~RLCS_MEX) | ((rlbae & RLCS_M_MEX) << RLCS_V_MEX);
|
||||
|
@ -366,27 +385,29 @@ return SCPE_OK;
|
|||
|
||||
t_stat rl_svc (UNIT *uptr)
|
||||
{
|
||||
int32 comp, err, awc, wc, maxwc;
|
||||
int32 func, pa, da, remc;
|
||||
static uint16 fill[RL_NUMWD] = { 0 };
|
||||
int32 err, wc, maxwc, t;
|
||||
int32 i, func, da, awc;
|
||||
t_addr ma;
|
||||
uint16 comp;
|
||||
|
||||
func = GET_FUNC (rlcs); /* get function */
|
||||
if (func == RLCS_GSTA) { /* get status */
|
||||
if (rlda & RLDA_GS_CLR) uptr -> STAT = uptr -> STAT & ~RLDS_ERR;
|
||||
rlmp = uptr -> STAT | (uptr -> TRK & RLDS_HD) |
|
||||
((uptr -> flags & UNIT_ATT)? RLDS_ATT: RLDS_UNATT);
|
||||
if (rlda & RLDA_GS_CLR) rlmp = rlmp & ~RLDS_ERR;
|
||||
if (uptr -> flags & UNIT_RL02) rlmp = rlmp | RLDS_RL02;
|
||||
if (uptr -> flags & UNIT_HWLK) rlmp = rlmp | RLDS_WLK;
|
||||
uptr -> STAT = rlmp2 = rlmp1 = rlmp;
|
||||
if (uptr -> flags & UNIT_WPRT) rlmp = rlmp | RLDS_WLK;
|
||||
rlmp2 = rlmp1 = rlmp;
|
||||
rl_set_done (0); /* done */
|
||||
return SCPE_OK; }
|
||||
|
||||
if ((uptr -> flags & UNIT_ATT) == 0) { /* attached? */
|
||||
rlcs = rlcs & ~RLCS_DRDY; /* clear drive ready */
|
||||
uptr -> STAT = uptr -> STAT | RLDS_SPE; /* spin error */
|
||||
rl_set_done (RLCS_ERR | RLCS_INCMP); /* flag error */
|
||||
return IORETURN (rl_stopioe, SCPE_UNATT); }
|
||||
|
||||
if ((func == RLCS_WRITE) && (uptr -> flags & UNIT_HWLK)) {
|
||||
if ((func == RLCS_WRITE) && (uptr -> flags & UNIT_WPRT)) {
|
||||
uptr -> STAT = uptr -> STAT | RLDS_WGE; /* write and locked */
|
||||
rl_set_done (RLCS_ERR | RLCS_DRE);
|
||||
return SCPE_OK; }
|
||||
|
@ -397,7 +418,7 @@ if (func == RLCS_SEEK) { /* seek? */
|
|||
|
||||
if (func == RLCS_RHDR) { /* read header? */
|
||||
rlmp = (uptr -> TRK & RLDA_TRACK) | GET_SECT (rlda);
|
||||
rlmp1 = 0;
|
||||
rlmp1 = rlmp2 = 0;
|
||||
rl_set_done (0); /* done */
|
||||
return SCPE_OK; }
|
||||
|
||||
|
@ -406,45 +427,53 @@ if (((func != RLCS_RNOHDR) && ((uptr -> TRK & RLDA_CYL) != (rlda & RLDA_CYL)))
|
|||
rl_set_done (RLCS_ERR | RLCS_HDE | RLCS_INCMP); /* wrong cylinder? */
|
||||
return SCPE_OK; }
|
||||
|
||||
pa = ((rlbae << 16) | rlba) >> 1; /* form phys addr */
|
||||
ma = (rlbae << 16) | rlba; /* get mem addr */
|
||||
da = GET_DA (rlda) * RL_NUMWD; /* get disk addr */
|
||||
wc = 0200000 - rlmp; /* get true wc */
|
||||
|
||||
maxwc = (RL_NUMSC - GET_SECT (rlda)) * RL_NUMWD; /* max transfer */
|
||||
if (wc > maxwc) wc = maxwc; /* track overrun? */
|
||||
if ((pa + wc) > RL_MAXMEM) { /* mem overrun? */
|
||||
rlcs = rlcs | RLCS_ERR | RLCS_NXM;
|
||||
wc = (RL_MAXMEM - pa); }
|
||||
if (wc < 0) { /* abort transfer? */
|
||||
rl_set_done (RLCS_INCMP);
|
||||
return SCPE_OK; }
|
||||
|
||||
err = fseek (uptr -> fileref, da * sizeof (int16), SEEK_SET);
|
||||
|
||||
if ((func >= RLCS_READ) && (err == 0)) { /* read (no hdr)? */
|
||||
awc = fxread (&M[pa], sizeof (int16), wc, uptr -> fileref);
|
||||
for ( ; awc < wc; awc++) M[pa + awc] = 0;
|
||||
err = ferror (uptr -> fileref); }
|
||||
i = fxread (rlxb, sizeof (int16), wc, uptr -> fileref);
|
||||
err = ferror (uptr -> fileref);
|
||||
for ( ; i < wc; i++) rlxb[i] = 0; /* fill buffer */
|
||||
if (t = Map_WriteW (ma, wc << 1, rlxb, UB)) { /* store buffer */
|
||||
rlcs = rlcs | RLCS_ERR | RLCS_NXM; /* nxm */
|
||||
wc = wc - t; } /* adjust wc */
|
||||
} /* end read */
|
||||
|
||||
if ((func == RLCS_WRITE) && (err == 0)) { /* write? */
|
||||
fxwrite (&M[pa], sizeof (int16), wc, uptr -> fileref);
|
||||
err = ferror (uptr -> fileref);
|
||||
if ((err == 0) && (remc = (wc & (RL_NUMWD - 1)))) {
|
||||
fxwrite (fill, sizeof (int16), RL_NUMWD - remc, uptr -> fileref);
|
||||
err = ferror (uptr -> fileref); } }
|
||||
if (t = Map_ReadW (ma, wc << 1, rlxb, UB)) { /* fetch buffer */
|
||||
rlcs = rlcs | RLCS_ERR | RLCS_NXM; /* nxm */
|
||||
wc = wc - t; } /* adj xfer lnt */
|
||||
if (wc) { /* any xfer? */
|
||||
awc = (wc + (RL_NUMWD - 1)) & ~(RL_NUMWD - 1); /* clr to */
|
||||
for (i = wc; i < awc; i++) rlxb[i] = 0; /* end of blk */
|
||||
fxwrite (rlxb, sizeof (int16), awc, uptr -> fileref);
|
||||
err = ferror (uptr -> fileref); }
|
||||
} /* end write */
|
||||
|
||||
if ((func == RLCS_WCHK) && (err == 0)) { /* write check? */
|
||||
remc = wc; /* xfer length */
|
||||
for (wc = 0; (err == 0) && (wc < remc); wc++) {
|
||||
awc = fxread (&comp, sizeof (int16), 1, uptr -> fileref);
|
||||
if (awc == 0) comp = 0;
|
||||
if (comp != M[pa + wc]) rlcs = rlcs | RLCS_ERR | RLCS_CRC; }
|
||||
err = ferror (uptr -> fileref); }
|
||||
i = fxread (rlxb, sizeof (int16), wc, uptr -> fileref);
|
||||
err = ferror (uptr -> fileref);
|
||||
for ( ; i < wc; i++) rlxb[i] = 0; /* fill buffer */
|
||||
awc = wc; /* save wc */
|
||||
for (wc = 0; (err == 0) && (wc < awc); wc++) { /* loop thru buf */
|
||||
if (Map_ReadW (ma + (wc << 1), 2, &comp, UB)) { /* mem wd */
|
||||
rlcs = rlcs | RLCS_ERR | RLCS_NXM; /* nxm */
|
||||
break; }
|
||||
if (comp != rlxb[wc]) /* check to buf */
|
||||
rlcs = rlcs | RLCS_ERR | RLCS_CRC;
|
||||
} /* end for */
|
||||
} /* end wcheck */
|
||||
|
||||
rlmp = (rlmp + wc) & 0177777; /* final word count */
|
||||
if (rlmp != 0) rlcs = rlcs | RLCS_ERR | RLCS_INCMP; /* completed? */
|
||||
pa = (pa + wc) << 1; /* final byte addr */
|
||||
rlbae = (pa >> 16) & RLBAE_IMP; /* upper 6b */
|
||||
rlba = pa & RLBA_IMP; /* lower 16b */
|
||||
ma = ma + (wc << 1); /* final byte addr */
|
||||
rlbae = (ma >> 16) & RLBAE_IMP; /* upper 6b */
|
||||
rlba = ma & RLBA_IMP; /* lower 16b */
|
||||
rlcs = (rlcs & ~RLCS_MEX) | ((rlbae & RLCS_M_MEX) << RLCS_V_MEX);
|
||||
rlda = rlda + ((wc + (RL_NUMWD - 1)) / RL_NUMWD);
|
||||
rl_set_done (0);
|
||||
|
@ -483,6 +512,8 @@ for (i = 0; i < RL_NUMDR; i++) {
|
|||
uptr = rl_dev.units + i;
|
||||
sim_cancel (uptr);
|
||||
uptr -> STAT = 0; }
|
||||
if (rlxb == NULL) rlxb = calloc (RL_MAXFR, sizeof (unsigned int16));
|
||||
if (rlxb == NULL) return SCPE_MEM;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
@ -496,9 +527,12 @@ t_stat r;
|
|||
uptr -> capac = (uptr -> flags & UNIT_RL02)? RL02_SIZE: RL01_SIZE;
|
||||
r = attach_unit (uptr, cptr);
|
||||
if ((r != SCPE_OK) || ((uptr -> flags & UNIT_AUTO) == 0)) return r;
|
||||
uptr -> TRK = 0; /* cylinder 0 */
|
||||
uptr -> STAT = RLDS_VCK; /* new volume */
|
||||
if (fseek (uptr -> fileref, 0, SEEK_END)) return SCPE_OK;
|
||||
if ((p = ftell (uptr -> fileref)) == 0)
|
||||
return pdp11_bad_block (uptr, RL_NUMSC, RL_NUMWD);
|
||||
if ((p = ftell (uptr -> fileref)) == 0) {
|
||||
if (uptr -> flags & UNIT_RO) return SCPE_OK;
|
||||
return pdp11_bad_block (uptr, RL_NUMSC, RL_NUMWD); }
|
||||
if (p > (RL01_SIZE * sizeof (int16))) {
|
||||
uptr -> flags = uptr -> flags | UNIT_RL02;
|
||||
uptr -> capac = RL02_SIZE; }
|
||||
|
@ -509,22 +543,24 @@ return SCPE_OK;
|
|||
|
||||
/* Set size routine */
|
||||
|
||||
t_stat rl_set_size (UNIT *uptr, int32 value)
|
||||
t_stat rl_set_size (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
if (uptr -> flags & UNIT_ATT) return SCPE_ALATT;
|
||||
uptr -> capac = (value & UNIT_RL02)? RL02_SIZE: RL01_SIZE;
|
||||
uptr -> capac = (val & UNIT_RL02)? RL02_SIZE: RL01_SIZE;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Set bad block routine */
|
||||
|
||||
t_stat rl_set_bad (UNIT *uptr, int32 value)
|
||||
t_stat rl_set_bad (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
return pdp11_bad_block (uptr, RL_NUMSC, RL_NUMWD);
|
||||
}
|
||||
|
||||
/* Device bootstrap */
|
||||
|
||||
#if defined (VM_PDP11)
|
||||
|
||||
#define BOOT_START 02000 /* start */
|
||||
#define BOOT_UNIT 02006 /* unit number */
|
||||
#define BOOT_LEN (sizeof (boot_rom) / sizeof (int32))
|
||||
|
@ -574,9 +610,18 @@ t_stat rl_boot (int32 unitno)
|
|||
{
|
||||
int32 i;
|
||||
extern int32 saved_PC;
|
||||
extern uint16 *M;
|
||||
|
||||
for (i = 0; i < BOOT_LEN; i++) M[(BOOT_START >> 1) + i] = boot_rom[i];
|
||||
M[BOOT_UNIT >> 1] = unitno & RLCS_M_DRIVE;
|
||||
saved_PC = BOOT_START;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
t_stat rl_boot (int32 unitno)
|
||||
{
|
||||
return SCPE_NOFNC;
|
||||
}
|
||||
#endif
|
|
@ -25,6 +25,9 @@
|
|||
|
||||
rp RH/RP/RM moving head disks
|
||||
|
||||
30-Nov-01 RMS Added read only unit, extended SET/SHOW support
|
||||
24-Nov-01 RMS Changed RPDS, RPER, FLG, CAPAC, RPFN to arrays
|
||||
09-Nov-01 RMS Added bus map, VAX support
|
||||
23-Oct-01 RMS Fixed bug in error interrupts
|
||||
15-Oct-01 RMS Added debug logging
|
||||
05-Oct-01 RMS Rewrote interrupt handling from schematics
|
||||
|
@ -66,14 +69,45 @@
|
|||
level sensitive.
|
||||
- The DONE interrupt, once set, is not disabled if IE is cleared,
|
||||
but the SC interrupt is.
|
||||
|
||||
The RP/RM functions in four environments:
|
||||
|
||||
- PDP-11 Q22 systems - the I/O map is one for one, so it's safe to
|
||||
go through the I/O map
|
||||
- PDP-11 Unibus systems with native 22b controllers - see above
|
||||
- PDP-11 Unibus 22b systems - the RP/RM behaves as an 18b Unibus
|
||||
peripheral and must go through the I/O map
|
||||
- VAX Q22 systems - the Rp/RM must go through the I/O map
|
||||
|
||||
To distinguish the two Unibus cases, the PDP-11 version of the RP/RM
|
||||
provides an internal mode flag for RH11 vs RH70
|
||||
*/
|
||||
|
||||
#if defined (USE_INT64) /* VAX version */
|
||||
#include "vax_defs.h"
|
||||
#define VM_VAX 1
|
||||
#define RP_RDX 16
|
||||
#define RP_WID 32
|
||||
#define DMASK 0xFFFF
|
||||
#define RH_18B FALSE /* always 22b */
|
||||
|
||||
#else /* PDP11 version */
|
||||
#include "pdp11_defs.h"
|
||||
#define VM_PDP11 1
|
||||
#define RP_RDX 8
|
||||
#define RP_WID 16 /* off by default */
|
||||
#define RH_18B (cpu_18b || (cpu_ubm && cpu_rh11))
|
||||
extern uint16 *M;
|
||||
extern int32 cpu_18b, cpu_ubm, cpu_rh11;
|
||||
extern int32 cpu_log;
|
||||
extern FILE *sim_log;
|
||||
#endif
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#define RP_NUMDR 8 /* #drives */
|
||||
#define RP_NUMWD 256 /* words/sector */
|
||||
#define RP_MAXFR 65536 /* max transfer */
|
||||
#define RP_MAXFR (1 << 16) /* max transfer */
|
||||
#define GET_SECTOR(x,d) ((int) fmod (sim_gtime() / ((double) (x)), \
|
||||
((double) drv_tab[d].sect)))
|
||||
|
||||
|
@ -90,6 +124,7 @@
|
|||
#define UNIT_V_DUMMY (UNIT_V_UF + UNIT_W_UF) /* dummy flag */
|
||||
#define UNIT_DUMMY (1 << UNIT_V_DUMMY)
|
||||
#define GET_DTYPE(x) (((x) >> UNIT_V_DTYPE) & UNIT_M_DTYPE)
|
||||
#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write prot */
|
||||
|
||||
/* Parameters in the unit descriptor */
|
||||
|
||||
|
@ -318,7 +353,7 @@ struct drvtyp {
|
|||
int devtype; /* device type */
|
||||
};
|
||||
|
||||
struct drvtyp drv_tab[] = {
|
||||
static struct drvtyp drv_tab[] = {
|
||||
{ RM03_SECT, RM03_SURF, RM03_CYL, RM03_SIZE, RM03_DEV },
|
||||
{ RP04_SECT, RP04_SURF, RP04_CYL, RP04_SIZE, RP04_DEV },
|
||||
{ RM80_SECT, RM80_SURF, RM80_CYL, RM80_SIZE, RM80_DEV },
|
||||
|
@ -327,11 +362,8 @@ struct drvtyp drv_tab[] = {
|
|||
{ RP07_SECT, RP07_SURF, RP07_CYL, RP07_SIZE, RP07_DEV },
|
||||
{ 0 } };
|
||||
|
||||
extern uint16 *M; /* memory */
|
||||
extern int32 int_req[IPL_HLVL];
|
||||
extern UNIT cpu_unit;
|
||||
extern int32 pdp11_log;
|
||||
extern FILE *sim_log;
|
||||
uint16 *rpxb = NULL; /* xfer buffer */
|
||||
int32 rpcs1 = 0; /* control/status 1 */
|
||||
int32 rpwc = 0; /* word count */
|
||||
int32 rpba = 0; /* bus address */
|
||||
|
@ -360,8 +392,8 @@ int reg_in_drive[32] = {
|
|||
|
||||
void update_rpcs (int32 flags, int32 drv);
|
||||
void rp_go (int32 drv, int32 fnc);
|
||||
t_stat rp_set_size (UNIT *uptr, int32 value);
|
||||
t_stat rp_set_bad (UNIT *uptr, int32 value);
|
||||
t_stat rp_set_size (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
t_stat rp_set_bad (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
t_stat rp_svc (UNIT *uptr);
|
||||
t_stat rp_reset (DEVICE *dptr);
|
||||
t_stat rp_boot (int32 unitno);
|
||||
|
@ -379,38 +411,40 @@ extern t_stat pdp11_bad_block (UNIT *uptr, int32 sec, int32 wds);
|
|||
|
||||
UNIT rp_unit[] = {
|
||||
{ UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+
|
||||
(RM03_DTYPE << UNIT_V_DTYPE), RM03_SIZE) },
|
||||
UNIT_ROABLE+(RM03_DTYPE << UNIT_V_DTYPE), RM03_SIZE) },
|
||||
{ UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+
|
||||
(RM03_DTYPE << UNIT_V_DTYPE), RM03_SIZE) },
|
||||
UNIT_ROABLE+(RM03_DTYPE << UNIT_V_DTYPE), RM03_SIZE) },
|
||||
{ UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+
|
||||
(RM03_DTYPE << UNIT_V_DTYPE), RM03_SIZE) },
|
||||
UNIT_ROABLE+(RM03_DTYPE << UNIT_V_DTYPE), RM03_SIZE) },
|
||||
{ UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+
|
||||
(RM03_DTYPE << UNIT_V_DTYPE), RM03_SIZE) },
|
||||
UNIT_ROABLE+(RM03_DTYPE << UNIT_V_DTYPE), RM03_SIZE) },
|
||||
{ UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+
|
||||
(RM03_DTYPE << UNIT_V_DTYPE), RM03_SIZE) },
|
||||
UNIT_ROABLE+(RM03_DTYPE << UNIT_V_DTYPE), RM03_SIZE) },
|
||||
{ UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+
|
||||
(RM03_DTYPE << UNIT_V_DTYPE), RM03_SIZE) },
|
||||
UNIT_ROABLE+(RM03_DTYPE << UNIT_V_DTYPE), RM03_SIZE) },
|
||||
{ UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+
|
||||
(RM03_DTYPE << UNIT_V_DTYPE), RM03_SIZE) },
|
||||
UNIT_ROABLE+(RM03_DTYPE << UNIT_V_DTYPE), RM03_SIZE) },
|
||||
{ UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+
|
||||
(RM03_DTYPE << UNIT_V_DTYPE), RM03_SIZE) } };
|
||||
UNIT_ROABLE+(RM03_DTYPE << UNIT_V_DTYPE), RM03_SIZE) } };
|
||||
|
||||
REG rp_reg[] = {
|
||||
{ ORDATA (RPCS1, rpcs1, 16) },
|
||||
{ ORDATA (RPWC, rpwc, 16) },
|
||||
{ ORDATA (RPBA, rpba, 16) },
|
||||
{ ORDATA (RPDA, rpda, 16) },
|
||||
{ ORDATA (RPCS2, rpcs2, 16) },
|
||||
{ ORDATA (RPOF, rpof, 16) },
|
||||
{ ORDATA (RPDC, rpdc, 16) },
|
||||
{ ORDATA (RPER2, rper2, 16) },
|
||||
{ ORDATA (RPER3, rper3, 16) },
|
||||
{ ORDATA (RPEC1, rpec1, 16) },
|
||||
{ ORDATA (RPEC2, rpec2, 16) },
|
||||
{ ORDATA (RPMR, rpmr, 16) },
|
||||
{ ORDATA (RPDB, rpdb, 16) },
|
||||
{ ORDATA (RPBAE, rpbae, 6) },
|
||||
{ ORDATA (RPCS3, rpcs3, 16) },
|
||||
{ GRDATA (RPCS1, rpcs1, RP_RDX, 16, 0) },
|
||||
{ GRDATA (RPWC, rpwc, RP_RDX, 16, 0) },
|
||||
{ GRDATA (RPBA, rpba, RP_RDX, 16, 0) },
|
||||
{ GRDATA (RPDA, rpda, RP_RDX, 16, 0) },
|
||||
{ GRDATA (RPCS2, rpcs2, RP_RDX, 16, 0) },
|
||||
{ BRDATA (RPDS, rpds, RP_RDX, 16, RP_NUMDR) },
|
||||
{ BRDATA (RPER1, rper1, RP_RDX, 16, RP_NUMDR) },
|
||||
{ GRDATA (RPOF, rpof, RP_RDX, 16, 0) },
|
||||
{ GRDATA (RPDC, rpdc, RP_RDX, 16, 0) },
|
||||
{ GRDATA (RPER2, rper2, RP_RDX, 16, 0) },
|
||||
{ GRDATA (RPER3, rper3, RP_RDX, 16, 0) },
|
||||
{ GRDATA (RPEC1, rpec1, RP_RDX, 16, 0) },
|
||||
{ GRDATA (RPEC2, rpec2, RP_RDX, 16, 0) },
|
||||
{ GRDATA (RPMR, rpmr, RP_RDX, 16, 0) },
|
||||
{ GRDATA (RPDB, rpdb, RP_RDX, 16, 0) },
|
||||
{ GRDATA (RPBAE, rpbae, RP_RDX, 6, 0) },
|
||||
{ GRDATA (RPCS3, rpcs3, RP_RDX, 16, 0) },
|
||||
{ FLDATA (IFF, rpiff, 0) },
|
||||
{ FLDATA (INT, IREQ (RP), INT_V_RP) },
|
||||
{ FLDATA (SC, rpcs1, CSR_V_ERR) },
|
||||
|
@ -418,46 +452,12 @@ REG rp_reg[] = {
|
|||
{ FLDATA (IE, rpcs1, CSR_V_IE) },
|
||||
{ DRDATA (STIME, rp_swait, 24), REG_NZ + PV_LEFT },
|
||||
{ DRDATA (RTIME, rp_rwait, 24), REG_NZ + PV_LEFT },
|
||||
{ ORDATA (RPDS0, rpds[0], 16) },
|
||||
{ ORDATA (RPDS1, rpds[1], 16) },
|
||||
{ ORDATA (RPDS2, rpds[2], 16) },
|
||||
{ ORDATA (RPDS3, rpds[3], 16) },
|
||||
{ ORDATA (RPDS4, rpds[4], 16) },
|
||||
{ ORDATA (RPDS5, rpds[5], 16) },
|
||||
{ ORDATA (RPDS6, rpds[6], 16) },
|
||||
{ ORDATA (RPDS7, rpds[7], 16) },
|
||||
{ ORDATA (RPDE0, rper1[0], 16) },
|
||||
{ ORDATA (RPDE1, rper1[1], 16) },
|
||||
{ ORDATA (RPDE2, rper1[2], 16) },
|
||||
{ ORDATA (RPDE3, rper1[3], 16) },
|
||||
{ ORDATA (RPDE4, rper1[4], 16) },
|
||||
{ ORDATA (RPDE5, rper1[5], 16) },
|
||||
{ ORDATA (RPDE6, rper1[6], 16) },
|
||||
{ ORDATA (RPDE7, rper1[7], 16) },
|
||||
{ ORDATA (RPFN0, rp_unit[0].FUNC, 5), REG_HRO },
|
||||
{ ORDATA (RPFN1, rp_unit[1].FUNC, 5), REG_HRO },
|
||||
{ ORDATA (RPFN2, rp_unit[2].FUNC, 5), REG_HRO },
|
||||
{ ORDATA (RPFN3, rp_unit[3].FUNC, 5), REG_HRO },
|
||||
{ ORDATA (RPFN4, rp_unit[4].FUNC, 5), REG_HRO },
|
||||
{ ORDATA (RPFN5, rp_unit[5].FUNC, 5), REG_HRO },
|
||||
{ ORDATA (RPFN6, rp_unit[6].FUNC, 5), REG_HRO },
|
||||
{ ORDATA (RPFN7, rp_unit[7].FUNC, 5), REG_HRO },
|
||||
{ GRDATA (FLG0, rp_unit[0].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ GRDATA (FLG1, rp_unit[1].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ GRDATA (FLG2, rp_unit[2].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ GRDATA (FLG3, rp_unit[3].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ GRDATA (FLG4, rp_unit[4].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ GRDATA (FLG5, rp_unit[5].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ GRDATA (FLG6, rp_unit[6].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ GRDATA (FLG7, rp_unit[7].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ URDATA (FNC, rp_unit[0].FUNC, RP_RDX, 5, 0,
|
||||
RP_NUMDR, REG_HRO) },
|
||||
{ URDATA (FLG, rp_unit[0].flags, RP_RDX, UNIT_W_UF, UNIT_V_UF - 1,
|
||||
RP_NUMDR, REG_HRO) },
|
||||
{ URDATA (CAPAC, rp_unit[0].capac, 10, 31, 0,
|
||||
RP_NUMDR, PV_LEFT | REG_HRO) },
|
||||
{ FLDATA (STOP_IOE, rp_stopioe, 0) },
|
||||
{ FLDATA (*DEVENB, rp_enb, 0), REG_HRO },
|
||||
{ NULL } };
|
||||
|
@ -508,7 +508,7 @@ MTAB rp_mod[] = {
|
|||
|
||||
DEVICE rp_dev = {
|
||||
"RP", rp_unit, rp_reg, rp_mod,
|
||||
RP_NUMDR, 8, 30, 1, 8, 16,
|
||||
RP_NUMDR, RP_RDX, 30, 1, RP_RDX, RP_WID,
|
||||
NULL, NULL, &rp_reset,
|
||||
&rp_boot, &rp_attach, &rp_detach };
|
||||
|
||||
|
@ -592,9 +592,11 @@ case 023: /* RPEC2 */
|
|||
*data = rpec2;
|
||||
break;
|
||||
case 024: /* RPBAE */
|
||||
if (RH_18B) return SCPE_NXM; /* not in RH11 */
|
||||
*data = rpbae = rpbae & ~AE_MBZ;
|
||||
break;
|
||||
case 025: /* RPCS3 */
|
||||
if (RH_18B) return SCPE_NXM; /* not in RH11 */
|
||||
*data = rpcs3 = (rpcs3 & ~(CS1_IE | CS3_MBZ)) | (rpcs1 & CS1_IE);
|
||||
break;
|
||||
default: /* all others */
|
||||
|
@ -704,11 +706,13 @@ case 016: /* RPDC */
|
|||
rpdc = data & ~DC_MBZ;
|
||||
break;
|
||||
case 024: /* RPBAE */
|
||||
if (RH_18B) return SCPE_NXM; /* not in RH11 */
|
||||
if ((access == WRITEB) && (PA & 1)) break;
|
||||
rpbae = data & ~AE_MBZ;
|
||||
rpcs1 = (rpcs1 & ~CS1_UAE) | ((rpbae << CS1_V_UAE) & CS1_UAE);
|
||||
break;
|
||||
case 025: /* RPCS3 */
|
||||
if (RH_18B) return SCPE_NXM; /* not in RH11 */
|
||||
if ((access == WRITEB) && (PA & 1)) break;
|
||||
rpcs3 = data & ~CS3_MBZ;
|
||||
rpcs1 = (rpcs1 & ~CS1_IE) | (rpcs3 & CS1_IE);
|
||||
|
@ -838,9 +842,11 @@ return;
|
|||
|
||||
t_stat rp_svc (UNIT *uptr)
|
||||
{
|
||||
int32 i, dtype, drv, err;
|
||||
int32 ba, wc, awc, twc, da, fc;
|
||||
static uint16 dbuf[RP_MAXFR];
|
||||
int32 i, t, dtype, drv, err;
|
||||
int32 wc, awc, da;
|
||||
t_addr ba;
|
||||
uint16 comp;
|
||||
int32 ub = RH_18B;
|
||||
|
||||
dtype = GET_DTYPE (uptr -> flags); /* get drive type */
|
||||
drv = uptr - rp_dev.units; /* get drv number */
|
||||
|
@ -866,7 +872,7 @@ case FNC_SEEK: /* seek */
|
|||
break;
|
||||
|
||||
case FNC_WRITE: /* write */
|
||||
if (uptr -> flags & UNIT_WLK) { /* write locked? */
|
||||
if (uptr -> flags & UNIT_WPRT) { /* write locked? */
|
||||
rper1[drv] = rper1[drv] | ER1_WLE; /* set drive error */
|
||||
update_rpcs (CS1_DONE | CS1_TRE, drv); /* set done, err */
|
||||
break; }
|
||||
|
@ -878,44 +884,65 @@ case FNC_READH: /* read headers */
|
|||
wc = 0200000 - rpwc; /* get true wc */
|
||||
|
||||
if ((da + wc) > drv_tab[dtype].size) { /* disk overrun? */
|
||||
rper1[drv] = rper1[drv] | ER1_AOE;
|
||||
if (wc > (drv_tab[dtype].size - da))
|
||||
wc = drv_tab[dtype].size - da; }
|
||||
rper1[drv] = rper1[drv] | ER1_AOE; /* set err */
|
||||
wc = drv_tab[dtype].size - da; /* trim xfer */
|
||||
if (da >= drv_tab[dtype].size) { /* none left? */
|
||||
update_rpcs (CS1_DONE | CS1_TRE, drv); /* set done, err */
|
||||
break; } }
|
||||
|
||||
err = fseek (uptr -> fileref, da * sizeof (int16), SEEK_SET);
|
||||
if (uptr -> FUNC == FNC_WRITE) { /* write? */
|
||||
for (twc = 0; twc < wc; twc++) {
|
||||
if (!ADDR_IS_MEM (ba)) { /* nx memory? */
|
||||
if (rpcs2 & CS2_UAI) { /* no addr inc? */
|
||||
if (t = Map_ReadW (ba, 2, &comp, ub)) { /* get 1st wd */
|
||||
wc = 0; /* NXM, no xfr */
|
||||
rpcs2 = rpcs2 | CS2_NEM; } /* set nxm err */
|
||||
for (i = 0; i < wc; i++) rpxb[i] = comp; }
|
||||
else { /* normal */
|
||||
if (t = Map_ReadW (ba, wc << 1, rpxb, ub)) { /* get buf */
|
||||
wc = wc - (t >> 1); /* NXM, adj wc */
|
||||
rpcs2 = rpcs2 | CS2_NEM; } /* set nxm err */
|
||||
ba = ba + (wc << 1); } /* adv ba */
|
||||
awc = (wc + (RP_NUMWD - 1)) & ~(RP_NUMWD - 1);
|
||||
for (i = wc; i < awc; i++) rpxb[i] = 0; /* fill buf */
|
||||
if (wc && !err) { /* write buf */
|
||||
fxwrite (rpxb, sizeof (uint16), wc, uptr -> fileref);
|
||||
err = ferror (uptr -> fileref); }
|
||||
} /* end if wr */
|
||||
else if ((uptr -> FUNC == FNC_READ) || /* read? */
|
||||
(uptr -> FUNC == FNC_READH)) {
|
||||
i = fxread (rpxb, sizeof (uint16), wc, uptr -> fileref);
|
||||
err = ferror (uptr -> fileref);
|
||||
for ( ; i < wc; i++) rpxb[i] = 0; /* fill buf */
|
||||
if (rpcs2 & CS2_UAI) { /* no addr inc? */
|
||||
if (t = Map_WriteW (ba, 2, &rpxb[wc - 1], ub)) {
|
||||
wc = 0; /* NXM, no xfr */
|
||||
rpcs2 = rpcs2 | CS2_NEM; } } /* set nxm err */
|
||||
else { /* normal */
|
||||
if (t = Map_WriteW (ba, wc << 1, rpxb, ub)) { /* put buf */
|
||||
wc = wc - (t >> 1); /* NXM, adj wc */
|
||||
rpcs2 = rpcs2 | CS2_NEM; } /* set nxm err */
|
||||
ba = ba + (wc << 1); } /* adv ba */
|
||||
} /* end if read */
|
||||
else { /* wchk */
|
||||
i = fxread (rpxb, sizeof (uint16), wc, uptr -> fileref);
|
||||
err = ferror (uptr -> fileref);
|
||||
for ( ; i < wc; i++) rpxb[i] = 0; /* fill buf */
|
||||
awc = wc;
|
||||
for (wc = 0; wc < awc; wc++) { /* loop thru buf */
|
||||
if (Map_ReadW (ba, 2, &comp, ub)) { /* read word */
|
||||
rpcs2 = rpcs2 | CS2_NEM; /* set error */
|
||||
break; }
|
||||
dbuf[twc] = M[ba >> 1]; /* write to disk */
|
||||
if ((rpcs2 & CS2_UAI) == 0) ba = ba + 2; }
|
||||
if (fc = twc & (RP_NUMWD - 1)) { /* fill? */
|
||||
fc = RP_NUMWD - fc;
|
||||
for (i = 0; i < fc; i++) dbuf[twc + i] = 0; }
|
||||
fxwrite (dbuf, sizeof (uint16), twc + fc, uptr -> fileref);
|
||||
err = ferror (uptr -> fileref);
|
||||
} /* end if */
|
||||
else { /* read, wchk */
|
||||
awc = fxread (dbuf, sizeof (uint16), wc, uptr -> fileref);
|
||||
err = ferror (uptr -> fileref);
|
||||
for ( ; awc < wc; awc++) dbuf[awc] = 0;
|
||||
for (twc = 0; twc < wc; twc++) {
|
||||
if (!ADDR_IS_MEM (ba)) { /* nx memory? */
|
||||
rpcs2 = rpcs2 | CS2_NEM; /* set error */
|
||||
break; }
|
||||
if (uptr -> FUNC == FNC_READ) M[ba >> 1] = dbuf[twc];
|
||||
else if (M[ba >> 1] != dbuf[twc]) {
|
||||
if (comp != rpxb[wc]) { /* compare wd */
|
||||
rpcs2 = rpcs2 | CS2_WCE; /* set error */
|
||||
break; }
|
||||
if ((rpcs2 & CS2_UAI) == 0) ba = ba + 2; }
|
||||
} /* end else */
|
||||
} /* end else wchk */
|
||||
|
||||
rpwc = (rpwc + twc) & 0177777; /* final word count */
|
||||
rpwc = (rpwc + wc) & 0177777; /* final word count */
|
||||
rpba = (ba & 0177777) & ~BA_MBZ; /* lower 16b */
|
||||
rpbae = (ba >> 16) & ~AE_MBZ; /* upper 6b */
|
||||
rpcs1 = (rpcs1 & ~ CS1_UAE) | ((rpbae << CS1_V_UAE) & CS1_UAE);
|
||||
da = da + twc + (RP_NUMWD - 1);
|
||||
da = da + wc + (RP_NUMWD - 1);
|
||||
if (da >= drv_tab[dtype].size) rpds[drv] = rpds[drv] | DS_LST;
|
||||
da = da / RP_NUMWD;
|
||||
rpda = da % drv_tab[dtype].sect;
|
||||
|
@ -1002,10 +1029,12 @@ for (i = 0; i < RP_NUMDR; i++) {
|
|||
sim_cancel (uptr);
|
||||
uptr -> CYL = uptr -> FUNC = 0;
|
||||
if (uptr -> flags & UNIT_ATT) rpds[i] = (rpds[i] & DS_VV) |
|
||||
DS_DPR | DS_RDY | DS_MOL | ((uptr -> flags & UNIT_WLK)? DS_WRL: 0);
|
||||
DS_DPR | DS_RDY | DS_MOL | ((uptr -> flags & UNIT_WPRT)? DS_WRL: 0);
|
||||
else if (uptr -> flags & UNIT_DIS) rpds[i] = 0;
|
||||
else rpds[i] = DS_DPR;
|
||||
rper1[i] = 0; }
|
||||
if (rpxb == NULL) rpxb = calloc (RP_MAXFR, sizeof (unsigned int16));
|
||||
if (rpxb == NULL) return SCPE_MEM;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
@ -1021,14 +1050,16 @@ r = attach_unit (uptr, cptr);
|
|||
if (r != SCPE_OK) return r;
|
||||
drv = uptr - rp_dev.units; /* get drv number */
|
||||
rpds[drv] = DS_ATA | DS_MOL | DS_RDY | DS_DPR |
|
||||
((uptr -> flags & UNIT_WLK)? DS_WRL: 0);
|
||||
((uptr -> flags & UNIT_WPRT)? DS_WRL: 0);
|
||||
rper1[drv] = 0;
|
||||
update_rpcs (CS1_SC, drv);
|
||||
|
||||
if ((uptr -> flags & UNIT_AUTO) == 0) return SCPE_OK; /* autosize? */
|
||||
if (fseek (uptr -> fileref, 0, SEEK_END)) return SCPE_OK;
|
||||
if ((p = ftell (uptr -> fileref)) == 0)
|
||||
return pdp11_bad_block (uptr, drv_tab[GET_DTYPE (uptr -> flags)].sect, RP_NUMWD);
|
||||
if ((p = ftell (uptr -> fileref)) == 0) {
|
||||
if (uptr -> flags & UNIT_RO) return SCPE_OK;
|
||||
return pdp11_bad_block (uptr,
|
||||
drv_tab[GET_DTYPE (uptr -> flags)].sect, RP_NUMWD); }
|
||||
for (i = 0; drv_tab[i].sect != 0; i++) {
|
||||
if (p <= (drv_tab[i].size * (int) sizeof (int16))) {
|
||||
uptr -> flags = (uptr -> flags & ~UNIT_DTYPE) | (i << UNIT_V_DTYPE);
|
||||
|
@ -1057,22 +1088,24 @@ return detach_unit (uptr);
|
|||
|
||||
/* Set size command validation routine */
|
||||
|
||||
t_stat rp_set_size (UNIT *uptr, int32 value)
|
||||
t_stat rp_set_size (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
if (uptr -> flags & UNIT_ATT) return SCPE_ALATT;
|
||||
uptr -> capac = drv_tab[GET_DTYPE (value)].size;
|
||||
uptr -> capac = drv_tab[GET_DTYPE (val)].size;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Set bad block routine */
|
||||
|
||||
t_stat rp_set_bad (UNIT *uptr, int32 value)
|
||||
t_stat rp_set_bad (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
return pdp11_bad_block (uptr, drv_tab[GET_DTYPE (uptr -> flags)].sect, RP_NUMWD);
|
||||
}
|
||||
|
||||
/* Device bootstrap */
|
||||
|
||||
#if defined (VM_PDP11)
|
||||
|
||||
#define BOOT_START 02000 /* start */
|
||||
#define BOOT_UNIT 02006 /* unit number */
|
||||
#define BOOT_LEN (sizeof (boot_rom) / sizeof (int32))
|
||||
|
@ -1111,3 +1144,12 @@ M[BOOT_UNIT >> 1] = unitno & CS2_M_UNIT;
|
|||
saved_PC = BOOT_START;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
t_stat rp_boot (int32 unitno)
|
||||
{
|
||||
return SCPE_NOFNC;
|
||||
}
|
||||
|
||||
#endif
|
1849
PDP11/pdp11_rq.c
Normal file
1849
PDP11/pdp11_rq.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -25,6 +25,8 @@
|
|||
|
||||
rx RX11/RX01 floppy disk
|
||||
|
||||
30-Nov-01 RMS Added read only unit, extended SET/SHOW support
|
||||
24-Nov-01 RMS Converted FLG to array
|
||||
07-Sep-01 RMS Revised device disable and interrupt mechanisms
|
||||
17-Jul-01 RMS Fixed warning from VC++ 6.0
|
||||
26-Apr-01 RMS Added device enable/disable support
|
||||
|
@ -48,6 +50,7 @@
|
|||
#define RX_M_NUMDR 01
|
||||
#define UNIT_V_WLK (UNIT_V_UF) /* write locked */
|
||||
#define UNIT_WLK (1u << UNIT_V_UF)
|
||||
#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */
|
||||
|
||||
#define IDLE 0 /* idle state */
|
||||
#define RWDS 1 /* rw, sect next */
|
||||
|
@ -139,8 +142,7 @@ REG rx_reg[] = {
|
|||
{ DRDATA (CTIME, rx_cwait, 24), PV_LEFT },
|
||||
{ DRDATA (STIME, rx_swait, 24), PV_LEFT },
|
||||
{ DRDATA (XTIME, rx_xwait, 24), PV_LEFT },
|
||||
{ FLDATA (FLG0, rx_unit[0].flags, UNIT_V_WLK), REG_HRO },
|
||||
{ FLDATA (FLG1, rx_unit[1].flags, UNIT_V_WLK), REG_HRO },
|
||||
{ URDATA (FLG, rx_unit[0].flags, 2, 1, UNIT_V_WLK, RX_NUMDR, REG_HRO) },
|
||||
{ FLDATA (STOP_IOE, rx_stopioe, 0) },
|
||||
{ BRDATA (SBUF, rx_buf, 8, 8, RX_NUMBY) },
|
||||
{ FLDATA (*DEVENB, rx_enb, 0), REG_HRO },
|
||||
|
@ -316,7 +318,7 @@ case RWDT: /* wait for track */
|
|||
if (func == RXCS_READ) { /* read? */
|
||||
for (i = 0; i < RX_NUMBY; i++)
|
||||
rx_buf[i] = *(((int8 *) uptr -> filebuf) + da + i); }
|
||||
else { if (uptr -> flags & UNIT_WLK) { /* write and locked? */
|
||||
else { if (uptr -> flags & UNIT_WPRT) { /* write and locked? */
|
||||
rx_esr = rx_esr | RXES_WLK; /* flag error */
|
||||
rx_done (rx_esr, 0100); /* done, error */
|
||||
break; }
|
|
@ -27,6 +27,8 @@
|
|||
tti,tto DL11 terminal input/output
|
||||
clk KW11L line frequency clock
|
||||
|
||||
29-Nov-01 RMS Added read only unit support
|
||||
09-Nov-01 RMS Added RQDX3 support
|
||||
07-Oct-01 RMS Upgraded clock to full KW11L for RSTS/E autoconfigure
|
||||
07-Sep-01 RMS Moved function prototypes, revised interrupt mechanism
|
||||
17-Jul-01 RMS Moved function prototype
|
||||
|
@ -60,6 +62,7 @@ int32 tto_csr = 0; /* control/status */
|
|||
int32 clk_csr = 0; /* control/status */
|
||||
int32 clk_tps = 60; /* ticks/second */
|
||||
int32 tmxr_poll = CLK_DELAY; /* term mux poll */
|
||||
int32 tmr_poll = CLK_DELAY; /* timer poll */
|
||||
|
||||
t_stat ptr_svc (UNIT *uptr);
|
||||
t_stat ptp_svc (UNIT *uptr);
|
||||
|
@ -84,7 +87,8 @@ t_stat ptp_detach (UNIT *uptr);
|
|||
*/
|
||||
|
||||
UNIT ptr_unit = {
|
||||
UDATA (&ptr_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_IN_WAIT };
|
||||
UDATA (&ptr_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0),
|
||||
SERIAL_IN_WAIT };
|
||||
|
||||
REG ptr_reg[] = {
|
||||
{ ORDATA (BUF, ptr_unit.buf, 8) },
|
||||
|
@ -500,6 +504,7 @@ clk_csr = clk_csr | CSR_DONE; /* set done */
|
|||
if (clk_csr & CSR_IE) SET_INT (CLK);
|
||||
t = sim_rtc_calb (clk_tps); /* calibrate clock */
|
||||
sim_activate (&clk_unit, t); /* reactivate unit */
|
||||
tmr_poll = t; /* set timer poll */
|
||||
tmxr_poll = t; /* set mux poll */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
@ -509,6 +514,7 @@ t_stat clk_reset (DEVICE *dptr)
|
|||
clk_csr = 0;
|
||||
CLR_INT (CLK);
|
||||
sim_activate (&clk_unit, clk_unit.wait); /* activate unit */
|
||||
tmr_poll = clk_unit.wait; /* set timer poll */
|
||||
tmxr_poll = clk_unit.wait; /* set mux poll */
|
||||
return SCPE_OK;
|
||||
}
|
|
@ -23,6 +23,7 @@
|
|||
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
29-Nov-01 RMS Added read only unit support
|
||||
17-Sep-01 RMS Removed multiconsole support
|
||||
26-Aug-01 RMS Added DZ11
|
||||
20-Aug-01 RMS Updated bad block inquiry
|
||||
|
@ -48,10 +49,10 @@ extern DEVICE ptr_dev, ptp_dev;
|
|||
extern DEVICE tti_dev, tto_dev;
|
||||
extern DEVICE lpt_dev, clk_dev;
|
||||
extern DEVICE dz_dev;
|
||||
extern DEVICE rk_dev, rx_dev;
|
||||
extern DEVICE rl_dev, rp_dev;
|
||||
extern DEVICE dt_dev, tm_dev;
|
||||
extern DEVICE ts_dev;
|
||||
extern DEVICE rk_dev, rl_dev;
|
||||
extern DEVICE rp_dev, rq_dev;
|
||||
extern DEVICE rx_dev, dt_dev;
|
||||
extern DEVICE tm_dev, ts_dev;
|
||||
/* extern DEVICE hk_dev; */
|
||||
extern UNIT cpu_unit;
|
||||
extern REG cpu_reg[];
|
||||
|
@ -80,8 +81,8 @@ DEVICE *sim_devices[] = {
|
|||
&tti_dev, &tto_dev,
|
||||
&lpt_dev, &clk_dev,
|
||||
&dz_dev,
|
||||
&rk_dev, /* &hk_dev, */
|
||||
&rl_dev, &rp_dev,
|
||||
&rk_dev, &rl_dev,
|
||||
&rp_dev, &rq_dev,
|
||||
&rx_dev, &dt_dev,
|
||||
&tm_dev, &ts_dev,
|
||||
NULL };
|
||||
|
@ -107,7 +108,8 @@ const char *sim_stop_messages[] = {
|
|||
"Breakpoint",
|
||||
"Wait state",
|
||||
"Trap vector fetch abort",
|
||||
"Trap stack push abort" };
|
||||
"Trap stack push abort",
|
||||
"RQDX3 consistency error" };
|
||||
|
||||
/* Binary loader.
|
||||
|
||||
|
@ -210,6 +212,7 @@ int16 *buf;
|
|||
|
||||
if ((sec < 2) || (wds < 16)) return SCPE_ARG;
|
||||
if ((uptr -> flags & UNIT_ATT) == 0) return SCPE_UNATT;
|
||||
if (uptr -> flags & UNIT_RO) return SCPE_RO;
|
||||
if (!get_yn ("Create bad block table on last track? [N]", FALSE)) return SCPE_OK;
|
||||
da = (uptr -> capac - (sec * wds)) * sizeof (int16);
|
||||
if (fseek (uptr -> fileref, da, SEEK_SET)) return SCPE_IOERR;
|
|
@ -25,6 +25,9 @@
|
|||
|
||||
tc TC11/TU56 DECtape
|
||||
|
||||
30-Nov-01 RMS Added read only unit, extended SET/SHOW support
|
||||
24-Nov-01 RMS Converted POS, STATT, LASTT to arrays
|
||||
09-Nov-01 RMS Added bus map support
|
||||
15-Sep-01 RMS Integrated debug logging
|
||||
27-Sep-01 RMS Fixed interrupt after stop for RSTS/E
|
||||
07-Sep-01 RMS Revised device disable and interrupt mechanisms
|
||||
|
@ -86,6 +89,7 @@
|
|||
#define UNIT_W_UF 3 /* saved flag width */
|
||||
#define STATE u3 /* unit state */
|
||||
#define LASTT u4 /* last time update */
|
||||
#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */
|
||||
|
||||
/* System independent DECtape constants */
|
||||
|
||||
|
@ -241,7 +245,7 @@ extern uint16 *M; /* memory */
|
|||
extern int32 int_req[IPL_HLVL];
|
||||
extern UNIT cpu_unit;
|
||||
extern int32 sim_switches;
|
||||
extern int32 pdp11_log;
|
||||
extern int32 cpu_log;
|
||||
extern FILE *sim_log;
|
||||
int32 tcst = 0; /* status */
|
||||
int32 tccm = 0; /* command */
|
||||
|
@ -311,46 +315,14 @@ REG dt_reg[] = {
|
|||
{ DRDATA (DCTIME, dt_dctime, 31), REG_NZ },
|
||||
{ ORDATA (SUBSTATE, dt_substate, 1) },
|
||||
{ DRDATA (LBLK, dt_logblk, 12), REG_HIDDEN },
|
||||
{ DRDATA (POS0, dt_unit[0].pos, 31), PV_LEFT + REG_RO },
|
||||
{ DRDATA (POS1, dt_unit[1].pos, 31), PV_LEFT + REG_RO },
|
||||
{ DRDATA (POS2, dt_unit[2].pos, 31), PV_LEFT + REG_RO },
|
||||
{ DRDATA (POS3, dt_unit[3].pos, 31), PV_LEFT + REG_RO },
|
||||
{ DRDATA (POS4, dt_unit[4].pos, 31), PV_LEFT + REG_RO },
|
||||
{ DRDATA (POS5, dt_unit[5].pos, 31), PV_LEFT + REG_RO },
|
||||
{ DRDATA (POS6, dt_unit[6].pos, 31), PV_LEFT + REG_RO },
|
||||
{ DRDATA (POS7, dt_unit[7].pos, 31), PV_LEFT + REG_RO },
|
||||
{ ORDATA (STATT0, dt_unit[0].STATE, 18), REG_RO },
|
||||
{ ORDATA (STATT1, dt_unit[1].STATE, 18), REG_RO },
|
||||
{ ORDATA (STATT2, dt_unit[2].STATE, 18), REG_RO },
|
||||
{ ORDATA (STATT3, dt_unit[3].STATE, 18), REG_RO },
|
||||
{ ORDATA (STATT4, dt_unit[4].STATE, 18), REG_RO },
|
||||
{ ORDATA (STATT5, dt_unit[5].STATE, 18), REG_RO },
|
||||
{ ORDATA (STATT6, dt_unit[6].STATE, 18), REG_RO },
|
||||
{ ORDATA (STATT7, dt_unit[7].STATE, 18), REG_RO },
|
||||
{ DRDATA (LASTT0, dt_unit[0].LASTT, 32), REG_HRO },
|
||||
{ DRDATA (LASTT1, dt_unit[1].LASTT, 32), REG_HRO },
|
||||
{ DRDATA (LASTT2, dt_unit[2].LASTT, 32), REG_HRO },
|
||||
{ DRDATA (LASTT3, dt_unit[3].LASTT, 32), REG_HRO },
|
||||
{ DRDATA (LASTT4, dt_unit[4].LASTT, 32), REG_HRO },
|
||||
{ DRDATA (LASTT5, dt_unit[5].LASTT, 32), REG_HRO },
|
||||
{ DRDATA (LASTT6, dt_unit[6].LASTT, 32), REG_HRO },
|
||||
{ DRDATA (LASTT7, dt_unit[7].LASTT, 32), REG_HRO },
|
||||
{ GRDATA (FLG0, dt_unit[0].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ GRDATA (FLG1, dt_unit[1].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ GRDATA (FLG2, dt_unit[2].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ GRDATA (FLG3, dt_unit[3].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ GRDATA (FLG4, dt_unit[4].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ GRDATA (FLG5, dt_unit[5].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ GRDATA (FLG6, dt_unit[6].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ GRDATA (FLG7, dt_unit[7].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ URDATA (POS, dt_unit[0].pos, 10, 31, 0,
|
||||
DT_NUMDR, PV_LEFT | REG_RO) },
|
||||
{ URDATA (STATT, dt_unit[0].STATE, 8, 18, 0,
|
||||
DT_NUMDR, REG_RO) },
|
||||
{ URDATA (LASTT, dt_unit[0].LASTT, 10, 32, 0,
|
||||
DT_NUMDR, REG_HRO) },
|
||||
{ URDATA (FLG, dt_unit[0].flags, 8, UNIT_W_UF, UNIT_V_UF - 1,
|
||||
DT_NUMDR, REG_HRO) },
|
||||
{ FLDATA (*DEVENB, dt_enb, 0), REG_HRO },
|
||||
{ NULL } };
|
||||
|
||||
|
@ -437,8 +409,8 @@ case 001: /* TCCM */
|
|||
if (uptr -> flags & UNIT_DIS) /* disabled? */
|
||||
dt_seterr (uptr, STA_SEL); /* select err */
|
||||
if ((fnc == FNC_WMRK) || /* write mark? */
|
||||
((fnc == FNC_WALL) && (uptr -> flags & UNIT_WLK)) ||
|
||||
((fnc == FNC_WRIT) && (uptr -> flags & UNIT_WLK)))
|
||||
((fnc == FNC_WALL) && (uptr -> flags & UNIT_WPRT)) ||
|
||||
((fnc == FNC_WRIT) && (uptr -> flags & UNIT_WPRT)))
|
||||
dt_seterr (uptr, STA_ILO); /* illegal op */
|
||||
if (!(tccm & CSR_ERR)) dt_newsa (tccm); }
|
||||
else if ((tccm & CSR_ERR) == 0) { /* clear err? */
|
||||
|
@ -712,7 +684,7 @@ int32 fnc = DTS_GETFNC (uptr -> STATE);
|
|||
int32 *bptr = uptr -> filebuf;
|
||||
int32 unum = uptr - dt_dev.units;
|
||||
int32 blk, wrd, relpos, dat;
|
||||
t_addr ma, ba;
|
||||
t_addr ma, mma, ba;
|
||||
|
||||
/* Motion cases
|
||||
|
||||
|
@ -775,11 +747,12 @@ case FNC_READ: /* read */
|
|||
tcwc = tcwc & DMASK; /* incr MA, WC */
|
||||
tcba = tcba & DMASK;
|
||||
ma = (CSR_GETMEX (tccm) << 16) | tcba; /* form 18b addr */
|
||||
if (ma >= MEMSIZE) { /* nx mem? */
|
||||
if (!Map_Addr (ma, &mma) || /* map addr */
|
||||
!ADDR_IS_MEM (mma)) { /* nx mem? */
|
||||
dt_seterr (uptr, STA_NXM);
|
||||
break; }
|
||||
ba = (blk * DTU_BSIZE (uptr)) + wrd; /* buffer ptr */
|
||||
M[ma >> 1] = tcdt = bptr[ba] & DMASK; /* read word */
|
||||
M[mma >> 1] = tcdt = bptr[ba] & DMASK; /* read word */
|
||||
tcwc = (tcwc + 1) & DMASK; /* incr MA, WC */
|
||||
tcba = (tcba + 2) & DMASK;
|
||||
if (tcba <= 1) tccm = CSR_INCMEX (tccm);
|
||||
|
@ -806,10 +779,11 @@ case FNC_WRIT: /* write */
|
|||
wrd = DT_LIN2WD (uptr -> pos, uptr); /* get word # */
|
||||
if (dt_substate) tcdt = 0; /* wc ovf? fill */
|
||||
else { ma = (CSR_GETMEX (tccm) << 16) | tcba; /* form 18b addr */
|
||||
if (ma >= MEMSIZE) { /* nx mem? */
|
||||
if (!Map_Addr (ma, &mma) || /* map addr */
|
||||
!ADDR_IS_MEM (mma)) { /* nx mem? */
|
||||
dt_seterr (uptr, STA_NXM);
|
||||
break; }
|
||||
else tcdt = M[ma >> 1]; /* get word */
|
||||
else tcdt = M[mma >> 1]; /* get word */
|
||||
tcwc = (tcwc + 1) & DMASK; /* incr MA, WC */
|
||||
tcba = (tcba + 2) & DMASK;
|
||||
if (tcba <= 1) tccm = CSR_INCMEX (tccm); }
|
||||
|
@ -1117,7 +1091,7 @@ if (sim_is_active (uptr)) { /* active? cancel op */
|
|||
tccm = tccm | CSR_ERR | CSR_DONE;
|
||||
if (tccm & CSR_IE) SET_INT (DTA); }
|
||||
uptr -> STATE = uptr -> pos = 0; }
|
||||
if (uptr -> hwmark) { /* any data? */
|
||||
if (uptr -> hwmark && ((uptr -> flags & UNIT_RO) == 0)) { /* any data? */
|
||||
printf ("TC: writing buffer to file\n");
|
||||
rewind (uptr -> fileref); /* start of file */
|
||||
if (uptr -> flags & UNIT_8FMT) { /* PDP8? */
|
|
@ -25,6 +25,9 @@
|
|||
|
||||
tm TM11/TU10 magtape
|
||||
|
||||
30-Nov-01 RMS Added read only unit, extended SET/SHOW support
|
||||
24-Nov-01 RMS Converted UST, POS, FLG to arrays
|
||||
09-Nov-01 RMS Added bus map support
|
||||
18-Oct-01 RMS Added stub diagnostic register (found by Thord Nilson)
|
||||
07-Sep-01 RMS Revised device disable and interrupt mechanisms
|
||||
26-Apr-01 RMS Added device enable/disable support
|
||||
|
@ -64,8 +67,8 @@
|
|||
#define UNIT_W_UF 2 /* saved user flags */
|
||||
#define USTAT u3 /* unit status */
|
||||
#define UNUM u4 /* unit number */
|
||||
#define DBSIZE (1 << 16) /* max data buf */
|
||||
#define DBMASK (SBSIZE - 1)
|
||||
#define TM_MAXFR (1 << 16) /* max transfer */
|
||||
#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */
|
||||
|
||||
/* Command - tm_cmd */
|
||||
|
||||
|
@ -133,7 +136,7 @@
|
|||
|
||||
extern uint16 *M; /* memory */
|
||||
extern int32 int_req[IPL_HLVL];
|
||||
extern UNIT cpu_unit;
|
||||
uint8 *tmxb = NULL; /* xfer buffer */
|
||||
int32 tm_sta = 0; /* status register */
|
||||
int32 tm_cmd = 0; /* command register */
|
||||
int32 tm_ca = 0; /* current address */
|
||||
|
@ -152,7 +155,7 @@ t_stat tm_boot (int32 unitno);
|
|||
void tm_go (UNIT *uptr);
|
||||
int32 tm_updcsta (UNIT *uptr);
|
||||
void tm_set_done (void);
|
||||
t_stat tm_vlock (UNIT *uptr, int32 val);
|
||||
t_stat tm_vlock (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
|
||||
/* MT data structures
|
||||
|
||||
|
@ -185,38 +188,11 @@ REG tm_reg[] = {
|
|||
{ FLDATA (IE, tm_cmd, CSR_V_IE) },
|
||||
{ FLDATA (STOP_IOE, tm_stopioe, 0) },
|
||||
{ DRDATA (TIME, tm_time, 24), PV_LEFT },
|
||||
{ ORDATA (UST0, tm_unit[0].USTAT, 16) },
|
||||
{ ORDATA (UST1, tm_unit[1].USTAT, 16) },
|
||||
{ ORDATA (UST2, tm_unit[2].USTAT, 16) },
|
||||
{ ORDATA (UST3, tm_unit[3].USTAT, 16) },
|
||||
{ ORDATA (UST4, tm_unit[4].USTAT, 16) },
|
||||
{ ORDATA (UST5, tm_unit[5].USTAT, 16) },
|
||||
{ ORDATA (UST6, tm_unit[6].USTAT, 16) },
|
||||
{ ORDATA (UST7, tm_unit[7].USTAT, 16) },
|
||||
{ DRDATA (POS0, tm_unit[0].pos, 31), PV_LEFT + REG_RO },
|
||||
{ DRDATA (POS1, tm_unit[1].pos, 31), PV_LEFT + REG_RO },
|
||||
{ DRDATA (POS2, tm_unit[2].pos, 31), PV_LEFT + REG_RO },
|
||||
{ DRDATA (POS3, tm_unit[3].pos, 31), PV_LEFT + REG_RO },
|
||||
{ DRDATA (POS4, tm_unit[4].pos, 31), PV_LEFT + REG_RO },
|
||||
{ DRDATA (POS5, tm_unit[5].pos, 31), PV_LEFT + REG_RO },
|
||||
{ DRDATA (POS6, tm_unit[6].pos, 31), PV_LEFT + REG_RO },
|
||||
{ DRDATA (POS7, tm_unit[7].pos, 31), PV_LEFT + REG_RO },
|
||||
{ GRDATA (FLG0, tm_unit[0].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ GRDATA (FLG1, tm_unit[1].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ GRDATA (FLG2, tm_unit[2].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ GRDATA (FLG3, tm_unit[3].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ GRDATA (FLG4, tm_unit[4].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ GRDATA (FLG5, tm_unit[5].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ GRDATA (FLG6, tm_unit[6].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ GRDATA (FLG7, tm_unit[7].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ URDATA (UST, tm_unit[0].USTAT, 8, 16, 0, TM_NUMDR, 0) },
|
||||
{ URDATA (POS, tm_unit[0].pos, 10, 31, 0,
|
||||
TM_NUMDR, PV_LEFT | REG_RO) },
|
||||
{ URDATA (FLG, tm_unit[0].flags, 8, UNIT_W_UF, UNIT_V_UF - 1,
|
||||
TM_NUMDR, REG_HRO) },
|
||||
{ FLDATA (*DEVENB, tm_enb, 0), REG_HRO },
|
||||
{ NULL } };
|
||||
|
||||
|
@ -326,7 +302,7 @@ f = GET_FNC (tm_cmd); /* get function */
|
|||
if (((uptr -> flags & UNIT_ATT) == 0) || /* not attached? */
|
||||
sim_is_active (uptr) || /* busy? */
|
||||
(((f == MTC_WRITE) || (f == MTC_WREOF) || (f == MTC_WREXT)) &&
|
||||
(uptr -> flags & UNIT_WLK))) { /* write locked? */
|
||||
(uptr -> flags & UNIT_WPRT))) { /* write locked? */
|
||||
tm_sta = tm_sta | STA_ILL; /* illegal */
|
||||
tm_set_done (); /* set done */
|
||||
return; }
|
||||
|
@ -352,19 +328,17 @@ return;
|
|||
|
||||
t_stat tm_svc (UNIT *uptr)
|
||||
{
|
||||
int32 f, i, p, err;
|
||||
int32 f, i, t, err;
|
||||
t_addr xma;
|
||||
t_stat rval;
|
||||
t_mtrlnt tbc, cbc;
|
||||
uint16 c;
|
||||
static uint8 dbuf[DBSIZE];
|
||||
static t_mtrlnt bceof = { 0 };
|
||||
|
||||
if (uptr -> USTAT & STA_REW) { /* rewind? */
|
||||
uptr -> pos = 0; /* update position */
|
||||
if (uptr -> flags & UNIT_ATT) /* still on line? */
|
||||
uptr -> USTAT = STA_ONL | STA_BOT |
|
||||
((uptr -> flags & UNIT_WLK)? STA_WLK: 0);
|
||||
((uptr -> flags & UNIT_WPRT)? STA_WLK: 0);
|
||||
else uptr -> USTAT = 0;
|
||||
if (uptr -> UNUM == GET_UNIT (tm_cmd)) { /* selected? */
|
||||
tm_set_done (); /* set done */
|
||||
|
@ -380,7 +354,7 @@ if ((uptr -> flags & UNIT_ATT) == 0) { /* if not attached */
|
|||
|
||||
f = GET_FNC (tm_cmd); /* get command */
|
||||
if (((f == MTC_WRITE) || (f == MTC_WREOF) || (f == MTC_WREXT)) &&
|
||||
(uptr -> flags & UNIT_WLK)) { /* write and locked? */
|
||||
(uptr -> flags & UNIT_WPRT)) { /* write and locked? */
|
||||
tm_sta = tm_sta | STA_ILL; /* illegal operation */
|
||||
tm_set_done (); /* set done */
|
||||
tm_updcsta (uptr); /* update status */
|
||||
|
@ -408,38 +382,31 @@ case MTC_READ: /* read */
|
|||
tbc = MTRL (tbc); /* ignore error flag */
|
||||
if (tbc > cbc) tm_sta = tm_sta | STA_RLE; /* wrong size? */
|
||||
if (tbc < cbc) cbc = tbc; /* use smaller */
|
||||
i = fxread (dbuf, sizeof (int8), cbc, uptr -> fileref);
|
||||
for ( ; i < tbc; i++) dbuf[i] = 0; /* fill with 0's */
|
||||
i = fxread (tmxb, sizeof (int8), cbc, uptr -> fileref);
|
||||
err = ferror (uptr -> fileref);
|
||||
for (i = 0; i < cbc; i++) { /* copy buffer */
|
||||
if (xma >= MEMSIZE) { /* nx memory? */
|
||||
tm_sta = tm_sta | STA_NXM;
|
||||
break; }
|
||||
p = xma >> 1; /* word address */
|
||||
c = dbuf[i]; /* character */
|
||||
if (i & 1) M[p] = (M[p] & 0377) | (c << 8);
|
||||
else M[p] = (M[p] & 0177400) | c;
|
||||
xma = (xma + 1) & 0777777;
|
||||
tm_bc = (tm_bc + 1) & 0177777; }
|
||||
uptr -> pos = uptr -> pos + ((tbc + 1) & ~1) +
|
||||
for ( ; i < cbc; i++) tmxb[i] = 0; /* fill with 0's */
|
||||
if (t = Map_WriteB (xma, cbc, tmxb, UB)) { /* copy buf to mem */
|
||||
tm_sta = tm_sta | STA_NXM; /* NXM, set err */
|
||||
cbc = cbc - t; } /* adj byte cnt */
|
||||
xma = (xma + cbc) & 0777777; /* inc bus addr */
|
||||
tm_bc = (tm_bc + cbc) & 0177777; /* inc byte cnt */
|
||||
uptr -> pos = uptr -> pos + ((tbc + 1) & ~1) + /* upd position */
|
||||
(2 * sizeof (t_mtrlnt));
|
||||
break;
|
||||
case MTC_WRITE: /* write */
|
||||
case MTC_WREXT: /* write ext gap */
|
||||
if (t = Map_ReadB (xma, cbc, tmxb, UB)) { /* copy mem to buf */
|
||||
tm_sta = tm_sta | STA_NXM; /* NXM, set err */
|
||||
cbc = cbc - t; /* adj byte cnt */
|
||||
if (cbc == 0) break; } /* no xfr? done */
|
||||
fseek (uptr -> fileref, uptr -> pos, SEEK_SET);
|
||||
fxwrite (&cbc, sizeof (t_mtrlnt), 1, uptr -> fileref);
|
||||
for (i = 0; i < cbc; i++) { /* copy buf to tape */
|
||||
if (xma >= MEMSIZE) { /* nx memory? */
|
||||
tm_sta = tm_sta | STA_NXM;
|
||||
break; }
|
||||
if (i & 1) dbuf[i] = (M[xma >> 1] >> 8) & 0377;
|
||||
else dbuf[i] = M[xma >> 1] & 0377;
|
||||
xma = (xma + 1) & 0777777;
|
||||
tm_bc = (tm_bc + 1) & 0177777; }
|
||||
fxwrite (dbuf, sizeof (int8), cbc, uptr -> fileref);
|
||||
fxwrite (tmxb, sizeof (int8), cbc, uptr -> fileref);
|
||||
fxwrite (&cbc, sizeof (t_mtrlnt), 1, uptr -> fileref);
|
||||
err = ferror (uptr -> fileref);
|
||||
uptr -> pos = uptr -> pos + ((cbc + 1) & ~1) +
|
||||
xma = (xma + cbc) & 0777777; /* inc bus addr */
|
||||
tm_bc = (tm_bc + cbc) & 0177777; /* inc byte cnt */
|
||||
uptr -> pos = uptr -> pos + ((cbc + 1) & ~1) + /* upd position */
|
||||
(2 * sizeof (t_mtrlnt));
|
||||
break;
|
||||
case MTC_WREOF:
|
||||
|
@ -546,8 +513,10 @@ for (u = 0; u < TM_NUMDR; u++) { /* loop thru units */
|
|||
sim_cancel (uptr); /* cancel activity */
|
||||
if (uptr -> flags & UNIT_ATT) uptr -> USTAT = STA_ONL |
|
||||
((uptr -> pos)? 0: STA_BOT) |
|
||||
((uptr -> flags & UNIT_WLK)? STA_WLK: 0);
|
||||
((uptr -> flags & UNIT_WPRT)? STA_WLK: 0);
|
||||
else uptr -> USTAT = 0; }
|
||||
if (tmxb == NULL) tmxb = calloc (TM_MAXFR, sizeof (unsigned int8));
|
||||
if (tmxb == NULL) return SCPE_MEM;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
@ -559,7 +528,7 @@ t_stat r;
|
|||
|
||||
r = attach_unit (uptr, cptr);
|
||||
if (r != SCPE_OK) return r;
|
||||
uptr -> USTAT = STA_ONL | STA_BOT | ((uptr -> flags & UNIT_WLK)? STA_WLK: 0);
|
||||
uptr -> USTAT = STA_ONL | STA_BOT | ((uptr -> flags & UNIT_WPRT)? STA_WLK: 0);
|
||||
if (uptr -> UNUM == GET_UNIT (tm_cmd)) tm_updcsta (uptr);
|
||||
return r;
|
||||
}
|
||||
|
@ -575,9 +544,11 @@ return detach_unit (uptr);
|
|||
|
||||
/* Write lock/enable routine */
|
||||
|
||||
t_stat tm_vlock (UNIT *uptr, int32 val)
|
||||
t_stat tm_vlock (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
if ((uptr -> flags & UNIT_ATT) && val) uptr -> USTAT = uptr -> USTAT | STA_WLK;
|
||||
if ((uptr -> flags & UNIT_ATT) &&
|
||||
(val || (uptr -> flags & UNIT_RO)))
|
||||
uptr -> USTAT = uptr -> USTAT | STA_WLK;
|
||||
else uptr -> USTAT = uptr -> USTAT & ~STA_WLK;
|
||||
if (uptr -> UNUM == GET_UNIT (tm_cmd)) tm_updcsta (uptr);
|
||||
return SCPE_OK;
|
|
@ -25,6 +25,8 @@
|
|||
|
||||
ts TS11/TSV05 magtape
|
||||
|
||||
30-Nov-01 RMS Added read only unit, extended SET/SHOW support
|
||||
09-Nov-01 RMS Added bus map, VAX support
|
||||
15-Oct-01 RMS Integrated debug logging across simulator
|
||||
27-Sep-01 RMS Implemented extended characteristics and status
|
||||
Fixed bug in write characteristics status return
|
||||
|
@ -47,14 +49,51 @@
|
|||
If the byte count is odd, the record is padded with an extra byte
|
||||
of junk. File marks are represented by a single record length of 0.
|
||||
End of tape is two consecutive end of file marks.
|
||||
|
||||
The TS11 functions in three environments:
|
||||
|
||||
- PDP-11 Q22 systems - the I/O map is one for one, so it's safe to
|
||||
go through the I/O map
|
||||
- PDP-11 Unibus 22b systems - the TS11 behaves as an 18b Unibus
|
||||
peripheral and must go through the I/O map
|
||||
- VAX Q22 systems - the TS11 must go through the I/O map
|
||||
*/
|
||||
|
||||
#if defined (USE_INT64) /* VAX version */
|
||||
#include "vax_defs.h"
|
||||
#define VM_VAX 1
|
||||
#define TS_RDX 16
|
||||
#define TS_DF_ENB 1 /* on by default */
|
||||
#define TS_18B FALSE /* always 22b */
|
||||
#define ADDRTEST 0177700
|
||||
#define DMASK 0xFFFF
|
||||
extern int32 ReadB (t_addr pa);
|
||||
extern void WriteB (t_addr pa, int32 val);
|
||||
extern int32 ReadW (t_addr pa);
|
||||
extern void WriteW (t_addr pa, int32 val);
|
||||
|
||||
#else /* PDP11 version */
|
||||
#include "pdp11_defs.h"
|
||||
#define VM_PDP11 1
|
||||
#define TS_RDX 8
|
||||
#define TS_DF_ENB 0 /* off by default */
|
||||
#define TS_18B (cpu_18b || cpu_ubm)
|
||||
#define ADDRTEST (TS_18B? 0177774: 0177700)
|
||||
extern uint16 *M;
|
||||
extern int32 cpu_18b, cpu_ubm;
|
||||
#define ReadB(p) ((M[(p) >> 1] >> (((p) & 1)? 8: 0)) & 0377)
|
||||
#define WriteB(p,v) M[(p) >> 1] = ((p) & 1)? \
|
||||
((M[(p) >> 1] & 0377) | ((v) << 8)): \
|
||||
((M[(p) >> 1] & ~0377) | (v))
|
||||
#define ReadW(p) M[(p) >> 1]
|
||||
#define WriteW(p,v) M[(p) >> 1] = (v)
|
||||
#endif
|
||||
|
||||
#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */
|
||||
#define UNIT_WLK (1 << UNIT_V_WLK)
|
||||
#define DBSIZE (1 << 16) /* data buffer */
|
||||
|
||||
#define TS_MAXFR (1 << 16) /* max xfer */
|
||||
#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */
|
||||
|
||||
/* TSBA/TSDB - 17772520: base address/data buffer register
|
||||
|
||||
read: most recent memory address
|
||||
|
@ -212,16 +251,11 @@
|
|||
#define WCHX_HDS 0000040 /* high density */
|
||||
|
||||
#define MAX(a,b) (((a) >= (b))? (a): (b))
|
||||
#define READ_BYTE(p) ((M[(p) >> 1] >> (((p) & 1)? 8: 0)) & 0377)
|
||||
#define WRITE_BYTE(d,p) M[(p) >> 1] = (p & 1)? \
|
||||
((M[(p) >> 1] & 0377) | ((d) << 8)): \
|
||||
((M[(p) >> 1] & ~0377) | (d))
|
||||
|
||||
extern uint16 *M; /* memory */
|
||||
extern int32 int_req[IPL_HLVL];
|
||||
extern UNIT cpu_unit;
|
||||
extern FILE *sim_log;
|
||||
extern int32 pdp11_log;
|
||||
uint8 *tsxb = NULL; /* xfer buffer */
|
||||
int32 tssr = 0; /* status register */
|
||||
int32 tsba = 0; /* mem addr */
|
||||
int32 tsdbx = 0; /* data buf ext */
|
||||
|
@ -233,8 +267,7 @@ int32 ts_ownm = 0; /* tape owns msg */
|
|||
int32 ts_qatn = 0; /* queued attn */
|
||||
int32 ts_bcmd = 0; /* boot cmd */
|
||||
int32 ts_time = 10; /* record latency */
|
||||
int32 ts_enb = 0; /* device enable */
|
||||
static uint8 dbuf[DBSIZE];
|
||||
int32 ts_enb = TS_DF_ENB; /* device enable */
|
||||
|
||||
t_stat ts_svc (UNIT *uptr);
|
||||
t_stat ts_reset (DEVICE *dptr);
|
||||
|
@ -257,25 +290,25 @@ void ts_endcmd (int32 ssf, int32 xs0f, int32 msg);
|
|||
UNIT ts_unit = { UDATA (&ts_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) };
|
||||
|
||||
REG ts_reg[] = {
|
||||
{ ORDATA (TSSR, tssr, 16) },
|
||||
{ ORDATA (TSBA, tsba, 22) },
|
||||
{ ORDATA (TSDBX, tsdbx, 8) },
|
||||
{ ORDATA (CHDR, cmdhdr, 16) },
|
||||
{ ORDATA (CADL, cmdadl, 16) },
|
||||
{ ORDATA (CADH, cmdadh, 16) },
|
||||
{ ORDATA (CLNT, cmdlnt, 16) },
|
||||
{ ORDATA (MHDR, msghdr, 16) },
|
||||
{ ORDATA (MRFC, msgrfc, 16) },
|
||||
{ ORDATA (MXS0, msgxs0, 16) },
|
||||
{ ORDATA (MXS1, msgxs1, 16) },
|
||||
{ ORDATA (MXS2, msgxs2, 16) },
|
||||
{ ORDATA (MXS3, msgxs3, 16) },
|
||||
{ ORDATA (MSX4, msgxs4, 16) },
|
||||
{ ORDATA (WADL, wchadl, 16) },
|
||||
{ ORDATA (WADH, wchadh, 16) },
|
||||
{ ORDATA (WLNT, wchlnt, 16) },
|
||||
{ ORDATA (WOPT, wchopt, 16) },
|
||||
{ ORDATA (WXOPT, wchxopt, 16) },
|
||||
{ GRDATA (TSSR, tssr, TS_RDX, 16, 0) },
|
||||
{ GRDATA (TSBA, tsba, TS_RDX, 22, 0) },
|
||||
{ GRDATA (TSDBX, tsdbx, TS_RDX, 8, 0) },
|
||||
{ GRDATA (CHDR, cmdhdr, TS_RDX, 16, 0) },
|
||||
{ GRDATA (CADL, cmdadl, TS_RDX, 16, 0) },
|
||||
{ GRDATA (CADH, cmdadh, TS_RDX, 16, 0) },
|
||||
{ GRDATA (CLNT, cmdlnt, TS_RDX, 16, 0) },
|
||||
{ GRDATA (MHDR, msghdr, TS_RDX, 16, 0) },
|
||||
{ GRDATA (MRFC, msgrfc, TS_RDX, 16, 0) },
|
||||
{ GRDATA (MXS0, msgxs0, TS_RDX, 16, 0) },
|
||||
{ GRDATA (MXS1, msgxs1, TS_RDX, 16, 0) },
|
||||
{ GRDATA (MXS2, msgxs2, TS_RDX, 16, 0) },
|
||||
{ GRDATA (MXS3, msgxs3, TS_RDX, 16, 0) },
|
||||
{ GRDATA (MSX4, msgxs4, TS_RDX, 16, 0) },
|
||||
{ GRDATA (WADL, wchadl, TS_RDX, 16, 0) },
|
||||
{ GRDATA (WADH, wchadh, TS_RDX, 16, 0) },
|
||||
{ GRDATA (WLNT, wchlnt, TS_RDX, 16, 0) },
|
||||
{ GRDATA (WOPT, wchopt, TS_RDX, 16, 0) },
|
||||
{ GRDATA (WXOPT, wchxopt, TS_RDX, 16, 0) },
|
||||
{ FLDATA (INT, IREQ (TS), INT_V_TS) },
|
||||
{ FLDATA (ATTN, ts_qatn, 0) },
|
||||
{ FLDATA (BOOT, ts_bcmd, 0) },
|
||||
|
@ -294,7 +327,7 @@ MTAB ts_mod[] = {
|
|||
|
||||
DEVICE ts_dev = {
|
||||
"TS", &ts_unit, ts_reg, ts_mod,
|
||||
1, 10, 31, 1, 8, 8,
|
||||
1, 10, 31, 1, TS_RDX, 8,
|
||||
NULL, NULL, &ts_reset,
|
||||
&ts_boot, &ts_attach, &ts_detach };
|
||||
|
||||
|
@ -319,6 +352,7 @@ return SCPE_OK;
|
|||
t_stat ts_wr (int32 data, int32 PA, int32 access)
|
||||
{
|
||||
int32 i;
|
||||
t_addr pa;
|
||||
|
||||
switch ((PA >> 1) & 01) { /* decode PA<1> */
|
||||
case 0: /* TSDB */
|
||||
|
@ -333,7 +367,8 @@ case 0: /* TSDB */
|
|||
msgrfc = msgxs1 = msgxs2 = msgxs3 = msgxs4 = 0; /* clr status */
|
||||
CLR_INT (TS); /* clr int req */
|
||||
for (i = 0; i < CMD_PLNT; i++) { /* get cmd pkt */
|
||||
if (ADDR_IS_MEM (tsba)) tscmdp[i] = M[(tsba >> 1)];
|
||||
if (Map_Addr (tsba, &pa) && ADDR_IS_MEM (pa))
|
||||
tscmdp[i] = ReadW (pa);
|
||||
else { ts_endcmd (TSSR_NXM + TC5, 0, MSG_ACK|MSG_MNEF|MSG_CFAIL);
|
||||
return SCPE_OK; }
|
||||
tsba = tsba + 2; } /* incr tsba */
|
||||
|
@ -342,6 +377,7 @@ case 0: /* TSDB */
|
|||
break;
|
||||
case 1: /* TSSR */
|
||||
if (PA & 1) { /* TSDBX */
|
||||
if (TS_18B) return SCPE_OK; /* not in TS11 */
|
||||
if (tssr & TSSR_SSR) { /* ready? */
|
||||
tsdbx = data; /* save */
|
||||
if (data & TSDBX_BOOT) {
|
||||
|
@ -463,7 +499,7 @@ int32 ts_readf (UNIT *uptr, int32 fc)
|
|||
{
|
||||
int32 i, st;
|
||||
t_mtrlnt tbc, wbc;
|
||||
t_addr wa;
|
||||
t_addr wa, pa;
|
||||
|
||||
msgrfc = fc;
|
||||
if (st = ts_rdlntf (uptr, &tbc)) return st; /* read rec lnt */
|
||||
|
@ -473,15 +509,16 @@ if (tbc == 0) { /* tape mark? */
|
|||
if (fc == 0) fc = 0200000; /* byte count */
|
||||
tsba = (cmdadh << 16) | cmdadl; /* buf addr */
|
||||
tbc = MTRL (tbc); /* ignore err flag */
|
||||
wbc = (tbc > DBSIZE)? DBSIZE: tbc; /* cap rec size */
|
||||
wbc = (tbc > TS_MAXFR)? TS_MAXFR: tbc; /* cap rec size */
|
||||
wbc = (wbc > fc)? fc: wbc; /* cap buf size */
|
||||
i = fxread (dbuf, sizeof (uint8), wbc, uptr -> fileref); /* read record */
|
||||
i = fxread (tsxb, sizeof (uint8), wbc, uptr -> fileref); /* read record */
|
||||
if (ferror (uptr -> fileref)) return XTC (XS0_EOT | XS0_RLS, TC2);
|
||||
for ( ; i < wbc; i++) dbuf[i] = 0; /* fill with 0's */
|
||||
for ( ; i < wbc; i++) tsxb[i] = 0; /* fill with 0's */
|
||||
uptr -> pos = uptr -> pos + ((tbc + 1) & ~1) + (2 * sizeof (t_mtrlnt));
|
||||
for (i = 0; i < wbc; i++) { /* copy buffer */
|
||||
wa = (cmdhdr & CMD_SWP)? tsba ^ 1: tsba; /* apply OPP */
|
||||
if (ADDR_IS_MEM (wa)) WRITE_BYTE (dbuf[i], wa); /* nxm? */
|
||||
if (Map_Addr (wa, &pa) && ADDR_IS_MEM (pa)) /* map addr, nxm? */
|
||||
WriteB (pa, tsxb[i]); /* no, store */
|
||||
else { tssr = ts_updtssr (tssr | TSSR_NXM); /* set error */
|
||||
return (XTC (XS0_RLS, TC4)); }
|
||||
tsba = tsba + 1;
|
||||
|
@ -495,7 +532,7 @@ int32 ts_readr (UNIT *uptr, int32 fc)
|
|||
{
|
||||
int32 i, st;
|
||||
t_mtrlnt tbc, wbc;
|
||||
t_addr wa;
|
||||
t_addr wa, pa;
|
||||
|
||||
msgrfc = fc;
|
||||
if (uptr -> pos == 0) { /* BOT? */
|
||||
|
@ -508,19 +545,20 @@ if (tbc == 0) { /* tape mark? */
|
|||
if (fc == 0) fc = 0200000; /* byte count */
|
||||
tsba = (cmdadh << 16) | cmdadl + fc; /* buf addr */
|
||||
tbc = MTRL (tbc); /* ignore err flag */
|
||||
wbc = (tbc > DBSIZE)? DBSIZE: tbc; /* cap rec size */
|
||||
wbc = (tbc > TS_MAXFR)? TS_MAXFR: tbc; /* cap rec size */
|
||||
wbc = (wbc > fc)? fc: wbc; /* cap buf size */
|
||||
fseek (uptr -> fileref, uptr -> pos - sizeof (t_mtrlnt) - wbc, SEEK_SET);
|
||||
i = fxread (dbuf, sizeof (uint8), wbc, uptr -> fileref);
|
||||
for ( ; i < wbc; i++) dbuf[i] = 0; /* fill with 0's */
|
||||
i = fxread (tsxb, sizeof (uint8), wbc, uptr -> fileref);
|
||||
for ( ; i < wbc; i++) tsxb[i] = 0; /* fill with 0's */
|
||||
if (ferror (uptr -> fileref)) { /* error? */
|
||||
msgxs3 = msgxs3 | XS3_OPI;
|
||||
return XTC (XS0_RLS, TC6); }
|
||||
uptr -> pos = uptr -> pos - ((tbc + 1) & ~1) - (2 * sizeof (t_mtrlnt));
|
||||
for (i = wbc; i > 0; i--) { /* copy buffer */
|
||||
tsba = tsba - 1;
|
||||
wa = (cmdhdr & CMD_SWP)? tsba ^ 1: tsba;
|
||||
if (ADDR_IS_MEM (wa)) WRITE_BYTE (dbuf[i - 1], wa);
|
||||
wa = (cmdhdr & CMD_SWP)? tsba ^ 1: tsba; /* apply OPP */
|
||||
if (Map_Addr (wa, &pa) && ADDR_IS_MEM (pa)) /* map addr, nxm? */
|
||||
WriteB (pa, tsxb[i - 1]); /* no, store */
|
||||
else { tssr = ts_updtssr (tssr | TSSR_NXM);
|
||||
return (XTC (XS0_RLS, TC4)); }
|
||||
msgrfc = (msgrfc - 1) & DMASK; }
|
||||
|
@ -532,20 +570,21 @@ return 0;
|
|||
int32 ts_write (UNIT *uptr, int32 fc)
|
||||
{
|
||||
int32 i;
|
||||
t_addr wa;
|
||||
t_addr wa, pa;
|
||||
|
||||
msgrfc = fc;
|
||||
if (fc == 0) fc = 0200000; /* byte count */
|
||||
tsba = (cmdadh << 16) | cmdadl; /* buf addr */
|
||||
for (i = 0; i < fc; i++) { /* copy mem to buf */
|
||||
wa = (cmdhdr & CMD_SWP)? tsba ^ 1: tsba; /* apply opp */
|
||||
if (ADDR_IS_MEM (wa)) dbuf[i] = READ_BYTE (wa); /* nxm? */
|
||||
wa = (cmdhdr & CMD_SWP)? tsba ^ 1: tsba; /* apply OPP */
|
||||
if (Map_Addr (wa, &pa) && ADDR_IS_MEM (pa)) /* map addr, nxm? */
|
||||
tsxb[i] = ReadB (pa); /* no, store */
|
||||
else { tssr = ts_updtssr (tssr | TSSR_NXM);
|
||||
return TC5; }
|
||||
tsba = tsba + 1; }
|
||||
fseek (uptr -> fileref, uptr -> pos, SEEK_SET); /* position */
|
||||
fxwrite (&fc, sizeof (t_mtrlnt), 1, uptr -> fileref);
|
||||
fxwrite (dbuf, sizeof (uint8), fc, uptr -> fileref);
|
||||
fxwrite (tsxb, sizeof (uint8), fc, uptr -> fileref);
|
||||
fxwrite (&fc, sizeof (t_mtrlnt), 1, uptr -> fileref);
|
||||
uptr -> pos = uptr -> pos + ((fc + 1) & ~1) + (2 * sizeof (t_mtrlnt));
|
||||
msgrfc = 0;
|
||||
|
@ -571,6 +610,8 @@ return XTC (XS0_TMK, TC0);
|
|||
t_stat ts_svc (UNIT *uptr)
|
||||
{
|
||||
int32 i, fnc, mod, st0, st1;
|
||||
t_addr pa;
|
||||
|
||||
static const int32 fnc_mod[CMD_N_FNC] = { /* max mod+1 0 ill */
|
||||
0, 4, 0, 0, 1, 2, 1, 0, /* 00 - 07 */
|
||||
5, 3, 5, 1, 0, 0, 0, 1, /* 10 - 17 */
|
||||
|
@ -619,7 +660,7 @@ if ((fnc_flg[fnc] & FLG_MO) && /* mot+(vck|!att)? */
|
|||
ts_endcmd (TC3, XS0_NEF, MSG_ACK | MSG_MNEF | MSG_CFAIL);
|
||||
return SCPE_OK; }
|
||||
if ((fnc_flg[fnc] & FLG_WR) && /* write? */
|
||||
(uptr -> flags & UNIT_WLK)) { /* write lck? */
|
||||
(uptr -> flags & UNIT_WPRT)) { /* write lck? */
|
||||
ts_endcmd (TC3, XS0_WLE | XS0_NEF, MSG_ACK | MSG_MNEF | MSG_CFAIL);
|
||||
return SCPE_OK; }
|
||||
if ((((fnc == FNC_READ) && (mod == 1)) || /* read rev */
|
||||
|
@ -627,7 +668,7 @@ if ((((fnc == FNC_READ) && (mod == 1)) || /* read rev */
|
|||
(uptr -> pos == 0)) { /* BOT? */
|
||||
ts_endcmd (TC3, XS0_NEF, MSG_ACK | MSG_MNEF | MSG_CFAIL);
|
||||
return SCPE_OK; }
|
||||
if ((fnc_flg[fnc] & FLG_AD) && (cmdadh & 0177700)) { /* buf addr > 22b? */
|
||||
if ((fnc_flg[fnc] & FLG_AD) && (cmdadh & ADDRTEST)) { /* buf addr > 22b? */
|
||||
ts_endcmd (TC3, XS0_ILA, MSG_ACK | MSG_MILL | MSG_CFAIL);
|
||||
return SCPE_OK; }
|
||||
|
||||
|
@ -640,12 +681,13 @@ case FNC_GSTA: /* get status */
|
|||
ts_endcmd (TC0, 0, MSG_ACK | MSG_CEND); /* send end packet */
|
||||
return SCPE_OK;
|
||||
case FNC_WCHR: /* write char */
|
||||
if ((cmdadh & 0177700) || (cmdadl & 1) || (cmdlnt < 6)) {
|
||||
if ((cmdadh & ADDRTEST) || (cmdadl & 1) || (cmdlnt < 6)) {
|
||||
ts_endcmd (TSSR_NBA | TC3, XS0_ILA, 0);
|
||||
break; }
|
||||
tsba = (cmdadh << 16) | cmdadl;
|
||||
for (i = 0; (i < WCH_PLNT) && (i < (cmdlnt / 2)); i++) {
|
||||
if (ADDR_IS_MEM (tsba)) tswchp[i] = M[tsba >> 1];
|
||||
if (Map_Addr (tsba, &pa) && ADDR_IS_MEM (pa))
|
||||
tswchp[i] = ReadW (pa);
|
||||
else { ts_endcmd (TSSR_NBA | TSSR_NXM | TC5, 0, 0);
|
||||
return SCPE_OK; }
|
||||
tsba = tsba + 2; }
|
||||
|
@ -745,9 +787,6 @@ case FNC_POS:
|
|||
break; }
|
||||
ts_cmpendcmd (st0, 0);
|
||||
break; }
|
||||
if (DBG_LOG (LOG_TS))
|
||||
fprintf (sim_log, ">>TS: cmd=%o, mod=%o, buf=%o, lnt=%o, sta = %o, tc=%o, pos=%d\n",
|
||||
fnc, mod, cmdadl, cmdlnt, msgxs0, (tssr & TSSR_TC) >> 1, ts_unit.pos);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
@ -766,7 +805,7 @@ int32 ts_updxs0 (int32 t)
|
|||
t = (t & ~(XS0_ONL | XS0_WLK | XS0_BOT | XS0_IE)) | XS0_PET;
|
||||
if (ts_unit.flags & UNIT_ATT) {
|
||||
t = t | XS0_ONL;
|
||||
if (ts_unit.flags & UNIT_WLK) t = t | XS0_WLK;
|
||||
if (ts_unit.flags & UNIT_WPRT) t = t | XS0_WLK;
|
||||
if (ts_unit.pos == 0) t = (t | XS0_BOT) & ~XS0_EOT; }
|
||||
else t = t & ~XS0_EOT;
|
||||
if (cmdhdr & CMD_IE) t = t | XS0_IE;
|
||||
|
@ -792,6 +831,7 @@ return;
|
|||
void ts_endcmd (int32 tc, int32 xs0, int32 msg)
|
||||
{
|
||||
int32 i;
|
||||
t_addr pa;
|
||||
|
||||
msgxs0 = ts_updxs0 (msgxs0 | xs0); /* update XS0 */
|
||||
if (wchxopt & WCHX_HDS) msgxs4 = msgxs4 | XS4_HDS; /* update XS4 */
|
||||
|
@ -800,7 +840,8 @@ if (msg && !(tssr & TSSR_NBA)) { /* send end pkt */
|
|||
msglnt = wchlnt - 4; /* exclude hdr, bc */
|
||||
tsba = (wchadh << 16) | wchadl;
|
||||
for (i = 0; (i < MSG_PLNT) && (i < (wchlnt / 2)); i++) {
|
||||
if (ADDR_IS_MEM (tsba)) M[tsba >> 1] = tsmsgp[i];
|
||||
if (Map_Addr (tsba, &pa) && ADDR_IS_MEM (pa))
|
||||
WriteW (pa, tsmsgp[i]);
|
||||
else { tssr = tssr | TSSR_NXM;
|
||||
tc = (tc & ~TSSR_TC) | TC4;
|
||||
break; }
|
||||
|
@ -816,9 +857,11 @@ return;
|
|||
t_stat ts_reset (DEVICE *dptr)
|
||||
{
|
||||
int32 i;
|
||||
#if defined (VM_PDP11)
|
||||
extern int32 tm_enb;
|
||||
|
||||
if (ts_enb) tm_enb = 0; /* TM or TS */
|
||||
#endif
|
||||
ts_unit.pos = 0;
|
||||
tsba = tsdbx = 0;
|
||||
ts_ownc = ts_ownm = 0;
|
||||
|
@ -830,6 +873,8 @@ for (i = 0; i < WCH_PLNT; i++) tswchp[i] = 0;
|
|||
for (i = 0; i < MSG_PLNT; i++) tsmsgp[i] = 0;
|
||||
msgxs0 = ts_updxs0 (XS0_VCK);
|
||||
CLR_INT (TS);
|
||||
if (tsxb == NULL) tsxb = calloc (TS_MAXFR, sizeof (unsigned int8));
|
||||
if (tsxb == NULL) return SCPE_MEM;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
@ -871,6 +916,7 @@ return r;
|
|||
|
||||
/* Boot */
|
||||
|
||||
#if defined (VM_PDP11)
|
||||
#define BOOT_START 01000
|
||||
#define BOOT_LEN (sizeof (boot_rom) / sizeof (int32))
|
||||
|
||||
|
@ -923,3 +969,10 @@ for (i = 0; i < BOOT_LEN; i++)
|
|||
saved_PC = BOOT_START;
|
||||
return SCPE_OK;
|
||||
}
|
||||
#else
|
||||
|
||||
t_stat ts_boot (int32 unitno)
|
||||
{
|
||||
return SCPE_NOFNC;
|
||||
}
|
||||
#endif
|
|
@ -25,6 +25,8 @@
|
|||
|
||||
cpu PDP-4/7/9/15 central processor
|
||||
|
||||
30-Nov-01 RMS Added extended SET/SHOW support
|
||||
25-Nov-01 RMS Revised interrupt structure
|
||||
19-Sep-01 RMS Fixed bug in EAE (found by Dave Conroy)
|
||||
17-Sep-01 RMS Fixed typo in conditional
|
||||
10-Aug-01 RMS Removed register from declarations
|
||||
|
@ -224,9 +226,9 @@
|
|||
nested XCT's
|
||||
I/O error in I/O simulator
|
||||
|
||||
2. Interrupts. Interrupt requests are maintained in the int_req
|
||||
register. If interrupts are on and not deferred, and at least
|
||||
one interrupt request is set, a program interrupt occurs.
|
||||
2. Interrupts. Interrupt requests are maintained in the int_hwre
|
||||
array. int_hwre[0:3] corresponds to API levels 0-3; int_hwre[4]
|
||||
holds PI requests.
|
||||
|
||||
3. Arithmetic. The 18b PDP's implements both 1's and 2's complement
|
||||
arithmetic for signed numbers. In 1's complement arithmetic, a
|
||||
|
@ -244,8 +246,6 @@
|
|||
|
||||
#include "pdp18b_defs.h"
|
||||
|
||||
#define ILL_ADR_FLAG (1 << ADDRSIZE)
|
||||
#define save_ibkpt (cpu_unit.u3)
|
||||
#define UNIT_V_NOEAE (UNIT_V_UF) /* EAE absent */
|
||||
#define UNIT_NOEAE (1 << UNIT_V_NOEAE)
|
||||
#define UNIT_V_NOAPI (UNIT_V_UF+1) /* API absent */
|
||||
|
@ -271,7 +271,8 @@ int32 saved_PC = 0; /* PC */
|
|||
int32 iors = 0; /* IORS */
|
||||
int32 ion = 0; /* int on */
|
||||
int32 ion_defer = 0; /* int defer */
|
||||
int32 int_req = 0; /* int requests */
|
||||
int32 int_pend = 0; /* int pending */
|
||||
int32 int_hwre[API_HLVL+1] = { 0 }; /* int requests */
|
||||
int32 api_enb = 0; /* API enable */
|
||||
int32 api_req = 0; /* API requests */
|
||||
int32 api_act = 0; /* API active */
|
||||
|
@ -297,16 +298,16 @@ int32 LR = 0; /* limit register */
|
|||
int32 stop_inst = 0; /* stop on rsrv inst */
|
||||
int32 xct_max = 16; /* nested XCT limit */
|
||||
int32 old_PC = 0; /* old PC */
|
||||
int32 ibkpt_addr = ILL_ADR_FLAG | ADDRMASK; /* breakpoint addr */
|
||||
int32 dev_enb = -1; /* device enables */
|
||||
extern int32 sim_int_char;
|
||||
extern int32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */
|
||||
|
||||
t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw);
|
||||
t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw);
|
||||
t_stat cpu_reset (DEVICE *dptr);
|
||||
t_stat cpu_svc (UNIT *uptr);
|
||||
t_stat cpu_set_size (UNIT *uptr, int32 value);
|
||||
t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
int32 upd_iors (void);
|
||||
int32 api_eval (void);
|
||||
int32 api_eval (int32 *pend);
|
||||
|
||||
static const int32 api_ffo[256] = {
|
||||
8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
|
||||
|
@ -326,11 +327,11 @@ static const int32 api_ffo[256] = {
|
|||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
static const int32 api_vec[32] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, ACH_TTO1, ACH_TTI1, ACH_CLK, 0, 0, 0, 0,
|
||||
0, ACH_LPT, ACH_LPT, ACH_PTR, 0, 0, 0, ACH_RP,
|
||||
ACH_RF, ACH_DRM, ACH_MTA, ACH_DTA, 0, 0, ACH_PWRFL, 0 };
|
||||
static const int32 api_vec[API_HLVL][32] = {
|
||||
{ ACH_PWRFL }, /* API 0 */
|
||||
{ ACH_DTA, ACH_MTA, ACH_DRM, ACH_RF, ACH_RP }, /* API 1 */
|
||||
{ ACH_PTR, ACH_LPT, ACH_LPT }, /* API 2 */
|
||||
{ ACH_CLK, ACH_TTI1, ACH_TTO1 } }; /* API 3 */
|
||||
|
||||
/* CPU data structures
|
||||
|
||||
|
@ -340,7 +341,7 @@ static const int32 api_vec[32] = {
|
|||
cpu_mod CPU modifier list
|
||||
*/
|
||||
|
||||
UNIT cpu_unit = { UDATA (&cpu_svc, UNIT_FIX + UNIT_BINK + EAE_DFLT + API_DFLT,
|
||||
UNIT cpu_unit = { UDATA (NULL, UNIT_FIX + UNIT_BINK + EAE_DFLT + API_DFLT,
|
||||
MAXMEMSIZE) };
|
||||
|
||||
REG cpu_reg[] = {
|
||||
|
@ -354,13 +355,14 @@ REG cpu_reg[] = {
|
|||
#endif
|
||||
{ ORDATA (SR, SR, 18) },
|
||||
{ ORDATA (IORS, iors, 18), REG_RO },
|
||||
{ ORDATA (INT, int_req, 32), REG_RO },
|
||||
{ BRDATA (INT, int_hwre, 8, 32, API_HLVL+1), REG_RO },
|
||||
{ FLDATA (ION, ion, 0) },
|
||||
{ ORDATA (ION_DELAY, ion_defer, 2) },
|
||||
#if defined (PDP7)
|
||||
{ FLDATA (TRAPM, usmd, 0) },
|
||||
{ FLDATA (TRAPP, trap_pending, 0) },
|
||||
{ FLDATA (EXTM, memm, 0) },
|
||||
{ FLDATA (EXTM_INIT, memm_init, 0) },
|
||||
{ FLDATA (EMIRP, emir_pending, 0) },
|
||||
#endif
|
||||
#if defined (PDP9)
|
||||
|
@ -377,7 +379,7 @@ REG cpu_reg[] = {
|
|||
{ FLDATA (EXTM_INIT, memm_init, 0) },
|
||||
{ FLDATA (EMIRP, emir_pending, 0) },
|
||||
{ FLDATA (RESTP, rest_pending, 0) },
|
||||
{ FLDATA (PWRFL, int_req, INT_V_PWRFL) },
|
||||
{ FLDATA (PWRFL, int_hwre[API_PWRFL], INT_V_PWRFL) },
|
||||
#endif
|
||||
#if defined (PDP15)
|
||||
{ FLDATA (APIENB, api_enb, 0) },
|
||||
|
@ -386,22 +388,21 @@ REG cpu_reg[] = {
|
|||
{ ORDATA (XR, XR, 18) },
|
||||
{ ORDATA (LR, LR, 18) },
|
||||
{ ORDATA (BR, BR, ADDRSIZE) },
|
||||
{ FLDATA (USMD, usmd, 0) },
|
||||
{ FLDATA (USMDBUF, usmdbuf, 0) },
|
||||
{ FLDATA (NEXM, nexm, 0) },
|
||||
{ FLDATA (PRVN, prvn, 0) },
|
||||
{ FLDATA (TRAPP, trap_pending, 0) },
|
||||
{ FLDATA (USMD, usmd, 0) },
|
||||
{ FLDATA (USMDBUF, usmdbuf, 0) },
|
||||
{ FLDATA (BANKM, memm, 0) },
|
||||
{ FLDATA (BANKM_INIT, memm_init, 0) },
|
||||
{ FLDATA (RESP, rest_pending, 0) },
|
||||
{ FLDATA (PWRFL, int_req, INT_V_PWRFL) },
|
||||
{ FLDATA (RESTP, rest_pending, 0) },
|
||||
{ FLDATA (PWRFL, int_hwre[API_PWRFL], INT_V_PWRFL) },
|
||||
#endif
|
||||
{ ORDATA (OLDPC, old_PC, ADDRSIZE), REG_RO },
|
||||
{ FLDATA (STOP_INST, stop_inst, 0) },
|
||||
{ FLDATA (NOEAE, cpu_unit.flags, UNIT_V_NOEAE), REG_HRO },
|
||||
{ FLDATA (NOAPI, cpu_unit.flags, UNIT_V_NOAPI), REG_HRO },
|
||||
{ DRDATA (XCT_MAX, xct_max, 8), PV_LEFT + REG_NZ },
|
||||
{ ORDATA (BREAK, ibkpt_addr, ADDRSIZE + 1) },
|
||||
{ ORDATA (WRU, sim_int_char, 8) },
|
||||
{ ORDATA (DEVENB, dev_enb, 32), REG_HRO },
|
||||
{ NULL } };
|
||||
|
@ -608,7 +609,7 @@ MQ = saved_MQ & 0777777;
|
|||
reason = 0;
|
||||
sim_rtc_init (clk_unit.wait); /* init calibration */
|
||||
if (cpu_unit.flags & UNIT_NOAPI) api_enb = api_req = api_act = 0;
|
||||
api_int = api_eval (); /* eval API */
|
||||
api_int = api_eval (&int_pend); /* eval API */
|
||||
api_cycle = 0; /* not API cycle */
|
||||
|
||||
/* Main instruction fetch/decode loop: check trap and interrupt */
|
||||
|
@ -619,7 +620,7 @@ int32 link_init, fill;
|
|||
|
||||
if (sim_interval <= 0) { /* check clock queue */
|
||||
if (reason = sim_process_event ()) break;
|
||||
api_int = api_eval (); } /* eval API */
|
||||
api_int = api_eval (&int_pend); } /* eval API */
|
||||
|
||||
/* Protection traps work like interrupts, with these quirks:
|
||||
|
||||
|
@ -653,18 +654,18 @@ if (trap_pending) { /* trap pending? */
|
|||
if (api_int && !ion_defer) { /* API intr? */
|
||||
int32 i, lvl = api_int - 1; /* get req level */
|
||||
api_act = api_act | (0200 >> lvl); /* set level active */
|
||||
if (lvl >= 4) { /* software req? */
|
||||
MA = ACH_SWRE + lvl - 4; /* vec = 40:43 */
|
||||
if (lvl >= API_HLVL) { /* software req? */
|
||||
MA = ACH_SWRE + lvl - API_HLVL; /* vec = 40:43 */
|
||||
api_req = api_req & ~(0200 >> lvl); } /* remove request */
|
||||
else { MA = 0; /* assume fails */
|
||||
for (i = 31; i >= 0; i--) { /* loop hi to lo */
|
||||
if ((int_req >> i) & 1) { /* int req set? */
|
||||
MA = api_vec[i]; /* get vector */
|
||||
break; } } } /* and stop */
|
||||
for (i = 0; i < 32; i++) { /* loop hi to lo */
|
||||
if ((int_hwre[lvl] >> i) & 1) { /* int req set? */
|
||||
MA = api_vec[lvl][i]; /* get vector */
|
||||
break; } } } /* and stop */
|
||||
if (MA == 0) { /* bad channel? */
|
||||
reason = STOP_API; /* API error */
|
||||
break; }
|
||||
api_int = api_eval (); /* no API int */
|
||||
api_int = api_eval (&int_pend); /* no API int */
|
||||
api_cycle = 1; /* in API cycle */
|
||||
emir_pending = rest_pending = 0; /* emir, restore off */
|
||||
xct_count = 0;
|
||||
|
@ -672,9 +673,9 @@ if (api_int && !ion_defer) { /* API intr? */
|
|||
|
||||
/* Standard program interrupt */
|
||||
|
||||
if (!(api_enb && api_act) && ion && !ion_defer && int_req) {
|
||||
if (!(api_enb && api_act) && ion && !ion_defer && int_pend) {
|
||||
#else
|
||||
if (ion && !ion_defer && int_req) { /* interrupt? */
|
||||
if (ion && !ion_defer && int_pend) { /* interrupt? */
|
||||
#endif
|
||||
old_PC = PC; /* save old PC */
|
||||
M[0] = JMS_WORD (usmd); /* save state */
|
||||
|
@ -688,10 +689,7 @@ if (ion && !ion_defer && int_req) { /* interrupt? */
|
|||
|
||||
/* Breakpoint */
|
||||
|
||||
if (PC == ibkpt_addr) { /* breakpoint? */
|
||||
save_ibkpt = ibkpt_addr; /* save ibkpt */
|
||||
ibkpt_addr = ibkpt_addr | ILL_ADR_FLAG; /* disable */
|
||||
sim_activate (&cpu_unit, 1); /* sched re-enable */
|
||||
if (sim_brk_summ && sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */
|
||||
reason = STOP_IBKPT; /* stop simulation */
|
||||
break; }
|
||||
|
||||
|
@ -862,7 +860,7 @@ case 001: case 000: /* CAL */
|
|||
usmd = 0; /* clear user mode */
|
||||
if ((cpu_unit.flags & UNIT_NOAPI) == 0) { /* if API, act lvl 4 */
|
||||
api_act = api_act | 010;
|
||||
api_int = api_eval (); }
|
||||
api_int = api_eval (&int_pend); }
|
||||
#endif
|
||||
if (IR & 0020000) { INDIRECT; } /* indirect? */
|
||||
CHECK_ADDR_W (MA);
|
||||
|
@ -1345,7 +1343,7 @@ case 034: /* IOT */
|
|||
else if (pulse == 044) nexm = 0;
|
||||
break;
|
||||
case 032: /* power fail */
|
||||
if ((pulse == 001) && (int_req & INT_PWRFL))
|
||||
if ((pulse == 001) && (TST_INT (PWRFL)))
|
||||
PC = INCR_ADDR (PC);
|
||||
break;
|
||||
case 033: /* CPU control */
|
||||
|
@ -1477,7 +1475,7 @@ case 034: /* IOT */
|
|||
LAC = LAC | (iot_data & 0777777);
|
||||
if (iot_data & IOT_SKP) PC = INCR_ADDR (PC);
|
||||
if (iot_data >= IOT_REASON) reason = iot_data >> IOT_V_REASON;
|
||||
api_int = api_eval (); /* eval API */
|
||||
api_int = api_eval (&int_pend); /* eval API */
|
||||
break; /* end case IOT */
|
||||
} /* end switch opcode */
|
||||
if (api_cycle) { /* API cycle? */
|
||||
|
@ -1497,16 +1495,17 @@ return reason;
|
|||
|
||||
/* Evaluate API */
|
||||
|
||||
int32 api_eval (void)
|
||||
int32 api_eval (int32 *pend)
|
||||
{
|
||||
int32 i, hi;
|
||||
static const uint32 api_mask[4] = {
|
||||
API_L0, API_L1, API_L2, API_L3 };
|
||||
|
||||
for (i = *pend = 0; i < API_HLVL+1; i++) { /* any intr? */
|
||||
if (int_hwre[i]) *pend = 1; }
|
||||
if (api_enb == 0) return 0; /* off? no req */
|
||||
api_req = api_req & ~0360; /* clr req<0:3> */
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (int_req & api_mask[i]) api_req = api_req | (0200 >> i); }
|
||||
for (i = 0; i < API_HLVL; i++) { /* loop thru levels */
|
||||
if (int_hwre[i]) /* req on level? */
|
||||
api_req = api_req | (0200 >> i); } /* set api req */
|
||||
hi = api_ffo[api_req & 0377]; /* find hi req */
|
||||
if (hi < api_ffo[api_act & 0377]) return (hi + 1);
|
||||
return 0;
|
||||
|
@ -1554,14 +1553,15 @@ t_stat cpu_reset (DEVICE *dptr)
|
|||
SC = 0;
|
||||
eae_ac_sign = 0;
|
||||
ion = ion_defer = 0;
|
||||
int_req = int_req & ~INT_PWRFL;
|
||||
CLR_INT (PWRFL);
|
||||
api_enb = api_req = api_act = 0;
|
||||
BR = 0;
|
||||
usmd = usmdbuf = 0;
|
||||
memm = memm_init;
|
||||
nexm = prvn = trap_pending = 0;
|
||||
emir_pending = rest_pending = 0;
|
||||
return cpu_svc (&cpu_unit);
|
||||
sim_brk_types = sim_brk_dflt = SWMASK ('E');
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Memory examine */
|
||||
|
@ -1582,28 +1582,19 @@ M[addr] = val & 0777777;
|
|||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Service breakpoint */
|
||||
|
||||
t_stat cpu_svc (UNIT *uptr)
|
||||
{
|
||||
if ((ibkpt_addr & ~ILL_ADR_FLAG) == save_ibkpt) ibkpt_addr = save_ibkpt;
|
||||
save_ibkpt = -1;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Change memory size */
|
||||
|
||||
t_stat cpu_set_size (UNIT *uptr, int32 value)
|
||||
t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
int32 mc = 0;
|
||||
t_addr i;
|
||||
|
||||
if ((value <= 0) || (value > MAXMEMSIZE) || ((value & 07777) != 0))
|
||||
if ((val <= 0) || (val > MAXMEMSIZE) || ((val & 07777) != 0))
|
||||
return SCPE_ARG;
|
||||
for (i = value; i < MEMSIZE; i++) mc = mc | M[i];
|
||||
for (i = val; i < MEMSIZE; i++) mc = mc | M[i];
|
||||
if ((mc != 0) && (!get_yn ("Really truncate memory [N]?", FALSE)))
|
||||
return SCPE_OK;
|
||||
MEMSIZE = value;
|
||||
MEMSIZE = val;
|
||||
for (i = MEMSIZE; i < MAXMEMSIZE; i++) M[i] = 0;
|
||||
return SCPE_OK;
|
||||
}
|
|
@ -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-Nov-01 RMS Revised interrupt structure
|
||||
27-May-01 RMS Added second Teletype support
|
||||
21-Jan-01 RMS Added DECtape support
|
||||
14-Apr-99 RMS Changed t_addr to unsigned
|
||||
|
@ -187,65 +188,101 @@
|
|||
35 LT15 TTI 3 PDP-15 only
|
||||
36 -
|
||||
37 -
|
||||
|
||||
Interrupt system, priority is left to right.
|
||||
|
||||
<30:28> = priority 0
|
||||
<27:20> = priority 1
|
||||
<19:12> = priority 2
|
||||
<11:8> = priority 3
|
||||
<7:0> = PI only
|
||||
*/
|
||||
|
||||
#define API_L0 0xF0000000
|
||||
#define API_L1 0x0FF00000
|
||||
#define API_L2 0x000FF000
|
||||
#define API_L3 0x00000F00
|
||||
#define API_HLVL 4 /* hwre levels */
|
||||
#define ACH_SWRE 040 /* swre int vec */
|
||||
|
||||
#define INT_V_PWRFL 30 /* powerfail */
|
||||
#define INT_V_DTA 27 /* DECtape */
|
||||
#define INT_V_MTA 26 /* magtape */
|
||||
#define INT_V_DRM 25 /* drum */
|
||||
#define INT_V_RF 24 /* fixed head disk */
|
||||
#define INT_V_RP 23 /* disk pack */
|
||||
#define INT_V_PTR 19 /* paper tape reader */
|
||||
#define INT_V_LPT 18 /* line printer */
|
||||
#define INT_V_LPTSPC 17 /* line printer spc */
|
||||
#define INT_V_CLK 11 /* clock */
|
||||
#define INT_V_TTI1 10 /* LT15 keyboard */
|
||||
#define INT_V_TTO1 9 /* LT15 output */
|
||||
#define INT_V_TTI 7 /* console keyboard */
|
||||
#define INT_V_TTO 6 /* console output */
|
||||
#define INT_V_PTP 5 /* paper tape punch */
|
||||
/* API level 0 */
|
||||
|
||||
#define INT_V_PWRFL 0 /* powerfail */
|
||||
|
||||
#define INT_PWRFL (1 << INT_V_PWRFL)
|
||||
|
||||
#define API_PWRFL 0
|
||||
|
||||
#define ACH_PWRFL 052
|
||||
|
||||
/*API level 1 */
|
||||
|
||||
#define INT_V_DTA 0 /* DECtape */
|
||||
#define INT_V_MTA 1 /* magtape */
|
||||
#define INT_V_DRM 2 /* drum */
|
||||
#define INT_V_RF 3 /* fixed head disk */
|
||||
#define INT_V_RP 4 /* disk pack */
|
||||
|
||||
#define INT_DTA (1 << INT_V_DTA)
|
||||
#define INT_MTA (1 << INT_V_MTA)
|
||||
#define INT_DRM (1 << INT_V_DRM)
|
||||
#define INT_RF (1 << INT_V_RF)
|
||||
#define INT_RP (1 << INT_V_RP)
|
||||
#define INT_PTR (1 << INT_V_PTR)
|
||||
#define INT_LPT (1 << INT_V_LPT)
|
||||
#define INT_LPTSPC (1 << INT_V_LPTSPC)
|
||||
#define INT_CLK (1 << INT_V_CLK)
|
||||
#define INT_TTI1 (1 << INT_V_TTI1)
|
||||
#define INT_TTO1 (1 << INT_V_TTO1)
|
||||
#define INT_TTI (1 << INT_V_TTI)
|
||||
#define INT_TTO (1 << INT_V_TTO)
|
||||
#define INT_PTP (1 << INT_V_PTP)
|
||||
|
||||
#define ACH_SWRE 040 /* API channels */
|
||||
#define ACH_PWRFL 052
|
||||
#define API_DTA 1
|
||||
#define API_MTA 1
|
||||
#define API_DRM 1
|
||||
#define API_RF 1
|
||||
#define API_RP 1
|
||||
|
||||
#define ACH_DTA 044
|
||||
#define ACH_MTA 045
|
||||
#define ACH_DRM 046
|
||||
#define ACH_RF 063
|
||||
#define ACH_RP 064
|
||||
|
||||
/* API level 2 */
|
||||
|
||||
#define INT_V_PTR 0 /* paper tape reader */
|
||||
#define INT_V_LPT 1 /* line printer */
|
||||
#define INT_V_LPTSPC 2 /* line printer spc */
|
||||
|
||||
#define INT_PTR (1 << INT_V_PTR)
|
||||
#define INT_LPT (1 << INT_V_LPT)
|
||||
#define INT_LPTSPC (1 << INT_V_LPTSPC)
|
||||
|
||||
#define API_PTR 2
|
||||
#define API_LPT 2
|
||||
#define API_LPTSPC 2
|
||||
|
||||
#define ACH_PTR 050
|
||||
#define ACH_LPT 056
|
||||
|
||||
/* API level 3 */
|
||||
|
||||
#define INT_V_CLK 0 /* clock */
|
||||
#define INT_V_TTI1 1 /* LT15 keyboard */
|
||||
#define INT_V_TTO1 2 /* LT15 output */
|
||||
|
||||
#define INT_CLK (1 << INT_V_CLK)
|
||||
#define INT_TTI1 (1 << INT_V_TTI1)
|
||||
#define INT_TTO1 (1 << INT_V_TTO1)
|
||||
|
||||
#define API_CLK 3
|
||||
#define API_TTI1 3
|
||||
#define API_TTO1 3
|
||||
|
||||
#define ACH_CLK 051
|
||||
#define ACH_TTI1 075
|
||||
#define ACH_TTO1 074
|
||||
|
||||
/* PI level */
|
||||
|
||||
#define INT_V_TTI 0 /* console keyboard */
|
||||
#define INT_V_TTO 1 /* console output */
|
||||
#define INT_V_PTP 2 /* paper tape punch */
|
||||
|
||||
#define INT_TTI (1 << INT_V_TTI)
|
||||
#define INT_TTO (1 << INT_V_TTO)
|
||||
#define INT_PTP (1 << INT_V_PTP)
|
||||
|
||||
#define API_TTI 4 /* PI level */
|
||||
#define API_TTO 4
|
||||
#define API_PTP 4
|
||||
|
||||
/* Interrupt macros */
|
||||
|
||||
#define SET_INT(dv) int_hwre[API_##dv] = int_hwre[API_##dv] | INT_##dv
|
||||
#define CLR_INT(dv) int_hwre[API_##dv] = int_hwre[API_##dv] & ~INT_##dv
|
||||
#define TST_INT(dv) (int_hwre[API_##dv] & INT_##dv)
|
||||
|
||||
/* I/O status flags for the IORS instruction
|
||||
|
782
PDP18B/pdp18b_doc.txt
Normal file
782
PDP18B/pdp18b_doc.txt
Normal file
|
@ -0,0 +1,782 @@
|
|||
To: Users
|
||||
From: Bob Supnik
|
||||
Subj: 18b PDP Simulator Usage
|
||||
Date: 1-Dec-01
|
||||
|
||||
COPYRIGHT NOTICE
|
||||
|
||||
The following copyright notice applies to both the SIMH source and binary:
|
||||
|
||||
Original code published in 1993-2001, written by Robert M Supnik
|
||||
Copyright (c) 1993-2001, Robert M Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation
|
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
and/or sell copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
Except as contained in this notice, the name of Robert M Supnik shall not
|
||||
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
This memorandum documents the PDP-4, PDP-7, PDP-9, and PDP-15 simulators.
|
||||
|
||||
|
||||
1. Simulator Files
|
||||
|
||||
To compile a particular model in the 18b family, you must include the appropriate
|
||||
switch in the compilation command line:
|
||||
|
||||
PDP-4/ PDP4
|
||||
PDP-7/ PDP7
|
||||
PDP-9/ PDP9
|
||||
PDP-15/ PDP15
|
||||
|
||||
If no model is specified, the default is the PDP-9.
|
||||
|
||||
sim/ sim_defs.h
|
||||
sim_sock.h
|
||||
sim_tmxr.h
|
||||
scp.c
|
||||
scp_tty.c
|
||||
sim_rev.c
|
||||
sim_sock.c
|
||||
sim_tmxr.c
|
||||
|
||||
sim/pdp18b/ pdp18b_defs.h
|
||||
pdp18b_cpu.c
|
||||
pdp18b_drm.c
|
||||
pdp18b_dt.c
|
||||
pdp18b_lp.c
|
||||
pdp18b_mt.c
|
||||
pdp18b_rf.c
|
||||
pdp18b_rp.c
|
||||
pdp18b_stddev.c
|
||||
pdp18b_sys.c
|
||||
pdp18b_tt1.c
|
||||
|
||||
2. 18b PDP Features
|
||||
|
||||
The other four 18b PDP's (PDP-4, PDP-7, PDP-9, PDP-15) are very similar
|
||||
and are configured as follows:
|
||||
|
||||
system device simulates
|
||||
name(s)
|
||||
|
||||
PDP-4 CPU PDP-4 CPU with 8KW of memory
|
||||
PTR,PTP integral paper tape/Type 75 punch
|
||||
TTI,TTO KSR28 console terminal (Baudot code)
|
||||
LPT Type 62 line printer (Hollerith code)
|
||||
CLK integral real-time clock
|
||||
|
||||
PDP-7 CPU PDP-7 CPU with 32KW of memory
|
||||
- Type 177 extended arithmetic element (EAE)
|
||||
- Type 148 memory extension
|
||||
PTR,PTP Type 444 paper tape reader/Type 75 punch
|
||||
TTI,TTO KSR 33 console terminal
|
||||
LPT Type 647 line printer
|
||||
CLK integral real-time clock
|
||||
DRM Type 24 serial drum
|
||||
|
||||
PDP-9 CPU PDP-9 CPU with 32KW of memory
|
||||
- KE09A extended arithmetic element (EAE)
|
||||
- KF09A automatic priority interrupt (API)
|
||||
- KG09B memory extension
|
||||
- KP09A power detection
|
||||
- KX09A memory protection
|
||||
PTR,PTP PC09A paper tape reader/punch
|
||||
TTI,TTO KSR 33 console terminal
|
||||
TTI1,TTO1 LT09A second console terminal
|
||||
LPT Type 647E line printer
|
||||
CLK integral real-time clock
|
||||
RF RF09/RS09 fixed-head disk
|
||||
DT TC02/TU55 DECtape
|
||||
MT TC59/TU10 magnetic tape
|
||||
|
||||
PDP-15 CPU PDP-15 CPU with 32KW of memory
|
||||
- KE15 extended arithmetic element (EAE)
|
||||
- KA15 automatic priority interrupt (API)
|
||||
- KF15 power detection
|
||||
- KM15 memory protection
|
||||
PTR,PTP PC15 paper tape reader/punch
|
||||
TTI,TTO KSR 35 console terminal
|
||||
TTI1,TTO1 LT15 second console terminal
|
||||
LPT LP15 line printer
|
||||
CLK integral real-time clock
|
||||
RP RP15/RP02 disk pack
|
||||
RF RF15/RS09 fixed-head disk
|
||||
DT TC15/TU56 DECtape
|
||||
MT TC59/TU10 magnetic tape
|
||||
|
||||
The DRM, RF, RP, DT, and MT devices can be DISABLEd.
|
||||
|
||||
The 18b PDP simulators implement several unique stop conditions:
|
||||
|
||||
- an unimplemented instruction is decoded, and register
|
||||
STOP_INST is set
|
||||
- more than XCTMAX nested executes are detected during
|
||||
instruction execution
|
||||
|
||||
The PDP-4 and PDP-7 loaders support only RIM format tapes. The PDP-9
|
||||
and PDP-15 support both RIM and BIN format tapes. If the file extension
|
||||
is .RIM, or the -r switch is specified with LOAD, the file is assumed to
|
||||
be RIM format; if the file extension is not .RIM, or if the -b switch is
|
||||
specified, the file is assumed to be BIN format.
|
||||
|
||||
2.1 CPU
|
||||
|
||||
The CPU options are the presence of the EAE, the presense of the API (for
|
||||
the PDP-9 and PDP-15), and the size of main memory.
|
||||
|
||||
SET CPU EAE enable EAE
|
||||
SET CPU NOEAE disable EAE
|
||||
SET CPU API enable API
|
||||
SET CPU NOAPI disable API
|
||||
SET CPU 4K set memory size = 4K
|
||||
SET CPU 8K set memory size = 8K
|
||||
SET CPU 12K set memory size = 12K
|
||||
SET CPU 16K set memory size = 16K
|
||||
SET CPU 20K set memory size = 20K
|
||||
SET CPU 24K set memory size = 24K
|
||||
SET CPU 28K set memory size = 28K
|
||||
SET CPU 32K set memory size = 32K
|
||||
SET CPU 48K set memory size = 48K
|
||||
SET CPU 64K set memory size = 64K
|
||||
SET CPU 80K set memory size = 80K
|
||||
SET CPU 96K set memory size = 96K
|
||||
SET CPU 112K set memory size = 112K
|
||||
SET CPU 128K set memory size = 128K
|
||||
|
||||
Memory sizes greater than 8K are only available on the PDP-7, PDP-9, and
|
||||
PDP-15; memory sizes greater than 32KW are only available on the PDP-15.
|
||||
If memory size is being reduced, and the memory being truncated contains
|
||||
non-zero data, the simulator asks for confirmation. Data in the truncated
|
||||
portion of memory is lost. Initial memory size is 8K for the PDP-4, 32K
|
||||
for the PDP-7 and PDP-9, and 128K for the PDP-15.
|
||||
|
||||
CPU registers include the visible state of the processor as well as the
|
||||
control registers for the interrupt system.
|
||||
|
||||
system name size comments
|
||||
|
||||
all PC addr program counter
|
||||
all AC 18 accumulator
|
||||
all L 1 link
|
||||
7,9,15 MQ 18 multiplier-quotient
|
||||
7,9,15 SC 6 shift counter
|
||||
7,9,15 EAE_AC_SIGN 1 EAE AC sign
|
||||
all SR 18 front panel switches
|
||||
all INT[0:4] 32 interrupt requests,
|
||||
0:3 = API levels 0-3
|
||||
4 = PI level
|
||||
all IORS 18 IORS register
|
||||
all ION 1 interrupt enable
|
||||
all ION_DELAY 2 interrupt enable delay
|
||||
9,15 APIENB 1 API enable
|
||||
9,15 APIREQ 8 API requesting levels
|
||||
9,15 APIACT 8 API active levels
|
||||
9,15 BR addr memory protection bounds
|
||||
15 XR 18 index register
|
||||
15 LR 18 limit register
|
||||
15 BR 17 memory protection bounds
|
||||
9,15 USMD 1 user mode
|
||||
9,15 USMDBUF 1 user mode buffer
|
||||
9,15 NEXM 1 non-existent memory violation
|
||||
9,15 PRVN 1 privilege violation
|
||||
7,9 EXTM 1 extend mode
|
||||
7,9 EXTM_INIT 1 extend mode value after reset
|
||||
15 BANKM 1 bank mode
|
||||
15 BANKM_INIT 1 bank mode value after reset
|
||||
7 TRAPM 1 trap mode
|
||||
7,9,15 TRAPP 1 trap pending
|
||||
7,9 EMIRP 1 EMIR instruction pending
|
||||
9,15 RESTP 1 DBR or RES instruction pending
|
||||
9,15 PWRFL 1 power fail flag
|
||||
all OLDPC addr PC prior to last transfer
|
||||
all STOP_INST 1 stop on undefined instruction
|
||||
all WRU 8 interrupt character
|
||||
|
||||
"addr" signifies the address width of the system (13b for the PDP-4, 15b for
|
||||
the PDP-7 and PDP-9, 17b for the PDP-15).
|
||||
|
||||
2.2 Programmed I/O Devices
|
||||
|
||||
2.2.1 Paper Tape Reader (PTR)
|
||||
|
||||
The paper tape reader (PTR) reads data from a disk file. The POS
|
||||
register specifies the number of the next data item to be read. Thus,
|
||||
by changing POS, the user can backspace or advance the reader.
|
||||
|
||||
On the PDP-4 and PDP-7, the paper tape reader supports the BOOT command.
|
||||
BOOT PTR copies the RIM loader into memory and starts it running, while
|
||||
BOOT -F PTR copies the funny format binary loader into memory and starts
|
||||
it running.
|
||||
|
||||
The paper tape reader implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
BUF 8 last data item processed
|
||||
INT 1 interrupt pending flag
|
||||
DONE 1 device done flag
|
||||
ERR 1 error flag (PDP-9, PDP-15 only)
|
||||
POS 31 position in the input file
|
||||
TIME 24 time from I/O initiation to interrupt
|
||||
STOP_IOE 1 stop on I/O error
|
||||
|
||||
Error handling is as follows:
|
||||
|
||||
error STOP_IOE processed as
|
||||
|
||||
not attached 1 report error and stop
|
||||
0 out of tape
|
||||
|
||||
end of file 1 report error and stop
|
||||
0 out of tape
|
||||
|
||||
OS I/O error x report error and stop
|
||||
|
||||
2.2.2 Paper Tape Punch (PTP)
|
||||
|
||||
The paper tape punch (PTP) writes data to a disk file. The POS
|
||||
register specifies the number of the next data item to be written.
|
||||
Thus, by changing POS, the user can backspace or advance the punch.
|
||||
|
||||
The paper tape punch implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
BUF 8 last data item processed
|
||||
INT 1 interrupt pending flag
|
||||
DONE 1 device done flag
|
||||
ERR 1 error flag (PDP-9, PDP-15 only)
|
||||
POS 31 position in the output file
|
||||
TIME 24 time from I/O initiation to interrupt
|
||||
STOP_IOE 1 stop on I/O error
|
||||
|
||||
Error handling is as follows:
|
||||
|
||||
error STOP_IOE processed as
|
||||
|
||||
not attached 1 report error and stop
|
||||
0 out of tape or paper
|
||||
|
||||
OS I/O error x report error and stop
|
||||
|
||||
2.2.3 Terminal Input (TTI)
|
||||
|
||||
The terminal input (TTI) polls the console keyboard for input. The
|
||||
input side has one option, UC; when set, it automatically converts lower
|
||||
case input to upper case.
|
||||
|
||||
The PDP-9 and PDP-15 operate the console terminal (TTI/TTO), by default,
|
||||
as half duplex. For backward compatibility, on the PDP-9 and PDP-15
|
||||
the first terminal input has a second option, FDX; when set, it operates
|
||||
the terminal input in full-duplex mode. The second terminal is always
|
||||
full duplex.
|
||||
|
||||
The terminal input implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
BUF 8 last data item processed
|
||||
INT 1 interrupt pending flag
|
||||
DONE 1 device done flag
|
||||
POS 31 number of characters input
|
||||
TIME 24 keyboard polling interval
|
||||
|
||||
2.2.4 Terminal Output (TTO)
|
||||
|
||||
The terminal output (TTO) writes to the simulator console window. The
|
||||
terminal output has one option, UC; when set, it suppresses lower case
|
||||
output (so that ALTMODE is not echoed as }).
|
||||
|
||||
The terminal output implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
BUF 8 last data item processed
|
||||
INT 1 interrupt pending flag
|
||||
DONE 1 device done flag
|
||||
POS 31 number of chararacters output
|
||||
TIME 24 time from I/O initiation to interrupt
|
||||
|
||||
2.2.5 Line Printer (LPT)
|
||||
|
||||
The line printer (LPT) writes data to a disk file. The POS register
|
||||
specifies the number of the next data item to be written. Thus,
|
||||
by changing POS, the user can backspace or advance the printer.
|
||||
|
||||
The PDP-4 used a Type 62 printer controller, with these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
BUF 8 last data item processed
|
||||
INT 1 interrupt pending flag
|
||||
DONE 1 device done flag
|
||||
SPC 1 spacing done flag
|
||||
BPTR 6 print buffer pointer
|
||||
POS 31 position in the output file
|
||||
TIME 24 time from I/O initiation to interrupt
|
||||
STOP_IOE 1 stop on I/O error
|
||||
LBUF[0:119] 8 line buffer
|
||||
|
||||
The PDP-7 and PDP-7 used a Type 647 printer controller, with these
|
||||
registers:
|
||||
|
||||
name size comments
|
||||
|
||||
BUF 8 last data item processed
|
||||
INT 1 interrupt pending flag
|
||||
DONE 1 device done flag
|
||||
ENABLE 1 interrupt enable (PDP-9 only)
|
||||
ERR 1 error flag
|
||||
BPTR 7 print buffer pointer
|
||||
POS 31 position in the output file
|
||||
TIME 24 time from I/O initiation to interrupt
|
||||
STOP_IOE 1 stop on I/O error
|
||||
LBUF[0:119] 8 line buffer
|
||||
|
||||
The PDP-15 used an LP15 printer controller, with these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
STA 18 status register
|
||||
MA 18 DMA memory address
|
||||
INT 1 interrupt pending flag
|
||||
ENABLE 1 interrupt enable
|
||||
LCNT 8 line counter
|
||||
BPTR 7 print buffer pointer
|
||||
POS 31 position in the output file
|
||||
TIME 24 time from I/O initiation to interrupt
|
||||
STOP_IOE 1 stop on I/O error
|
||||
LBUF[0:131] 8 line buffer
|
||||
|
||||
For all three models, error handling is as follows:
|
||||
|
||||
error STOP_IOE processed as
|
||||
|
||||
not attached 1 report error and stop
|
||||
0 out of tape or paper
|
||||
|
||||
OS I/O error x report error and stop
|
||||
|
||||
2.2.6 Real-Time Clock (CLK)
|
||||
|
||||
The real-time clock (CLK) implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
INT 1 interrupt pending flag
|
||||
DONE 1 device done flag
|
||||
ENABLE 1 clock enable
|
||||
TIME 24 clock frequency
|
||||
TPS 8 ticks per second (60 or 50)
|
||||
|
||||
The real-time clock autocalibrates; the clock interval is adjusted up or
|
||||
down so that the clock tracks actual elapsed time.
|
||||
|
||||
2.2.7 Second Terminal (TTI1, TTO1)
|
||||
|
||||
The second terminal consists of two independent devices, TTI1 and TTO1.
|
||||
The second terminal performs input and output through a Telnet session
|
||||
connected to a user-specified port. The ATTACH command specifies the
|
||||
port to be used:
|
||||
|
||||
ATTACH TTI1 <port>(cr) -- set up listening port
|
||||
|
||||
where port is a decimal number between 1 and 65535 that is not being used
|
||||
for other TCP/IP activities.
|
||||
|
||||
Once TTI1 is attached and the simulator is running, the terminal listens
|
||||
for a connection on the specified port. It assumes that the incoming
|
||||
connection is a Telnet connection. The connection remain opens until
|
||||
disconnected by the Telnet client, or by a DETACH TTI1 command.
|
||||
|
||||
The second terminal input has one option, UC; when set, it automatically
|
||||
converts lower case input to upper case. The second terminal output also
|
||||
has one option, UC; when set, it suppresses lower case output (so that
|
||||
ALTMODE is not echoed as }).
|
||||
|
||||
The SHOW TTI1 LINESTATUS command displays the current connection to the
|
||||
second terminal.
|
||||
|
||||
The second terminal input implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
BUF 8 last data item processed
|
||||
INT 1 interrupt pending flag
|
||||
DONE 1 device done flag
|
||||
POS 31 number of characters input
|
||||
TIME 24 keyboard polling interval
|
||||
|
||||
The second terminal output implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
BUF 8 last data item processed
|
||||
INT 1 interrupt pending flag
|
||||
DONE 1 device done flag
|
||||
POS 31 number of chararacters output
|
||||
TIME 24 time from I/O initiation to interrupt
|
||||
|
||||
2.3 RP15/RP02 Disk Pack (RP)
|
||||
|
||||
RP15 options include the ability to make units write enabled or write locked:
|
||||
|
||||
SET RPn LOCKED set unit n write locked
|
||||
SET RPn ENABLED set unit n write enabled
|
||||
|
||||
Units can also be REMOVEd or ADDed to the configuration.
|
||||
|
||||
The RP15 implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
STA 18 status A
|
||||
STB 18 status B
|
||||
DA 18 disk address
|
||||
MA 18 current memory address
|
||||
WC 18 word count
|
||||
INT 1 interrupt pending flag
|
||||
BUSY 1 control busy flag
|
||||
STIME 24 seek time, per cylinder
|
||||
RTIME 24 rotational delay
|
||||
STOP_IOE 1 stop on I/O error
|
||||
|
||||
Error handling is as follows:
|
||||
|
||||
error STOP_IOE processed as
|
||||
|
||||
not attached 1 report error and stop
|
||||
0 disk not ready
|
||||
|
||||
end of file x assume rest of disk is zero
|
||||
|
||||
OS I/O error x report error and stop
|
||||
|
||||
2.4 Type 24 Serial Drum (DRM)
|
||||
|
||||
The serial drum (DRM) implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
DA 9 drum address (sector number)
|
||||
MA 15 current memory address
|
||||
INT 1 interrupt pending flag
|
||||
DONE 1 device done flag
|
||||
ERR 1 error flag
|
||||
WLK 32 write lock switches
|
||||
TIME 24 rotational latency, per word
|
||||
STOP_IOE 1 stop on I/O error
|
||||
|
||||
Error handling is as follows:
|
||||
|
||||
error STOP_IOE processed as
|
||||
|
||||
not attached 1 report error and stop
|
||||
0 disk not ready
|
||||
|
||||
Drum data files are buffered in memory; therefore, end of file and OS
|
||||
I/O errors cannot occur.
|
||||
|
||||
2.5 RF09/RF15/RS09 Fixed Head Disk (RF)
|
||||
|
||||
The RF09/RF15 implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
STA 18 status
|
||||
DA 21 current disk address
|
||||
MA 18 memory address (in memory)
|
||||
WC 18 word count (in memory)
|
||||
BUF 18 data buffer (diagnostic only)
|
||||
INT 1 interrupt pending flag
|
||||
WLK[0:7] 16 write lock switches for disks 0-7
|
||||
TIME 24 rotational delay, per word
|
||||
BURST 1 burst flag
|
||||
STOP_IOE 1 stop on I/O error
|
||||
|
||||
The RF09/RF15 is a three-cycle data break device. If BURST = 0, word
|
||||
transfers are scheduled individually; if BURST = 1, the entire transfer
|
||||
occurs in a single data break.
|
||||
|
||||
Error handling is as follows:
|
||||
|
||||
error STOP_IOE processed as
|
||||
|
||||
not attached 1 report error and stop
|
||||
0 disk not ready
|
||||
|
||||
RF15/RF09 data files are buffered in memory; therefore, end of file and OS
|
||||
I/O errors cannot occur.
|
||||
|
||||
2.6 TC02/TU55 and TC15/TU56 DECtape (DT)
|
||||
|
||||
DECtapes drives are numbered 1-8; in the simulator, drive 8 is unit 0.
|
||||
DECtape options include the ability to make units write enabled or write
|
||||
locked.
|
||||
|
||||
SET DTn LOCKED set unit n write locked
|
||||
SET DTn ENABLED set unit n write enabled
|
||||
|
||||
Units can also be REMOVEd or ADDed to the configuration.
|
||||
|
||||
The TC02/TC15 supports both PDP-8 format and PDP-9/11/15 format DECtape
|
||||
images. ATTACH tries to determine the tape format from the DECtape image;
|
||||
the user can force a particular format with switches:
|
||||
|
||||
-f foreign (PDP-8) format
|
||||
-n native (PDP-9/11/15) format
|
||||
|
||||
The DECtape controller is a data-only simulator; the timing and mark
|
||||
track, and block header and trailer, are not stored. Thus, the WRITE
|
||||
TIMING AND MARK TRACK function is not supported; the READ ALL function
|
||||
always returns the hardware standard block header and trailer; and the
|
||||
WRITE ALL function dumps non-data words into the bit bucket.
|
||||
|
||||
The DECtape controller implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
DTSA 12 status register A
|
||||
DTSB 12 status register B
|
||||
INT 1 interrupt pending flag
|
||||
ENB 1 interrupt enable flag
|
||||
DTF 1 DECtape flag
|
||||
ERF 1 error flag
|
||||
CA 18 current address (memory location 30)
|
||||
WC 18 word count (memory location 31)
|
||||
LTIME 31 time between lines
|
||||
ACTIME 31 time to accelerate to full speed
|
||||
DCTIME 31 time to decelerate to a full stop
|
||||
SUBSTATE 2 read/write command substate
|
||||
POS[0:7] 31 position, in lines, units 0-7
|
||||
STATT[0:7] 31 unit state, units 0-7
|
||||
|
||||
It is critically important to maintain certain timing relationships
|
||||
among the DECtape parameters, or the DECtape simulator will fail to
|
||||
operate correctly.
|
||||
|
||||
- LTIME must be at least 6
|
||||
- ACTIME must be less than DCTIME, and both need to be at
|
||||
least 100 times LTIME
|
||||
|
||||
2.7 TC59/TU10 Magnetic Tape (MT)
|
||||
|
||||
Magnetic tape options include the ability to make units write enabled or
|
||||
or write locked.
|
||||
|
||||
SET MTn LOCKED set unit n write locked
|
||||
SET MTn ENABLED set unit n write enabled
|
||||
|
||||
Units can also be REMOVEd or ADDed to the configuration.
|
||||
|
||||
The magnetic tape controller implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
CMD 18 command
|
||||
STA 18 main status
|
||||
MA 18 memory address (in memory)
|
||||
WC 18 word count (in memory)
|
||||
INT 1 interrupt pending flag
|
||||
STOP_IOE 1 stop on I/O error
|
||||
TIME 24 record delay
|
||||
UST[0:7] 24 unit status, units 0-7
|
||||
POS[0:7] 31 position, units 0-7
|
||||
|
||||
Error handling is as follows:
|
||||
|
||||
error processed as
|
||||
|
||||
not attached tape not ready
|
||||
|
||||
end of file (read or space) end of physical tape
|
||||
(write) ignored
|
||||
|
||||
OS I/O error report error and stop
|
||||
|
||||
2.8 Symbolic Display and Input
|
||||
|
||||
The 18b PDP simulators implement symbolic display and input. Display is
|
||||
controlled by command line switches:
|
||||
|
||||
-a display as ASCII character
|
||||
-c display as (sixbit) character string
|
||||
-m display instruction mnemonics
|
||||
|
||||
The PDP-15 also recognizes an additional switch:
|
||||
|
||||
-p display as packed ASCII (five 7b ASCII
|
||||
characters in two 18b words)
|
||||
|
||||
Input parsing is controlled by the first character typed in or by command
|
||||
line switches:
|
||||
|
||||
' or -a ASCII character
|
||||
" or -c three character sixbit string
|
||||
alphabetic instruction mnemonic
|
||||
numeric octal number
|
||||
|
||||
The PDP-15 also recognizes an additional input mode:
|
||||
|
||||
# or -p five character packed ASCII string in
|
||||
two 18b words
|
||||
|
||||
Instruction input uses standard 18b PDP assembler syntax. There are six
|
||||
instruction classes: memory reference, EAE, index (PDP-15 only), IOT,
|
||||
operate, and LAW.
|
||||
|
||||
Memory reference instructions have the format
|
||||
|
||||
memref {I/@} address{,X}
|
||||
|
||||
where I (PDP-4, PDP-7, PDP-9) /@ (PDP-15) signifies indirect reference,
|
||||
and X signifies indexing (PDP-15 in page mode only). The address is an
|
||||
octal number in the range 0 - 017777 (PDP-4, PDP-7, PDP-9, and PDP-15 in
|
||||
bank mode) or 0 - 07777 (PDP-15 in page mode).
|
||||
|
||||
IOT instructions consist of single mnemonics, eg, KRB, TLS. IOT instructions
|
||||
may be or'd together
|
||||
|
||||
iot iot iot...
|
||||
|
||||
IOT's may also include the number 10, signifying clear the accumulator
|
||||
|
||||
iot 10
|
||||
|
||||
The simulator does not check the legality of IOT combinations. IOT's for
|
||||
which there is no opcode may be specified as IOT n, where n is an octal
|
||||
number in the range 0 - 07777.
|
||||
|
||||
EAE instructions have the format
|
||||
|
||||
eae {+/- shift count}
|
||||
|
||||
EAE instructions may be or'd together
|
||||
|
||||
eae eae eae...
|
||||
|
||||
The simulator does not check the legality of EAE combinations. EAE's for
|
||||
which there is no opcode may be specified as EAE n, where n is an octal
|
||||
number in the range 0 - 037777.
|
||||
|
||||
Index instructions (PDP-15 only) have the format
|
||||
|
||||
index {immediate}
|
||||
|
||||
The immediate, if allowed, must be in the range of -0400 to +0377.
|
||||
|
||||
Operate instructions have the format
|
||||
|
||||
opr opr opr...
|
||||
|
||||
The simulator does not check the legality of the proposed combination. The
|
||||
operands for MUY and DVI must be deposited explicitly.
|
||||
|
||||
Finally, the LAW instruction has the format
|
||||
|
||||
LAW immediate
|
||||
|
||||
where immediate is in the range of 0 to 017777.
|
||||
|
||||
2.9 Character Sets
|
||||
|
||||
The PDP-4's console was an ASR-28 Teletype; its character encoding was
|
||||
Baudot. The PDP-4's line printer used a modified Hollerith character
|
||||
set. The PDP-7's and PDP-9's consoles were KSR-33 Teletypes; their
|
||||
character sets were basically ASCII. The PDP-7's and PDP-9's line
|
||||
printers used sixbit encoding (ASCII codes 040 - 0137 masked to six
|
||||
bits). The PDP-15's I/O devices were all ASCII. The following table
|
||||
provides equivalences between ASCII characters and the PDP-4's I/O devices.
|
||||
In the console table, FG stands for figures (upper case).
|
||||
|
||||
PDP-4 PDP-4
|
||||
ASCII console line printer
|
||||
|
||||
000 - 006 none none
|
||||
bell FG+024 none
|
||||
010 - 011 none none
|
||||
lf 010 none
|
||||
013 - 014 none none
|
||||
cr 002 none
|
||||
016 - 037 none none
|
||||
space 004 000
|
||||
! FG+026 none
|
||||
" FG+021 none
|
||||
# FG+005 none
|
||||
$ FG+062 none
|
||||
% none none
|
||||
& FG+013 none
|
||||
' FG+032 none
|
||||
( FG+036 057
|
||||
) FG+011 055
|
||||
* none 072
|
||||
+ none 074
|
||||
, FG+006 033
|
||||
- FG+030 054
|
||||
. FG+007 073
|
||||
/ FG+027 021
|
||||
0 FG+015 020
|
||||
1 FG+035 001
|
||||
2 FG+031 002
|
||||
3 FG+020 003
|
||||
4 FG+012 004
|
||||
5 FG+001 005
|
||||
6 FG+025 006
|
||||
7 FG+034 007
|
||||
8 FG+014 010
|
||||
9 FG+003 011
|
||||
: FG+016 none
|
||||
; FG+017 none
|
||||
< none 034
|
||||
= none 053
|
||||
> none 034
|
||||
? FG+023 037
|
||||
@ none {MID DOT} 040
|
||||
A 030 061
|
||||
B 023 062
|
||||
C 016 063
|
||||
D 022 064
|
||||
E 020 065
|
||||
F 026 066
|
||||
G 013 067
|
||||
H 005 070
|
||||
I 014 071
|
||||
J 032 041
|
||||
K 036 042
|
||||
L 011 043
|
||||
M 007 044
|
||||
N 006 045
|
||||
O 003 046
|
||||
P 015 047
|
||||
Q 035 050
|
||||
R 012 051
|
||||
S 024 022
|
||||
T 001 023
|
||||
U 034 024
|
||||
V 017 025
|
||||
W 031 026
|
||||
X 027 027
|
||||
Y 025 030
|
||||
Z 021 031
|
||||
[ none none
|
||||
\ none {OVERLINE} 056
|
||||
] none none
|
||||
^ none {UP ARROW} 035
|
||||
_ none UC+040
|
||||
0140 - 0177 none none
|
|
@ -26,6 +26,7 @@
|
|||
drm (PDP-7) Type 24 serial drum
|
||||
(PDP-9) RM09 serial drum
|
||||
|
||||
25-Nov-01 RMS Revised interrupt structure
|
||||
10-Jun-01 RMS Cleaned up IOT decoding to reflect hardware
|
||||
26-Apr-01 RMS Added device enable/disable support
|
||||
14-Apr-99 RMS Changed t_addr to unsigned
|
||||
|
@ -54,7 +55,7 @@
|
|||
((double) DRM_NUMWDT)))
|
||||
|
||||
extern int32 M[];
|
||||
extern int32 int_req, dev_enb;
|
||||
extern int32 int_hwre[API_HLVL+1], dev_enb;
|
||||
extern UNIT cpu_unit;
|
||||
int32 drm_da = 0; /* track address */
|
||||
int32 drm_ma = 0; /* memory address */
|
||||
|
@ -80,8 +81,8 @@ UNIT drm_unit =
|
|||
REG drm_reg[] = {
|
||||
{ ORDATA (DA, drm_da, 9) },
|
||||
{ ORDATA (MA, drm_ma, 15) },
|
||||
{ FLDATA (INT, int_req, INT_V_DRM) },
|
||||
{ FLDATA (DONE, int_req, INT_V_DRM) },
|
||||
{ FLDATA (INT, int_hwre[API_DRM], INT_V_DRM) },
|
||||
{ FLDATA (DONE, int_hwre[API_DRM], INT_V_DRM) },
|
||||
{ FLDATA (ERR, drm_err, 0) },
|
||||
{ ORDATA (WLK, drm_wlk, 32) },
|
||||
{ DRDATA (TIME, drm_time, 24), REG_NZ + PV_LEFT },
|
||||
|
@ -110,9 +111,9 @@ int32 drm61 (int32 pulse, int32 AC)
|
|||
int32 t;
|
||||
|
||||
if (pulse & 001) { /* DRSF */
|
||||
if (int_req & INT_DRM) AC = AC | IOT_SKP; }
|
||||
if (TST_INT (DRM)) AC = AC | IOT_SKP; }
|
||||
if (pulse & 002) { /* DRCF */
|
||||
int_req = int_req & ~INT_DRM; /* clear done */
|
||||
CLR_INT (DRM); /* clear done */
|
||||
drm_err = 0; } /* clear error */
|
||||
if (pulse & 004) { /* DRSS */
|
||||
drm_da = AC & DRM_SMASK; /* load sector # */
|
||||
|
@ -129,7 +130,7 @@ int32 t;
|
|||
if (pulse & 001) { /* DRSN */
|
||||
if (drm_err == 0) AC = AC | IOT_SKP; }
|
||||
if (pulse & 004) { /* DRCS */
|
||||
int_req = int_req & ~INT_DRM; /* clear done */
|
||||
CLR_INT (DRM); /* clear done */
|
||||
drm_err = 0; /* clear error */
|
||||
t = ((drm_da % DRM_NUMSC) * DRM_NUMWDS) - GET_POS (drm_time);
|
||||
if (t < 0) t = t + DRM_NUMWDT; /* wrap around? */
|
||||
|
@ -149,7 +150,7 @@ t_addr da;
|
|||
|
||||
if ((uptr -> flags & UNIT_BUF) == 0) { /* not buf? abort */
|
||||
drm_err = 1; /* set error */
|
||||
int_req = int_req | INT_DRM; /* set done */
|
||||
SET_INT (DRM); /* set done */
|
||||
return IORETURN (drm_stopioe, SCPE_UNATT); }
|
||||
|
||||
da = drm_da * DRM_NUMWDS; /* compute dev addr */
|
||||
|
@ -163,7 +164,7 @@ for (i = 0; i < DRM_NUMWDS; i++, da++) { /* do transfer */
|
|||
uptr -> hwmark = da + 1; } }
|
||||
drm_ma = (drm_ma + 1) & ADDRMASK; } /* incr mem addr */
|
||||
drm_da = (drm_da + 1) & DRM_SMASK; /* incr dev addr */
|
||||
int_req = int_req | INT_DRM; /* set done */
|
||||
SET_INT (DRM); /* set done */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
@ -172,7 +173,7 @@ return SCPE_OK;
|
|||
t_stat drm_reset (DEVICE *dptr)
|
||||
{
|
||||
drm_ma = drm_ma = drm_err = 0;
|
||||
int_req = int_req & ~INT_DRM;
|
||||
CLR_INT (DRM); /* clear done */
|
||||
sim_cancel (&drm_unit);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
@ -181,7 +182,7 @@ return SCPE_OK;
|
|||
|
||||
int32 drm_iors (void)
|
||||
{
|
||||
return ((int_req & INT_DRM)? IOS_DRM: 0);
|
||||
return (TST_INT (DRM)? IOS_DRM: 0);
|
||||
}
|
||||
|
||||
/* Bootstrap routine */
|
|
@ -26,6 +26,9 @@
|
|||
dt (PDP-9) TC02/TU55 DECtape
|
||||
(PDP-15) TC15/TU56 DECtape
|
||||
|
||||
29-Nov-01 RMS Added read only unit support
|
||||
25-Nov-01 RMS Revised interrupt structure
|
||||
Changed POS, STATT, LASTT, FLG to arrays
|
||||
29-Aug-01 RMS Added casts to PDP-8 unpack routine
|
||||
17-Jul-01 RMS Moved function prototype
|
||||
11-May-01 RMS Fixed bug in reset
|
||||
|
@ -83,6 +86,7 @@
|
|||
#define LASTT u4 /* last time update */
|
||||
#define DT_WC 030 /* word count */
|
||||
#define DT_CA 031 /* current addr */
|
||||
#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */
|
||||
|
||||
/* System independent DECtape constants */
|
||||
|
||||
|
@ -227,12 +231,12 @@
|
|||
#define LOG_BL 010 /* block # lblk */
|
||||
|
||||
#define DT_UPDINT if ((dtsa & DTA_ENB) && (dtsb & (DTB_ERF | DTB_DTF))) \
|
||||
int_req = int_req | INT_DTA; \
|
||||
else int_req = int_req & ~INT_DTA;
|
||||
SET_INT (DTA); \
|
||||
else CLR_INT (DTA);
|
||||
#define ABS(x) (((x) < 0)? (-(x)): (x))
|
||||
|
||||
extern int32 M[];
|
||||
extern int32 int_req, dev_enb;
|
||||
extern int32 int_hwre[API_HLVL+1], dev_enb;
|
||||
extern UNIT cpu_unit;
|
||||
extern int32 sim_switches;
|
||||
int32 dtsa = 0; /* status A */
|
||||
|
@ -267,19 +271,27 @@ extern int32 sim_is_running;
|
|||
*/
|
||||
|
||||
UNIT dt_unit[] = {
|
||||
{ UDATA (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, DT_CAPAC) },
|
||||
{ UDATA (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, DT_CAPAC) },
|
||||
{ UDATA (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, DT_CAPAC) },
|
||||
{ UDATA (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, DT_CAPAC) },
|
||||
{ UDATA (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, DT_CAPAC) },
|
||||
{ UDATA (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, DT_CAPAC) },
|
||||
{ UDATA (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, DT_CAPAC) },
|
||||
{ UDATA (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, DT_CAPAC) } };
|
||||
{ UDATA (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE, DT_CAPAC) },
|
||||
{ UDATA (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE, DT_CAPAC) },
|
||||
{ UDATA (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE, DT_CAPAC) },
|
||||
{ UDATA (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE, DT_CAPAC) },
|
||||
{ UDATA (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE, DT_CAPAC) },
|
||||
{ UDATA (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE, DT_CAPAC) },
|
||||
{ UDATA (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE, DT_CAPAC) },
|
||||
{ UDATA (&dt_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE, DT_CAPAC) } };
|
||||
|
||||
REG dt_reg[] = {
|
||||
{ GRDATA (DTSA, dtsa, 8, 12, 6) },
|
||||
{ GRDATA (DTSB, dtsb, 8, 12, 6) },
|
||||
{ FLDATA (INT, int_req, INT_V_DTA) },
|
||||
{ FLDATA (INT, int_hwre[API_DTA], INT_V_DTA) },
|
||||
{ FLDATA (ENB, dtsa, DTA_V_ENB) },
|
||||
{ FLDATA (DTF, dtsb, DTB_V_DTF) },
|
||||
{ FLDATA (ERF, dtsb, DTB_V_ERF) },
|
||||
|
@ -291,46 +303,14 @@ REG dt_reg[] = {
|
|||
{ ORDATA (SUBSTATE, dt_substate, 2) },
|
||||
{ ORDATA (LOG, dt_log, 4), REG_HIDDEN },
|
||||
{ DRDATA (LBLK, dt_logblk, 12), REG_HIDDEN },
|
||||
{ DRDATA (POS0, dt_unit[0].pos, 31), PV_LEFT + REG_RO },
|
||||
{ DRDATA (POS1, dt_unit[1].pos, 31), PV_LEFT + REG_RO },
|
||||
{ DRDATA (POS2, dt_unit[2].pos, 31), PV_LEFT + REG_RO },
|
||||
{ DRDATA (POS3, dt_unit[3].pos, 31), PV_LEFT + REG_RO },
|
||||
{ DRDATA (POS4, dt_unit[4].pos, 31), PV_LEFT + REG_RO },
|
||||
{ DRDATA (POS5, dt_unit[5].pos, 31), PV_LEFT + REG_RO },
|
||||
{ DRDATA (POS6, dt_unit[6].pos, 31), PV_LEFT + REG_RO },
|
||||
{ DRDATA (POS7, dt_unit[7].pos, 31), PV_LEFT + REG_RO },
|
||||
{ ORDATA (STATE0, dt_unit[0].STATE, 18), REG_RO },
|
||||
{ ORDATA (STATE1, dt_unit[1].STATE, 18), REG_RO },
|
||||
{ ORDATA (STATE2, dt_unit[2].STATE, 18), REG_RO },
|
||||
{ ORDATA (STATE3, dt_unit[3].STATE, 18), REG_RO },
|
||||
{ ORDATA (STATE4, dt_unit[4].STATE, 18), REG_RO },
|
||||
{ ORDATA (STATE5, dt_unit[5].STATE, 18), REG_RO },
|
||||
{ ORDATA (STATE6, dt_unit[6].STATE, 18), REG_RO },
|
||||
{ ORDATA (STATE7, dt_unit[7].STATE, 18), REG_RO },
|
||||
{ DRDATA (LASTT0, dt_unit[0].LASTT, 32), REG_HRO },
|
||||
{ DRDATA (LASTT1, dt_unit[1].LASTT, 32), REG_HRO },
|
||||
{ DRDATA (LASTT2, dt_unit[2].LASTT, 32), REG_HRO },
|
||||
{ DRDATA (LASTT3, dt_unit[3].LASTT, 32), REG_HRO },
|
||||
{ DRDATA (LASTT4, dt_unit[4].LASTT, 32), REG_HRO },
|
||||
{ DRDATA (LASTT5, dt_unit[5].LASTT, 32), REG_HRO },
|
||||
{ DRDATA (LASTT6, dt_unit[6].LASTT, 32), REG_HRO },
|
||||
{ DRDATA (LASTT7, dt_unit[7].LASTT, 32), REG_HRO },
|
||||
{ GRDATA (FLG0, dt_unit[0].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ GRDATA (FLG1, dt_unit[1].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ GRDATA (FLG2, dt_unit[2].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ GRDATA (FLG3, dt_unit[3].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ GRDATA (FLG4, dt_unit[4].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ GRDATA (FLG5, dt_unit[5].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ GRDATA (FLG6, dt_unit[6].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ GRDATA (FLG7, dt_unit[7].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ URDATA (POS, dt_unit[0].pos, 10, 31, 0,
|
||||
DT_NUMDR, PV_LEFT | REG_RO) },
|
||||
{ URDATA (STATT, dt_unit[0].STATE, 8, 18, 0,
|
||||
DT_NUMDR, REG_RO) },
|
||||
{ URDATA (LASTT, dt_unit[0].LASTT, 10, 32, 0,
|
||||
DT_NUMDR, REG_HRO) },
|
||||
{ URDATA (FLG, dt_unit[0].flags, 8, UNIT_W_UF, UNIT_V_UF - 1,
|
||||
DT_NUMDR, REG_HRO) },
|
||||
{ FLDATA (*DEVENB, dev_enb, INT_V_DTA), REG_HRO },
|
||||
{ NULL } };
|
||||
|
||||
|
@ -366,8 +346,8 @@ if (((pulse & 060) == 040) && (pulse & 05)) { /* select */
|
|||
fnc = DTA_GETFNC (dtsa); /* get fnc */
|
||||
if (((uptr -> flags) & UNIT_DIS) || /* disabled? */
|
||||
(fnc >= FNC_WMRK) || /* write mark? */
|
||||
((fnc == FNC_WRIT) && (uptr -> flags & UNIT_WLK)) ||
|
||||
((fnc == FNC_WALL) && (uptr -> flags & UNIT_WLK)))
|
||||
((fnc == FNC_WRIT) && (uptr -> flags & UNIT_WPRT)) ||
|
||||
((fnc == FNC_WALL) && (uptr -> flags & UNIT_WPRT)))
|
||||
dt_seterr (uptr, DTB_SEL); /* select err */
|
||||
else dt_newsa (dtsa); /* new func */
|
||||
DT_UPDINT;
|
||||
|
@ -1046,7 +1026,7 @@ if (sim_is_active (uptr)) {
|
|||
dtsb = dtsb | DTB_ERF | DTB_SEL | DTB_DTF;
|
||||
DT_UPDINT; }
|
||||
uptr -> STATE = uptr -> pos = 0; }
|
||||
if (uptr -> hwmark) { /* any data? */
|
||||
if (uptr -> hwmark && ((uptr -> flags & UNIT_RO) == 0)) { /* any data? */
|
||||
printf ("DT: writing buffer to file\n");
|
||||
rewind (uptr -> fileref); /* start of file */
|
||||
if (uptr -> flags & UNIT_8FMT) { /* PDP8? */
|
|
@ -27,6 +27,7 @@
|
|||
(PDP-7,9) Type 647 line printer
|
||||
(PDP-15) LP15 line printer
|
||||
|
||||
25-Nov-01 RMS Revised interrupt structure
|
||||
19-Sep-01 RMS Fixed bug in 647
|
||||
13-Feb-01 RMS Revised for register arrays
|
||||
15-Feb-01 RMS Fixed 3 cycle data break sequence
|
||||
|
@ -42,7 +43,7 @@
|
|||
#define BPTR_MAX 40 /* pointer max */
|
||||
#define LPT_BSIZE 120 /* line size */
|
||||
#define BPTR_MASK 077 /* buf ptr max */
|
||||
extern int32 int_req;
|
||||
extern int32 int_hwre[API_HLVL+1];
|
||||
int32 lpt_iot = 0, lpt_stopioe = 0, bptr = 0;
|
||||
char lpt_buf[LPT_BSIZE + 1] = { 0 };
|
||||
|
||||
|
@ -61,9 +62,9 @@ UNIT lpt_unit = {
|
|||
|
||||
REG lpt_reg[] = {
|
||||
{ ORDATA (BUF, lpt_unit.buf, 8) },
|
||||
{ FLDATA (INT, int_req, INT_V_LPT) },
|
||||
{ FLDATA (DONE, int_req, INT_V_LPT) },
|
||||
{ FLDATA (SPC, int_req, INT_V_LPTSPC) },
|
||||
{ FLDATA (INT, int_hwre[API_LPT], INT_V_LPT) },
|
||||
{ FLDATA (DONE, int_hwre[API_LPT], INT_V_LPT) },
|
||||
{ FLDATA (SPC, int_hwre[API_LPTSPC], INT_V_LPTSPC) },
|
||||
{ DRDATA (BPTR, bptr, 6) },
|
||||
{ ORDATA (STATE, lpt_iot, 6), REG_HRO },
|
||||
{ DRDATA (POS, lpt_unit.pos, 31), PV_LEFT },
|
||||
|
@ -90,8 +91,8 @@ static const char lpt_trans[64] = {
|
|||
'o','J','K','L','M','N','O','P','Q','R','$','=','-',')','-','(',
|
||||
'_','A','B','C','D','E','F','G','H','I','*','.','+',']','|','[' };
|
||||
|
||||
if (pulse == 001) return (int_req & INT_LPT)? IOT_SKP + AC: AC; /* LPSF */
|
||||
if (pulse == 002) int_req = int_req & ~INT_LPT; /* LPCF */
|
||||
if (pulse == 001) return (TST_INT (LPT))? IOT_SKP + AC: AC; /* LPSF */
|
||||
if (pulse == 002) CLR_INT (LPT); /* LPCF */
|
||||
else if (pulse == 042) { /* LPLD */
|
||||
if (bptr < BPTR_MAX) { /* limit test ptr */
|
||||
i = bptr * 3; /* cvt to chr ptr */
|
||||
|
@ -100,17 +101,17 @@ else if (pulse == 042) { /* LPLD */
|
|||
lpt_buf[i++] = lpt_trans[AC & 077]; }
|
||||
bptr = (bptr + 1) & BPTR_MASK; }
|
||||
else if (pulse == 006) { /* LPSE */
|
||||
int_req = int_req & ~INT_LPT; /* clear flag */
|
||||
CLR_INT (LPT); /* clear flag */
|
||||
sim_activate (&lpt_unit, lpt_unit.wait); } /* activate */
|
||||
return AC;
|
||||
}
|
||||
|
||||
int32 lpt66 (int32 pulse, int32 AC)
|
||||
{
|
||||
if (pulse == 001) return (int_req & INT_LPTSPC)? IOT_SKP + AC: AC; /* LSSF */
|
||||
if (pulse & 002) int_req = int_req & ~INT_LPTSPC; /* LSCF */
|
||||
if (pulse == 001) return (TST_INT (LPTSPC))? IOT_SKP + AC: AC; /* LSSF */
|
||||
if (pulse & 002) CLR_INT (LPTSPC); /* LSCF */
|
||||
if (pulse & 004) { /* LSPR */
|
||||
int_req = int_req & ~INT_LPTSPC; /* clear flag */
|
||||
CLR_INT (LPTSPC); /* clear flag */
|
||||
lpt_iot = 020 | (AC & 07); /* space, no print */
|
||||
sim_activate (&lpt_unit, lpt_unit.wait); } /* activate */
|
||||
return AC;
|
||||
|
@ -137,7 +138,7 @@ static const char *lpt_cc[] = {
|
|||
"\f" };
|
||||
|
||||
if (lpt_iot & 020) { /* space? */
|
||||
int_req = int_req | INT_LPTSPC; /* set flag */
|
||||
SET_INT (LPTSPC); /* set flag */
|
||||
if ((lpt_unit.flags & UNIT_ATT) == 0) /* attached? */
|
||||
return IORETURN (lpt_stopioe, SCPE_UNATT);
|
||||
fputs (lpt_cc[lpt_iot & 07], lpt_unit.fileref); /* print cctl */
|
||||
|
@ -146,7 +147,7 @@ if (lpt_iot & 020) { /* space? */
|
|||
clearerr (lpt_unit.fileref);
|
||||
return SCPE_IOERR; }
|
||||
lpt_iot = 0; } /* clear state */
|
||||
else { int_req = int_req | INT_LPT; /* print */
|
||||
else { SET_INT (LPT); /* print */
|
||||
if ((lpt_unit.flags & UNIT_ATT) == 0) /* attached? */
|
||||
return IORETURN (lpt_stopioe, SCPE_UNATT);
|
||||
if (lpt_iot & 010) fputc ('\r', lpt_unit.fileref);
|
||||
|
@ -168,7 +169,8 @@ t_stat lpt_reset (DEVICE *dptr)
|
|||
{
|
||||
int32 i;
|
||||
|
||||
int_req = int_req & ~(INT_LPT + INT_LPTSPC); /* clear flag, space */
|
||||
CLR_INT (LPT); /* clear intrs */
|
||||
CLR_INT (LPTSPC);
|
||||
sim_cancel (&lpt_unit); /* deactivate unit */
|
||||
bptr = 0; /* clear buffer ptr */
|
||||
for (i = 0; i <= LPT_BSIZE; i++) lpt_buf[i] = 0; /* clear buffer */
|
||||
|
@ -180,14 +182,14 @@ return SCPE_OK;
|
|||
|
||||
int32 lpt_iors (void)
|
||||
{
|
||||
return ((int_req & INT_LPT)? IOS_LPT: 0) |
|
||||
((int_req & INT_LPTSPC)? IOS_LPT1: 0);
|
||||
return (TST_INT (LPT)? IOS_LPT: 0) |
|
||||
(TST_INT (LPTSPC)? IOS_LPT1: 0);
|
||||
}
|
||||
|
||||
#elif defined (TYPE647)
|
||||
|
||||
#define LPT_BSIZE 120 /* line size */
|
||||
extern int32 int_req;
|
||||
extern int32 int_hwre[API_HLVL+1];
|
||||
int32 lpt_done = 0, lpt_ie = 1, lpt_err = 0;
|
||||
int32 lpt_iot = 0, lpt_stopioe = 0, bptr = 0;
|
||||
char lpt_buf[LPT_BSIZE] = { 0 };
|
||||
|
@ -209,7 +211,7 @@ UNIT lpt_unit = {
|
|||
|
||||
REG lpt_reg[] = {
|
||||
{ ORDATA (BUF, lpt_unit.buf, 8) },
|
||||
{ FLDATA (INT, int_req, INT_V_LPT) },
|
||||
{ FLDATA (INT, int_hwre[API_LPT], INT_V_LPT) },
|
||||
{ FLDATA (DONE, lpt_done, 0) },
|
||||
#if defined (PDP9)
|
||||
{ FLDATA (ENABLE, lpt_ie, 0) },
|
||||
|
@ -238,16 +240,16 @@ int32 i;
|
|||
if (pulse == 001) return (lpt_done? IOT_SKP + AC: AC); /* LPSF */
|
||||
if (pulse & 002) { /* pulse 02 */
|
||||
lpt_done = 0; /* clear done */
|
||||
int_req = int_req & ~INT_LPT; } /* clear int req */
|
||||
CLR_INT (LPT); } /* clear int req */
|
||||
if (pulse == 002) { /* LPCB */
|
||||
for (i = 0; i < LPT_BSIZE; i++) lpt_buf[i] = 0;
|
||||
bptr = 0; /* reset buf ptr */
|
||||
lpt_done = 1; /* set done */
|
||||
if (lpt_ie) int_req = int_req | INT_LPT; } /* set int */
|
||||
if (lpt_ie) SET_INT (LPT); } /* set int */
|
||||
#if defined (PDP9)
|
||||
if (pulse == 004) { /* LPDI */
|
||||
lpt_ie = 0; /* clear int enable */
|
||||
int_req = int_req & ~INT_LPT; } /* clear int req */
|
||||
CLR_INT (LPT); } /* clear int req */
|
||||
#endif
|
||||
if ((pulse == 046) && (bptr < LPT_BSIZE)) { /* LPB3 */
|
||||
lpt_buf[bptr] = lpt_buf[bptr] | ((AC >> 12) & 077);
|
||||
|
@ -260,7 +262,7 @@ if ((pulse == 046) || (pulse == 026) || (pulse == 066)) {
|
|||
lpt_buf[bptr] = lpt_buf[bptr] | (AC & 077);
|
||||
bptr = bptr + 1; }
|
||||
lpt_done = 1; /* set done */
|
||||
if (lpt_ie) int_req = int_req | INT_LPT; } /* set int */
|
||||
if (lpt_ie) SET_INT (LPT); } /* set int */
|
||||
return AC;
|
||||
}
|
||||
|
||||
|
@ -269,14 +271,14 @@ int32 lpt66 (int32 pulse, int32 AC)
|
|||
if (pulse == 001) return (lpt_err? IOT_SKP + AC: AC); /* LPSE */
|
||||
if (pulse & 002) { /* LPCF */
|
||||
lpt_done = 0; /* clear done, int */
|
||||
int_req = int_req & ~INT_LPT; }
|
||||
CLR_INT (LPT); }
|
||||
if (((pulse & 060) < 060) && (pulse & 004)) { /* LPLS, LPPB, LPPS */
|
||||
lpt_iot = (pulse & 060) | (AC & 07); /* save parameters */
|
||||
sim_activate (&lpt_unit, lpt_unit.wait); } /* activate */
|
||||
#if defined (PDP9)
|
||||
if (pulse == 064) { /* LPEI */
|
||||
lpt_ie = 1; /* set int enable */
|
||||
if (lpt_done) int_req = int_req | INT_LPT; }
|
||||
if (lpt_done) SET_INT (LPT); }
|
||||
#endif
|
||||
return AC;
|
||||
}
|
||||
|
@ -303,7 +305,7 @@ static const char *lpt_cc[] = {
|
|||
"\f" };
|
||||
|
||||
lpt_done = 1;
|
||||
if (lpt_ie) int_req = int_req | INT_LPT; /* set flag */
|
||||
if (lpt_ie) SET_INT (LPT); /* set flag */
|
||||
if ((lpt_unit.flags & UNIT_ATT) == 0) { /* not attached? */
|
||||
lpt_err = 1; /* set error */
|
||||
return IORETURN (lpt_stopioe, SCPE_UNATT); }
|
||||
|
@ -338,7 +340,7 @@ int32 i;
|
|||
lpt_done = 0; /* clear done */
|
||||
lpt_err = (lpt_unit.flags & UNIT_ATT)? 0: 1; /* compute error */
|
||||
lpt_ie = 1; /* set enable */
|
||||
int_req = int_req & ~INT_LPT; /* clear int */
|
||||
CLR_INT (LPT); /* clear int */
|
||||
sim_cancel (&lpt_unit); /* deactivate unit */
|
||||
bptr = 0; /* clear buffer ptr */
|
||||
lpt_iot = 0; /* clear state */
|
||||
|
@ -391,7 +393,7 @@ return detach_unit (uptr);
|
|||
#define STA_CLR 0003777 /* always clear */
|
||||
|
||||
extern int32 M[];
|
||||
extern int32 int_req;
|
||||
extern int32 int_hwre[API_HLVL+1];
|
||||
int32 lpt_sta = 0, lpt_ie = 1, lpt_stopioe = 0;
|
||||
int32 mode = 0, lcnt = 0, bptr = 0;
|
||||
char lpt_buf[LPT_BSIZE] = { 0 };
|
||||
|
@ -413,7 +415,7 @@ UNIT lpt_unit = {
|
|||
REG lpt_reg[] = {
|
||||
{ ORDATA (STA, lpt_sta, 18) },
|
||||
{ ORDATA (CA, M[LPT_CA], 18) },
|
||||
{ FLDATA (INT, int_req, INT_V_LPT) },
|
||||
{ FLDATA (INT, int_hwre[API_LPT], INT_V_LPT) },
|
||||
{ FLDATA (ENABLE, lpt_ie, 0) },
|
||||
{ DRDATA (LCNT, lcnt, 9) },
|
||||
{ DRDATA (BPTR, bptr, 8) },
|
||||
|
@ -523,8 +525,8 @@ int32 lpt_updsta (int32 new)
|
|||
lpt_sta = (lpt_sta | new) & ~(STA_CLR | STA_ERR | STA_BUSY);
|
||||
if (lpt_sta & STA_EFLGS) lpt_sta = lpt_sta | STA_ERR; /* update errors */
|
||||
if (sim_is_active (&lpt_unit)) lpt_sta = lpt_sta | STA_BUSY;
|
||||
if (lpt_ie && (lpt_sta & STA_DON)) int_req = int_req | INT_LPT;
|
||||
else int_req = int_req & ~INT_LPT; /* update int */
|
||||
if (lpt_ie && (lpt_sta & STA_DON)) SET_INT (LPT);
|
||||
else CLR_INT (LPT); /* update int */
|
||||
return lpt_sta;
|
||||
}
|
||||
|
|
@ -26,6 +26,9 @@
|
|||
mt (PDP-9) TC59 magtape
|
||||
(PDP-15) TC59D magtape
|
||||
|
||||
29-Nov-01 RMS Added read only unit support
|
||||
25-Nov-01 RMS Revised interrupt structure
|
||||
Changed UST, POS, FLG to arrays
|
||||
26-Apr-01 RMS Added device enable/disable support
|
||||
15-Feb-01 RMS Fixed 3-cycle data break sequence
|
||||
04-Oct-98 RMS V2.4 magtape format
|
||||
|
@ -59,6 +62,7 @@
|
|||
#define DBMASK (DBSIZE - 1)
|
||||
#define MT_WC 032 /* word count */
|
||||
#define MT_CA 033 /* current addr */
|
||||
#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */
|
||||
|
||||
/* Command/unit - mt_cu */
|
||||
|
||||
|
@ -109,7 +113,7 @@
|
|||
/* error flags */
|
||||
|
||||
extern int32 M[];
|
||||
extern int32 int_req, dev_enb;
|
||||
extern int32 int_hwre[API_HLVL+1], dev_enb;
|
||||
extern UNIT cpu_unit;
|
||||
int32 mt_cu = 0; /* command/unit */
|
||||
int32 mt_sta = 0; /* status register */
|
||||
|
@ -131,55 +135,28 @@ UNIT *mt_busy (void);
|
|||
*/
|
||||
|
||||
UNIT mt_unit[] = {
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) } };
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) } };
|
||||
|
||||
REG mt_reg[] = {
|
||||
{ ORDATA (STA, mt_sta, 18) },
|
||||
{ ORDATA (CMD, mt_cu, 18) },
|
||||
{ ORDATA (WC, M[MT_WC], 18) },
|
||||
{ ORDATA (CA, M[MT_CA], 18) },
|
||||
{ FLDATA (INT, int_req, INT_V_MTA) },
|
||||
{ FLDATA (INT, int_hwre[API_MTA], INT_V_MTA) },
|
||||
{ FLDATA (STOP_IOE, mt_stopioe, 0) },
|
||||
{ DRDATA (TIME, mt_time, 24), PV_LEFT },
|
||||
{ ORDATA (UST0, mt_unit[0].USTAT, 18) },
|
||||
{ ORDATA (UST1, mt_unit[1].USTAT, 18) },
|
||||
{ ORDATA (UST2, mt_unit[2].USTAT, 18) },
|
||||
{ ORDATA (UST3, mt_unit[3].USTAT, 18) },
|
||||
{ ORDATA (UST4, mt_unit[4].USTAT, 18) },
|
||||
{ ORDATA (UST5, mt_unit[5].USTAT, 18) },
|
||||
{ ORDATA (UST6, mt_unit[6].USTAT, 18) },
|
||||
{ ORDATA (UST7, mt_unit[7].USTAT, 18) },
|
||||
{ DRDATA (POS0, mt_unit[0].pos, 31), PV_LEFT + REG_RO },
|
||||
{ DRDATA (POS1, mt_unit[1].pos, 31), PV_LEFT + REG_RO },
|
||||
{ DRDATA (POS2, mt_unit[2].pos, 31), PV_LEFT + REG_RO },
|
||||
{ DRDATA (POS3, mt_unit[3].pos, 31), PV_LEFT + REG_RO },
|
||||
{ DRDATA (POS4, mt_unit[4].pos, 31), PV_LEFT + REG_RO },
|
||||
{ DRDATA (POS5, mt_unit[5].pos, 31), PV_LEFT + REG_RO },
|
||||
{ DRDATA (POS6, mt_unit[6].pos, 31), PV_LEFT + REG_RO },
|
||||
{ DRDATA (POS7, mt_unit[7].pos, 31), PV_LEFT + REG_RO },
|
||||
{ GRDATA (FLG0, mt_unit[0].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ GRDATA (FLG1, mt_unit[1].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ GRDATA (FLG2, mt_unit[2].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ GRDATA (FLG3, mt_unit[3].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ GRDATA (FLG4, mt_unit[4].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ GRDATA (FLG5, mt_unit[5].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ GRDATA (FLG6, mt_unit[6].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ GRDATA (FLG7, mt_unit[7].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ URDATA (UST, mt_unit[0].USTAT, 8, 16, 0, MT_NUMDR, 0) },
|
||||
{ URDATA (POS, mt_unit[0].pos, 10, 31, 0,
|
||||
MT_NUMDR, PV_LEFT | REG_RO) },
|
||||
{ URDATA (FLG, mt_unit[0].flags, 8, UNIT_W_UF, UNIT_V_UF - 1,
|
||||
MT_NUMDR, REG_HRO) },
|
||||
{ FLDATA (*DEVENB, dev_enb, INT_V_MTA), REG_HRO },
|
||||
{ NULL } };
|
||||
|
||||
|
@ -220,7 +197,7 @@ if (pulse == 004) { /* MTGO */
|
|||
f = GET_CMD (mt_cu); /* get function */
|
||||
if (mt_busy () || (sim_is_active (uptr)) ||
|
||||
(((f == FN_SPACER) || (f == FN_REWIND)) & (uptr -> pos == 0)) ||
|
||||
(((f == FN_WRITE) || (f == FN_WREOF)) && (uptr -> flags & UNIT_WLK))
|
||||
(((f == FN_WRITE) || (f == FN_WREOF)) && (uptr -> flags & UNIT_WPRT))
|
||||
|| ((uptr -> flags & UNIT_ATT) == 0) || (f == FN_NOP))
|
||||
mt_sta = mt_sta | STA_ILL; /* illegal op flag */
|
||||
else { if (f == FN_REWIND) uptr -> USTAT = STA_REW; /* rewind? */
|
||||
|
@ -259,7 +236,7 @@ if ((uptr -> flags & UNIT_ATT) == 0) { /* if not attached */
|
|||
return IORETURN (mt_stopioe, SCPE_UNATT); }
|
||||
|
||||
if ((f == FN_WRITE) || (f == FN_WREOF)) { /* write? */
|
||||
if (uptr -> flags & UNIT_WLK) { /* write locked? */
|
||||
if (uptr -> flags & UNIT_WPRT) { /* write locked? */
|
||||
mt_updcsta (uptr, STA_ILL); /* illegal operation */
|
||||
return SCPE_OK; }
|
||||
mt_cu = mt_cu & ~CU_ERASE; } /* clear erase flag */
|
||||
|
@ -404,8 +381,8 @@ mt_sta = (mt_sta & ~(STA_DYN | STA_ERR | STA_CLR)) |
|
|||
(uptr -> USTAT & STA_DYN) | new;
|
||||
if (mt_sta & STA_EFLGS) mt_sta = mt_sta | STA_ERR; /* error flag */
|
||||
if ((mt_sta & (STA_ERR | STA_DON)) && ((mt_cu & CU_IE) == 0))
|
||||
int_req = int_req | INT_MTA;
|
||||
else int_req = int_req & ~INT_MTA; /* int request */
|
||||
SET_INT (MTA);
|
||||
else CLR_INT (MTA); /* int request */
|
||||
return mt_sta;
|
||||
}
|
||||
|
|
@ -26,6 +26,8 @@
|
|||
rf (PDP-9) RF09/RF09
|
||||
(PDP-15) RF15/RS09
|
||||
|
||||
25-Nov-01 RMS Revised interrupt structure
|
||||
24-Nov-01 RMS Changed WLK to array
|
||||
26-Apr-01 RMS Added device enable/disable support
|
||||
15-Feb-01 RMS Fixed 3 cycle data break sequencing
|
||||
30-Nov-99 RMS Added non-zero requirement to rf_time
|
||||
|
@ -85,7 +87,7 @@
|
|||
#define RF_BUSY (sim_is_active (&rf_unit))
|
||||
|
||||
extern int32 M[];
|
||||
extern int32 int_req, dev_enb;
|
||||
extern int32 int_hwre[API_HLVL+1], dev_enb;
|
||||
extern UNIT cpu_unit;
|
||||
int32 rf_sta = 0; /* status register */
|
||||
int32 rf_da = 0; /* disk address */
|
||||
|
@ -115,15 +117,8 @@ REG rf_reg[] = {
|
|||
{ ORDATA (WC, M[RF_WC], 18) },
|
||||
{ ORDATA (CA, M[RF_CA], 18) },
|
||||
{ ORDATA (BUF, rf_dbuf, 18) },
|
||||
{ FLDATA (INT, int_req, INT_V_RF) },
|
||||
{ ORDATA (WLK0, rf_wlk[0], 16) },
|
||||
{ ORDATA (WLK1, rf_wlk[1], 16) },
|
||||
{ ORDATA (WLK2, rf_wlk[2], 16) },
|
||||
{ ORDATA (WLK3, rf_wlk[3], 16) },
|
||||
{ ORDATA (WLK4, rf_wlk[4], 16) },
|
||||
{ ORDATA (WLK5, rf_wlk[5], 16) },
|
||||
{ ORDATA (WLK6, rf_wlk[6], 16) },
|
||||
{ ORDATA (WLK7, rf_wlk[7], 16) },
|
||||
{ FLDATA (INT, int_hwre[API_RF], INT_V_RF) },
|
||||
{ BRDATA (WLK, rf_wlk, 8, 16, RF_NUMDK) },
|
||||
{ DRDATA (TIME, rf_time, 24), PV_LEFT + REG_NZ },
|
||||
{ FLDATA (BURST, rf_burst, 0) },
|
||||
{ FLDATA (STOP_IOE, rf_stopioe, 0) },
|
||||
|
@ -244,8 +239,8 @@ int32 rf_updsta (int32 new)
|
|||
rf_sta = (rf_sta | new) & ~(RFS_ERR | RFS_CLR);
|
||||
if (rf_sta & RFS_EFLGS) rf_sta = rf_sta | RFS_ERR;
|
||||
if ((rf_sta & (RFS_ERR | RFS_DON)) && (rf_sta & RFS_IE))
|
||||
int_req = int_req | INT_RF;
|
||||
else int_req = int_req & ~INT_RF;
|
||||
SET_INT (RF);
|
||||
else CLR_INT (RF);
|
||||
return rf_sta;
|
||||
}
|
||||
|
|
@ -25,6 +25,9 @@
|
|||
|
||||
rp RP15/RP02 disk pack
|
||||
|
||||
29-Nov-01 RMS Added read only unit support
|
||||
25-Nov-01 RMS Revised interrupt structure
|
||||
Changed FLG to array
|
||||
26-Apr-01 RMS Added device enable/disable support
|
||||
14-Apr-99 RMS Changed t_addr to unsigned
|
||||
29-Jun-96 RMS Added unit enable/disable support
|
||||
|
@ -43,9 +46,10 @@
|
|||
|
||||
/* Unit specific flags */
|
||||
|
||||
#define UNIT_V_HWLK (UNIT_V_UF + 0) /* hwre write lock */
|
||||
#define UNIT_V_WLK (UNIT_V_UF + 0) /* hwre write lock */
|
||||
#define UNIT_W_UF 2 /* user flags width */
|
||||
#define UNIT_HWLK (1u << UNIT_V_HWLK)
|
||||
#define UNIT_WLK (1u << UNIT_V_WLK)
|
||||
#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */
|
||||
|
||||
/* Parameters in the unit descriptor */
|
||||
|
||||
|
@ -124,7 +128,7 @@
|
|||
#define MAX(x,y) (((x) > (y))? (x): (y))
|
||||
|
||||
extern int32 M[];
|
||||
extern int32 int_req, dev_enb, nexm;
|
||||
extern int32 int_hwre[API_HLVL+1], dev_enb, nexm;
|
||||
extern UNIT cpu_unit;
|
||||
int32 rp_sta = 0; /* status A */
|
||||
int32 rp_stb = 0; /* status B */
|
||||
|
@ -165,33 +169,19 @@ REG rp_reg[] = {
|
|||
{ ORDATA (DA, rp_da, 18) },
|
||||
{ ORDATA (MA, rp_ma, 18) },
|
||||
{ ORDATA (WC, rp_wc, 18) },
|
||||
{ FLDATA (INT, int_req, INT_V_RP) },
|
||||
{ FLDATA (INT, int_hwre[API_RP], INT_V_RP) },
|
||||
{ FLDATA (BUSY, rp_busy, 0) },
|
||||
{ FLDATA (STOP_IOE, rp_stopioe, 0) },
|
||||
{ DRDATA (STIME, rp_swait, 24), PV_LEFT },
|
||||
{ DRDATA (RTIME, rp_rwait, 24), PV_LEFT },
|
||||
{ GRDATA (FLG0, rp_unit[0].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ GRDATA (FLG1, rp_unit[1].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ GRDATA (FLG2, rp_unit[2].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ GRDATA (FLG3, rp_unit[3].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ GRDATA (FLG4, rp_unit[4].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ GRDATA (FLG5, rp_unit[5].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ GRDATA (FLG6, rp_unit[6].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ GRDATA (FLG7, rp_unit[7].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
|
||||
REG_HRO },
|
||||
{ URDATA (FLG, rp_unit[0].flags, 8, UNIT_W_UF, UNIT_V_UF - 1,
|
||||
RP_NUMDR, REG_HRO) },
|
||||
{ FLDATA (*DEVENB, dev_enb, INT_V_RP), REG_HRO },
|
||||
{ NULL } };
|
||||
|
||||
MTAB rp_mod[] = {
|
||||
{ UNIT_HWLK, 0, "write enabled", "ENABLED", NULL },
|
||||
{ UNIT_HWLK, UNIT_HWLK, "write locked", "LOCKED", NULL },
|
||||
{ UNIT_WLK, 0, "write enabled", "ENABLED", NULL },
|
||||
{ UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL },
|
||||
{ 0 } };
|
||||
|
||||
DEVICE rp_dev = {
|
||||
|
@ -315,6 +305,10 @@ if ((uptr -> flags & UNIT_ATT) == 0) { /* not attached? */
|
|||
rp_updsta (STA_DON, STB_SUFU); /* done, unsafe */
|
||||
return IORETURN (rp_stopioe, SCPE_UNATT); }
|
||||
|
||||
if ((f == FN_WRITE) && (uptr -> flags & UNIT_WPRT)) { /* write locked? */
|
||||
rp_updsta (STA_DON | STA_WPE, 0); /* error */
|
||||
return SCPE_OK; }
|
||||
|
||||
if (GET_SECT (rp_da) >= RP_NUMSC) rp_updsta (STA_NXS, 0);
|
||||
if (GET_SURF (rp_da) >= RP_NUMSF) rp_updsta (STA_NXF, 0);
|
||||
if (GET_CYL (rp_da) >= RP_NUMCY) rp_updsta (STA_NXC, 0);
|
||||
|
@ -381,7 +375,7 @@ UNIT *uptr;
|
|||
uptr = rp_dev.units + GET_UNIT (rp_sta);
|
||||
rp_sta = (rp_sta & ~(STA_DYN | STA_ERR)) | newa;
|
||||
rp_stb = (rp_stb & ~STB_DYN) | newb;
|
||||
if (uptr -> flags & UNIT_HWLK) rp_sta = rp_sta | STA_SUWP;
|
||||
if (uptr -> flags & UNIT_WPRT) rp_sta = rp_sta | STA_SUWP;
|
||||
if ((uptr -> flags & UNIT_ATT) == 0) rp_stb = rp_stb | STB_SUFU | STB_SUNR;
|
||||
else if (sim_is_active (uptr)) {
|
||||
f = (uptr -> FUNC) & STA_M_FUNC;
|
||||
|
@ -390,8 +384,8 @@ else if (sim_is_active (uptr)) {
|
|||
else if (uptr -> CYL >= RP_NUMCY) rp_sta = rp_sta | STA_SUSI;
|
||||
if ((rp_sta & STA_EFLGS) || (rp_stb & STB_EFLGS)) rp_sta = rp_sta | STA_ERR;
|
||||
if (((rp_sta & (STA_ERR | STA_DON)) && (rp_sta & STA_IED)) ||
|
||||
((rp_stb & STB_ATTN) && (rp_sta & STA_IEA))) int_req = int_req | INT_RP;
|
||||
else int_req = int_req & ~INT_RP;
|
||||
((rp_stb & STB_ATTN) && (rp_sta & STA_IEA))) SET_INT (RP);
|
||||
else CLR_INT (RP);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -403,7 +397,7 @@ int32 i;
|
|||
UNIT *uptr;
|
||||
|
||||
rp_sta = rp_stb = rp_da = rp_wc = rp_ma = rp_busy = 0;
|
||||
int_req = int_req & ~INT_RP;
|
||||
CLR_INT (RP);
|
||||
for (i = 0; i < RP_NUMDR; i++) {
|
||||
uptr = rp_dev.units + i;
|
||||
sim_cancel (uptr);
|
|
@ -29,6 +29,8 @@
|
|||
tto teleprinter
|
||||
clk clock
|
||||
|
||||
29-Nov-01 RMS Added read only unit support
|
||||
25-Nov-01 RMS Revised interrupt structure
|
||||
17-Sep-01 RMS Removed multiconsole support
|
||||
07-Sep-01 RMS Added terminal multiplexor support
|
||||
17-Jul-01 RMS Moved function prototype
|
||||
|
@ -47,7 +49,7 @@
|
|||
#include <ctype.h>
|
||||
|
||||
extern int32 M[];
|
||||
extern int32 int_req, saved_PC;
|
||||
extern int32 int_hwre[API_HLVL+1], saved_PC;
|
||||
extern UNIT cpu_unit;
|
||||
int32 clk_state = 0;
|
||||
int32 ptr_err = 0, ptr_stopioe = 0, ptr_state = 0;
|
||||
|
@ -83,8 +85,8 @@ t_stat ptr_boot (int32 unitno);
|
|||
UNIT clk_unit = { UDATA (&clk_svc, 0, 0), 16000 };
|
||||
|
||||
REG clk_reg[] = {
|
||||
{ FLDATA (INT, int_req, INT_V_CLK) },
|
||||
{ FLDATA (DONE, int_req, INT_V_CLK) },
|
||||
{ FLDATA (INT, int_hwre[API_CLK], INT_V_CLK) },
|
||||
{ FLDATA (DONE, int_hwre[API_CLK], INT_V_CLK) },
|
||||
{ FLDATA (ENABLE, clk_state, 0) },
|
||||
{ DRDATA (TIME, clk_unit.wait, 24), REG_NZ + PV_LEFT },
|
||||
{ DRDATA (TPS, clk_tps, 8), REG_NZ + PV_LEFT },
|
||||
|
@ -104,12 +106,13 @@ DEVICE clk_dev = {
|
|||
*/
|
||||
|
||||
UNIT ptr_unit = {
|
||||
UDATA (&ptr_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_IN_WAIT };
|
||||
UDATA (&ptr_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0),
|
||||
SERIAL_IN_WAIT };
|
||||
|
||||
REG ptr_reg[] = {
|
||||
{ ORDATA (BUF, ptr_unit.buf, 18) },
|
||||
{ FLDATA (INT, int_req, INT_V_PTR) },
|
||||
{ FLDATA (DONE, int_req, INT_V_PTR) },
|
||||
{ FLDATA (INT, int_hwre[API_PTR], INT_V_PTR) },
|
||||
{ FLDATA (DONE, int_hwre[API_PTR], INT_V_PTR) },
|
||||
#if defined (IOS_PTRERR)
|
||||
{ FLDATA (ERR, ptr_err, 0) },
|
||||
#endif
|
||||
|
@ -137,8 +140,8 @@ UNIT ptp_unit = {
|
|||
|
||||
REG ptp_reg[] = {
|
||||
{ ORDATA (BUF, ptp_unit.buf, 8) },
|
||||
{ FLDATA (INT, int_req, INT_V_PTP) },
|
||||
{ FLDATA (DONE, int_req, INT_V_PTP) },
|
||||
{ FLDATA (INT, int_hwre[API_PTP], INT_V_PTP) },
|
||||
{ FLDATA (DONE, int_hwre[API_PTP], INT_V_PTP) },
|
||||
#if defined (IOS_PTPERR)
|
||||
{ FLDATA (ERR, ptp_err, 0) },
|
||||
#endif
|
||||
|
@ -205,8 +208,8 @@ UNIT tti_unit = { UDATA (&tti_svc, UNIT_UC+UNIT_HDX, 0), KBD_POLL_WAIT };
|
|||
|
||||
REG tti_reg[] = {
|
||||
{ ORDATA (BUF, tti_unit.buf, TTI_WIDTH) },
|
||||
{ FLDATA (INT, int_req, INT_V_TTI) },
|
||||
{ FLDATA (DONE, int_req, INT_V_TTI) },
|
||||
{ FLDATA (INT, int_hwre[API_TTI], INT_V_TTI) },
|
||||
{ FLDATA (DONE, int_hwre[API_TTI], INT_V_TTI) },
|
||||
#if defined (KSR28)
|
||||
{ ORDATA (TTI_STATE, tti_state, (TTI_WIDTH + 3)), REG_HRO },
|
||||
#else
|
||||
|
@ -264,8 +267,8 @@ UNIT tto_unit = { UDATA (&tto_svc, UNIT_UC, 0), SERIAL_OUT_WAIT };
|
|||
|
||||
REG tto_reg[] = {
|
||||
{ ORDATA (BUF, tto_unit.buf, TTO_WIDTH) },
|
||||
{ FLDATA (INT, int_req, INT_V_TTO) },
|
||||
{ FLDATA (DONE, int_req, INT_V_TTO) },
|
||||
{ FLDATA (INT, int_hwre[API_TTO], INT_V_TTO) },
|
||||
{ FLDATA (DONE, int_hwre[API_TTO], INT_V_TTO) },
|
||||
#if defined (KSR28)
|
||||
{ FLDATA (TTO_STATE, tto_state, 0), REG_HRO },
|
||||
#endif
|
||||
|
@ -291,10 +294,10 @@ DEVICE tto_dev = {
|
|||
int32 clk (int32 pulse, int32 AC)
|
||||
{
|
||||
if (pulse & 001) { /* CLSF */
|
||||
if (int_req & INT_CLK) AC = AC | IOT_SKP; }
|
||||
if (TST_INT (CLK)) AC = AC | IOT_SKP; }
|
||||
if (pulse & 004) { /* CLON/CLOF */
|
||||
if (pulse & 040) { /* CLON */
|
||||
int_req = int_req & ~INT_CLK; /* clear flag */
|
||||
CLR_INT (CLK); /* clear flag */
|
||||
clk_state = 1; /* clock on */
|
||||
if (!sim_is_active (&clk_unit)) /* already on? */
|
||||
sim_activate (&clk_unit, /* start, calibr */
|
||||
|
@ -311,7 +314,7 @@ int32 t;
|
|||
|
||||
if (clk_state) { /* clock on? */
|
||||
M[7] = (M[7] + 1) & 0777777; /* incr counter */
|
||||
if (M[7] == 0) int_req = int_req | INT_CLK; /* ovrflo? set flag */
|
||||
if (M[7] == 0) SET_INT (CLK); /* ovrflo? set flag */
|
||||
t = sim_rtc_calb (clk_tps); /* calibrate clock */
|
||||
sim_activate (&clk_unit, t); /* reactivate unit */
|
||||
tmxr_poll = t; } /* set mux poll */
|
||||
|
@ -322,7 +325,7 @@ return SCPE_OK;
|
|||
|
||||
t_stat clk_reset (DEVICE *dptr)
|
||||
{
|
||||
int_req = int_req & ~INT_CLK; /* clear flag */
|
||||
CLR_INT (CLK); /* clear flag */
|
||||
clk_state = 0; /* clock off */
|
||||
sim_cancel (&clk_unit); /* stop clock */
|
||||
tmxr_poll = clk_unit.wait; /* set mux poll */
|
||||
|
@ -333,18 +336,18 @@ return SCPE_OK;
|
|||
|
||||
int32 std_iors (void)
|
||||
{
|
||||
return ((int_req & INT_CLK)? IOS_CLK: 0) |
|
||||
((int_req & INT_PTR)? IOS_PTR: 0) |
|
||||
((int_req & INT_PTP)? IOS_PTP: 0) |
|
||||
((int_req & INT_TTI)? IOS_TTI: 0) |
|
||||
((int_req & INT_TTO)? IOS_TTO: 0) |
|
||||
return ((TST_INT (CLK)? IOS_CLK: 0) |
|
||||
(TST_INT (PTR)? IOS_PTR: 0) |
|
||||
(TST_INT (PTP)? IOS_PTP: 0) |
|
||||
(TST_INT (TTI)? IOS_TTI: 0) |
|
||||
(TST_INT (TTO)? IOS_TTO: 0) |
|
||||
#if defined (IOS_PTRERR)
|
||||
(ptr_err? IOS_PTRERR: 0) |
|
||||
#endif
|
||||
#if defined (IOS_PTPERR)
|
||||
(ptp_err? IOS_PTPERR: 0) |
|
||||
#endif
|
||||
(clk_state? IOS_CLKON: 0);
|
||||
(clk_state? IOS_CLKON: 0));
|
||||
}
|
||||
|
||||
/* Paper tape reader: IOT routine */
|
||||
|
@ -352,13 +355,13 @@ return ((int_req & INT_CLK)? IOS_CLK: 0) |
|
|||
int32 ptr (int32 pulse, int32 AC)
|
||||
{
|
||||
if (pulse & 001) { /* RSF */
|
||||
if (int_req & INT_PTR) AC = AC | IOT_SKP; }
|
||||
if (TST_INT (PTR)) AC = AC | IOT_SKP; }
|
||||
if (pulse & 002) { /* RRB, RCF */
|
||||
int_req = int_req & ~INT_PTR; /* clear done */
|
||||
CLR_INT (PTR); /* clear done */
|
||||
AC = AC | ptr_unit.buf; } /* return buffer */
|
||||
if (pulse & 004) { /* RSA, RSB */
|
||||
ptr_state = (pulse & 040)? 18: 0; /* set mode */
|
||||
int_req = int_req & ~INT_PTR; /* clear done */
|
||||
CLR_INT (PTR); /* clear done */
|
||||
ptr_unit.buf = 0; /* clear buffer */
|
||||
sim_activate (&ptr_unit, ptr_unit.wait); }
|
||||
return AC;
|
||||
|
@ -372,13 +375,13 @@ int32 temp;
|
|||
|
||||
if ((ptr_unit.flags & UNIT_ATT) == 0) { /* attached? */
|
||||
#if defined (IOS_PTRERR)
|
||||
int_req = int_req | INT_PTR; /* if err, set int */
|
||||
SET_INT (PTR); /* if err, set int */
|
||||
ptr_err = 1;
|
||||
#endif
|
||||
return IORETURN (ptr_stopioe, SCPE_UNATT); }
|
||||
if ((temp = getc (ptr_unit.fileref)) == EOF) { /* end of file? */
|
||||
#if defined (IOS_PTRERR)
|
||||
int_req = int_req | INT_PTR; /* if err, set done */
|
||||
SET_INT (PTR); /* if err, set done */
|
||||
ptr_err = 1;
|
||||
#endif
|
||||
if (feof (ptr_unit.fileref)) {
|
||||
|
@ -391,7 +394,7 @@ if (ptr_state == 0) ptr_unit.buf = temp & 0377; /* alpha */
|
|||
else if (temp & 0200) { /* binary */
|
||||
ptr_state = ptr_state - 6;
|
||||
ptr_unit.buf = ptr_unit.buf | ((temp & 077) << ptr_state); }
|
||||
if (ptr_state == 0) int_req = int_req | INT_PTR; /* if done, set flag */
|
||||
if (ptr_state == 0) SET_INT (PTR); /* if done, set flag */
|
||||
else sim_activate (&ptr_unit, ptr_unit.wait); /* else restart */
|
||||
ptr_unit.pos = ptr_unit.pos + 1;
|
||||
return SCPE_OK;
|
||||
|
@ -403,7 +406,7 @@ t_stat ptr_reset (DEVICE *dptr)
|
|||
{
|
||||
ptr_state = 0; /* clear state */
|
||||
ptr_unit.buf = 0;
|
||||
int_req = int_req & ~INT_PTR; /* clear flag */
|
||||
CLR_INT (PTR); /* clear flag */
|
||||
ptr_err = (ptr_unit.flags & UNIT_ATT)? 0: 1;
|
||||
sim_cancel (&ptr_unit); /* deactivate unit */
|
||||
return SCPE_OK;
|
||||
|
@ -605,10 +608,10 @@ return SCPE_ARG;
|
|||
int32 ptp (int32 pulse, int32 AC)
|
||||
{
|
||||
if (pulse & 001) { /* PSF */
|
||||
if (int_req & INT_PTP) AC = AC | IOT_SKP; }
|
||||
if (pulse & 002) int_req = int_req & ~INT_PTP; /* PCF */
|
||||
if (TST_INT (PTP)) AC = AC | IOT_SKP; }
|
||||
if (pulse & 002) CLR_INT (PTP); /* PCF */
|
||||
if (pulse & 004) { /* PSA, PSB, PLS */
|
||||
int_req = int_req & ~INT_PTP; /* clear flag */
|
||||
CLR_INT (PTP); /* clear flag */
|
||||
ptp_unit.buf = (pulse & 040)? /* load punch buf */
|
||||
(AC & 077) | 0200: AC & 0377; /* bin or alpha */
|
||||
sim_activate (&ptp_unit, ptp_unit.wait); } /* activate unit */
|
||||
|
@ -619,7 +622,7 @@ return AC;
|
|||
|
||||
t_stat ptp_svc (UNIT *uptr)
|
||||
{
|
||||
int_req = int_req | INT_PTP; /* set done flag */
|
||||
SET_INT (PTP); /* set done flag */
|
||||
if ((ptp_unit.flags & UNIT_ATT) == 0) { /* not attached? */
|
||||
ptp_err = 1; /* set error */
|
||||
return IORETURN (ptp_stopioe, SCPE_UNATT); }
|
||||
|
@ -637,7 +640,7 @@ return SCPE_OK;
|
|||
t_stat ptp_reset (DEVICE *dptr)
|
||||
{
|
||||
ptp_unit.buf = 0;
|
||||
int_req = int_req & ~INT_PTP; /* clear flag */
|
||||
CLR_INT (PTP); /* clear flag */
|
||||
ptp_err = (ptp_unit.flags & UNIT_ATT)? 0: 1;
|
||||
sim_cancel (&ptp_unit); /* deactivate unit */
|
||||
return SCPE_OK;
|
||||
|
@ -667,9 +670,9 @@ return detach_unit (uptr);
|
|||
int32 tti (int32 pulse, int32 AC)
|
||||
{
|
||||
if (pulse & 001) { /* KSF */
|
||||
if (int_req & INT_TTI) AC = AC | IOT_SKP; }
|
||||
if (TST_INT (TTI)) AC = AC | IOT_SKP; }
|
||||
if (pulse & 002) { /* KRB */
|
||||
int_req = int_req & ~INT_TTI; /* clear flag */
|
||||
CLR_INT (TTI); /* clear flag */
|
||||
AC = AC | tti_unit.buf & TTI_MASK; } /* return buffer */
|
||||
return AC;
|
||||
}
|
||||
|
@ -705,7 +708,7 @@ if ((tti_unit.flags & UNIT_HDX) &&
|
|||
tto_unit.pos = tto_unit.pos + 1; }
|
||||
tti_unit.buf = temp | 0200; /* got char */
|
||||
#endif
|
||||
int_req = int_req | INT_TTI; /* set flag */
|
||||
SET_INT (TTI); /* set flag */
|
||||
tti_unit.pos = tti_unit.pos + 1;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
@ -716,7 +719,7 @@ t_stat tti_reset (DEVICE *dptr)
|
|||
{
|
||||
tti_unit.buf = 0; /* clear buffer */
|
||||
tti_state = 0; /* clear state */
|
||||
int_req = int_req & ~INT_TTI; /* clear flag */
|
||||
CLR_INT (TTI); /* clear flag */
|
||||
sim_activate (&tti_unit, tti_unit.wait); /* activate unit */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
@ -726,8 +729,8 @@ return SCPE_OK;
|
|||
int32 tto (int32 pulse, int32 AC)
|
||||
{
|
||||
if (pulse & 001) { /* TSF */
|
||||
if (int_req & INT_TTO) AC = AC | IOT_SKP; }
|
||||
if (pulse & 002) int_req = int_req & ~INT_TTO; /* clear flag */
|
||||
if (TST_INT (TTO)) AC = AC | IOT_SKP; }
|
||||
if (pulse & 002) CLR_INT (TTO); /* clear flag */
|
||||
if (pulse & 004) { /* load buffer */
|
||||
sim_activate (&tto_unit, tto_unit.wait); /* activate unit */
|
||||
tto_unit.buf = AC & TTO_MASK; } /* load buffer */
|
||||
|
@ -740,7 +743,7 @@ t_stat tto_svc (UNIT *uptr)
|
|||
{
|
||||
int32 out, temp;
|
||||
|
||||
int_req = int_req | INT_TTO; /* set flag */
|
||||
SET_INT (TTO); /* set flag */
|
||||
#if defined (KSR28) /* Baudot... */
|
||||
if (tto_unit.buf == BAUDOT_FIGURES) { /* set figures? */
|
||||
tto_state = TTO_FIGURES;
|
||||
|
@ -766,7 +769,7 @@ t_stat tto_reset (DEVICE *dptr)
|
|||
{
|
||||
tto_unit.buf = 0; /* clear buffer */
|
||||
tto_state = 0; /* clear state */
|
||||
int_req = int_req & ~INT_TTO; /* clear flag */
|
||||
CLR_INT (TTO); /* clear flag */
|
||||
sim_cancel (&tto_unit); /* deactivate unit */
|
||||
return SCPE_OK;
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue