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:
committed by
Mark Pizzolato
parent
4ffd3be790
commit
f9564b81b9
1211
PDP18B/pdp18b_cpu.c
1211
PDP18B/pdp18b_cpu.c
File diff suppressed because it is too large
Load Diff
@@ -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 */
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
774
PDP18B/pdp18b_fpp.c
Normal 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;
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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? */
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user