1
0
mirror of https://github.com/open-simh/simh.git synced 2026-01-25 19:57:36 +00:00

Notes For V3.0-1

RESTRICTION: The FP15 and XVM features of the PDP-15 are only partially
debugged.  Do NOT enable these features for normal operations.

1. New Features in 3.0-1

1.1 PDP-1

- Added block loader format support to LOAD.
- Changed BOOT PTR to allow loading of all of the first bank of memory.

1.2 PDP-18b Family

- Added PDP-4 EAE support.
- Added PDP-15 FP15 support.
- Added PDP-15 XVM support.
- Added PDP-15 "re-entrancy ECO".
- Added PDP-7, PDP-9, PDP-15 hardware RIM loader support in BOOT PTR.

2. Bugs Fixed in 3.0-1

2.1 PDP-11/VAX

- Fixed bug in user disk size (found by Chaskiel M Grundman).

2.2 PDP-1

- Updated CPU, line printer, standard devices to detect indefinite I/O wait.
- Fixed incorrect logical, missing activate, break in drum simulator.
- Fixed bugs in instruction decoding, overprinting for line printer.

2.3 PDP-10

- Fixed bug in RP read header.

2.4 PDP-18b Family

- Fixed bug in PDP-4 line printer overprinting.
- Fixed bug in PDP-15 memory protect/skip interaction.
- Fixed bug in RF set size routine.
- Increased PTP TIME for PDP-15 operating systems.

2.5 PDP-8

- Fixed bug in DF, RF set size routine.

2.6 Nova

- Fixed bug in DSK set size routine.

2.7 1401

- Revised fetch to model hardware more closely.

2.8 Ibm1130

- Fixed bugs found by APL 1130.

2.9 Altairz80

- Fixed bug in real-time clock on Windows host.

2.10 HP2100

-- Fixed DR drum sizes.
-- Fixed DR variable capacity interaction with SAVE/RESTORE.

3. New Features in 3.0 vs prior releases

3.1 SCP and Libraries

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

3.2 All magtapes

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

3.3 VAX

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

4. Bugs Fixed in 3.0 vs prior releases

4.1 VAX

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

4.2 1401

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

4.3 Nova

- Fixed DSK variable size interaction with restore.

4.4 PDP-1

- Fixed DT variable size interaction with restore.

4.5 PDP-11

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

4.6 PDP-18B

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

4.7 PDP-8

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

4.8 HP2100

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

4.9 GRI

- Fixed bug in SC queue pointer management.
This commit is contained in:
Bob Supnik
2003-07-31 16:17:00 -07:00
committed by Mark Pizzolato
parent 4ffd3be790
commit f9564b81b9
74 changed files with 6938 additions and 2812 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -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.
18-Jul-03 RMS Added FP15 support
Added XVM support
Added EAE option for PDP-4
25-Apr-03 RMS Revised for extended file support
04-Feb-03 RMS Added RB09, LP09 support
22-Nov-02 RMS Added PDP-4 drum support
@@ -48,7 +51,7 @@
model memory CPU options I/O options
PDP4 8K ??Type 18 EAE Type 65 KSR-28 Teletype (Baudot)
PDP4 8K Type 18 EAE Type 65 KSR-28 Teletype (Baudot)
integral paper tape reader
Type 75 paper tape punch
integral real time clock
@@ -79,19 +82,19 @@
KA15 auto pri intr PC15 paper tape reader and punch
KF15 power detection KW15 real time clock
KM15 mem protection LP09 line printer
??KT15 mem relocation LP15 line printer
RP15 disk pack
RF15/RF09 fixed head disk
KT15 mem relocation LP15 line printer
FP15 floating point RP15 disk pack
XVM option RF15/RF09 fixed head disk
TC59D magnetic tape
TC15/TU56 DECtape
LT15 second Teletype
??Indicates not implemented. The PDP-4 manual refers to both an EAE
??and a memory extension control; there is no documentation on either.
??Indicates not implemented. The PDP-4 manual refers to a memory
??extension control; there is no documentation on it.
*/
#if !defined (PDP4) && !defined (PDP7) && !defined (PDP9) && !defined (PDP15)
#define PDP9 0 /* default to PDP-9 */
#define PDP15 0 /* default to PDP-15 */
#endif
/* Simulator stop codes */
@@ -102,6 +105,7 @@
#define STOP_XCT 4 /* nested XCT's */
#define STOP_API 5 /* invalid API int */
#define STOP_NONSTD 6 /* non-std dev num */
#define STOP_MME 7 /* mem mgt error */
/* Peripheral configuration */
@@ -136,17 +140,49 @@
#define TC02 0 /* DECtape */
#define TTY1 0 /* second Teletype */
#define BRMASK 0377400 /* bounds mask */
#define BRMASK_XVM 0777400 /* bounds mask, XVM */
#endif
/* Memory */
#define ADDRMASK ((1 << ADDRSIZE) - 1) /* address mask */
#define AMASK ((1 << ADDRSIZE) - 1) /* address mask */
#define IAMASK 077777 /* ind address mask */
#define BLKMASK (ADDRMASK & (~IAMASK)) /* block mask */
#define BLKMASK (AMASK & (~IAMASK)) /* block mask */
#define MAXMEMSIZE (1 << ADDRSIZE) /* max memory size */
#define MEMSIZE (cpu_unit.capac) /* actual memory size */
#define MEM_ADDR_OK(x) (((uint32) (x)) < MEMSIZE)
/* Instructions */
#define I_V_OP 14 /* opcode */
#define I_M_OP 017
#define I_V_IND 13 /* indirect */
#define I_V_IDX 12 /* index */
#define I_IND (1 << I_V_IND)
#define I_IDX (1 << I_V_IDX)
#define B_DAMASK 017777 /* bank mode address */
#define B_EPCMASK (AMASK & ~B_DAMASK)
#define P_DAMASK 007777 /* page mode address */
#define P_EPCMASK (AMASK & ~P_DAMASK)
/* Memory cycles */
#define FE 0
#define DF 1
#define RD 2
#define WR 3
/* Memory status codes */
#define MM_OK 0
#define MM_ERR 1
/* Memory management relocation checks (PDP-15 KT15 and XVM only) */
#define REL_C -1 /* console */
#define REL_R 0 /* read */
#define REL_W 1 /* write */
/* Architectural constants */
#define DMASK 0777777 /* data mask */
@@ -165,6 +201,39 @@
#define IOT_REASON (1 << IOT_V_REASON)
#define IORETURN(f,v) ((f)? (v): SCPE_OK) /* stop on error */
/* PC change queue */
#define PCQ_SIZE 64 /* must be 2**n */
#define PCQ_MASK (PCQ_SIZE - 1)
#define PCQ_ENTRY pcq[pcq_p = (pcq_p - 1) & PCQ_MASK] = PC
/* XVM memory management registers */
#define MM_RDIS 0400000 /* reloc disabled */
#define MM_V_GM 15 /* G mode */
#define MM_M_GM 03
#define MM_GM (MM_M_GM << MM_V_GM)
#define MM_G_W0 0077777 /* virt addr width */
#define MM_G_W1 0177777
#define MM_G_W2 0777777
#define MM_G_W3 0377777
#define MM_G_B0 0060000 /* SAS base */
#define MM_G_B1 0160000
#define MM_G_B2 0760000
#define MM_G_B3 0360000
#define MM_UIOT 0040000 /* user mode IOT's */
#define MM_WP 0020000 /* share write prot */
#define MM_SH 0010000 /* share enabled */
#define MM_V_SLR 10 /* segment length reg */
#define MM_M_SLR 03
#define MM_SLR_L0 001000 /* SAS length */
#define MM_SLR_L1 002000
#define MM_SLR_L2 010000
#define MM_SLR_L3 020000
#define MM_SBR_MASK 01777 /* share base reg */
#define MM_GETGM(x) (((x) >> MM_V_GM) & MM_M_GM)
#define MM_GETSLR(x) (((x) >> MM_V_SLR) & MM_M_SLR)
/* Device information block */
@@ -239,6 +308,15 @@ typedef struct pdp18b_dib DIB;
37 -
*/
#define API_ML0 0200 /* API masks: level 0 */
#define API_ML1 0100
#define API_ML2 0040
#define API_ML3 0020
#define API_ML4 0010
#define API_ML5 0004
#define API_ML6 0002
#define API_ML7 0001 /* level 7 */
#define API_HLVL 4 /* hwre levels */
#define ACH_SWRE 040 /* swre int vec */

View File

@@ -1,7 +1,7 @@
To: Users
From: Bob Supnik
Subj: 18b PDP Simulator Usage
Date: 01-Feb-2003
Date: 25-Jul-2003
COPYRIGHT NOTICE
@@ -44,29 +44,33 @@ PDP-7/ PDP7
PDP-9/ PDP9
PDP-15/ PDP15
If no model is specified, the default is the PDP-9.
If no model is specified, the default is the PDP-15.
sim/ sim_defs.h
sim_rev.h
sim_sock.h
sim_tmxr.h
scp.c
scp_tty.c
sim_sock.c
sim_tmxr.c
PDP-4 PDP-7 PDP-9 PDP-15
sim/ sim_defs.h x x x x
sim_rev.h x x x x
sim_sock.h x x x x
sim_tape.h x x
sim_tmxr.h x x x x
scp.c x x x x
scp_tty.c x x x x
sim_sock.c x x x x
sim_tape.c x x
sim_tmxr.c x x x x
sim/pdp18b/ pdp18b_defs.h
pdp18b_cpu.c
pdp18b_drm.c
pdp18b_dt.c
pdp18b_lp.c
pdp18b_mt.c
pdp18b_rb.c
pdp18b_rf.c
pdp18b_rp.c
pdp18b_stddev.c
pdp18b_sys.c
pdp18b_tt1.c
sim/pdp18b/ pdp18b_defs.h x x x x
pdp18b_cpu.c x x x x
pdp18b_drm.c x x
pdp18b_dt.c x x x x
pdp18b_fpp.c x
pdp18b_lp.c x x x x
pdp18b_mt.c x x
pdp18b_rb.c x
pdp18b_rf.c x x
pdp18b_rp.c x
pdp18b_stddev.c x x x x
pdp18b_sys.c x x x x
pdp18b_tt1.c x x
2. 18b PDP Features
@@ -77,6 +81,7 @@ system device simulates
name(s)
PDP-4 CPU PDP-4 CPU with 8KW of memory
- Type 18 extended arithmetic element (EAE)
PTR,PTP integral paper tape/Type 75 punch
TTI,TTO KSR28 console terminal (Baudot code)
LPT Type 62 line printer (Hollerith code)
@@ -116,6 +121,9 @@ PDP-15 CPU PDP-15 CPU with 32KW of memory
- KA15 automatic priority interrupt (API)
- KF15 power detection
- KM15 memory protection
- KT15 memory relocation and protection
- XVM memory relocation and protection
FPP FP15 floating point processor
PTR,PTP PC15 paper tape reader/punch
TTI,TTO KSR 35 console terminal
TTI1,TTO1 LT15 second console terminal
@@ -145,36 +153,58 @@ The 18b PDP simulators implement several unique stop conditions:
- 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. RIM loading requires
that the loading address be specified on the command line.
The PDP-4 and PDP-7 LOAD command supports only "second stage" RIM format
files (alternating DAC address instructions and data):
LOAD file load PDP-4/PDP-7 RIM format file
The PDP-9 and PDP-15 LOAD commands upports hardware RIM format (data only),
PDP-4/PDP-7 RIM loader format (for compatability with Macro7), and BIN
loader format:
LOAD -S file load PDP-4/PDP-7 RIM format file
LOAD -R file address load PDP-9/PDP-15 RIM format
file starting at address
LOAD file.RIM address assume file is PDP-9/PDP-15
RIM format
LOAD -B file load PDP-9/PDP-15 BIN format file
LOAD file.BIN assume file is PDP-9/PDP-15
BIN format
If no address is given for a RIM format load, a starting address of 200
(octal) is assumed. If no switch is specified, and the file extension is
neither RIM nor BIN, the file format is assumed to be BIN.
2.1 CPU
The CPU options are the presence of the EAE, the presense of the API (for
the PDP-9 and PDP-15), and the size of main memory.
The CPU options are the presence of the EAE, the presense of the API and
memory protection (for the PDP-9 and PDP-15), the presense of relocation
or XVM (PDP-15 only), and the size of main memory.
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
system option comment
all SET CPU EAE enable EAE
all SET CPU NOEAE disable EAE
9,15 SET CPU API enable API
9,15 SET CPU NOAPI disable API
9,15 SET CPU PROT enable memory protection
15 SET CPU RELOC enable memory relocation
15 SET CPU XVM enable XVM relocation
9,15 SET CPU NOPROT disable protection, relocation, XVM
4 SET CPU 4K set memory size = 4K
all SET CPU 8K set memory size = 8K
all SET CPU 12K set memory size = 12K
all SET CPU 16K set memory size = 16K
all SET CPU 20K set memory size = 20K
all SET CPU 24K set memory size = 24K
all SET CPU 28K set memory size = 28K
all SET CPU 32K set memory size = 32K
15 SET CPU 48K set memory size = 48K
15 SET CPU 64K set memory size = 64K
15 SET CPU 80K set memory size = 80K
15 SET CPU 96K set memory size = 96K
15 SET CPU 112K set memory size = 112K
15 SET CPU 128K set memory size = 128K
Memory sizes greater than 8K are only available on the PDP-7, PDP-9, and
PDP-15; memory sizes greater than 32KW are only available on the PDP-15.
@@ -183,6 +213,12 @@ non-zero data, the simulator asks for confirmation. Data in the truncated
portion of memory is lost. Initial memory size is 8K for the PDP-4, 32K
for the PDP-7 and PDP-9, and 128K for the PDP-15.
The PROT option corresponds to the KX09A on the PDP-9 and the KM15 for the
PDP-15. The PROT option is required to run the Foreground/Background
Monitor. The RELOC option corresponds to the KT15 on the PDP-15, and the
XVM option corresponds to the XM15 on the PDP-15. ADSS-15, ADSS-15 Foreground/
Background, and standard DOS-15 will <not> run if these options are enabled.
CPU registers include the visible state of the processor as well as the
control registers for the interrupt system.
@@ -191,10 +227,11 @@ control registers for the interrupt system.
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 MQ 18 multiplier-quotient
all SC 6 shift counter
all EAE_AC_SIGN 1 EAE AC sign
all SR 18 front panel switches
all ASW addr address switches for RIM load
all INT[0:4] 32 interrupt requests,
0:3 = API levels 0-3
4 = PI level
@@ -204,12 +241,15 @@ control registers for the interrupt system.
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
9,15 BR 18 memory protection bounds
15 XR 18 index register
15 LR 18 limit register
15 BR 17 memory protection bounds
9,15 BR 18 memory protection bounds
15 RR 18 memory protection relocation
15 MMR 18 memory protection control
9,15 USMD 1 user mode
9,15 USMDBUF 1 user mode buffer
9,15 USMDDEF 1 user mode load defer
9,15 NEXM 1 non-existent memory violation
9,15 PRVN 1 privilege violation
7,9 EXTM 1 extend mode
@@ -229,18 +269,49 @@ control registers for the interrupt system.
"addr" signifies the address width of the system (13b for the PDP-4, 15b for
the PDP-7 and PDP-9, 17b for the PDP-15).
2.2 Programmed I/O Devices
2.2 Floating Point Processor (FPP)
2.2.1 Paper Tape Reader (PTR)
The PDP-15 features an optional floating point processor, the FP15 (FPP).
The FPP can be enabled and disabled; by default it is disabled.
The FPP implements these registers:
name size comments
FIR 12 floating instruction register
EPA 18 EPA (A exponent)
FMAS 1 FMA sign
FMAH 17 FMA<1:17>
FMAL 18 FMA<18:35>
EPB 18 EPB (B exponent)
FMBS 1 FMB sign
FMBH 17 FMB<1:17>
FMBL 18 FMB<18:35>
FGUARD 1 guard bit
FMQH 17 FMQ<1:17>
FMQL 18 FMQ<18:35>
JEA 18 exception address register
2.3 Programmed I/O Devices
2.3.1 Paper Tape Reader (PTR)
The paper tape reader (PTR) reads data from a disk file. The POS
register specifies the number of the next data item to be read. Thus,
by changing POS, the user can backspace or advance the reader.
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 supports the BOOT command. The specific forms
recognized vary from system to system:
BOOT PTR PDP-4, PDP-7: load RIM loader and start it running
BOOT -F PTR PDP-4, PDP-7: load funny format loader and start
it running
BOOT -H PTR PDP-7: start hardware RIM load at address given
by address switches (ASW)
BOOT {-H} PTR PDP-9, PDP-15: start hardware RIM load at addrss
given by address switches (ASW)
The PDP-4 did not have a hardware read-in mode load capability.
The PTR ATTACH command recognizes one switch, -A for ASCII mode. In
ASCII mode, data returned by the read alphabetic command has even parity.
@@ -270,7 +341,7 @@ Error handling is as follows:
OS I/O error x report error and stop
2.2.2 Paper Tape Punch (PTP)
2.3.2 Paper Tape Punch (PTP)
The paper tape punch (PTP) writes data to a disk file. The POS
register specifies the number of the next data item to be written.
@@ -302,7 +373,7 @@ Error handling is as follows:
OS I/O error x report error and stop
2.2.3 Terminal Input (TTI)
2.3.3 Terminal Input (TTI)
On the PDP-7, PDP-9, and PDP-15, the terminal interfaces (TTI, TTO)
can be set to one of three modes: KSR, 7B, or 8B. In KSR mode, lower
@@ -333,7 +404,7 @@ to simulate typing ^C:
SET TTI CTRL-C
2.2.4 Terminal Output (TTO)
2.3.4 Terminal Output (TTO)
The terminal output (TTO) writes to the simulator console window. It
implements these registers:
@@ -346,7 +417,7 @@ implements these registers:
POS 32 number of chararacters output
TIME 24 time from I/O initiation to interrupt
2.2.5 Line Printers (LPT, LP9)
2.3.5 Line Printers (LPT, LP9)
The line printers (LPT, LP9) write data to a disk file. The POS
register specifies the number of the next data item to be written.
@@ -423,7 +494,7 @@ For all printers, error handling is as follows:
OS I/O error x report error and stop
2.2.6 Real-Time Clock (CLK)
2.3.6 Real-Time Clock (CLK)
The real-time clock (CLK) frequency can be adjusted as follows:
@@ -444,7 +515,7 @@ The clock implements these registers:
The real-time clock autocalibrates; the clock interval is adjusted up or
down so that the clock tracks actual elapsed time.
2.2.7 Second Terminal (TTI1, TTO1)
2.3.7 Second Terminal (TTI1, TTO1)
The second terminal consists of two independent devices, TTI1 and TTO1.
The second terminal performs input and output through a Telnet session
@@ -491,7 +562,7 @@ The second terminal output implements these registers:
DONE 1 device done flag
TIME 24 time from I/O initiation to interrupt
2.3 RP15/RP02 Disk Pack (RP)
2.4 RP15/RP02 Disk Pack (RP)
RP15 options include the ability to make units write enabled or write locked:
@@ -526,7 +597,7 @@ Error handling is as follows:
OS I/O error x report error and stop
2.4 Type 24 Serial Drum (DRM)
2.5 Type 24 Serial Drum (DRM)
The serial drum (DRM) implements these registers:
@@ -551,7 +622,7 @@ Error handling is as follows:
Drum data files are buffered in memory; therefore, end of file and OS
I/O errors cannot occur.
2.5 RB09 Fixed Head Disk (RB)
2.6 RB09 Fixed Head Disk (RB)
The RB09 was an early fixed-head disk for the PDP-9. It was superceded
by the RF09/RS09. It is disabled by default.
@@ -585,7 +656,7 @@ Error handling is as follows:
RB09 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)
2.7 RF09/RF15/RS09 Fixed Head Disk (RF)
RF09/RF15 options include the ability to set the number of platters
to a fixed value between 1 and 8, or to autosize the number of platters
@@ -632,7 +703,7 @@ Error handling is as follows:
RF15/RF09 data files are buffered in memory; therefore, end of file and OS
I/O errors cannot occur.
2.6 Type 550/555, TC02/TU55, and TC15/TU56 DECtape (DT)
2.8 Type 550/555, TC02/TU55, and TC15/TU56 DECtape (DT)
The PDP-4 and PDP-7 use the Type 550 DECtape, a programmed I/O controller.
The PDP-9 uses the TC02, and the PDP-15 uses the TC15. The TC02 and TC15
@@ -693,7 +764,7 @@ operate correctly.
- ACTIME must be less than DCTIME, and both need to be at
least 100 times LTIME
2.7 TC59/TU10 Magnetic Tape (MT)
2.9 TC59/TU10 Magnetic Tape (MT)
Magnetic tape options include the ability to make units write enabled or
or write locked.
@@ -727,7 +798,7 @@ Error handling is as follows:
OS I/O error parity error; if STOP_IOE, stop
2.8 Symbolic Display and Input
2.10 Symbolic Display and Input
The 18b PDP simulators implement symbolic display and input. Display is
controlled by command line switches:
@@ -754,15 +825,18 @@ 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 input uses standard 18b PDP assembler syntax. There are eight
instruction classes: memory reference, EAE, index (PDP-15 only), IOT,
operate, and LAW.
operate, LAW, FP15 memory reference (PDP-15 only), and FP15 no operand
(PDP-15 only).
Memory reference instructions have the format
memref {I/@} address{,X}
PDP-4, PDP-7: memref {I} address
PDP-9: memref{*} address
PDP-15: memref{*} address{,X}
where I (PDP-4, PDP-7, PDP-9) /@ (PDP-15) signifies indirect reference,
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).
@@ -805,13 +879,27 @@ Operate instructions have the format
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
The LAW instruction has the format
LAW immediate
where immediate is in the range of 0 to 017777.
2.9 Character Sets
FP15 memory reference instructions occupy two successive words and have
the format
fpmem{*} address
where * signifies indirect addressing. The address is a number in the range
0 - 0377777.
FP15 no operand instructions occupy two successive words and have the format
fpop
The second word is ignored on output and set to 0 on input.
2.11 Character Sets
The PDP-4's console was an ASR-28 Teletype; its character encoding was
Baudot. The PDP-4's line printer used a modified Hollerith character

View File

@@ -221,10 +221,10 @@ static const int32 boot_rom[] = {
t_stat drm_boot (int32 unitno, DEVICE *dptr)
{
int32 i;
extern int32 saved_PC;
extern int32 PC;
if (drm_dib.dev != DEV_DRM) return STOP_NONSTD; /* non-std addr? */
for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i];
saved_PC = BOOT_START;
PC = BOOT_START;
return SCPE_OK;
}

View File

@@ -327,8 +327,8 @@ static const int32 map_unit[16] = { /* Type 550 unit map */
0, -1, -1, -1, -1, -1, -1, -1 };
DEVICE dt_dev;
int32 dt75 (int32 pulse, int32 AC);
int32 dt76 (int32 pulse, int32 AC);
int32 dt75 (int32 pulse, int32 dat);
int32 dt76 (int32 pulse, int32 dat);
int32 dt_iors (void);
t_stat dt_svc (UNIT *uptr);
t_stat dt_reset (DEVICE *dptr);
@@ -423,18 +423,18 @@ DEVICE dt_dev = {
/* IOT routines */
#if defined (TC02) /* TC02/TC15 */
int32 dt75 (int32 pulse, int32 AC)
int32 dt75 (int32 pulse, int32 dat)
{
int32 old_dtsa = dtsa, fnc;
UNIT *uptr;
if (((pulse & 060) == 040) && (pulse & 05)) { /* select */
if (pulse & 01) dtsa = 0; /* DTCA */
if (pulse & 02) AC = dtsa; /* DTRA!... */
if (pulse & 02) dat = dtsa; /* DTRA!... */
if (pulse & 04) { /* DTXA */
if ((AC & DTA_CERF) == 0) dtsb = dtsb & ~DTB_ALLERR;
if ((AC & DTA_CDTF) == 0) dtsb = dtsb & ~DTB_DTF;
dtsa = dtsa ^ (AC & DTA_RW); }
if ((dat & DTA_CERF) == 0) dtsb = dtsb & ~DTB_ALLERR;
if ((dat & DTA_CDTF) == 0) dtsb = dtsb & ~DTB_DTF;
dtsa = dtsa ^ (dat & DTA_RW); }
if ((old_dtsa ^ dtsa) & DTA_UNIT) dt_deselect (old_dtsa);
uptr = dt_dev.units + DTA_GETUNIT (dtsa); /* get unit */
fnc = DTA_GETFNC (dtsa); /* get fnc */
@@ -445,41 +445,41 @@ if (((pulse & 060) == 040) && (pulse & 05)) { /* select */
dt_seterr (uptr, DTB_SEL); /* select err */
else dt_newsa (dtsa); /* new func */
DT_UPDINT;
return AC; }
return dat; }
if ((pulse & 067) == 042) return dtsa; /* DTRA */
if ((pulse & 067) == 061) /* DTEF */
return ((dtsb & DTB_ERF)? IOT_SKP + AC: AC);
return ((dtsb & DTB_ERF)? IOT_SKP + dat: dat);
if ((pulse & 067) == 062) return dtsb; /* DTRB */
if ((pulse & 067) == 063) /* DTEF!DTRB */
return ((dtsb & DTB_ERF)? IOT_SKP + dtsb: dtsb);
return AC;
return dat;
}
int32 dt76 (int32 pulse, int32 AC)
int32 dt76 (int32 pulse, int32 dat)
{
if ((pulse & 01) && (dtsb & DTB_DTF)) /* DTDF */
return IOT_SKP + AC;
return AC;
return IOT_SKP + dat;
return dat;
}
#else /* Type 550 */
int32 dt75 (int32 pulse, int32 AC)
int32 dt75 (int32 pulse, int32 dat)
{
if (((pulse & 041) == 001) && (dtsb & DTB_DTF)) /* MMDF */
AC = AC | IOT_SKP;
dat = dat | IOT_SKP;
else if (((pulse & 041) == 041) && (dtsb & DTB_ERF)) /* MMEF */
AC = AC | IOT_SKP;
dat = dat | IOT_SKP;
if (pulse & 002) { /* MMRD */
AC = (AC & ~DMASK) | dtdb;
dat = (dat & ~DMASK) | dtdb;
dtsb = dtsb & ~(DTB_DTF | DTB_BEF); }
if (pulse & 004) { /* MMWR */
dtdb = AC & DMASK;
dtdb = dat & DMASK;
dtsb = dtsb & ~(DTB_DTF | DTB_BEF); }
DT_UPDINT;
return AC;
return dat;
}
int32 dt76 (int32 pulse, int32 AC)
int32 dt76 (int32 pulse, int32 dat)
{
int32 fnc, mot, unum;
UNIT *uptr = NULL;
@@ -487,7 +487,7 @@ UNIT *uptr = NULL;
unum = DTA_GETUNIT (dtsa); /* get unit no */
if (unum >= 0) uptr = dt_dev.units + unum; /* get unit */
if ((pulse & 001) && (dtsb & DTB_BEF)) /* MMBF */
AC = AC | IOT_SKP;
dat = dat | IOT_SKP;
if (pulse & 002) { /* MMRS */
dtsb = dtsb & ~(DTB_REV | DTB_GO); /* clr rev, go */
if (uptr) { /* valid unit? */
@@ -495,13 +495,13 @@ if (pulse & 002) { /* MMRS */
if (mot & DTS_DIR) dtsb = dtsb | DTB_REV; /* rev? set */
if ((mot >= DTS_ACCF) || (uptr->STATE & 0777700))
dtsb = dtsb | DTB_GO; } /* accel? go */
AC = (AC & ~DMASK) | dtsb; }
dat = (dat & ~DMASK) | dtsb; }
if ((pulse & 044) == 044) { /* MMSE */
if ((dtsa ^ AC) & DTA_UNIT) dt_deselect (dtsa); /* new unit? */
dtsa = (dtsa & ~DTA_UNIT) | (AC & DTA_UNIT);
if ((dtsa ^ dat) & DTA_UNIT) dt_deselect (dtsa); /* new unit? */
dtsa = (dtsa & ~DTA_UNIT) | (dat & DTA_UNIT);
dtsb = dtsb & ~(DTB_DTF | DTB_BEF | DTB_ERF | DTB_ALLERR); }
else if ((pulse & 044) == 004) { /* MMLC */
dtsa = (dtsa & ~DTA_RW) | (AC & DTA_RW); /* load dtsa */
dtsa = (dtsa & ~DTA_RW) | (dat & DTA_RW); /* load dtsa */
dtsb = dtsb & ~(DTB_DTF | DTB_BEF | DTB_ERF | DTB_ALLERR);
fnc = DTA_GETFNC (dtsa); /* get fnc */
if ((uptr == NULL) || /* invalid? */
@@ -512,7 +512,7 @@ else if ((pulse & 044) == 004) { /* MMLC */
dt_seterr (uptr, DTB_SEL); /* select err */
else dt_newsa (dtsa); }
DT_UPDINT;
return AC;
return dat;
}
#endif
@@ -836,7 +836,7 @@ case FNC_SRCH: /* search */
return SCPE_OK; }
sim_activate (uptr, DTU_LPERB (uptr) * dt_ltime);/* sched next block */
M[DT_WC] = (M[DT_WC] + 1) & DMASK; /* inc WC */
ma = M[DT_CA] & ADDRMASK; /* get mem addr */
ma = M[DT_CA] & AMASK; /* get mem addr */
if (MEM_ADDR_OK (ma)) M[ma] = blk; /* store block # */
if (((dtsa & DTA_MODE) == 0) || (M[DT_WC] == 0))
dtsb = dtsb | DTB_DTF; /* set DTF */
@@ -870,7 +870,7 @@ case FNC_READ: /* read */
case 0: /* normal read */
M[DT_WC] = (M[DT_WC] + 1) & DMASK; /* incr WC, CA */
M[DT_CA] = (M[DT_CA] + 1) & DMASK;
ma = M[DT_CA] & ADDRMASK; /* mem addr */
ma = M[DT_CA] & AMASK; /* mem addr */
ba = (blk * DTU_BSIZE (uptr)) + wrd; /* buffer ptr */
dtdb = bptr[ba]; /* get tape word */
if (dir) dtdb = dt_comobv (dtdb); /* rev? comp obv */
@@ -920,7 +920,7 @@ case FNC_WRIT: /* write */
M[DT_WC] = (M[DT_WC] + 1) & DMASK; /* incr WC, CA */
M[DT_CA] = (M[DT_CA] + 1) & DMASK;
case DTO_WCO: /* wc ovflo */
ma = M[DT_CA] & ADDRMASK; /* mem addr */
ma = M[DT_CA] & AMASK; /* mem addr */
ba = (blk * DTU_BSIZE (uptr)) + wrd; /* buffer ptr */
dtdb = dt_substate? 0: M[ma]; /* get word */
if (dir) dtdb = dt_comobv (dtdb); /* rev? comp obv */
@@ -955,7 +955,7 @@ case FNC_RALL:
relpos = DT_LIN2OF (uptr->pos, uptr); /* cur pos in blk */
M[DT_WC] = (M[DT_WC] + 1) & DMASK; /* incr WC, CA */
M[DT_CA] = (M[DT_CA] + 1) & DMASK;
ma = M[DT_CA] & ADDRMASK; /* mem addr */
ma = M[DT_CA] & AMASK; /* mem addr */
if ((relpos >= DT_HTLIN) && /* in data zone? */
(relpos < (DTU_LPERB (uptr) - DT_HTLIN))) {
wrd = DT_LIN2WD (uptr->pos, uptr);
@@ -989,7 +989,7 @@ case FNC_WALL:
relpos = DT_LIN2OF (uptr->pos, uptr); /* cur pos in blk */
M[DT_WC] = (M[DT_WC] + 1) & DMASK; /* incr WC, CA */
M[DT_CA] = (M[DT_CA] + 1) & DMASK;
ma = M[DT_CA] & ADDRMASK; /* mem addr */
ma = M[DT_CA] & AMASK; /* mem addr */
if ((relpos >= DT_HTLIN) && /* in data zone? */
(relpos < (DTU_LPERB (uptr) - DT_HTLIN))) {
dtdb = M[ma]; /* get mem word */
@@ -1122,7 +1122,7 @@ return;
int32 dt_comobv (int32 dat)
{
dat = dat ^ 0777777; /* compl obverse */
dat = dat ^ DMASK; /* compl obverse */
dat = ((dat >> 15) & 07) | ((dat >> 9) & 070) |
((dat >> 3) & 0700) | ((dat & 0700) << 3) |
((dat & 070) << 9) | ((dat & 07) << 15);
@@ -1140,16 +1140,16 @@ int32 i, csum, wrd;
#if defined (TC02) /* TC02/TC15 */
csum = 077; /* init csum */
for (i = 0; i < DTU_BSIZE (uptr); i++) { /* loop thru buf */
wrd = bptr[ba + i] ^ 0777777; /* get ~word */
wrd = bptr[ba + i] ^ DMASK; /* get ~word */
csum = csum ^ (wrd >> 12) ^ (wrd >> 6) ^ wrd; }
return (csum & 077);
#else /* Type 550 */
csum = 0777777;
csum = DMASK;
for (i = 0; i < DTU_BSIZE (uptr); i++) { /* loop thru buf */
wrd = bptr[ba + i]; /* get word */
csum = csum + wrd; /* 1's comp add */
if (csum > 0777777) csum = (csum + 1) & 0777777; }
return (csum ^ 0777777); /* 1's comp res */
if (csum > DMASK) csum = (csum + 1) & DMASK; }
return (csum ^ DMASK); /* 1's comp res */
#endif
}
@@ -1164,7 +1164,7 @@ if (wrd == DT_BLKWD) return blk; /* fwd blknum */
if (wrd == (2 * DT_HTWRD + DTU_BSIZE (uptr) - DT_CSMWD - 1)) /* fwd csum */
return (dt_csum (uptr, blk) << 12);
#else
if (wrd == DT_CSMWD) return 0777777; /* rev csum */
if (wrd == DT_CSMWD) return DMASK; /* rev csum */
if (wrd == (2 * DT_HTWRD + DTU_BSIZE (uptr) - DT_CSMWD - 1)) /* fwd csum */
return (dt_csum (uptr, blk));
#endif /* Type 550 */

774
PDP18B/pdp18b_fpp.c Normal file
View File

@@ -0,0 +1,774 @@
/* pdp18b_fpp.c: FP15 floating point processor simulator
Copyright (c) 2003, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of Robert M Supnik shall not
be used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
fpp PDP-15 floating point processor
The FP15 instruction format is:
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| 1 1 1 0 0 1| subop | microcoded modifiers | floating point
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|in| address |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
Indirection is always single level.
The FP15 supports four data formats:
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| S| 2's complement integer | A: integer
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| S| 2's complement integer (high) | A: extended integer
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| 2's complement integer (low) | A+1
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| fraction (low) |SE|2's complement exponent| A: single floating
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|SF| fraction (high) | A+1
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|SE| 2's complement exponent | A: double floating
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|SF| fraction (high) | A+1
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| fraction (low) | A+2
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
*/
#include "pdp18b_defs.h"
/* Instruction */
#define FI_V_OP 8 /* subopcode */
#define FI_M_OP 017
#define FI_GETOP(x) (((x) >> FI_V_OP) & FI_M_OP)
#define FI_NOLOAD 0200 /* don't load */
#define FI_DP 0100 /* single/double */
#define FI_FP 0040 /* int/flt point */
#define FI_NONORM 0020 /* don't normalize */
#define FI_NORND 0010 /* don't round */
#define FI_V_SGNOP 0 /* A sign change */
#define FI_M_SGNOP 03
#define FI_GETSGNOP(x) (((x) >> FI_V_SGNOP) & FI_M_SGNOP)
/* Exception register */
#define JEA_V_SIGN 17 /* A sign */
#define JEA_V_GUARD 16 /* guard */
#define JEA_EAMASK 077777 /* exc address */
#define JEA_OFF_OVF 0 /* ovf offset */
#define JEA_OFF_UNF 2 /* unf offset */
#define JEA_OFF_DIV 4 /* div offset */
#define JEA_OFF_MM 6 /* mem mgt offset */
/* Status codes - must relate directly to JEA offsets */
#define FP_OK 0 /* no error - mbz */
#define FP_OVF (JEA_OFF_OVF + 1) /* overflow */
#define FP_UNF (JEA_OFF_UNF + 1) /* underflow */
#define FP_DIV (JEA_OFF_DIV + 1) /* divide exception */
#define FP_MM (JEA_OFF_MM + 1) /* mem mgt error */
/* Unpacked floating point fraction */
#define UFP_FH_CARRY 0400000 /* carry out */
#define UFP_FH_NORM 0200000 /* normalized */
#define UFP_FH_MASK 0377777 /* hi mask */
#define UFP_FL_MASK 0777777 /* low mask */
#define UFP_FL_SMASK 0777000 /* low mask, single */
#define UFP_FL_SRND 0000400 /* round bit, single */
#define GET_SIGN(x) (((x) >> 17) & 1)
#define SEXT18(x) (((x) & SIGN)? ((x) | ~DMASK): ((x) & DMASK))
#define SEXT9(x) (((x) & 0400)? ((x) | ~0377): ((x) & 0377))
enum fop {
FOP_TST, FOP_SUB, FOP_RSUB, FOP_MUL,
FOP_DIV, FOP_RDIV, FOP_LD, FOP_ST,
FOP_FLT, FOP_FIX, FOP_LFMQ, FOP_JEA,
FOP_ADD, FOP_BR, FOP_DIAG, FOP_UND };
struct ufp {
int32 exp; /* exponent */
int32 sign; /* sign */
int32 hi; /* hi frac, 17b */
int32 lo; }; /* lo frac, 18b */
typedef struct ufp UFP;
static int32 fir; /* instruction */
static int32 jea; /* exc address */
static int32 fguard; /* guard bit */
static UFP fma; /* FMA */
static UFP fmb; /* FMB */
static UFP fmq; /* FMQ - hi,lo only */
extern int32 M[MAXMEMSIZE];
extern int32 pcq[PCQ_SIZE];
extern int32 pcq_p;
extern int32 PC;
extern int32 trap_pending, usmd;
t_stat fp15_reset (DEVICE *dptr);
t_stat fp15_opnd (int32 ir, int32 addr, UFP *a);
t_stat fp15_store (int32 ir, int32 addr, UFP *a);
t_stat fp15_iadd (int32 ir, UFP *a, UFP *b, t_bool sub);
t_stat fp15_imul (int32 ir, UFP *a, UFP *b);
t_stat fp15_idiv (int32 ir, UFP *a, UFP *b);
t_stat fp15_fadd (int32 ir, UFP *a, UFP *b, t_bool sub);
t_stat fp15_fmul (int32 ir, UFP *a, UFP *b);
t_stat fp15_fdiv (int32 ir, UFP *a, UFP *b);
t_stat fp15_fix (int32 ir, UFP *a);
t_stat fp15_norm (int32 ir, UFP *a, UFP *b, t_bool rnd);
t_stat fp15_exc (int32 sta);
void fp15_asign (int32 ir, UFP *a);
void dp_add (UFP *a, UFP *b);
void dp_sub (UFP *a, UFP *b);
void dp_inc (UFP *a);
int32 dp_cmp (UFP *a, UFP *b);
void dp_mul (UFP *a, UFP *b);
void dp_lsh_1 (UFP *a, UFP *b);
void dp_rsh_1 (UFP *a, UFP *b);
void dp_dnrm_r (int32 ir, UFP *a, int32 sc);
void dp_swap (UFP *a, UFP *b);
extern t_stat Read (int32 ma, int32 *dat, int32 cyc);
extern t_stat Write (int32 ma, int32 dat, int32 cyc);
extern t_stat Ia (int32 ma, int32 *ea, t_bool jmp);
extern int32 Incr_addr (int32 addr);
extern int32 Jms_word (int32 t);
/* FPP data structures
fpp_dev FPP device descriptor
fpp_unit FPP unit
fpp_reg FPP register list
fpp_mod FPP modifier list
*/
UNIT fpp_unit = { UDATA (NULL, 0, 0) };
REG fpp_reg[] = {
{ ORDATA (FIR, fir, 12) },
{ ORDATA (EPA, fma.exp, 18) },
{ FLDATA (FMAS, fma.sign, 0) },
{ ORDATA (FMAH, fma.hi, 17) },
{ ORDATA (FMAL, fma.lo, 18) },
{ ORDATA (EPB, fmb.exp, 18) },
{ FLDATA (FMBS, fmb.sign, 0) },
{ ORDATA (FMBH, fmb.hi, 17) },
{ ORDATA (FMBL, fmb.lo, 18) },
{ FLDATA (FGUARD, fguard, 0) },
{ ORDATA (FMQH, fmq.hi, 17) },
{ ORDATA (FMQL, fmq.lo, 18) },
{ ORDATA (JEA, jea, 18) },
{ NULL } };
DEVICE fpp_dev = {
"FPP", &fpp_unit, fpp_reg, NULL,
1, 8, 1, 1, 8, 18,
NULL, NULL, &fp15_reset,
NULL, NULL, NULL,
NULL, DEV_DISABLE | DEV_DIS };
/* Instruction decode for FP15
The CPU actually fetches the instruction and the word after. If the
instruction is 71XXXX, the CPU executes it as a NOP, and the FP15 fools
the CPU into thinking that the second word is also a NOP.
Indirect addresses are resolved during fetch, unless the NOLOAD modifier
is set and the instruction is not a store. */
t_stat fp15 (int32 ir)
{
int32 ar, ma, fop, dat;
t_stat sta = FP_OK;
if (fpp_dev.flags & DEV_DIS) return MM_OK; /* disabled? */
fir = ir & 07777; /* save subop + mods */
ma = PC; /* fetch next word */
PC = Incr_addr (PC);
if (Read (ma, &ar, RD)) return fp15_exc (FP_MM); /* error? MM exc */
fop = FI_GETOP (fir); /* get subopcode */
if ((ar & SIGN) && /* indirect? */
((fop == FOP_ST) || !(ir & FI_NOLOAD))) { /* store or load? */
ma = ar & AMASK; /* fetch indirect */
if (Read (ma, &ar, RD)) return fp15_exc (FP_MM); }
fma.exp = SEXT18 (fma.exp); /* sext exponents */
fmb.exp = SEXT18 (fmb.exp);
switch (fop) { /* case on subop */
case FOP_TST: /* NOP */
break;
case FOP_SUB: /* subtract */
if (sta = fp15_opnd (fir, ar, &fmb)) break; /* fetch op to FMB */
if (fir & FI_FP) sta = fp15_fadd (fir, &fma, &fmb, 1); /* fp? */
else sta = fp15_iadd (fir, &fma, &fmb, 1); /* no, int sub */
break;
case FOP_RSUB: /* reverse sub */
fmb = fma; /* FMB <- FMA */
if (sta = fp15_opnd (fir, ar, &fma)) break; /* fetch op to FMA */
if (fir & FI_FP) sta = fp15_fadd (fir, &fma, &fmb, 1); /* fp? */
else sta = fp15_iadd (fir, &fma, &fmb, 1); /* no, int sub */
break;
case FOP_MUL: /* multiply */
if (sta = fp15_opnd (fir, ar, &fmb)) break; /* fetch op to FMB */
if (fir & FI_FP) sta = fp15_fmul (fir, &fma, &fmb); /* fp? */
else sta = fp15_imul (fir, &fma, &fmb); /* no, int mul */
break;
case FOP_DIV: /* divide */
if (sta = fp15_opnd (fir, ar, &fmb)) break; /* fetch op to FMB */
if (fir & FI_FP) sta = fp15_fdiv (fir, &fma, &fmb); /* fp? */
else sta = fp15_idiv (fir, &fma, &fmb); /* no, int div */
break;
case FOP_RDIV: /* reverse divide */
fmb = fma; /* FMB <- FMA */
if (sta = fp15_opnd (fir, ar, &fma)) break; /* fetch op to FMA */
if (fir & FI_FP) sta = fp15_fdiv (fir, &fma, &fmb); /* fp? */
else sta = fp15_idiv (fir, &fma, &fmb); /* no, int div */
break;
case FOP_LD: /* load */
if (sta = fp15_opnd (fir, ar, &fma)) break; /* fetch op to FMA */
fp15_asign (fir, &fma); /* modify A sign */
if (fir & FI_FP) /* fp? */
sta = fp15_norm (ir, &fma, NULL, 0); /* normalize */
break;
case FOP_ST: /* store */
fp15_asign (fir, &fma); /* modify A sign */
sta = fp15_store (fir, ar, &fma); /* store result */
break;
case FOP_FLT: /* float */
if (sta = fp15_opnd (fir, ar, &fma)) break; /* fetch op to FMA */
fma.exp = 35;
fp15_asign (fir, &fma); /* adjust A sign */
sta = fp15_norm (ir, &fma, NULL, 0); /* normalize */
break;
case FOP_FIX: /* fix */
if (sta = fp15_opnd (fir, ar, &fma)) break; /* fetch op to FMA */
sta = fp15_fix (fir, &fma); /* fix */
break;
case FOP_LFMQ: /* load FMQ */
if (sta = fp15_opnd (fir, ar, &fma)) break; /* fetch op to FMA */
dp_swap (&fma, &fmq); /* swap FMA, FMQ */
fp15_asign (fir, &fma); /* adjust A sign */
if (fir & FI_FP) /* fp? norm, no rnd */
sta = fp15_norm (ir | FI_NORND, &fma, &fmq, 0);
break;
case FOP_JEA: /* JEA */
if (ir & 0200) { /* store? */
dat = jea | (fma.sign << JEA_V_SIGN) | (fguard << JEA_V_GUARD);
sta = Write (ar, dat, WR); }
else { /* no, load */
if (sta = Read (ar, &dat, RD)) break;
fguard = (dat >> JEA_V_GUARD) & 1;
jea = dat; }
break;
case FOP_ADD: /* add */
if (sta = fp15_opnd (fir, ar, &fmb)) break; /* fetch op to FMB */
if (fir & FI_FP) sta = fp15_fadd (fir, &fma, &fmb, 0); /* fp? */
else sta = fp15_iadd (fir, &fma, &fmb, 0); /* no, int add */
break;
case FOP_BR: /* branch */
if (((fir & 001) && ((fma.hi | fma.lo) == 0)) ||
((fir & 002) && fma.sign) ||
((fir & 004) && !fma.sign) ||
((fir & 010) && ((fma.hi | fma.lo) != 0)) ||
((fir & 020) && fguard)) { /* cond met? */
PCQ_ENTRY; /* save current PC */
PC = (PC & BLKMASK) | (ar & IAMASK); } /* branch within 32K */
break;
default:
break; }
fma.exp = fma.exp & DMASK; /* mask exp to 18b */
fmb.exp = fmb.exp & DMASK;
if (sta != FP_OK) return fp15_exc (sta); /* error? */
return MM_OK;
}
/* Operand load and store */
t_stat fp15_opnd (int32 ir, int32 addr, UFP *fpn)
{
int32 i, numwd, wd[3];
fguard = 0; /* clear guard */
if (ir & FI_NOLOAD) return FP_OK; /* no load? */
if (ir & FI_FP) numwd = 2; /* fp? at least 2 */
else numwd = 1; /* else at least 1 */
if (ir & FI_DP) numwd = numwd + 1; /* dp? 1 more */
for (i = 0; i < numwd; i++) { /* fetch words */
if (Read (addr, &wd[i], RD)) return FP_MM;
addr = (addr + 1) & AMASK; }
if (ir & FI_FP) { /* fp? */
fpn->sign = GET_SIGN (wd[1]); /* frac sign */
fpn->hi = wd[1] & UFP_FH_MASK; /* frac high */
if (ir & FI_DP) { /* dp? */
fpn->exp = SEXT18 (wd[0]); /* exponent */
fpn->lo = wd[2]; } /* frac low */
else { /* sp */
fpn->exp = SEXT9 (wd[0]); /* exponent */
fpn->lo = wd[0] & UFP_FL_SMASK; } /* frac low */
}
else { fpn->sign = GET_SIGN (wd[0]); /* int, get sign */
if (ir & FI_DP) { /* dp? */
fpn->lo = wd[1]; /* 2 words */
fpn->hi = wd[0]; }
else { /* single */
fpn->lo = wd[0]; /* 1 word */
fpn->hi = fpn->sign? DMASK: 0; } /* sign extended */
if (fpn->sign) { /* negative? */
fpn->lo = (-fpn->lo) & UFP_FL_MASK; /* take abs val */
fpn->hi = (~fpn->hi + (fpn->lo == 0)) & UFP_FH_MASK; }
}
return FP_OK;
}
t_stat fp15_store (int32 ir, int32 addr, UFP *a)
{
int32 i, numwd, wd[3];
t_stat sta;
fguard = 0; /* clear guard */
if (ir & FI_FP) { /* fp? */
if (sta = fp15_norm (ir, a, NULL, 0)) return sta; /* normalize */
wd[1] = (a->sign << 17) | a->hi; /* hi frac */
if (ir & FI_DP) { /* dp? */
numwd = 3; /* 3 words */
wd[0] = a->exp & DMASK; /* exponent */
wd[2] = a->lo; } /* low frac */
else { /* single */
if (!(ir & FI_NORND) && (a->lo & UFP_FL_SRND)) { /* round? */
a->lo = (a->lo + UFP_FL_SRND) & UFP_FL_SMASK;
a->hi = (a->hi + (a->lo == 0)) & UFP_FH_MASK;
if ((a->hi | a->lo) == 0) { /* carry out? */
a->hi = UFP_FH_NORM; /* shift back */
a->exp = a->exp + 1; } }
if (a->exp > 0377) return FP_OVF; /* sp ovf? */
if (a->exp < -0400) return FP_UNF; /* sp unf? */
numwd = 2; /* 2 words */
wd[0] = (a->exp & 0777) | a->lo; } /* low frac'exp */
}
else { fmb.lo = (-a->lo) & UFP_FL_MASK; /* 2's complement */
fmb.hi = (~a->hi + (fmb.lo == 0)) & UFP_FH_MASK;/* to FMB */
if (ir & FI_DP) { /* dp? */
numwd = 2; /* 2 words */
if (a->sign) { /* negative? */
wd[0] = fmb.hi | SIGN; /* store FMB */
wd[1] = fmb.lo; }
else { /* pos, store FMA */
wd[0] = a->hi;
wd[1] = a->lo; } }
else { /* single */
if (a->hi || (a->lo & SIGN)) return FP_OVF; /* check int ovf */
numwd = 1; /* 1 word */
if (a->sign) wd[0] = fmb.lo; /* neg? store FMB */
else wd[0] = a->lo; } /* pos, store FMA */
}
for (i = 0; i < numwd; i++) { /* store words */
if (Write (addr, wd[i], WR)) return FP_MM;
addr = (addr + 1) & AMASK; }
return FP_OK;
}
/* Integer arithmetic routines */
/* Integer add - overflow only on add, if carry out of high fraction */
t_stat fp15_iadd (int32 ir, UFP *a, UFP *b, t_bool sub)
{
fmq.hi = fmq.lo = 0; /* clear FMQ */
if (a->sign ^ b->sign ^ sub) dp_sub (a, b); /* eff subtract? */
else { dp_add (a, b); /* no, add */
if (a->hi & UFP_FH_CARRY) { /* carry out? */
a->hi = a->hi & UFP_FH_MASK; /* mask to 35b */
return FP_OVF; } } /* overflow */
fp15_asign (ir, a); /* adjust A sign */
return FP_OK;
}
/* Integer multiply - overflow if high result (FMQ after swap) non-zero */
t_stat fp15_imul (int32 ir, UFP *a, UFP *b)
{
a->sign = a->sign ^ b->sign; /* sign of result */
dp_mul (a, b); /* a'FMQ <- a * b */
dp_swap (a, &fmq); /* swap a, FMQ */
if (fmq.hi | fmq.lo) return FP_OVF; /* FMQ != 0? ovf */
fp15_asign (ir, a); /* adjust A sign */
return FP_OK;
}
/* Integer divide - actually done as fraction divide
- If divisor zero, error
- If dividend zero, done
- Normalize dividend and divisor together
- If divisor normalized but dividend not, result is zero
- If divisor not normalized, normalize and count shifts
- Do fraction divide for number of shifts, +1, steps
Note that dp_lsh_1 returns a 72b result; the last right shift
guarantees a 71b remainder. The quotient cannot exceed 71b */
t_stat fp15_idiv (int32 ir, UFP *a, UFP *b)
{
int32 i, sc;
a->sign = a->sign ^ b->sign; /* sign of result */
fmq.hi = fmq.lo = 0; /* clear quotient */
a->exp = 0; /* clear a exp */
if ((b->hi | b->lo) == 0) return FP_DIV; /* div by 0? */
if ((a->hi | a->lo) == 0) return FP_OK; /* div into 0? */
while (((a->hi & UFP_FH_NORM) == 0) && /* normalize divd */
((b->hi & UFP_FH_NORM) == 0)) { /* and divr */
dp_lsh_1 (a, NULL); /* lsh divd, divr */
dp_lsh_1 (b, NULL); } /* can't carry out */
if (!(a->hi & UFP_FH_NORM) && (b->hi & UFP_FH_NORM)) { /* divr norm, divd not? */
a->hi = a->lo = 0; /* result is 0 */
return FP_OK; }
while ((b->hi & UFP_FH_NORM) == 0) { /* normalize divr */
dp_lsh_1 (b, NULL); /* can't carry out */
a->exp = a->exp + 1; } /* count steps */
sc = a->exp;
for (i = 0; i <= sc; i++) { /* n+1 steps */
dp_lsh_1 (&fmq, NULL); /* left shift quo */
if (dp_cmp (a, b) >= 0) { /* sub work? */
dp_sub (a, b); /* a -= b */
if (i == 0) a->exp = a->exp + 1; /* first step? */
fmq.lo = fmq.lo | 1; } /* set quo bit */
dp_lsh_1 (a, NULL); } /* left shift divd */
dp_rsh_1 (a, NULL); /* shift back */
dp_swap (a, &fmq); /* swap a, FMQ */
fp15_asign (ir, a); /* adjust A sign */
return FP_OK;
}
/* Floating point arithmetic routines */
/* Floating add
- Special add case, overflow if carry out increments exp out of range
- All cases, overflow/underflow detected in normalize */
t_stat fp15_fadd (int32 ir, UFP *a, UFP *b, t_bool sub)
{
int32 ediff;
fmq.hi = fmq.lo = 0; /* clear FMQ */
ediff = a->exp - b->exp; /* exp diff */
if (((a->hi | a->lo) == 0) || (ediff < -35)) { /* a = 0 or "small"? */
*a = *b; /* rslt is b */
a->sign = a->sign ^ sub; } /* or -b if sub */
else if (((b->hi | b->lo) != 0) && (ediff <= 35)) { /* b!=0 && ~"small"? */
if (ediff > 0) dp_dnrm_r (ir, b, ediff); /* |a| > |b|? dnorm b */
else if (ediff < 0) { /* |a| < |b|? */
a->exp = b->exp; /* b exp is rslt */
dp_dnrm_r (ir, a, -ediff); } /* denorm A */
if (a->sign ^ b->sign ^ sub) dp_sub (a, b); /* eff sub? */
else { /* eff add */
dp_add (a, b); /* add */
if (a->hi & UFP_FH_CARRY) { /* carry out? */
fguard = a->lo & 1; /* set guard */
dp_rsh_1 (a, NULL); /* right shift */
a->exp = a->exp + 1; /* incr exponent */
if (!(ir & FI_NORND) && fguard) /* rounding? */
dp_inc (a);
if (a->exp > 0377777) return FP_OVF; } }
} /* end if b != 0 */
fp15_asign (ir, a); /* adjust A sign */
return fp15_norm (ir, a, NULL, 0); /* normalize */
}
/* Floating multiply - overflow/underflow detected in normalize */
t_stat fp15_fmul (int32 ir, UFP *a, UFP *b)
{
a->sign = a->sign ^ b->sign; /* sign of result */
a->exp = a->exp + b->exp; /* exp of result */
dp_mul (a, b); /* mul fractions */
fp15_asign (ir, a); /* adjust A sign */
return fp15_norm (ir, a, &fmq, 1); /* norm and round */
}
/* Floating divide - overflow/underflow detected in normalize */
t_stat fp15_fdiv (int32 ir, UFP *a, UFP *b)
{
int32 i;
a->sign = a->sign ^ b->sign; /* sign of result */
a->exp = a->exp - b->exp; /* exp of result */
fmq.hi = fmq.lo = 0; /* clear quotient */
if (!(b->hi & UFP_FH_NORM)) return FP_DIV; /* divr not norm? */
if (a->hi | a->lo) { /* divd non-zero? */
fp15_norm (0, a, NULL, 0); /* normalize divd */
for (i = 0; (fmq.hi & UFP_FH_NORM) == 0; i++) { /* until quo */
dp_lsh_1 (&fmq, NULL); /* left shift quo */
if (dp_cmp (a, b) >= 0) { /* sub work? */
dp_sub (a, b); /* a -= b */
if (i == 0) a->exp = a->exp + 1;
fmq.lo = fmq.lo | 1; } /* set quo bit */
dp_lsh_1 (a, NULL); } /* left shift divd */
dp_rsh_1 (a, NULL); /* shift back */
dp_swap (a, &fmq); } /* swap a, FMQ */
fp15_asign (ir, a); /* adjust A sign */
return fp15_norm (ir, a, &fmq, 1); /* norm and round */
}
/* Floating to integer - overflow only if exponent out of range */
t_stat fp15_fix (int32 ir, UFP *a)
{
int32 i;
fmq.hi = fmq.lo = 0; /* clear FMQ */
if (a->exp > 35) return FP_OVF; /* exp > 35? ovf */
if (a->exp < 0) a->hi = a->lo = 0; /* exp <0 ? rslt 0 */
else { for (i = a->exp; i < 35; i++) /* denorm frac */
dp_rsh_1 (a, &fmq);
if (fmq.hi & UFP_FH_NORM) { /* last out = 1? */
fguard = 1; /* set guard */
if (!(ir & FI_NORND)) dp_inc (a); } } /* round */
fp15_asign (ir, a); /* adjust A sign */
return FP_OK;
}
/* Double precision routines */
/* Double precision add - returns 72b result (including carry) */
void dp_add (UFP *a, UFP *b)
{
int32 a_hi_orig = a->hi;
a->lo = (a->lo + b->lo) & UFP_FL_MASK; /* add low */
a->hi = a->hi + b->hi + (a->lo < b->lo); /* add hi + carry */
return;
}
/* Double precision increment - returns 72b result (including carry) */
void dp_inc (UFP *a)
{
a->lo = (a->lo + 1) & UFP_FL_MASK; /* inc low */
a->hi = a->hi + (a->lo == 0); /* propagate carry */
return;
}
/* Double precision subtract - result always fits in 71b */
void dp_sub (UFP *a, UFP *b)
{
if (dp_cmp (a,b) >= 0) { /* |a| >= |b|? */
a->hi = (a->hi - b->hi - (a->lo < b->lo)) & UFP_FH_MASK;
a->lo = (a->lo - b->lo) & UFP_FL_MASK; } /* a - b */
else { a->hi = (b->hi - a->hi - (b->lo < a->lo)) & UFP_FH_MASK;
a->lo = (b->lo - a->lo) & UFP_FL_MASK; /* b - a */
a->sign = a->sign ^ 1; } /* change a sign */
return;
}
/* Double precision compare - returns +1 (>), 0 (=), -1 (<) */
int32 dp_cmp (UFP *a, UFP *b)
{
if (a->hi < b->hi) return -1;
if (a->hi > b->hi) return +1;
if (a->lo < b->lo) return -1;
if (a->lo > b->lo) return +1;
return 0;
}
/* Double precision multiply - returns 70b result */
void dp_mul (UFP *a, UFP *b)
{
int32 i;
fmq.hi = a->hi; /* FMQ <- a */
fmq.lo = a->lo;
a->hi = a->lo = 0; /* a <- 0 */
if (((fmq.hi | fmq.lo) == 0) || ((b->hi | b->lo) == 0)) return;
for (i = 0; i < 35; i++) { /* 35 iterations */
if (fmq.lo & 1) dp_add (a, b); /* FMQ<35>? a += b */
dp_rsh_1 (a, &fmq); } /* rsh a'FMQ */
return;
}
/* Double (quad) precision left shift - returns 72b (143b) result */
void dp_lsh_1 (UFP *a, UFP *b)
{
int32 t = b? b->lo: 0;
a->hi = (a->hi << 1) | (a->lo >> 17);
a->lo = ((a->lo << 1) | (t >> 16)) & UFP_FL_MASK;
if (b) {
b->hi = ((b->hi << 1) | (b->lo >> 17)) & UFP_FH_MASK;
b->lo = (b->lo << 1) & UFP_FL_MASK; }
return;
}
/* Double (quad) precision right shift - returns 71b (142b) result */
void dp_rsh_1 (UFP *a, UFP *b)
{
if (b) {
b->lo = (b->lo >> 1) | ((b->hi & 1) << 17);
b->hi = (b->hi >> 1) | ((a->lo & 1) << 16); }
a->lo = (a->lo >> 1) | ((a->hi & 1) << 17);
a->hi = a->hi >> 1;
return;
}
/* Double precision denormalize and round - returns 71b result */
void dp_dnrm_r (int32 ir, UFP *a, int32 sc)
{
int32 i;
if (sc <= 0) return; /* legit? */
for (i = 0; i < sc; i++) dp_rsh_1 (a, &fmq); /* dnorm to fmq */
if (!(ir & FI_NORND) && (fmq.hi & UFP_FH_NORM)) /* round & fmq<1>? */
dp_inc (a); /* incr a */
return;
}
/* Double precision swap */
void dp_swap (UFP *a, UFP *b)
{
int32 t;
t = a->hi; /* swap fractions */
a->hi = b->hi;
b->hi = t;
t = a->lo;
a->lo = b->lo;
b->lo = t;
return;
}
/* Support routines */
void fp15_asign (int32 fir, UFP *a)
{
int32 sgnop = FI_GETSGNOP (fir);
switch (sgnop) { /* modify FMA sign */
case 1:
a->sign = 0;
break;
case 2:
a->sign = 1;
break;
case 3:
a->sign = a->sign ^ 1;
break;
default:
break; }
return;
}
/* FP15 normalization and rounding
- Do normalization if enabled (NOR phase, part 1)
Normalization also does zero detect
- Do rounding if enabled (NOR phase, part 2) */
t_stat fp15_norm (int32 ir, UFP *a, UFP *b, t_bool rnd)
{
if (!(ir & FI_NONORM)) { /* norm enabled? */
if ((a->hi | a->lo) || (b && (b->hi | b->lo))) { /* frac != 0? */
while ((a->hi & UFP_FH_NORM) == 0) { /* until norm */
dp_lsh_1 (a, b); /* lsh a'b, no cry */
a->exp = a->exp - 1; } } /* decr exp */
else a->sign = a->exp = 0; } /* true zero */
if (rnd && b && (b->hi & UFP_FH_NORM)) { /* rounding? */
fguard = 1; /* set guard */
if (!(ir & FI_NORND)) { /* round enabled? */
dp_inc (a); /* add 1 */
if (a->hi & UFP_FH_CARRY) { /* carry out? */
a->hi = UFP_FH_NORM; /* set hi bit */
a->exp = a->exp + 1; } } } /* incr exp */
if (a->exp > 0377777) return FP_OVF; /* overflow? */
if (a->exp < -0400000) return FP_UNF; /* underflow? */
return FP_OK;
}
/* Exception */
t_stat fp15_exc (t_stat sta)
{
int32 ma, mb;
if (sta == FP_MM) trap_pending = 0; /* if mm, kill trap */
ma = (jea & JEA_EAMASK) + sta - 1; /* JEA address */
PCQ_ENTRY; /* record branch */
PC = Incr_addr (PC); /* PC+1 for "JMS" */
mb = Jms_word (usmd); /* form JMS word */
if (Write (ma, mb, WR)) return MM_ERR; /* store */
PC = (jea + 1) & IAMASK; /* new PC */
return MM_OK;
}
/* Reset routine */
t_stat fp15_reset (DEVICE *dptr)
{
jea = 0;
fir = 0;
fguard = 0;
fma.exp = fma.hi = fma.lo = fma.sign = 0;
fmb.exp = fmb.hi = fmb.lo = fmb.sign = 0;
fmq.exp = fmq.hi = fmq.lo = fmq.sign = 0;
return SCPE_OK;
}

View File

@@ -28,6 +28,7 @@
lp09 (PDP-9,15) LP09 line printer
lp15 (PDP-15) LP15 line printer
23-Jul-03 RMS Fixed overprint bug in Type 62
25-Apr-03 RMS Revised for extended file support
05-Feb-03 RMS Added LP09, fixed conditionalization
05-Oct-02 RMS Added DIB, device number support
@@ -53,7 +54,8 @@ extern int32 int_hwre[API_HLVL+1];
#define BPTR_MAX 40 /* pointer max */
#define BPTR_MASK 077 /* buf ptr max */
int32 lp62_iot = 0; /* saved state */
int32 lp62_spc = 0; /* print vs spc */
int32 lp62_ovrpr = 0; /* overprint */
int32 lp62_stopioe = 0;
int32 lp62_bp = 0; /* buffer ptr */
char lp62_buf[LP62_BSIZE + 1] = { 0 };
@@ -73,8 +75,8 @@ static const char *lp62_cc[] = {
"\f" };
DEVICE lp62_dev;
int32 lp62_65 (int32 pulse, int32 AC);
int32 lp62_66 (int32 pulse, int32 AC);
int32 lp62_65 (int32 pulse, int32 dat);
int32 lp62_66 (int32 pulse, int32 dat);
int32 lp62_iors (void);
t_stat lp62_svc (UNIT *uptr);
t_stat lp62_reset (DEVICE *dptr);
@@ -97,7 +99,8 @@ REG lp62_reg[] = {
{ FLDATA (DONE, int_hwre[API_LPT], INT_V_LPT) },
{ FLDATA (SPC, int_hwre[API_LPTSPC], INT_V_LPTSPC) },
{ DRDATA (BPTR, lp62_bp, 6) },
{ ORDATA (STATE, lp62_iot, 6), REG_HRO },
{ ORDATA (STATE, lp62_spc, 6), REG_HRO },
{ FLDATA (OVRPR, lp62_ovrpr, 0), REG_HRO },
{ DRDATA (POS, lp62_unit.pos, T_ADDR_W), PV_LEFT },
{ DRDATA (TIME, lp62_unit.wait, 24), PV_LEFT },
{ FLDATA (STOP_IOE, lp62_stopioe, 0) },
@@ -118,62 +121,62 @@ DEVICE lp62_dev = {
/* IOT routines */
int32 lp62_65 (int32 pulse, int32 AC)
int32 lp62_65 (int32 pulse, int32 dat)
{
int32 i;
if ((pulse & 01) && TST_INT (LPT)) AC = IOT_SKP | AC; /* LPSF */
if ((pulse & 01) && TST_INT (LPT)) dat = IOT_SKP | dat; /* LPSF */
if (pulse & 02) {
int32 sb = pulse & 060; /* subopcode */
if (sb == 000) CLR_INT (LPT); /* LPCF */
if ((sb == 040) && (lp62_bp < BPTR_MAX)) { /* LPLD */
i = lp62_bp * 3; /* cvt to chr ptr */
lp62_buf[i] = lp62_trans[(AC >> 12) & 077];
lp62_buf[i + 1] = lp62_trans[(AC >> 6) & 077];
lp62_buf[i + 2] = lp62_trans[AC & 077];
lp62_buf[i] = lp62_trans[(dat >> 12) & 077];
lp62_buf[i + 1] = lp62_trans[(dat >> 6) & 077];
lp62_buf[i + 2] = lp62_trans[dat & 077];
lp62_bp = (lp62_bp + 1) & BPTR_MASK; }
}
if (pulse & 04) /* LPSE */
sim_activate (&lp62_unit, lp62_unit.wait); /* activate */
return AC;
if (pulse & 04) { /* LPSE */
lp62_spc = 0; /* print */
sim_activate (&lp62_unit, lp62_unit.wait); } /* activate */
return dat;
}
int32 lp62_66 (int32 pulse, int32 AC)
int32 lp62_66 (int32 pulse, int32 dat)
{
if ((pulse & 01) && TST_INT (LPTSPC)) /* LSSF */
AC = IOT_SKP | AC;
dat = IOT_SKP | dat;
if (pulse & 02) CLR_INT (LPTSPC); /* LSCF */
if (pulse & 04) { /* LSPR */
lp62_iot = 020 | (AC & 07); /* space, no print */
lp62_spc = 020 | (dat & 07); /* space */
sim_activate (&lp62_unit, lp62_unit.wait); } /* activate */
return AC;
return dat;
}
/* Unit service, printer is in one of three states
/* Unit service, action based on lp62_spc
lp62_iot = 0 write buffer to file, set state to
lp62_iot = 10 write cr, then write buffer to file
lp62_iot = 2x space command x, then set state to 0
lp62_spc = 0 write buffer to file, set overprint
lp62_spc = 2x space command x, clear overprint
*/
t_stat lp62_svc (UNIT *uptr)
{
int32 i;
if (lp62_iot & 020) { /* space? */
if (lp62_spc) { /* space? */
SET_INT (LPTSPC); /* set flag */
if ((uptr->flags & UNIT_ATT) == 0) /* attached? */
return IORETURN (lp62_stopioe, SCPE_UNATT);
fputs (lp62_cc[lp62_iot & 07], uptr->fileref); /* print cctl */
fputs (lp62_cc[lp62_spc & 07], uptr->fileref); /* print cctl */
if (ferror (uptr->fileref)) { /* error? */
perror ("LPT I/O error");
clearerr (uptr->fileref);
return SCPE_IOERR; }
lp62_iot = 0; } /* clear state */
lp62_ovrpr = 0; } /* clear overprint */
else { SET_INT (LPT); /* print */
if ((uptr->flags & UNIT_ATT) == 0) /* attached? */
return IORETURN (lp62_stopioe, SCPE_UNATT);
if (lp62_iot & 010) fputc ('\r', uptr->fileref);
if (lp62_ovrpr) fputc ('\r', uptr->fileref); /* overprint? */
fputs (lp62_buf, uptr->fileref); /* print buffer */
if (ferror (uptr->fileref)) { /* test error */
perror ("LPT I/O error");
@@ -181,7 +184,7 @@ else { SET_INT (LPT); /* print */
return SCPE_IOERR; }
lp62_bp = 0;
for (i = 0; i <= LP62_BSIZE; i++) lp62_buf[i] = 0; /* clear buffer */
lp62_iot = 010; } /* set state */
lp62_ovrpr = 1; } /* set overprint */
uptr->pos = ftell (uptr->fileref); /* update position */
return SCPE_OK;
}
@@ -197,7 +200,8 @@ CLR_INT (LPTSPC);
sim_cancel (&lp62_unit); /* deactivate unit */
lp62_bp = 0; /* clear buffer ptr */
for (i = 0; i <= LP62_BSIZE; i++) lp62_buf[i] = 0; /* clear buffer */
lp62_iot = 0; /* clear state */
lp62_spc = 0; /* clear state */
lp62_ovrpr = 0; /* clear overprint */
return SCPE_OK;
}
@@ -235,8 +239,8 @@ static const char *lp647_cc[] = {
"\f" };
DEVICE lp647_dev;
int32 lp647_65 (int32 pulse, int32 AC);
int32 lp647_66 (int32 pulse, int32 AC);
int32 lp647_65 (int32 pulse, int32 dat);
int32 lp647_66 (int32 pulse, int32 dat);
int32 lp647_iors (void);
t_stat lp647_svc (UNIT *uptr);
t_stat lp647_reset (DEVICE *dptr);
@@ -285,12 +289,12 @@ DEVICE lp647_dev = {
/* IOT routines */
int32 lp647_65 (int32 pulse, int32 AC)
int32 lp647_65 (int32 pulse, int32 dat)
{
int32 i, sb;
sb = pulse & 060; /* subcode */
if ((pulse & 01) && lp647_don) AC = IOT_SKP | AC; /* LPSF */
if ((pulse & 01) && lp647_don) dat = IOT_SKP | dat; /* LPSF */
if (pulse & 02) { /* pulse 02 */
lp647_don = 0; /* clear done */
CLR_INT (LPT); /* clear int req */
@@ -310,32 +314,32 @@ if (pulse & 004) { /* LPDI */
break;
case 040: /* LPB3 */
if (lp647_bp < LP647_BSIZE) {
lp647_buf[lp647_bp] = lp647_buf[lp647_bp] | ((AC >> 12) & 077);
lp647_buf[lp647_bp] = lp647_buf[lp647_bp] | ((dat >> 12) & 077);
lp647_bp = lp647_bp + 1; }
case 020: /* LPB2 */
if (lp647_bp < LP647_BSIZE) {
lp647_buf[lp647_bp] = lp647_buf[lp647_bp] | ((AC >> 6) & 077);
lp647_buf[lp647_bp] = lp647_buf[lp647_bp] | ((dat >> 6) & 077);
lp647_bp = lp647_bp + 1; }
case 060: /* LPB1 */
if (lp647_bp < LP647_BSIZE) {
lp647_buf[lp647_bp] = lp647_buf[lp647_bp] | (AC & 077);
lp647_buf[lp647_bp] = lp647_buf[lp647_bp] | (dat & 077);
lp647_bp = lp647_bp + 1; }
lp647_don = 1; /* set done */
if (lp647_ie) SET_INT (LPT); /* set int */
break; } /* end case */
}
return AC;
return dat;
}
int32 lp647_66 (int32 pulse, int32 AC)
int32 lp647_66 (int32 pulse, int32 dat)
{
if ((pulse & 01) && lp647_err) AC = IOT_SKP | AC; /* LPSE */
if ((pulse & 01) && lp647_err) dat = IOT_SKP | dat; /* LPSE */
if (pulse & 02) { /* LPCF */
lp647_don = 0; /* clear done, int */
CLR_INT (LPT); }
if (pulse & 04) {
if ((pulse & 060) < 060) { /* LPLS, LPPB, LPPS */
lp647_iot = (pulse & 060) | (AC & 07); /* save parameters */
lp647_iot = (pulse & 060) | (dat & 07); /* save parameters */
sim_activate (&lp647_unit, lp647_unit.wait); } /* activate */
#if defined (PDP9)
else { /* LPEI */
@@ -343,7 +347,7 @@ if (pulse & 04) {
if (lp647_don) SET_INT (LPT); }
#endif
}
return AC;
return dat;
}
/* Unit service. lp647_iot specifies the action to be taken
@@ -442,7 +446,7 @@ int32 lp09_ie = 1; /* int enable */
int32 lp09_stopioe = 0;
DEVICE lp09_dev;
int32 lp09_66 (int32 pulse, int32 AC);
int32 lp09_66 (int32 pulse, int32 dat);
int32 lp09_iors (void);
t_stat lp09_svc (UNIT *uptr);
t_stat lp09_reset (DEVICE *dptr);
@@ -486,13 +490,13 @@ DEVICE lp09_dev = {
/* IOT routines */
int32 lp09_66 (int32 pulse, int32 AC)
int32 lp09_66 (int32 pulse, int32 dat)
{
int32 sb = pulse & 060; /* subopcode */
if (pulse & 001) {
if ((sb == 000) && lp09_don) AC = IOT_SKP | AC; /* LSDF */
if ((sb == 020) && lp09_err) AC = IOT_SKP | AC; /* LSEF */
if ((sb == 000) && lp09_don) dat = IOT_SKP | dat; /* LSDF */
if ((sb == 020) && lp09_err) dat = IOT_SKP | dat; /* LSEF */
}
if (pulse & 002) {
if (sb == 000) { /* LSCF */
@@ -501,11 +505,11 @@ if (pulse & 002) {
else if (sb == 020) { /* LPLD */
lp09_don = 0; /* clear done, int */
CLR_INT (LPT);
lp09_unit.buf = AC & 0177; /* load char */
lp09_unit.buf = dat & 0177; /* load char */
if ((lp09_unit.buf == 015) || (lp09_unit.buf == 014) ||
(lp09_unit.buf == 012))
sim_activate (&lp09_unit, lp09_unit.wait);
else AC = AC | (lp09_svc (&lp09_unit) << IOT_V_REASON); }
else dat = dat | (lp09_svc (&lp09_unit) << IOT_V_REASON); }
}
if (pulse & 004) {
if (sb == 000) { /* LIOF */
@@ -515,7 +519,7 @@ if (pulse & 004) {
lp09_ie = 1; /* set int enab */
if (lp09_don) SET_INT (LPT); } /* if done, set int */
}
return AC;
return dat;
}
/* Unit service */
@@ -608,8 +612,8 @@ int32 lp15_bp = 0;
char lp15_buf[LP15_BSIZE] = { 0 };
DEVICE lp15_dev;
int32 lp15_65 (int32 pulse, int32 AC);
int32 lp15_66 (int32 pulse, int32 AC);
int32 lp15_65 (int32 pulse, int32 dat);
int32 lp15_66 (int32 pulse, int32 dat);
int32 lp15_iors (void);
t_stat lp15_svc (UNIT *uptr);
t_stat lp15_reset (DEVICE *dptr);
@@ -656,18 +660,18 @@ DEVICE lp15_dev = {
/* IOT routines */
int32 lp15_65 (int32 pulse, int32 AC)
int32 lp15_65 (int32 pulse, int32 dat)
{
int32 header, sb;
sb = pulse & 060; /* subopcode */
if (pulse & 01) {
if ((sb == 000) && (lp15_sta & (STA_ERR | STA_DON))) /* LPSF */
AC = IOT_SKP | AC;
dat = IOT_SKP | dat;
else if ((sb == 020) || (sb == 040)) { /* LPP1, LPPM */
sim_activate (&lp15_unit, lp15_unit.wait); /* activate */
header = M[(M[LPT_CA] + 1) & ADDRMASK]; /* get first word */
M[LPT_CA] = (M[LPT_CA] + 2) & 0777777;
header = M[(M[LPT_CA] + 1) & AMASK]; /* get first word */
M[LPT_CA] = (M[LPT_CA] + 2) & DMASK;
lp15_mode = header & 1; /* mode */
if (sb == 040) lp15_lc = 1; /* line count */
else lp15_lc = (header >> 9) & 0377;
@@ -675,18 +679,18 @@ if (pulse & 01) {
lp15_bp = 0; } /* reset buf ptr */
else if (sb == 060) lp15_ie = 0; /* LPDI */
}
if ((pulse & 02) && (sb == 040)) AC = AC | lp15_updsta (0); /* LPOS, LPRS */
if ((pulse & 02) && (sb == 040)) dat = dat | lp15_updsta (0); /* LPOS, LPRS */
if ((pulse & 04) && (sb == 040)) lp15_ie = 1; /* LPEI */
lp15_updsta (0); /* update status */
return AC;
return dat;
}
int32 lp15_66 (int32 pulse, int32 AC)
int32 lp15_66 (int32 pulse, int32 dat)
{
if (pulse == 021) lp15_sta = lp15_sta & ~STA_DON; /* LPCD */
if (pulse == 041) lp15_sta = 0; /* LPCF */
lp15_updsta (0); /* update status */
return AC;
return dat;
}
/* Unit service */
@@ -709,9 +713,9 @@ if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */
return IORETURN (lp15_stopioe, SCPE_UNATT); }
for (more = 1; more != 0; ) { /* loop until ctrl */
w0 = M[(M[LPT_CA] + 1) & ADDRMASK]; /* get first word */
w1 = M[(M[LPT_CA] + 2) & ADDRMASK]; /* get second word */
M[LPT_CA] = (M[LPT_CA] + 2) & 0777777; /* advance mem addr */
w0 = M[(M[LPT_CA] + 1) & AMASK]; /* get first word */
w1 = M[(M[LPT_CA] + 2) & AMASK]; /* get second word */
M[LPT_CA] = (M[LPT_CA] + 2) & DMASK; /* advance mem addr */
if (lp15_mode) { /* unpacked? */
c[0] = w0 & 0177;
c[1] = w1 & 0177;

View File

@@ -131,7 +131,7 @@ int32 mt_log = 0;
uint8 *mtxb = NULL; /* transfer buffer */
DEVICE mt_dev;
int32 mt (int32 pulse, int32 AC);
int32 mt (int32 pulse, int32 dat);
int32 mt_iors (void);
t_stat mt_svc (UNIT *uptr);
t_stat mt_reset (DEVICE *dptr);
@@ -194,7 +194,7 @@ DEVICE mt_dev = {
/* IOT routine */
int32 mt (int32 pulse, int32 AC)
int32 mt (int32 pulse, int32 dat)
{
int32 f, sb;
UNIT *uptr;
@@ -205,21 +205,21 @@ sb = pulse & 060; /* subop */
if (pulse & 01) {
if ((sb == 000) && (uptr->flags & UNIT_ATT) && /* MTTR */
!sim_is_active (uptr))
AC = IOT_SKP | AC;
dat = IOT_SKP | dat;
else if ((sb == 020) && !mt_busy ()) /* MTCR */
AC = IOT_SKP | AC;
dat = IOT_SKP | dat;
else if ((sb == 040) && (mt_sta & (STA_ERR | STA_DON))) /* MTSF */
AC = IOT_SKP | AC;
dat = IOT_SKP | dat;
}
if ((pulse & 06) && mt_log)
printf ("[MT%d: IOT=%o, AC=%o, sta=%o]\n",
GET_UNIT (mt_cu), 0707300 + pulse, AC, mt_sta);
GET_UNIT (mt_cu), 0707300 + pulse, dat, mt_sta);
if (pulse & 02) {
if (sb == 000) AC = AC | (mt_cu & 0777700); /* MTRC */
if (sb == 000) dat = dat | (mt_cu & 0777700); /* MTRC */
else if (sb == 020) { /* MTAF, MTLC */
if (!mt_busy ()) mt_cu = mt_sta = 0; /* if not busy, clr */
mt_sta = mt_sta & ~(STA_ERR | STA_DON); } /* clear flags */
else if (sb == 040) AC = AC | mt_sta; /* MTRS */
else if (sb == 040) dat = dat | mt_sta; /* MTRS */
}
if (pulse & 04) {
if (sb == 000) { /* MTGO */
@@ -236,10 +236,10 @@ if (pulse & 04) {
else mt_sta = uptr->USTAT = 0; /* no, clear status */
sim_activate (uptr, mt_time); } } /* start io */
if (sb == 020) /* MTCM, MTLC */
mt_cu = (mt_cu & 0770700) | (AC & 0777700); /* load status */
mt_cu = (mt_cu & 0770700) | (dat & 0777700); /* load status */
}
mt_updcsta (mt_dev.units + GET_UNIT (mt_cu), 0); /* update status */
return AC;
return dat;
}
/* Unit service
@@ -289,9 +289,9 @@ case FN_CMPARE: /* read/compare */
cbc = tbc; /* use smaller */
wc = PACKED (mt_cu)? ((tbc + 2) / 3): ((tbc + 1) / 2); }
for (i = p = 0; i < wc; i++) { /* copy buffer */
M[MT_WC] = (M[MT_WC] + 1) & 0777777; /* inc WC, CA */
M[MT_CA] = (M[MT_CA] + 1) & 0777777;
xma = M[MT_CA] & ADDRMASK;
M[MT_WC] = (M[MT_WC] + 1) & DMASK; /* inc WC, CA */
M[MT_CA] = (M[MT_CA] + 1) & DMASK;
xma = M[MT_CA] & AMASK;
if (PACKED (mt_cu)) { /* packed? */
c1 = mtxb[p++] & 077;
c2 = mtxb[p++] & 077;
@@ -303,16 +303,16 @@ case FN_CMPARE: /* read/compare */
c = (c1 << 8) | c2; }
if ((f == FN_READ) && MEM_ADDR_OK (xma)) M[xma] = c;
else if ((f == FN_CMPARE) && (c != (M[xma] &
(PACKED (mt_cu)? 0777777: 0177777)))) {
(PACKED (mt_cu)? DMASK: 0177777)))) {
mt_updcsta (uptr, STA_CPE);
break; } }
break;
case FN_WRITE: /* write */
tbc = PACKED (mt_cu)? wc * 3: wc * 2;
xma = M[MT_CA] & ADDRMASK; /* get mem addr */
xma = M[MT_CA] & AMASK; /* get mem addr */
for (i = p = 0; i < wc; i++) { /* copy buf to tape */
xma = (xma + 1) & ADDRMASK; /* incr mem addr */
xma = (xma + 1) & AMASK; /* incr mem addr */
if (PACKED (mt_cu)) { /* packed? */
mtxb[p++] = (M[xma] >> 12) & 077;
mtxb[p++] = (M[xma] >> 6) & 077;
@@ -323,7 +323,7 @@ case FN_WRITE: /* write */
if (st = sim_tape_wrrecf (uptr, mtxb, tbc)) /* write rec, err? */
r = mt_map_err (uptr, st); /* map error */
else {
M[MT_CA] = (M[MT_CA] + wc) & 0777777; /* advance mem addr */
M[MT_CA] = (M[MT_CA] + wc) & DMASK; /* advance mem addr */
M[MT_WC] = 0; } /* clear word cnt */
mt_cu = mt_cu & ~CU_ERASE; /* clear erase flag */
break;
@@ -339,7 +339,7 @@ case FN_WREOF:
case FN_SPACEF: /* space forward */
do {
M[MT_WC] = (M[MT_WC] + 1) & 0777777; /* inc WC */
M[MT_WC] = (M[MT_WC] + 1) & DMASK; /* inc WC */
if (st = sim_tape_sprecf (uptr, &tbc)) { /* space rec fwd, err? */
r = mt_map_err (uptr, st); /* map error */
break; }
@@ -349,7 +349,7 @@ case FN_SPACEF: /* space forward */
case FN_SPACER: /* space reverse */
do {
M[MT_WC] = (M[MT_WC] + 1) & 0777777; /* inc WC */
M[MT_WC] = (M[MT_WC] + 1) & DMASK; /* inc WC */
if (st = sim_tape_sprecr (uptr, &tbc)) { /* space rec rev, err? */
r = mt_map_err (uptr, st); /* map error */
break; }

View File

@@ -149,7 +149,7 @@ if (pulse & 001) {
if (pulse & 002) {
if (sb == 000) AC = AC | rb_make_da (rb_da); /* DBRD */
if (sb == 020) AC = AC | rb_sta; /* DBRS */
if (sb == 040) rb_ma = AC & ADDRMASK; /* DBLM */
if (sb == 040) rb_ma = AC & AMASK; /* DBLM */
}
if (pulse & 004) {
if (sb == 000) rb_da = rb_set_da (AC, rb_da); /* DBLD */
@@ -236,7 +236,7 @@ do { if (rb_sta & RBS_WR) { /* write? */
else if (MEM_ADDR_OK (rb_ma)) /* read, valid addr? */
M[rb_ma] = *(((int32 *) uptr->filebuf) + rb_da);
rb_wc = (rb_wc + 1) & 0177777; /* incr word count */
rb_ma = (rb_ma + 1) & ADDRMASK; /* incr mem addr */
rb_ma = (rb_ma + 1) & AMASK; /* incr mem addr */
rb_da = rb_da + 1; /* incr disk addr */
if (rb_da > RB_SIZE) rb_da = 0; /* disk wraparound? */
}

View File

@@ -26,6 +26,7 @@
rf (PDP-9) RF09/RF09
(PDP-15) RF15/RS09
26-Jul-03 RMS Fixed bug in set size routine
14-Mar-03 RMS Fixed variable platter interaction with save/restore
03-Mar-03 RMS Fixed autosizing
12-Feb-03 RMS Removed 8 platter sizing hack
@@ -113,8 +114,8 @@ int32 rf_burst = 1; /* burst mode flag */
int32 rf_stopioe = 1; /* stop on error */
DEVICE rf_dev;
int32 rf70 (int32 pulse, int32 AC);
int32 rf72 (int32 pulse, int32 AC);
int32 rf70 (int32 pulse, int32 dat);
int32 rf72 (int32 pulse, int32 dat);
int32 rf_iors (void);
t_stat rf_svc (UNIT *uptr);
t_stat rf_reset (DEVICE *dptr);
@@ -151,14 +152,14 @@ REG rf_reg[] = {
{ NULL } };
MTAB rf_mod[] = {
{ UNIT_PLAT, 0, NULL, "1P", &rf_set_size },
{ UNIT_PLAT, 1, NULL, "2P", &rf_set_size },
{ UNIT_PLAT, 2, NULL, "3P", &rf_set_size },
{ UNIT_PLAT, 3, NULL, "4P", &rf_set_size },
{ UNIT_PLAT, 4, NULL, "5P", &rf_set_size },
{ UNIT_PLAT, 5, NULL, "6P", &rf_set_size },
{ UNIT_PLAT, 6, NULL, "7P", &rf_set_size },
{ UNIT_PLAT, 7, NULL, "8P", &rf_set_size },
{ UNIT_PLAT, (0 << UNIT_V_PLAT), NULL, "1P", &rf_set_size },
{ UNIT_PLAT, (1 << UNIT_V_PLAT), NULL, "2P", &rf_set_size },
{ UNIT_PLAT, (2 << UNIT_V_PLAT), NULL, "3P", &rf_set_size },
{ UNIT_PLAT, (3 << UNIT_V_PLAT), NULL, "4P", &rf_set_size },
{ UNIT_PLAT, (4 << UNIT_V_PLAT), NULL, "5P", &rf_set_size },
{ UNIT_PLAT, (5 << UNIT_V_PLAT), NULL, "6P", &rf_set_size },
{ UNIT_PLAT, (6 << UNIT_V_PLAT), NULL, "7P", &rf_set_size },
{ UNIT_PLAT, (7 << UNIT_V_PLAT), NULL, "8P", &rf_set_size },
{ UNIT_AUTO, UNIT_AUTO, "autosize", "AUTOSIZE", NULL },
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", &set_devno, &show_devno },
{ 0 } };
@@ -172,14 +173,14 @@ DEVICE rf_dev = {
/* IOT routines */
int32 rf70 (int32 pulse, int32 AC)
int32 rf70 (int32 pulse, int32 dat)
{
int32 t, sb;
sb = pulse & 060; /* subopcode */
if (pulse & 01) {
if ((sb == 000) && (rf_sta & (RFS_ERR | RFS_DON)))
AC = IOT_SKP | AC; /* DSSF */
dat = IOT_SKP | dat; /* DSSF */
else if (sb == 020) rf_reset (&rf_dev); /* DSCC */
else if (sb == 040) { /* DSCF */
if (RF_BUSY) rf_sta = rf_sta | RFS_PGE; /* busy inhibits */
@@ -187,19 +188,19 @@ if (pulse & 01) {
}
if (pulse & 02) {
if (RF_BUSY) rf_sta = rf_sta | RFS_PGE; /* busy sets PGE */
else if (sb == 000) AC = AC | rf_dbuf; /* DRBR */
else if (sb == 000) dat = dat | rf_dbuf; /* DRBR */
else if (sb == 020) /* DRAL */
AC = AC | (rf_da & 0777777);
dat = dat | (rf_da & DMASK);
else if (sb == 040) /* DSFX */
rf_sta = rf_sta ^ (AC & (RFS_FNC | RFS_IE)); /* xor func */
rf_sta = rf_sta ^ (dat & (RFS_FNC | RFS_IE)); /* xor func */
else if (sb == 060) /* DRAH */
AC = AC | (rf_da >> 18) | ((rf_sta & RFS_NED)? 010: 0);
dat = dat | (rf_da >> 18) | ((rf_sta & RFS_NED)? 010: 0);
}
if (pulse & 04) {
if (RF_BUSY) rf_sta = rf_sta | RFS_PGE; /* busy sets PGE */
else if (sb == 000) rf_dbuf = AC & 0777777; /* DLBR */
else if (sb == 000) rf_dbuf = dat & DMASK; /* DLBR */
else if (sb == 020) /* DLAL */
rf_da = (rf_da & ~0777777) | (AC & 0777777);
rf_da = (rf_da & ~DMASK) | (dat & DMASK);
else if (sb == 040) { /* DSCN */
rf_sta = rf_sta & ~RFS_DON; /* clear done */
if (GET_FNC (rf_sta) != FN_NOP) {
@@ -207,20 +208,20 @@ if (pulse & 04) {
if (t < 0) t = t + RF_NUMWD; /* wrap around? */
sim_activate (&rf_unit, t * rf_time); } } /* schedule op */
else if (sb == 060) { /* DLAH */
rf_da = (rf_da & 0777777) | ((AC & 07) << 18);
rf_da = (rf_da & DMASK) | ((dat & 07) << 18);
if ((uint32) rf_da >= rf_unit.capac) /* for sizing */
rf_updsta (RFS_NED); }
}
rf_updsta (0); /* update status */
return AC;
return dat;
}
int32 rf72 (int32 pulse, int32 AC)
int32 rf72 (int32 pulse, int32 dat)
{
int32 sb = pulse & 060;
if (pulse & 02) {
if (sb == 000) AC = AC | GET_POS (rf_time) | /* DLOK */
if (sb == 000) dat = dat | GET_POS (rf_time) | /* DLOK */
(sim_is_active (&rf_unit)? 0400000: 0);
else if (sb == 040) { /* DSCD */
if (RF_BUSY) rf_sta = rf_sta | RFS_PGE; /* busy inhibits */
@@ -228,9 +229,9 @@ if (pulse & 02) {
rf_updsta (0); }
else if (sb == 060) { /* DSRS */
if (RF_BUSY) rf_sta = rf_sta | RFS_PGE; /* busy sets PGE */
AC = AC | rf_updsta (0); }
dat = dat | rf_updsta (0); }
}
return AC;
return dat;
}
/* Unit service - assumes the entire disk is buffered */
@@ -247,8 +248,8 @@ f = GET_FNC (rf_sta); /* get function */
do { if ((uint32) rf_da >= uptr->capac) { /* disk overflow? */
rf_updsta (RFS_NED); /* nx disk error */
break; }
M[RF_WC] = (M[RF_WC] + 1) & 0777777; /* incr word count */
pa = M[RF_CA] = (M[RF_CA] + 1) & ADDRMASK; /* incr mem addr */
M[RF_WC] = (M[RF_WC] + 1) & DMASK; /* incr word count */
pa = M[RF_CA] = (M[RF_CA] + 1) & AMASK; /* incr mem addr */
if ((f == FN_READ) && MEM_ADDR_OK (pa)) /* read? */
M[pa] = *(((int32 *) uptr->filebuf) + rf_da);
if ((f == FN_WCHK) && /* write check? */
@@ -323,9 +324,9 @@ return attach_unit (uptr, cptr);
t_stat rf_set_size (UNIT *uptr, int32 val, char *cptr, void *desc)
{
if ((val < 0) || (val > RF_NUMDK)) return SCPE_IERR;
if (val < 0) return SCPE_IERR;
if (uptr->flags & UNIT_ATT) return SCPE_ALATT;
uptr->capac = (val + 1) * RF_DKSIZE;
uptr->capac = UNIT_GETP (val) * RF_DKSIZE;
uptr->flags = uptr->flags & ~UNIT_AUTO;
return SCPE_OK;
}

View File

@@ -144,8 +144,8 @@ int32 rp_swait = 10; /* seek time */
int32 rp_rwait = 10; /* rotate time */
DEVICE rp_dev;
int32 rp63 (int32 pulse, int32 AC);
int32 rp64 (int32 pulse, int32 AC);
int32 rp63 (int32 pulse, int32 dat);
int32 rp64 (int32 pulse, int32 dat);
int32 rp_iors (void);
t_stat rp_svc (UNIT *uptr);
void rp_updsta (int32 newa, int32 newb);
@@ -202,7 +202,7 @@ DEVICE rp_dev = {
/* IOT routines */
int32 rp63 (int32 pulse, int32 AC)
int32 rp63 (int32 pulse, int32 dat)
{
int32 sb = pulse & 060; /* subopcode */
@@ -210,24 +210,24 @@ rp_updsta (0, 0);
if (pulse & 01) {
if ((sb == 000) && /* DPSF */
((rp_sta & (STA_DON | STA_ERR)) || (rp_stb & STB_ATTN)))
AC = IOT_SKP | AC;
dat = IOT_SKP | dat;
else if ((sb == 020) && (rp_stb & STB_ATTN)) /* DPSA */
AC = IOT_SKP | AC;
dat = IOT_SKP | dat;
else if ((sb == 040) && (rp_sta & STA_DON)) /* DPSJ */
AC = IOT_SKP | AC;
dat = IOT_SKP | dat;
else if ((sb == 060) && (rp_sta & STA_ERR)) /* DPSE */
AC = IOT_SKP | AC;
dat = IOT_SKP | dat;
}
if (pulse & 02) {
if (sb == 000) AC = AC | rp_sta; /* DPOSA */
else if (sb == 020) AC = AC | rp_stb; /* DPOSB */
if (sb == 000) dat = dat | rp_sta; /* DPOSA */
else if (sb == 020) dat = dat | rp_stb; /* DPOSB */
}
if (pulse & 04) {
if (rp_busy) { /* busy? */
rp_updsta (0, STB_PGE);
return AC; }
return dat; }
else if (sb == 000) { /* DPLA */
rp_da = AC & 0777777;
rp_da = dat & DMASK;
if (GET_SECT (rp_da) >= RP_NUMSC) rp_updsta (STA_NXS, 0);
if (GET_SURF (rp_da) >= RP_NUMSF) rp_updsta (STA_NXF, 0);
if (GET_CYL (rp_da) >= RP_NUMCY) rp_updsta (STA_NXC, 0); }
@@ -236,38 +236,38 @@ if (pulse & 04) {
rp_stb = rp_stb & ~(STB_FME | STB_WPE | STB_LON | STB_WCE |
STB_TME | STB_PGE | STB_EOP);
rp_updsta (0, 0); }
else if (sb == 040) rp_ma = AC & 0777777; /* DPCA */
else if (sb == 060) rp_wc = AC & 0777777; /* DPWC */
else if (sb == 040) rp_ma = dat & DMASK; /* DPCA */
else if (sb == 060) rp_wc = dat & DMASK; /* DPWC */
}
return AC;
return dat;
}
/* IOT 64 */
int32 rp64 (int32 pulse, int32 AC)
int32 rp64 (int32 pulse, int32 dat)
{
int32 u, f, c, sb;
UNIT *uptr;
sb = pulse & 060;
if (pulse & 01) {
if (sb == 020) AC = IOT_SKP | AC; /* DPSN */
if (sb == 020) dat = IOT_SKP | dat; /* DPSN */
}
if (pulse & 02) {
if (sb == 000) AC = AC | rp_unit[GET_UNIT (rp_sta)].CYL; /* DPOU */
else if (sb == 020) AC = AC | rp_da; /* DPOA */
else if (sb == 040) AC = AC | rp_ma; /* DPOC */
else if (sb == 060) AC = AC | rp_wc; /* DPOW */
if (sb == 000) dat = dat | rp_unit[GET_UNIT (rp_sta)].CYL; /* DPOU */
else if (sb == 020) dat = dat | rp_da; /* DPOA */
else if (sb == 040) dat = dat | rp_ma; /* DPOC */
else if (sb == 060) dat = dat | rp_wc; /* DPOW */
}
if (pulse & 04) {
if (rp_busy) { /* busy? */
rp_updsta (0, STB_PGE);
return AC; }
return dat; }
if (sb == 000) rp_sta = rp_sta & ~STA_RW; /* DPCF */
else if (sb == 020) rp_sta = rp_sta & (AC | ~STA_RW); /* DPLZ */
else if (sb == 040) rp_sta = rp_sta | (AC & STA_RW); /* DPLO */
else if (sb == 020) rp_sta = rp_sta & (dat | ~STA_RW); /* DPLZ */
else if (sb == 040) rp_sta = rp_sta | (dat & STA_RW); /* DPLO */
else if (sb == 060) /* DPLF */
rp_sta = (rp_sta & ~STA_RW) | (AC & STA_RW);
rp_sta = (rp_sta & ~STA_RW) | (dat & STA_RW);
rp_sta = rp_sta & ~STA_DON; /* clear done */
u = GET_UNIT (rp_sta); /* get unit num */
uptr = rp_dev.units + u; /* select unit */
@@ -286,7 +286,7 @@ if (pulse & 04) {
sim_activate (uptr, MAX (RP_MIN, c + rp_rwait)); } }
}
rp_updsta (0, 0);
return AC;
return dat;
}
/* Unit service
@@ -342,7 +342,7 @@ if (rp_sta & (STA_NXS | STA_NXF | STA_NXC)) { /* or bad disk addr? */
rp_updsta (STA_DON, STB_SUFU); /* done, unsafe */
return SCPE_OK; }
pa = rp_ma & ADDRMASK; /* get mem addr */
pa = rp_ma & AMASK; /* get mem addr */
da = GET_DA (rp_da) * RP_NUMWD; /* get disk addr */
wc = 01000000 - rp_wc; /* get true wc */
if (((uint32) (pa + wc)) > MEMSIZE) { /* memory overrun? */
@@ -373,8 +373,8 @@ if ((f == FN_WRCHK) && (err == 0)) { /* write check? */
if (comp != M[pa + i]) rp_updsta (0, STB_WCE); }
err = ferror (uptr->fileref); }
rp_wc = (rp_wc + wc) & 0777777; /* final word count */
rp_ma = (rp_ma + wc) & 0777777; /* final mem addr */
rp_wc = (rp_wc + wc) & DMASK; /* final word count */
rp_ma = (rp_ma + wc) & DMASK; /* final mem addr */
da = (da + wc + (RP_NUMWD - 1)) / RP_NUMWD; /* final sector num */
cyl = da / (RP_NUMSC * RP_NUMSF); /* get cyl */
if (cyl >= RP_NUMCY) cyl = RP_NUMCY - 1;

View File

@@ -29,6 +29,8 @@
tto teleprinter
clk clock
26-Jul-03 RMS Increased PTP, TTO timeouts for PDP-15 operating systems
Added hardware read-in mode support for PDP-7/9/15
25-Apr-03 RMS Revised for extended file support
14-Mar-03 RMS Clean up flags on detach
01-Mar-03 RMS Added SET/SHOW CLK FREQ support, SET TTI CTRL-C support
@@ -62,7 +64,7 @@
#define UNIT_PASCII (1 << UNIT_V_PASCII)
extern int32 M[];
extern int32 int_hwre[API_HLVL+1], saved_PC;
extern int32 int_hwre[API_HLVL+1], PC, ASW;
extern int32 sim_switches;
extern UNIT cpu_unit;
@@ -74,10 +76,10 @@ int32 tto_state = 0;
int32 clk_tps = 60; /* ticks/second */
int32 tmxr_poll = 16000; /* term mux poll */
int32 ptr (int32 pulse, int32 AC);
int32 ptp (int32 pulse, int32 AC);
int32 tti (int32 pulse, int32 AC);
int32 tto (int32 pulse, int32 AC);
int32 ptr (int32 pulse, int32 dat);
int32 ptp (int32 pulse, int32 dat);
int32 tti (int32 pulse, int32 dat);
int32 tto (int32 pulse, int32 dat);
int32 clk_iors (void);
int32 ptr_iors (void);
int32 ptp_iors (void);
@@ -188,7 +190,7 @@ DEVICE ptr_dev = {
DIB ptp_dib = { DEV_PTP, 1, &ptp_iors, { &ptp } };
UNIT ptp_unit = {
UDATA (&ptp_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT };
UDATA (&ptp_svc, UNIT_SEQ+UNIT_ATTABLE, 0), 1000 };
REG ptp_reg[] = {
{ ORDATA (BUF, ptp_unit.buf, 8) },
@@ -327,7 +329,7 @@ static const char tto_trans[64] = {
DIB tto_dib = { DEV_TTO, 1, &tto_iors, { &tto } };
UNIT tto_unit = { UDATA (&tto_svc, UNIT_KSR, 0), SERIAL_OUT_WAIT };
UNIT tto_unit = { UDATA (&tto_svc, UNIT_KSR, 0), 1000 };
REG tto_reg[] = {
{ ORDATA (BUF, tto_unit.buf, TTO_WIDTH) },
@@ -358,10 +360,10 @@ DEVICE tto_dev = {
/* Clock: IOT routine */
int32 clk (int32 pulse, int32 AC)
int32 clk (int32 pulse, int32 dat)
{
if (pulse & 001) { /* CLSF */
if (TST_INT (CLK)) AC = AC | IOT_SKP; }
if (TST_INT (CLK)) dat = dat | IOT_SKP; }
if (pulse & 004) { /* CLON/CLOF */
if (pulse & 040) { /* CLON */
CLR_INT (CLK); /* clear flag */
@@ -370,7 +372,7 @@ if (pulse & 004) { /* CLON/CLOF */
sim_activate (&clk_unit, /* start, calibr */
sim_rtc_init (clk_unit.wait)); }
else clk_reset (&clk_dev); } /* CLOF */
return AC;
return dat;
}
/* Unit service */
@@ -380,7 +382,7 @@ t_stat clk_svc (UNIT *uptr)
int32 t;
if (clk_state) { /* clock on? */
M[7] = (M[7] + 1) & 0777777; /* incr counter */
M[7] = (M[7] + 1) & DMASK; /* incr counter */
if (M[7] == 0) SET_INT (CLK); /* ovrflo? set flag */
t = sim_rtc_calb (clk_tps); /* calibrate clock */
sim_activate (&clk_unit, t); /* reactivate unit */
@@ -426,19 +428,19 @@ return SCPE_OK;
/* Paper tape reader: IOT routine */
int32 ptr (int32 pulse, int32 AC)
int32 ptr (int32 pulse, int32 dat)
{
if (pulse & 001) { /* RSF */
if (TST_INT (PTR)) AC = AC | IOT_SKP; }
if (TST_INT (PTR)) dat = dat | IOT_SKP; }
if (pulse & 002) { /* RRB, RCF */
CLR_INT (PTR); /* clear done */
AC = AC | ptr_unit.buf; } /* return buffer */
dat = dat | ptr_unit.buf; } /* return buffer */
if (pulse & 004) { /* RSA, RSB */
ptr_state = (pulse & 040)? 18: 0; /* set mode */
CLR_INT (PTR); /* clear done */
ptr_unit.buf = 0; /* clear buffer */
sim_activate (&ptr_unit, ptr_unit.wait); }
return AC;
return dat;
}
/* Unit service */
@@ -526,6 +528,39 @@ ptr_unit.flags = ptr_unit.flags & ~UNIT_RASCII;
return detach_unit (uptr);
}
/* Hardware RIM loader routines, PDP-7/9/15 */
int32 ptr_getw (FILE *fileref, int32 *hi)
{
int32 word, bits, st, ch;
word = st = bits = 0;
do { if ((ch = getc (fileref)) == EOF) return -1;
if (ch & 0200) {
word = (word << 6) | (ch & 077);
bits = (bits << 1) | ((ch >> 6) & 1);
st++; } }
while (st < 3);
if (hi != NULL) *hi = bits;
return word;
}
t_stat ptr_rim_load (FILE *fileref, int32 origin)
{
int32 bits, val;
for (;;) { /* word loop */
if ((val = ptr_getw (fileref, &bits)) < 0) return SCPE_FMT;
if (bits & 1) { /* end of tape? */
if ((val & 0760000) == OP_JMP) {
PC = ((origin - 1) & 060000) | (val & 017777);
return SCPE_OK; }
else if (val == OP_HLT) return STOP_HALT;
break; }
else if (MEM_ADDR_OK (origin)) M[origin++] = val; }
return SCPE_FMT;
}
#if defined (PDP4) || defined (PDP7)
/* Bootstrap routine, PDP-4 and PDP-7
@@ -533,12 +568,11 @@ return detach_unit (uptr);
In a 4K system, the boostrap resides at 7762-7776.
In an 8K or greater system, the bootstrap resides at 17762-17776.
Because the program is so small, simple masking can be
used to remove addr<5> for a 4K system.
*/
used to remove addr<5> for a 4K system. */
#define BOOT_START 017577
#define BOOT_FPC 017577
#define BOOT_RPC 017770
#define BOOT_FPC 017577 /* funny format loader */
#define BOOT_RPC 017770 /* RIM loader */
#define BOOT_LEN (sizeof (boot_rom) / sizeof (int))
static const int32 boot_rom[] = {
@@ -677,6 +711,10 @@ t_stat ptr_boot (int32 unitno, DEVICE *dptr)
int32 i, mask, wd;
extern int32 sim_switches;
#if defined (PDP7)
if (sim_switches & SWMASK ('H')) /* hardware RIM load? */
return ptr_rim_load (ptr_unit.fileref, ASW);
#endif
if (ptr_dib.dev != DEV_PTR) return STOP_NONSTD; /* non-std addr? */
if (MEMSIZE < 8192) mask = 0767777; /* 4k? */
else mask = 0777777;
@@ -684,7 +722,7 @@ for (i = 0; i < BOOT_LEN; i++) {
wd = boot_rom[i];
if ((wd >= 0040000) && (wd < 0640000)) wd = wd & mask;
M[(BOOT_START & mask) + i] = wd; }
saved_PC = ((sim_switches & SWMASK ('F'))? BOOT_FPC: BOOT_RPC) & mask;
PC = ((sim_switches & SWMASK ('F'))? BOOT_FPC: BOOT_RPC) & mask;
return SCPE_OK;
}
@@ -694,24 +732,24 @@ return SCPE_OK;
t_stat ptr_boot (int32 unitno, DEVICE *dptr)
{
return SCPE_ARG;
return ptr_rim_load (ptr_unit.fileref, ASW);
}
#endif
/* Paper tape punch: IOT routine */
int32 ptp (int32 pulse, int32 AC)
int32 ptp (int32 pulse, int32 dat)
{
if (pulse & 001) { /* PSF */
if (TST_INT (PTP)) AC = AC | IOT_SKP; }
if (TST_INT (PTP)) dat = dat | IOT_SKP; }
if (pulse & 002) CLR_INT (PTP); /* PCF */
if (pulse & 004) { /* PSA, PSB, PLS */
CLR_INT (PTP); /* clear flag */
ptp_unit.buf = (pulse & 040)? /* load punch buf */
(AC & 077) | 0200: AC & 0377; /* bin or alpha */
(dat & 077) | 0200: dat & 0377; /* bin or alpha */
sim_activate (&ptp_unit, ptp_unit.wait); } /* activate unit */
return AC;
return dat;
}
/* Unit service */
@@ -782,16 +820,16 @@ return detach_unit (uptr);
/* Terminal input: IOT routine */
int32 tti (int32 pulse, int32 AC)
int32 tti (int32 pulse, int32 dat)
{
if (pulse & 001) { /* KSF */
if (TST_INT (TTI)) AC = AC | IOT_SKP; }
if (TST_INT (TTI)) dat = dat | IOT_SKP; }
if (pulse & 002) { /* KRB */
CLR_INT (TTI); /* clear flag */
AC = AC | tti_unit.buf & TTI_MASK; } /* return buffer */
dat = dat | tti_unit.buf & TTI_MASK; } /* return buffer */
if (pulse & 004) { /* IORS */
AC = AC | upd_iors (); }
return AC;
dat = dat | upd_iors (); }
return dat;
}
/* Unit service */
@@ -870,15 +908,15 @@ return SCPE_OK;
/* Terminal output: IOT routine */
int32 tto (int32 pulse, int32 AC)
int32 tto (int32 pulse, int32 dat)
{
if (pulse & 001) { /* TSF */
if (TST_INT (TTO)) AC = AC | IOT_SKP; }
if (TST_INT (TTO)) dat = dat | IOT_SKP; }
if (pulse & 002) CLR_INT (TTO); /* clear flag */
if (pulse & 004) { /* load buffer */
sim_activate (&tto_unit, tto_unit.wait); /* activate unit */
tto_unit.buf = AC & TTO_MASK; } /* load buffer */
return AC;
tto_unit.buf = dat & TTO_MASK; } /* load buffer */
return dat;
}
/* Unit service */

View File

@@ -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.
30-Jul-03 RMS Fixed FPM class mask
18-Jul-03 RMS Added FP15 support
02-Mar-03 RMS Split loaders apart for greater flexibility
09-Feb-03 RMS Fixed bug in FMTASC (found by Hans Pufal)
31-Jan-03 RMS Added support for RB09
@@ -47,6 +49,9 @@
#include <ctype.h>
extern DEVICE cpu_dev;
#if defined (PDP15)
extern DEVICE fpp_dev;
#endif
extern DEVICE ptr_dev, ptp_dev;
extern DEVICE tti_dev, tto_dev;
extern UNIT tti_unit, tto_unit;
@@ -87,7 +92,7 @@ extern UNIT cpu_unit;
extern REG cpu_reg[];
extern int32 M[];
extern int32 memm;
extern int32 saved_PC;
extern int32 PC;
/* SCP data structures and interface routines
@@ -111,9 +116,13 @@ char sim_name[] = "PDP-15";
REG *sim_PC = &cpu_reg[0];
int32 sim_emax = 3;
int32 sim_emax = 2;
DEVICE *sim_devices[] = { &cpu_dev,
DEVICE *sim_devices[] = {
&cpu_dev,
#if defined (PDP15)
&fpp_dev,
#endif
&ptr_dev,
&ptp_dev,
&tti_dev,
@@ -159,7 +168,8 @@ const char *sim_stop_messages[] = {
"Breakpoint",
"Nested XCT's",
"Invalid API interrupt",
"Non-standard device number" };
"Non-standard device number",
"Memory management error" };
/* Binary loaders */
@@ -202,7 +212,7 @@ for (;;) {
if ((val = getword (fileref, NULL)) < 0) return SCPE_FMT;
if (MEM_ADDR_OK (origin)) M[origin++] = val; }
else if ((val & 0760000) == OP_JMP) { /* JMP? */
saved_PC = ((origin - 1) & 060000) | (val & 017777);
PC = ((origin - 1) & 060000) | (val & 017777);
return SCPE_OK; }
else if (val == OP_HLT) return SCPE_OK; /* HLT? */
else return SCPE_FMT; } /* error */
@@ -226,7 +236,7 @@ t_stat r;
if (*cptr != 0) { /* more input? */
cptr = get_glyph (cptr, gbuf, 0); /* get origin */
origin = get_uint (gbuf, 8, ADDRMASK, &r);
origin = get_uint (gbuf, 8, AMASK, &r);
if (r != SCPE_OK) return r;
if (*cptr != 0) return SCPE_ARG; } /* no more */
else origin = 0200; /* default 200 */
@@ -234,7 +244,7 @@ else origin = 0200; /* default 200 */
for (;;) { /* word loop */
if ((val = getword (fileref, &bits)) < 0) return SCPE_FMT;
if (bits & 1) { /* end of tape? */
if ((val & 0760000) == OP_JMP) saved_PC =
if ((val & 0760000) == OP_JMP) PC =
((origin - 1) & 060000) | (val & 017777);
else if (val != OP_HLT) return SCPE_FMT;
break; }
@@ -258,16 +268,16 @@ return SCPE_OK;
t_stat bin_load_915 (FILE *fileref, char *cptr)
{
int32 i, val, origin, count, cksum;
int32 i, val, bits, origin, count, cksum;
if (*cptr != 0) return SCPE_2MARG; /* no arguments */
do { val = getc (fileref); } /* find end RIM */
while (((val & 0100) == 0) && (val != EOF));
if (val == EOF) rewind (fileref); /* no RIM? rewind */
do { val = getword (fileref, & bits); } /* find end RIM */
while ((val >= 0) && ((bits & 1) == 0));
if (val < 0) rewind (fileref); /* no RIM? rewind */
for (;;) { /* block loop */
if ((val = getword (fileref, NULL)) < 0) return SCPE_FMT;
if (val & SIGN) {
if (val != DMASK) saved_PC = val & 077777;
if (val != DMASK) PC = val & 077777;
break; }
cksum = origin = val; /* save origin */
if ((val = getword (fileref, NULL)) < 0) return SCPE_FMT;
@@ -328,23 +338,30 @@ return bin_load_915 (fileref, cptr); /* must be BIN */
#define I_V_EST 8 /* EAE setup */
#define I_V_ESH 9 /* EAE shift */
#define I_V_EMD 10 /* EAE mul-div */
#define I_NPN (I_V_NPN << I_V_FL) /* no operand */
#define I_NPI (I_V_NPI << I_V_FL) /* no operand IOT */
#define I_IOT (I_V_IOT << I_V_FL) /* IOT */
#define I_MRF (I_V_MRF << I_V_FL) /* memory reference */
#define I_OPR (I_V_OPR << I_V_FL) /* OPR */
#define I_LAW (I_V_LAW << I_V_FL) /* LAW */
#define I_XR (I_V_XR << I_V_FL) /* index */
#define I_XR9 (I_V_XR9 << I_V_FL) /* index literal */
#define I_EST (I_V_EST << I_V_FL) /* EAE setup */
#define I_ESH (I_V_ESH << I_V_FL) /* EAE shift */
#define I_EMD (I_V_EMD << I_V_FL) /* EAE mul-div */
#define I_V_FPM 11 /* FP15 mem ref */
#define I_V_FPI 12 /* FP15 indirect */
#define I_V_FPN 13 /* FP15 no operand */
#define I_NPN (I_V_NPN << I_V_FL)
#define I_NPI (I_V_NPI << I_V_FL)
#define I_IOT (I_V_IOT << I_V_FL)
#define I_MRF (I_V_MRF << I_V_FL)
#define I_OPR (I_V_OPR << I_V_FL)
#define I_LAW (I_V_LAW << I_V_FL)
#define I_XR (I_V_XR << I_V_FL)
#define I_XR9 (I_V_XR9 << I_V_FL)
#define I_EST (I_V_EST << I_V_FL)
#define I_ESH (I_V_ESH << I_V_FL)
#define I_EMD (I_V_EMD << I_V_FL)
#define I_FPM (I_V_FPM << I_V_FL)
#define I_FPI (I_V_FPI << I_V_FL)
#define I_FPN (I_V_FPN << I_V_FL)
#define MD(x) ((I_EMD) + ((x) << I_V_DC))
static const int32 masks[] = {
0777777, 0777767, 0740000, 0760000,
0777777, 0777767, 0770000, 0760000,
0763730, 0760000, 0777000, 0777000,
0740700, 0760700, 0777700 };
0740700, 0760700, 0777700, 0777777,
0777777, 0777777 };
static const char *opcode[] = {
"CAL", "DAC", "JMS", "DZM", /* mem refs */
@@ -452,9 +469,75 @@ static const char *opcode[] = {
#if defined (PDP15)
"SPCO", "SKP15", "RES",
"SBA", "DBA", "EBA",
"ORMM", "RDMM", "LDMM", "MPLR",
"ENB", "INH", "MPRC", "IPFH",
"AAS", "PAX", "PAL", "AAC",
"PXA", "AXS", "PXL", "PLA",
"PLX", "CLAC","CLX", "CLLR", "AXR",
"FPT", /* FP15 */
"ISB", "ESB", /* mem ref */
"FSB", "URFSB", "UNFSB", "UUFSB",
"DSB", "URDSB", "UNDSB", "UUDSB",
"IRS", "ERS",
"FRS", "URFRS", "UNFRS", "UUFRS",
"DRS", "URDRS", "UNDRS", "UUDRS",
"IMP", "EMP",
"FMP", "URFMP", "UNFMP", "UUFMP",
"DMP", "URDMP", "UNDMP", "UUDMP",
"IDV", "EDV",
"FDV", "URFDV", "UNFDV", "UUFDV",
"DDV", "URDDV", "UNDDV", "UUDDV",
"IRD", "ERD",
"FRD", "URFRD", "UNFRD", "UUFRD",
"DRD", "URDRD", "UNDRD", "UUDRD",
"ILD", "ELD",
"FLD", "UNFLD", "DLD", "UNDLD",
"IST", "EST",
"FST", "URFST", "UNFST", "UUFST",
"DST", "UNDST",
"ILF", "UNILF", "ELF", "UNELF",
"FLX", "URFLX", "DLX", "URDLX",
"ILQ", "ELQ",
"FLQ", "UNFLQ", "DLQ", "UNDLQ",
"LJE", "SJE",
"IAD", "EAD",
"FAD", "URFAD", "UNFAD", "UUFAD",
"DAD", "URDAD", "UNDAD", "UUDAD",
"BZA", "BMA", "BLE", "BPA",
"BRU", "BNA", "BAC",
"ISB*", "ESB*", /* indirect */
"FSB*", "URFSB*", "UNFSB*", "UUFSB*",
"DSB*", "URDSB*", "UNDSB*", "UUDSB*",
"IRS*", "ERS*",
"FRS*", "URFRS*", "UNFRS*", "UUFRS*",
"DRS*", "URDRS*", "UNDRS*", "UUDRS*",
"IMP*", "EMP*",
"FMP*", "URFMP*", "UNFMP*", "UUFMP*",
"DMP*", "URDMP*", "UNDMP*", "UUDMP*",
"IDV*", "EDV*",
"FDV*", "URFDV*", "UNFDV*", "UUFDV*",
"DDV*", "URDDV*", "UNDDV*", "UUDDV*",
"IRD*", "ERD",
"FRD*", "URFRD*", "UNFRD*", "UUFRD*",
"DRD*", "URDRD*", "UNDRD*", "UUDRD*",
"ILD*", "ELD",
"FLD*", "UNFLD*", "DLD*", "UNDLD*",
"IST*", "EST",
"FST*", "URFST*", "UNFST*", "UUFST*",
"DST*", "UNDST*",
"ILF*", "UNILF*", "ELF*", "UNELF*",
"FLX*", "URFLX*", "DLX*", "URDLX*",
"ILQ*", "ELQ*",
"FLQ*", "UNFLQ*", "DLQ*", "UNDLQ*",
"LJE*", "SJE*",
"IAD*", "EAD*",
"FAD*", "URFAD*", "UNFAD*", "UUFAD*",
"DAD*", "URDAD*", "UNDAD*", "UUDAD*",
"FLA", "UNFLA", "FXA", "URFXA", /* no operand */
"SWQ", "UNSWQ", "FZR",
"FAB", "FNG", "FCM", "FNM",
#endif
#if defined (PDP9) || defined (PDP15)
"MPSK", "MPSNE", "MPCV", "MPEU",
@@ -617,9 +700,74 @@ static const int32 opc_val[] = {
#if defined (PDP15)
0703341+I_NPI, 0707741+I_NPI, 0707742+I_NPI,
0707761+I_NPI, 0707762+I_NPI, 0707764+I_NPI,
0700022+I_NPI, 0700032+I_NPN, 0700024+I_NPI, 0701724+I_NPI,
0705521+I_NPI, 0705522+I_NPI, 0701722+I_NPI, 0701764+I_NPI,
0720000+I_XR9, 0721000+I_XR, 0722000+I_XR, 0723000+I_XR9,
0724000+I_XR, 0725000+I_XR9, 0726000+I_XR, 0730000+I_XR,
0731000+I_XR, 0734000+I_XR, 0735000+I_XR, 0736000+I_XR, 0737000+I_XR9,
0710314+I_FPN,
0710400+I_FPM, 0710500+I_FPM,
0710440+I_FPM, 0710450+I_FPM, 0710460+I_FPM, 0710470+I_FPM,
0710540+I_FPM, 0710550+I_FPM, 0710560+I_FPM, 0710570+I_FPM,
0711000+I_FPM, 0711100+I_FPM,
0711040+I_FPM, 0711050+I_FPM, 0711060+I_FPM, 0711070+I_FPM,
0711140+I_FPM, 0711150+I_FPM, 0711160+I_FPM, 0711170+I_FPM,
0711400+I_FPM, 0711500+I_FPM,
0711440+I_FPM, 0711450+I_FPM, 0711460+I_FPM, 0711470+I_FPM,
0711540+I_FPM, 0711550+I_FPM, 0711560+I_FPM, 0711570+I_FPM,
0712000+I_FPM, 0712100+I_FPM,
0712040+I_FPM, 0712050+I_FPM, 0712060+I_FPM, 0712070+I_FPM,
0712140+I_FPM, 0712150+I_FPM, 0712160+I_FPM, 0712170+I_FPM,
0712400+I_FPM, 0712500+I_FPM,
0712440+I_FPM, 0712450+I_FPM, 0712460+I_FPM, 0712470+I_FPM,
0712540+I_FPM, 0712550+I_FPM, 0712560+I_FPM, 0712570+I_FPM,
0713000+I_FPM, 0713100+I_FPM,
0713050+I_FPM, 0713070+I_FPM, 0713150+I_FPM, 0713170+I_FPM,
0713600+I_FPM, 0713700+I_FPM,
0713640+I_FPM, 0713650+I_FPM, 0713660+I_FPM, 0713670+I_FPM,
0713750+I_FPM, 0713770+I_FPM,
0714010+I_FPM, 0714030+I_FPM, 0714110+I_FPM, 0714130+I_FPM,
0714460+I_FPM, 0714470+I_FPM, 0714560+I_FPM, 0714570+I_FPM,
0715000+I_FPM, 0715100+I_FPM,
0715050+I_FPM, 0715070+I_FPM, 0715150+I_FPM, 0715170+I_FPM,
0715400+I_FPM, 0715600+I_FPM,
0716000+I_FPM, 0716100+I_FPM,
0716040+I_FPM, 0716050+I_FPM, 0716060+I_FPM, 0716070+I_FPM,
0716140+I_FPM, 0716150+I_FPM, 0716160+I_FPM, 0716170+I_FPM,
0716601+I_FPM, 0716602+I_FPM, 0716603+I_FPM,
0716604+I_FPM, 0716606+I_FPM, 0716610+I_FPM, 0716620+I_FPM,
0710400+I_FPI, 0710500+I_FPI, /* indirect */
0710440+I_FPI, 0710450+I_FPI, 0710460+I_FPI, 0710470+I_FPI,
0710540+I_FPI, 0710550+I_FPI, 0710560+I_FPI, 0710570+I_FPI,
0711000+I_FPI, 0711100+I_FPI,
0711040+I_FPI, 0711050+I_FPI, 0711060+I_FPI, 0711070+I_FPI,
0711140+I_FPI, 0711150+I_FPI, 0711160+I_FPI, 0711170+I_FPI,
0711400+I_FPI, 0711500+I_FPI,
0711440+I_FPI, 0711450+I_FPI, 0711460+I_FPI, 0711470+I_FPI,
0711540+I_FPI, 0711550+I_FPI, 0711560+I_FPI, 0711570+I_FPI,
0712000+I_FPI, 0712100+I_FPI,
0712040+I_FPI, 0712050+I_FPI, 0712060+I_FPI, 0712070+I_FPI,
0712140+I_FPI, 0712150+I_FPI, 0712160+I_FPI, 0712170+I_FPI,
0712400+I_FPI, 0712500+I_FPI,
0712440+I_FPI, 0712450+I_FPI, 0712460+I_FPI, 0712470+I_FPI,
0712540+I_FPI, 0712550+I_FPI, 0712560+I_FPI, 0712570+I_FPI,
0713000+I_FPI, 0713100+I_FPI,
0713050+I_FPI, 0713070+I_FPI, 0713150+I_FPI, 0713170+I_FPI,
0713600+I_FPI, 0713700+I_FPI,
0713640+I_FPI, 0713650+I_FPI, 0713660+I_FPI, 0713670+I_FPI,
0713750+I_FPI, 0713770+I_FPI,
0714010+I_FPI, 0714030+I_FPI, 0714110+I_FPI, 0714130+I_FPI,
0714460+I_FPI, 0714470+I_FPI, 0714560+I_FPI, 0714570+I_FPI,
0715000+I_FPI, 0715100+I_FPI,
0715050+I_FPI, 0715070+I_FPI, 0715150+I_FPI, 0715170+I_FPI,
0715400+I_FPI, 0715600+I_FPI,
0716000+I_FPI, 0716100+I_FPI,
0716040+I_FPI, 0716050+I_FPI, 0716060+I_FPI, 0716070+I_FPI,
0716140+I_FPI, 0716150+I_FPI, 0716160+I_FPI, 0716170+I_FPI,
0714210+I_FPN, 0714230+I_FPN, 0714660+I_FPN, 0714670+I_FPN,
0715250+I_FPN, 0715270+I_FPN, 0711200+I_FPN,
0713271+I_FPN, 0713272+I_FPN, 0713273+I_FPN, 0713250+I_FPN,
#endif
#if defined (PDP9) || defined (PDP15)
0701701+I_NPI, 0701741+I_NPI, 0701702+I_NPI, 0701742+I_NPI,
@@ -741,7 +889,7 @@ if (!(sw & SWMASK ('M'))) return SCPE_ARG;
for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */
j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */
if ((opc_val[i] & 0777777) == (inst & masks[j])) { /* match? */
if ((opc_val[i] & DMASK) == (inst & masks[j])) { /* match? */
switch (j) { /* case on class */
case I_V_NPN: /* no operands */
@@ -758,17 +906,17 @@ for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */
case I_V_MRF: /* mem ref */
#if defined (PDP15)
if (memm) {
disp = inst & 017777;
ma = (addr & 0760000) | disp; }
disp = inst & B_DAMASK;
ma = (addr & (AMASK & ~B_DAMASK)) | disp; }
else {
disp = inst & 007777;
ma = (addr & 0770000) | disp; }
fprintf (of, "%s %-o", opcode[i], (cflag? ma & ADDRMASK: disp));
if (!memm && (inst & 0010000)) fprintf (of, ",X");
disp = inst & P_DAMASK;
ma = (addr & (AMASK & ~P_DAMASK)) | disp; }
fprintf (of, "%s %-o", opcode[i], (cflag? ma & AMASK: disp));
if (!memm && (inst & I_IDX)) fprintf (of, ",X");
#else
disp = inst & 017777;
ma = (addr & 0760000) | disp;
fprintf (of, "%s %-o", opcode[i], (cflag? ma & ADDRMASK: disp));
disp = inst & B_DAMASK;
ma = (addr & (AMASK & ~B_DAMASK)) | disp;
fprintf (of, "%s %-o", opcode[i], (cflag? ma & AMASK: disp));
#endif
break;
case I_V_OPR: /* operate */
@@ -796,7 +944,15 @@ for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */
if (disp == k) fprintf (of, "%s", opcode[i]);
else if (disp < k) fprintf (of, "%s -%-o", opcode[i], k - disp);
else fprintf (of, "%s +%-o", opcode[i], disp - k);
break; } /* end case */
break;
case I_V_FPM: case I_V_FPI: /* FP15 mem ref */
fprintf (of, "%s", opcode[i]);
if (val[1] & SIGN) fputc ('*', of);
fprintf (of, " %-o", val[1] & ~SIGN);
return -1;
case I_V_FPN: /* FP15 no operand */
fprintf (of, "%s", opcode[i]);
return -1; } /* end case */
return SCPE_OK; } /* end if */
} /* end for */
return SCPE_ARG;
@@ -838,8 +994,8 @@ return get_uint (cptr, 8, 0777777, status);
t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw)
{
int32 cflag, d, i, j, k, sign, dmask, epcmask;
t_stat r;
int32 cflag, d, i, j, k, sign, damask, epcmask;
t_stat r, sta = SCPE_OK;
char gbuf[CBUFSIZE];
cflag = (uptr == NULL) || (uptr == &cpu_unit);
@@ -895,31 +1051,31 @@ case I_V_LAW: /* law */
break;
case I_V_MRF: /* mem ref */
#if defined (PDP15)
if (memm) dmask = 017777;
else dmask = 07777;
if (memm) damask = B_DAMASK;
else damask = P_DAMASK;
cptr = get_glyph (cptr, gbuf, ','); /* get glyph */
#else
dmask = 017777;
damask = B_DAMASK;
cptr = get_glyph (cptr, gbuf, 0); /* get next field */
#endif
#if defined (PDP4) || defined (PDP7)
if (strcmp (gbuf, "I") == 0) { /* indirect? */
val[0] = val[0] | 020000;
val[0] = val[0] | I_IND;
cptr = get_glyph (cptr, gbuf, 0); }
#endif
epcmask = ADDRMASK & ~dmask; /* get ePC */
d = get_uint (gbuf, 8, ADDRMASK, &r); /* get addr */
epcmask = AMASK & ~damask; /* get ePC */
d = get_uint (gbuf, 8, AMASK, &r); /* get addr */
if (r != SCPE_OK) return SCPE_ARG;
if (d <= dmask) val[0] = val[0] | d; /* fit in 12/13b? */
if (d <= damask) val[0] = val[0] | d; /* fit in 12/13b? */
else if (cflag && (((addr ^ d) & epcmask) == 0))
val[0] = val[0] | (d & dmask); /* hi bits = ePC? */
val[0] = val[0] | (d & damask); /* hi bits = ePC? */
else return SCPE_ARG;
#if defined (PDP15)
if (!memm) {
cptr = get_glyph (cptr, gbuf, 0);
if (gbuf[0] != 0) {
if (strcmp (gbuf, "X") != 0) return SCPE_ARG;
val[0] = val[0] | 010000; } }
val[0] = val[0] | I_IDX; } }
#endif
break;
case I_V_EMD: /* or'able */
@@ -940,7 +1096,23 @@ case I_V_NPN: case I_V_NPI: case I_V_IOT: case I_V_OPR:
if (sign > 0) val[0] = val[0] + d;
else if (sign < 0) val[0] = val[0] - d;
else val[0] = val[0] | d; } }
break;
case I_V_FPM: /* FP15 mem ref */
cptr = get_glyph (cptr, gbuf, 0); /* get next field */
val[1] = get_uint (gbuf, 8, AMASK, &r); /* get addr */
if (r != SCPE_OK) return SCPE_ARG;
sta = -1;
break;
case I_V_FPI: /* FP15 ind mem ref */
cptr = get_glyph (cptr, gbuf, 0); /* get next field */
val[1] = get_uint (gbuf, 8, AMASK, &r) | SIGN; /* get @addr */
if (r != SCPE_OK) return SCPE_ARG;
sta = -1;
break;
case I_V_FPN: /* FP15 no operand */
val[1] = 0;
sta = -1;
break; } /* end case */
if (*cptr != 0) return SCPE_ARG; /* junk at end? */
return SCPE_OK;
return sta;
}

View File

@@ -58,8 +58,8 @@ TMLN tt1_ldsc = { 0 }; /* line descriptors */
TMXR tt_desc = { 1, 0, 0, &tt1_ldsc }; /* mux descriptor */
DEVICE tti1_dev, tto1_dev;
int32 tti1 (int32 pulse, int32 AC);
int32 tto1 (int32 pulse, int32 AC);
int32 tti1 (int32 pulse, int32 dat);
int32 tto1 (int32 pulse, int32 dat);
t_stat tti1_svc (UNIT *uptr);
t_stat tto1_svc (UNIT *uptr);
t_stat tti1_reset (DEVICE *dptr);
@@ -150,14 +150,14 @@ DEVICE tto1_dev = {
/* Terminal input: IOT routine */
int32 tti1 (int32 pulse, int32 AC)
int32 tti1 (int32 pulse, int32 dat)
{
if (pulse & 001) { /* KSF1 */
if (TST_INT (TTI1)) AC = AC | IOT_SKP; }
if (TST_INT (TTI1)) dat = dat | IOT_SKP; }
if (pulse & 002) { /* KRB1 */
CLR_INT (TTI1); /* clear flag */
AC= AC | tti1_unit.buf; } /* return buffer */
return AC;
dat= dat | tti1_unit.buf; } /* return buffer */
return dat;
}
/* Unit service */
@@ -204,15 +204,15 @@ return SCPE_OK;
/* Terminal output: IOT routine */
int32 tto1 (int32 pulse, int32 AC)
int32 tto1 (int32 pulse, int32 dat)
{
if (pulse & 001) { /* TSF */
if (TST_INT (TTO1)) AC = AC | IOT_SKP; }
if (TST_INT (TTO1)) dat = dat | IOT_SKP; }
if (pulse & 002) CLR_INT (TTO1); /* clear flag */
if (pulse & 004) { /* load buffer */
sim_activate (&tto1_unit, tto1_unit.wait); /* activate unit */
tto1_unit.buf = AC & 0377; } /* load buffer */
return AC;
tto1_unit.buf = dat & 0377; } /* load buffer */
return dat;
}
/* Unit service */